1 /* mswindows.c -- Windows-specific support
2 Copyright (C) 1996-2006 Free Software Foundation, Inc.
4 This file is part of GNU Wget.
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Wget. If not, see <http://www.gnu.org/licenses/>.
19 In addition, as a special exception, the Free Software Foundation
20 gives permission to link the code of its release of Wget with the
21 OpenSSL project's "OpenSSL" library (or with modified versions of it
22 that use the same license as the "OpenSSL" library), and distribute
23 the linked executables. You must obey the GNU General Public License
24 in all respects for all of the code used other than "OpenSSL". If you
25 modify this file, you may extend this exception to your version of the
26 file, but you are not obligated to do so. If you do not wish to do
27 so, delete this exception statement from your version. */
38 #define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
44 #ifndef ES_SYSTEM_REQUIRED
45 #define ES_SYSTEM_REQUIRED 0x00000001
49 #define ES_CONTINUOUS 0x80000000
53 /* Defined in log.c. */
54 void log_request_redirect_output (const char *);
56 /* Windows version of xsleep in utils.c. */
59 xsleep (double seconds)
64 /* Explained in utils.c. */
66 seconds -= (long) seconds;
68 usleep (seconds * 1000000);
69 #else /* not HAVE_USLEEP */
70 SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
71 #endif /* not HAVE_USLEEP */
75 windows_main (int *argc, char **argv, char **exec_name)
79 /* Remove .EXE from filename if it has one. */
80 *exec_name = xstrdup (*exec_name);
81 p = strrchr (*exec_name, '.');
92 #if defined(CTRLBREAK_BACKGND) || defined(CTRLC_BACKGND)
94 ws_hangup (const char *reason)
96 fprintf (stderr, _("Continuing in background.\n"));
97 log_request_redirect_output (reason);
99 /* Detach process from the current console. Under Windows 9x, if we
100 were launched from a 16-bit process (which is usually the case;
101 command.com is 16-bit) the parent process should resume right away.
102 Under NT or if launched from a 32-process under 9x, this is a futile
103 gesture as the parent will wait for us to terminate before resuming. */
108 /* Construct the name for a named section (a.k.a. `file mapping') object.
109 The returned string is dynamically allocated and needs to be xfree()'d. */
111 make_section_name (DWORD pid)
113 return aprintf ("gnu_wget_fake_fork_%lu", pid);
116 /* This structure is used to hold all the data that is exchanged between
118 struct fake_fork_info
121 bool logfile_changed;
122 char lfilename[MAX_PATH + 1];
125 /* Determines if we are the child and if so performs the child logic.
132 fake_fork_child (void)
134 HANDLE section, event;
135 struct fake_fork_info *info;
138 name = make_section_name (GetCurrentProcessId ());
139 section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
141 /* It seems that Windows 9x and NT set last-error inconsistently when
142 OpenFileMapping() fails; so we assume it failed because the section
143 object does not exist. */
145 return 0; /* We are the parent. */
147 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
150 CloseHandle (section);
156 info->logfile_changed = false;
159 /* See utils:fork_to_background for explanation. */
160 FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
163 info->logfile_changed = true;
164 strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
165 info->lfilename[sizeof (info->lfilename) - 1] = '\0';
170 UnmapViewOfFile (info);
171 CloseHandle (section);
173 /* Inform the parent that we've done our part. */
174 if (!SetEvent (event))
178 return 1; /* We are the child. */
181 /* Windows doesn't support the fork() call; so we fake it by invoking
182 another copy of Wget with the same arguments with which we were
183 invoked. The child copy of Wget should perform the same initialization
184 sequence as the parent; so we should have two processes that are
185 essentially identical. We create a specially named section object that
186 allows the child to distinguish itself from the parent and is used to
187 exchange information between the two processes. We use an event object
188 for synchronization. */
192 char exe[MAX_PATH + 1];
194 SECURITY_ATTRIBUTES sa;
195 HANDLE section, event, h[2];
197 PROCESS_INFORMATION pi;
198 struct fake_fork_info *info;
202 section = pi.hProcess = pi.hThread = NULL;
204 /* Get the fully qualified name of our executable. This is more reliable
205 than using argv[0]. */
206 exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
207 if (!exe_len || (exe_len >= sizeof (exe)))
210 sa.nLength = sizeof (sa);
211 sa.lpSecurityDescriptor = NULL;
212 sa.bInheritHandle = TRUE;
214 /* Create an anonymous inheritable event object that starts out
216 event = CreateEvent (&sa, FALSE, FALSE, NULL);
220 /* Create the child process detached form the current console and in a
224 rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
225 CREATE_SUSPENDED | DETACHED_PROCESS,
226 NULL, NULL, &si, &pi);
230 /* Create a named section object with a name based on the process id of
232 name = make_section_name (pi.dwProcessId);
234 CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
235 sizeof (struct fake_fork_info), name);
238 /* Fail if the section object already exists (should not happen). */
239 if (!section || (le == ERROR_ALREADY_EXISTS))
245 /* Copy the event handle into the section object. */
246 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
255 UnmapViewOfFile (info);
257 /* Start the child process. */
258 rv = ResumeThread (pi.hThread);
261 TerminateProcess (pi.hProcess, (DWORD) -1);
265 /* Wait for the child to signal to us that it has done its part. If it
266 terminates before signaling us it's an error. */
270 rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
274 info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
281 /* Ensure string is properly terminated. */
282 if (info->logfile_changed &&
283 !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
289 printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
290 if (info->logfile_changed)
291 printf (_("Output will be written to `%s'.\n"), info->lfilename);
293 UnmapViewOfFile (info);
300 CloseHandle (section);
302 CloseHandle (pi.hThread);
304 CloseHandle (pi.hProcess);
306 /* We're the parent. If all is well, terminate. */
310 /* We failed, return. */
313 /* This is the corresponding Windows implementation of the
314 fork_to_background() function in utils.c. */
316 fork_to_background (void)
320 rv = fake_fork_child ();
323 fprintf (stderr, "fake_fork_child() failed\n");
328 /* We're the parent. */
330 /* If fake_fork() returns, it failed. */
331 fprintf (stderr, "fake_fork() failed\n");
334 /* If we get here, we're the child. */
338 ws_handler (DWORD dwEvent)
344 ws_hangup ("CTRL+C");
347 #ifdef CTRLBREAK_BACKGND
348 case CTRL_BREAK_EVENT:
349 ws_hangup ("CTRL+Break");
357 static char *title_buf = NULL;
358 static char *curr_url = NULL;
359 static int old_percentage = -1;
361 /* Updates the console title with the URL of the current file being
364 ws_changetitle (const char *url)
366 xfree_null (title_buf);
367 xfree_null (curr_url);
368 title_buf = xmalloc (strlen (url) + 20);
369 curr_url = xstrdup (url);
371 sprintf (title_buf, "Wget %s", curr_url);
372 SetConsoleTitle (title_buf);
375 /* Updates the console title with the percentage of the current file
378 ws_percenttitle (double percentage_float)
382 if (!title_buf || !curr_url)
385 percentage = (int) percentage_float;
387 /* Clamp percentage value. */
390 if (percentage > 100)
393 /* Only update the title when the percentage has changed. */
394 if (percentage == old_percentage)
397 old_percentage = percentage;
399 sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
400 SetConsoleTitle (title_buf);
403 /* Returns a pointer to the fully qualified name of the directory that
404 contains the Wget binary (wget.exe). The returned path does not have a
405 trailing path separator. Returns NULL on failure. */
409 static char *wspathsave = NULL;
413 char buf[MAX_PATH + 1];
417 len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
418 if (!len || (len >= sizeof (buf)))
421 p = strrchr (buf, PATH_SEPARATOR);
426 wspathsave = xstrdup (buf);
432 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
433 a lengthy transfer. Windows does not, by default, consider network
434 activity in console-programs as activity! Works on Win-98/ME/2K
437 set_sleep_mode (void)
439 typedef DWORD (WINAPI *func_t) (DWORD);
440 func_t set_exec_state;
443 (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
444 "SetThreadExecutionState");
447 set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
450 /* Perform Windows specific initialization. */
455 WORD requested = MAKEWORD (1, 1);
456 int err = WSAStartup (requested, &data);
459 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
464 if (data.wVersion < requested)
466 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
474 SetConsoleCtrlHandler (ws_handler, TRUE);
477 /* run_with_timeout Windows implementation. */
479 /* Stack size 0 uses default thread stack-size (reserve+commit).
480 Determined by what's in the PE header. */
481 #define THREAD_STACK_SIZE 0
485 void (*fun) (void *);
490 /* The callback that runs FUN(ARG) in a separate thread. This
491 function exists for two reasons: a) to not require FUN to be
492 declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
493 which are per-thread. The latter is useful when FUN calls Winsock
494 functions, which is how run_with_timeout is used in Wget.
496 [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
497 the default (wcc386 -3r). */
500 thread_helper (void *arg)
502 struct thread_data *td = (struct thread_data *) arg;
504 /* Initialize Winsock error to what it was in the parent. That way
505 the subsequent call to WSAGetLastError will return the same value
506 if td->fun doesn't change Winsock error state. */
507 WSASetLastError (td->ws_error);
511 /* Return Winsock error to the caller, in case FUN ran Winsock
513 td->ws_error = WSAGetLastError ();
517 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
518 seconds. Returns true if the function was interrupted with a
519 timeout, false otherwise.
521 This works by running FUN in a separate thread and terminating the
522 thread if it doesn't finish in the specified time. */
525 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
528 struct thread_data thread_arg;
532 DEBUGP (("seconds %.2f, ", seconds));
541 thread_arg.fun = fun;
542 thread_arg.arg = arg;
543 thread_arg.ws_error = WSAGetLastError ();
544 thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
545 &thread_arg, 0, &thread_id);
548 DEBUGP (("CreateThread() failed; [0x%x]\n", GetLastError ()));
549 goto blocking_fallback;
552 if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
555 /* Propagate error state (which is per-thread) to this thread,
556 so the caller can inspect it. */
557 WSASetLastError (thread_arg.ws_error);
558 DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
563 TerminateThread (thread_hnd, 1);
567 CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
572 /* Wget expects network calls such as connect, recv, send, etc., to set
573 errno on failure. To achieve that, Winsock calls are wrapped with code
574 that, in case of error, sets errno to the value of WSAGetLastError().
575 In addition, we provide a wrapper around strerror, which recognizes
576 Winsock errors and prints the appropriate error message. */
578 /* Define a macro that creates a function definition that wraps FUN into
579 a function that sets errno the way the rest of the code expects. */
581 #define WRAP(fun, decl, call) int wrapped_##fun decl { \
582 int retval = fun call; \
584 errno = WSAGetLastError (); \
588 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
589 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
590 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
591 WRAP (listen, (int s, int backlog), (s, backlog))
592 WRAP (accept, (int s, struct sockaddr *a, int *alen), (s, a, alen))
593 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
594 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
595 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
597 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
598 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
599 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
600 (s, level, opt, val, len))
601 WRAP (closesocket, (int s), (s))
603 /* Return the text of the error message for Winsock error WSERR. */
606 get_winsock_error (int wserr)
609 case WSAEINTR: return "Interrupted system call";
610 case WSAEBADF: return "Bad file number";
611 case WSAEACCES: return "Permission denied";
612 case WSAEFAULT: return "Bad address";
613 case WSAEINVAL: return "Invalid argument";
614 case WSAEMFILE: return "Too many open files";
615 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
616 case WSAEINPROGRESS: return "Operation now in progress";
617 case WSAEALREADY: return "Operation already in progress";
618 case WSAENOTSOCK: return "Socket operation on nonsocket";
619 case WSAEDESTADDRREQ: return "Destination address required";
620 case WSAEMSGSIZE: return "Message too long";
621 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
622 case WSAENOPROTOOPT: return "Bad protocol option";
623 case WSAEPROTONOSUPPORT: return "Protocol not supported";
624 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
625 case WSAEOPNOTSUPP: return "Operation not supported";
626 case WSAEPFNOSUPPORT: return "Protocol family not supported";
627 case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
628 case WSAEADDRINUSE: return "Address already in use";
629 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
630 case WSAENETDOWN: return "Network is down";
631 case WSAENETUNREACH: return "Network is unreachable";
632 case WSAENETRESET: return "Network dropped connection on reset";
633 case WSAECONNABORTED: return "Software caused connection abort";
634 case WSAECONNRESET: return "Connection reset by peer";
635 case WSAENOBUFS: return "No buffer space available";
636 case WSAEISCONN: return "Socket is already connected";
637 case WSAENOTCONN: return "Socket is not connected";
638 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
639 case WSAETOOMANYREFS: return "Too many references";
640 case WSAETIMEDOUT: return "Connection timed out";
641 case WSAECONNREFUSED: return "Connection refused";
642 case WSAELOOP: return "Too many levels of symbolic links";
643 case WSAENAMETOOLONG: return "File name too long";
644 case WSAEHOSTDOWN: return "Host is down";
645 case WSAEHOSTUNREACH: return "No route to host";
646 case WSAENOTEMPTY: return "Not empty";
647 case WSAEPROCLIM: return "Too many processes";
648 case WSAEUSERS: return "Too many users";
649 case WSAEDQUOT: return "Bad quota";
650 case WSAESTALE: return "Something is stale";
651 case WSAEREMOTE: return "Remote error";
652 case WSAEDISCON: return "Disconnected";
654 /* Extended Winsock errors */
655 case WSASYSNOTREADY: return "Winsock library is not ready";
656 case WSANOTINITIALISED: return "Winsock library not initalised";
657 case WSAVERNOTSUPPORTED: return "Winsock version not supported";
659 case WSAHOST_NOT_FOUND: return "Host not found";
660 case WSATRY_AGAIN: return "Host not found, try again";
661 case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
662 case WSANO_DATA: return "No data record of requested type";
669 /* Return the error message corresponding to ERR. This is different
670 from Windows libc strerror() in that it handles Winsock errors
674 windows_strerror (int err)
677 if (err >= 0 && err < sys_nerr)
678 return strerror (err);
679 else if ((p = get_winsock_error (err)) != NULL)
684 snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
690 /* An inet_ntop implementation that uses WSAAddressToString.
691 Prototype complies with POSIX 1003.1-2004. This is only used under
692 IPv6 because Wget prints IPv4 addresses using inet_ntoa. */
695 inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
697 /* struct sockaddr can't accomodate struct sockaddr_in6. */
699 struct sockaddr_in6 sin6;
700 struct sockaddr_in sin;
709 sa.sin.sin_family = AF_INET;
710 sa.sin.sin_addr = *(struct in_addr *) src;
711 srcsize = sizeof (sa.sin);
714 sa.sin6.sin6_family = AF_INET6;
715 sa.sin6.sin6_addr = *(struct in6_addr *) src;
716 srcsize = sizeof (sa.sin6);
722 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
724 errno = WSAGetLastError();
727 return (const char *) dst;