1 /* mswindows.c -- Windows-specific support
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
3 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Wget.
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Wget. If not, see <http://www.gnu.org/licenses/>.
20 Additional permission under GNU GPL version 3 section 7
22 If you modify this program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a
24 modified version of that library), containing parts covered by the
25 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
26 grants you additional permission to convey the resulting work.
27 Corresponding Source for a non-source form of such a combination
28 shall include the source code for the parts of OpenSSL used as well
29 as that of the covered work. */
31 #define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
46 #ifndef ES_SYSTEM_REQUIRED
47 #define ES_SYSTEM_REQUIRED 0x00000001
51 #define ES_CONTINUOUS 0x80000000
55 /* Defined in log.c. */
56 void log_request_redirect_output (const char *);
58 /* Windows version of xsleep in utils.c. */
61 xsleep (double seconds)
66 /* Explained in utils.c. */
68 seconds -= (long) seconds;
70 usleep (seconds * 1000000);
71 #else /* not HAVE_USLEEP */
72 SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
73 #endif /* not HAVE_USLEEP */
77 windows_main (char **exec_name)
81 /* Remove .EXE from filename if it has one. */
82 *exec_name = xstrdup (*exec_name);
83 p = strrchr (*exec_name, '.');
91 xfree ((char*)exec_name);
95 #if defined(CTRLBREAK_BACKGND) || defined(CTRLC_BACKGND)
97 ws_hangup (const char *reason)
99 fprintf (stderr, _("Continuing in background.\n"));
100 log_request_redirect_output (reason);
102 /* Detach process from the current console. Under Windows 9x, if we
103 were launched from a 16-bit process (which is usually the case;
104 command.com is 16-bit) the parent process should resume right away.
105 Under NT or if launched from a 32-process under 9x, this is a futile
106 gesture as the parent will wait for us to terminate before resuming. */
111 /* Construct the name for a named section (a.k.a. `file mapping') object.
112 The returned string is dynamically allocated and needs to be xfree()'d. */
114 make_section_name (DWORD pid)
116 return aprintf ("gnu_wget_fake_fork_%lu", pid);
119 /* This structure is used to hold all the data that is exchanged between
121 struct fake_fork_info
124 bool logfile_changed;
125 char lfilename[MAX_PATH + 1];
128 /* Determines if we are the child and if so performs the child logic.
135 fake_fork_child (void)
137 HANDLE section, event;
138 struct fake_fork_info *info;
141 name = make_section_name (GetCurrentProcessId ());
142 section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
144 /* It seems that Windows 9x and NT set last-error inconsistently when
145 OpenFileMapping() fails; so we assume it failed because the section
146 object does not exist. */
148 return 0; /* We are the parent. */
150 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
153 CloseHandle (section);
159 info->logfile_changed = false;
160 if (!opt.lfilename && (!opt.quiet || opt.server_response))
162 /* See utils:fork_to_background for explanation. */
163 FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
166 info->logfile_changed = true;
167 strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
168 info->lfilename[sizeof (info->lfilename) - 1] = '\0';
173 UnmapViewOfFile (info);
174 CloseHandle (section);
176 /* Inform the parent that we've done our part. */
177 if (!SetEvent (event))
181 return 1; /* We are the child. */
184 /* Windows doesn't support the fork() call; so we fake it by invoking
185 another copy of Wget with the same arguments with which we were
186 invoked. The child copy of Wget should perform the same initialization
187 sequence as the parent; so we should have two processes that are
188 essentially identical. We create a specially named section object that
189 allows the child to distinguish itself from the parent and is used to
190 exchange information between the two processes. We use an event object
191 for synchronization. */
195 char exe[MAX_PATH + 1];
197 SECURITY_ATTRIBUTES sa;
198 HANDLE section, event, h[2];
200 PROCESS_INFORMATION pi;
201 struct fake_fork_info *info;
205 section = pi.hProcess = pi.hThread = NULL;
207 /* Get the fully qualified name of our executable. This is more reliable
208 than using argv[0]. */
209 exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
210 if (!exe_len || (exe_len >= sizeof (exe)))
213 sa.nLength = sizeof (sa);
214 sa.lpSecurityDescriptor = NULL;
215 sa.bInheritHandle = TRUE;
217 /* Create an anonymous inheritable event object that starts out
219 event = CreateEvent (&sa, FALSE, FALSE, NULL);
223 /* Create the child process detached form the current console and in a
227 rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
228 CREATE_SUSPENDED | DETACHED_PROCESS,
229 NULL, NULL, &si, &pi);
233 /* Create a named section object with a name based on the process id of
235 name = make_section_name (pi.dwProcessId);
237 CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
238 sizeof (struct fake_fork_info), name);
241 /* Fail if the section object already exists (should not happen). */
242 if (!section || (le == ERROR_ALREADY_EXISTS))
248 /* Copy the event handle into the section object. */
249 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
258 UnmapViewOfFile (info);
260 /* Start the child process. */
261 rv = ResumeThread (pi.hThread);
264 TerminateProcess (pi.hProcess, (DWORD) -1);
268 /* Wait for the child to signal to us that it has done its part. If it
269 terminates before signaling us it's an error. */
273 rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
277 info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
284 /* Ensure string is properly terminated. */
285 if (info->logfile_changed &&
286 !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
293 printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
294 if (info->logfile_changed)
295 printf (_("Output will be written to `%s'.\n"), info->lfilename);
297 UnmapViewOfFile (info);
304 CloseHandle (section);
306 CloseHandle (pi.hThread);
308 CloseHandle (pi.hProcess);
310 /* We're the parent. If all is well, terminate. */
314 /* We failed, return. */
317 /* This is the corresponding Windows implementation of the
318 fork_to_background() function in utils.c. */
320 fork_to_background (void)
324 rv = fake_fork_child ();
327 fprintf (stderr, "fake_fork_child() failed\n");
332 /* We're the parent. */
334 /* If fake_fork() returns, it failed. */
335 fprintf (stderr, "fake_fork() failed\n");
338 /* If we get here, we're the child. */
342 ws_handler (DWORD dwEvent)
348 ws_hangup ("CTRL+C");
351 #ifdef CTRLBREAK_BACKGND
352 case CTRL_BREAK_EVENT:
353 ws_hangup ("CTRL+Break");
361 static char *title_buf = NULL;
362 static char *curr_url = NULL;
363 static int old_percentage = -1;
365 /* Updates the console title with the URL of the current file being
368 ws_changetitle (const char *url)
370 xfree_null (title_buf);
371 xfree_null (curr_url);
372 title_buf = xmalloc (strlen (url) + 20);
373 curr_url = xstrdup (url);
375 sprintf (title_buf, "Wget %s", curr_url);
376 SetConsoleTitle (title_buf);
379 /* Updates the console title with the percentage of the current file
382 ws_percenttitle (double percentage_float)
386 if (!title_buf || !curr_url)
389 percentage = (int) percentage_float;
391 /* Clamp percentage value. */
394 if (percentage > 100)
397 /* Only update the title when the percentage has changed. */
398 if (percentage == old_percentage)
401 old_percentage = percentage;
403 sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
404 SetConsoleTitle (title_buf);
407 /* Returns a pointer to the fully qualified name of the directory that
408 contains the Wget binary (wget.exe). The returned path does not have a
409 trailing path separator. Returns NULL on failure. */
413 static char *wspathsave = NULL;
417 char buf[MAX_PATH + 1];
421 len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
422 if (!len || (len >= sizeof (buf)))
425 p = strrchr (buf, PATH_SEPARATOR);
430 wspathsave = xstrdup (buf);
436 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
437 a lengthy transfer. Windows does not, by default, consider network
438 activity in console-programs as activity! Works on Win-98/ME/2K
441 set_sleep_mode (void)
443 typedef DWORD (WINAPI *func_t) (DWORD);
444 func_t set_exec_state;
447 (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
448 "SetThreadExecutionState");
451 set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
454 /* Perform Windows specific initialization. */
459 WORD requested = MAKEWORD (1, 1);
460 int err = WSAStartup (requested, &data);
463 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
468 if (data.wVersion < requested)
470 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
478 SetConsoleCtrlHandler (ws_handler, TRUE);
481 /* run_with_timeout Windows implementation. */
483 /* Stack size 0 uses default thread stack-size (reserve+commit).
484 Determined by what's in the PE header. */
485 #define THREAD_STACK_SIZE 0
489 void (*fun) (void *);
494 /* The callback that runs FUN(ARG) in a separate thread. This
495 function exists for two reasons: a) to not require FUN to be
496 declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
497 which are per-thread. The latter is useful when FUN calls Winsock
498 functions, which is how run_with_timeout is used in Wget.
500 [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
501 the default (wcc386 -3r). */
504 thread_helper (void *arg)
506 struct thread_data *td = (struct thread_data *) arg;
508 /* Initialize Winsock error to what it was in the parent. That way
509 the subsequent call to WSAGetLastError will return the same value
510 if td->fun doesn't change Winsock error state. */
511 WSASetLastError (td->ws_error);
515 /* Return Winsock error to the caller, in case FUN ran Winsock
517 td->ws_error = WSAGetLastError ();
521 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
522 seconds. Returns true if the function was interrupted with a
523 timeout, false otherwise.
525 This works by running FUN in a separate thread and terminating the
526 thread if it doesn't finish in the specified time. */
529 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
532 struct thread_data thread_arg;
536 DEBUGP (("seconds %.2f, ", seconds));
545 thread_arg.fun = fun;
546 thread_arg.arg = arg;
547 thread_arg.ws_error = WSAGetLastError ();
548 thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
549 &thread_arg, 0, &thread_id);
552 DEBUGP (("CreateThread() failed; [%#lx]\n",
553 (unsigned long) GetLastError ()));
554 goto blocking_fallback;
557 if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
560 /* Propagate error state (which is per-thread) to this thread,
561 so the caller can inspect it. */
562 WSASetLastError (thread_arg.ws_error);
563 DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
568 TerminateThread (thread_hnd, 1);
572 CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
577 /* Wget expects network calls such as connect, recv, send, etc., to set
578 errno on failure. To achieve that, Winsock calls are wrapped with code
579 that, in case of error, sets errno to the value of WSAGetLastError().
580 In addition, we provide a wrapper around strerror, which recognizes
581 Winsock errors and prints the appropriate error message. */
583 /* Define a macro that creates a function definition that wraps FUN into
584 a function that sets errno the way the rest of the code expects. */
586 #define WRAP(fun, decl, call) int wrapped_##fun decl { \
587 int retval = fun call; \
589 errno = WSAGetLastError (); \
593 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
594 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
595 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
596 WRAP (listen, (int s, int backlog), (s, backlog))
597 WRAP (accept, (int s, struct sockaddr *a, int *alen), (s, a, alen))
598 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
599 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
600 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
602 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
603 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
604 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
605 (s, level, opt, val, len))
606 WRAP (closesocket, (int s), (s))
608 /* Return the text of the error message for Winsock error WSERR. */
611 get_winsock_error (int wserr)
614 case WSAEINTR: return "Interrupted system call";
615 case WSAEBADF: return "Bad file number";
616 case WSAEACCES: return "Permission denied";
617 case WSAEFAULT: return "Bad address";
618 case WSAEINVAL: return "Invalid argument";
619 case WSAEMFILE: return "Too many open files";
620 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
621 case WSAEINPROGRESS: return "Operation now in progress";
622 case WSAEALREADY: return "Operation already in progress";
623 case WSAENOTSOCK: return "Socket operation on nonsocket";
624 case WSAEDESTADDRREQ: return "Destination address required";
625 case WSAEMSGSIZE: return "Message too long";
626 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
627 case WSAENOPROTOOPT: return "Bad protocol option";
628 case WSAEPROTONOSUPPORT: return "Protocol not supported";
629 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
630 case WSAEOPNOTSUPP: return "Operation not supported";
631 case WSAEPFNOSUPPORT: return "Protocol family not supported";
632 case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
633 case WSAEADDRINUSE: return "Address already in use";
634 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
635 case WSAENETDOWN: return "Network is down";
636 case WSAENETUNREACH: return "Network is unreachable";
637 case WSAENETRESET: return "Network dropped connection on reset";
638 case WSAECONNABORTED: return "Software caused connection abort";
639 case WSAECONNRESET: return "Connection reset by peer";
640 case WSAENOBUFS: return "No buffer space available";
641 case WSAEISCONN: return "Socket is already connected";
642 case WSAENOTCONN: return "Socket is not connected";
643 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
644 case WSAETOOMANYREFS: return "Too many references";
645 case WSAETIMEDOUT: return "Connection timed out";
646 case WSAECONNREFUSED: return "Connection refused";
647 case WSAELOOP: return "Too many levels of symbolic links";
648 case WSAENAMETOOLONG: return "File name too long";
649 case WSAEHOSTDOWN: return "Host is down";
650 case WSAEHOSTUNREACH: return "No route to host";
651 case WSAENOTEMPTY: return "Not empty";
652 case WSAEPROCLIM: return "Too many processes";
653 case WSAEUSERS: return "Too many users";
654 case WSAEDQUOT: return "Bad quota";
655 case WSAESTALE: return "Something is stale";
656 case WSAEREMOTE: return "Remote error";
657 case WSAEDISCON: return "Disconnected";
659 /* Extended Winsock errors */
660 case WSASYSNOTREADY: return "Winsock library is not ready";
661 case WSANOTINITIALISED: return "Winsock library not initalised";
662 case WSAVERNOTSUPPORTED: return "Winsock version not supported";
664 case WSAHOST_NOT_FOUND: return "Host not found";
665 case WSATRY_AGAIN: return "Host not found, try again";
666 case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
667 case WSANO_DATA: return "No data record of requested type";
674 /* Return the error message corresponding to ERR. This is different
675 from Windows libc strerror() in that it handles Winsock errors
679 windows_strerror (int err)
682 if (err >= 0 && err < sys_nerr)
683 return strerror (err);
684 else if ((p = get_winsock_error (err)) != NULL)
689 snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
695 /* An inet_ntop implementation that uses WSAAddressToString.
696 Prototype complies with POSIX 1003.1-2004. This is only used under
697 IPv6 because Wget prints IPv4 addresses using inet_ntoa. */
700 inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
702 /* struct sockaddr can't accomodate struct sockaddr_in6. */
704 struct sockaddr_in6 sin6;
705 struct sockaddr_in sin;
714 sa.sin.sin_family = AF_INET;
715 sa.sin.sin_addr = *(struct in_addr *) src;
716 srcsize = sizeof (sa.sin);
719 sa.sin6.sin6_family = AF_INET6;
720 sa.sin6.sin6_addr = *(struct in6_addr *) src;
721 srcsize = sizeof (sa.sin6);
727 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
729 errno = WSAGetLastError();
732 return (const char *) dst;