1 /* mswindows.c -- Windows-specific support
2 Copyright (C) 1996-2005 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 2 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, write to the Free Software Foundation, Inc.,
18 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables. You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL". If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so. If you do not wish to do
28 so, delete this exception statement from your version. */
39 #define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
45 #ifndef ES_SYSTEM_REQUIRED
46 #define ES_SYSTEM_REQUIRED 0x00000001
50 #define ES_CONTINUOUS 0x80000000
54 /* Defined in log.c. */
55 void log_request_redirect_output (const char *);
57 /* Windows version of xsleep in utils.c. */
60 xsleep (double seconds)
65 /* Explained in utils.c. */
67 seconds -= (long) seconds;
69 usleep (seconds * 1000000);
70 #else /* not HAVE_USLEEP */
71 SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
72 #endif /* not HAVE_USLEEP */
76 windows_main (int *argc, char **argv, char **exec_name)
80 /* Remove .EXE from filename if it has one. */
81 *exec_name = xstrdup (*exec_name);
82 p = strrchr (*exec_name, '.');
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. */
107 /* Construct the name for a named section (a.k.a. `file mapping') object.
108 The returned string is dynamically allocated and needs to be xfree()'d. */
110 make_section_name (DWORD pid)
112 return aprintf ("gnu_wget_fake_fork_%lu", pid);
115 /* This structure is used to hold all the data that is exchanged between
117 struct fake_fork_info
120 bool logfile_changed;
121 char lfilename[MAX_PATH + 1];
124 /* Determines if we are the child and if so performs the child logic.
131 fake_fork_child (void)
133 HANDLE section, event;
134 struct fake_fork_info *info;
137 name = make_section_name (GetCurrentProcessId ());
138 section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
140 /* It seems that Windows 9x and NT set last-error inconsistently when
141 OpenFileMapping() fails; so we assume it failed because the section
142 object does not exist. */
144 return 0; /* We are the parent. */
146 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
149 CloseHandle (section);
155 info->logfile_changed = false;
158 /* See utils:fork_to_background for explanation. */
159 FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
162 info->logfile_changed = true;
163 strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
164 info->lfilename[sizeof (info->lfilename) - 1] = '\0';
169 UnmapViewOfFile (info);
170 CloseHandle (section);
172 /* Inform the parent that we've done our part. */
173 if (!SetEvent (event))
177 return 1; /* We are the child. */
180 /* Windows doesn't support the fork() call; so we fake it by invoking
181 another copy of Wget with the same arguments with which we were
182 invoked. The child copy of Wget should perform the same initialization
183 sequence as the parent; so we should have two processes that are
184 essentially identical. We create a specially named section object that
185 allows the child to distinguish itself from the parent and is used to
186 exchange information between the two processes. We use an event object
187 for synchronization. */
191 char exe[MAX_PATH + 1];
193 SECURITY_ATTRIBUTES sa;
194 HANDLE section, event, h[2];
196 PROCESS_INFORMATION pi;
197 struct fake_fork_info *info;
201 section = pi.hProcess = pi.hThread = NULL;
203 /* Get the fully qualified name of our executable. This is more reliable
204 than using argv[0]. */
205 exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
206 if (!exe_len || (exe_len >= sizeof (exe)))
209 sa.nLength = sizeof (sa);
210 sa.lpSecurityDescriptor = NULL;
211 sa.bInheritHandle = TRUE;
213 /* Create an anonymous inheritable event object that starts out
215 event = CreateEvent (&sa, FALSE, FALSE, NULL);
219 /* Create the child process detached form the current console and in a
223 rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
224 CREATE_SUSPENDED | DETACHED_PROCESS,
225 NULL, NULL, &si, &pi);
229 /* Create a named section object with a name based on the process id of
231 name = make_section_name (pi.dwProcessId);
233 CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
234 sizeof (struct fake_fork_info), name);
237 /* Fail if the section object already exists (should not happen). */
238 if (!section || (le == ERROR_ALREADY_EXISTS))
244 /* Copy the event handle into the section object. */
245 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
254 UnmapViewOfFile (info);
256 /* Start the child process. */
257 rv = ResumeThread (pi.hThread);
260 TerminateProcess (pi.hProcess, (DWORD) -1);
264 /* Wait for the child to signal to us that it has done its part. If it
265 terminates before signaling us it's an error. */
269 rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
273 info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
280 /* Ensure string is properly terminated. */
281 if (info->logfile_changed &&
282 !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
288 printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
289 if (info->logfile_changed)
290 printf (_("Output will be written to `%s'.\n"), info->lfilename);
292 UnmapViewOfFile (info);
299 CloseHandle (section);
301 CloseHandle (pi.hThread);
303 CloseHandle (pi.hProcess);
305 /* We're the parent. If all is well, terminate. */
309 /* We failed, return. */
312 /* This is the corresponding Windows implementation of the
313 fork_to_background() function in utils.c. */
315 fork_to_background (void)
319 rv = fake_fork_child ();
322 fprintf (stderr, "fake_fork_child() failed\n");
327 /* We're the parent. */
329 /* If fake_fork() returns, it failed. */
330 fprintf (stderr, "fake_fork() failed\n");
333 /* If we get here, we're the child. */
337 ws_handler (DWORD dwEvent)
343 ws_hangup ("CTRL+C");
346 #ifdef CTRLBREAK_BACKGND
347 case CTRL_BREAK_EVENT:
348 ws_hangup ("CTRL+Break");
356 static char *title_buf = NULL;
357 static char *curr_url = NULL;
358 static int old_percentage = -1;
360 /* Updates the console title with the URL of the current file being
363 ws_changetitle (const char *url)
365 xfree_null (title_buf);
366 xfree_null (curr_url);
367 title_buf = xmalloc (strlen (url) + 20);
368 curr_url = xstrdup (url);
370 sprintf (title_buf, "Wget %s", curr_url);
371 SetConsoleTitle (title_buf);
374 /* Updates the console title with the percentage of the current file
377 ws_percenttitle (double percentage_float)
381 if (!title_buf || !curr_url)
384 percentage = (int) percentage_float;
386 /* Clamp percentage value. */
389 if (percentage > 100)
392 /* Only update the title when the percentage has changed. */
393 if (percentage == old_percentage)
396 old_percentage = percentage;
398 sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
399 SetConsoleTitle (title_buf);
402 /* Returns a pointer to the fully qualified name of the directory that
403 contains the Wget binary (wget.exe). The returned path does not have a
404 trailing path separator. Returns NULL on failure. */
408 static char *wspathsave = NULL;
412 char buf[MAX_PATH + 1];
416 len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
417 if (!len || (len >= sizeof (buf)))
420 p = strrchr (buf, PATH_SEPARATOR);
425 wspathsave = xstrdup (buf);
431 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
432 a lengthy transfer. Windows does not, by default, consider network
433 activity in console-programs as activity! Works on Win-98/ME/2K
436 set_sleep_mode (void)
438 typedef DWORD (WINAPI *func_t) (DWORD);
439 func_t set_exec_state;
442 (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
443 "SetThreadExecutionState");
446 set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
449 /* Perform Windows specific initialization. */
454 WORD requested = MAKEWORD (1, 1);
455 int err = WSAStartup (requested, &data);
458 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
463 if (data.wVersion < requested)
465 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
473 SetConsoleCtrlHandler (ws_handler, TRUE);
476 /* run_with_timeout Windows implementation. */
478 /* Stack size 0 uses default thread stack-size (reserve+commit).
479 Determined by what's in the PE header. */
480 #define THREAD_STACK_SIZE 0
484 void (*fun) (void *);
489 /* The callback that runs FUN(ARG) in a separate thread. This
490 function exists for two reasons: a) to not require FUN to be
491 declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
492 which are per-thread. The latter is useful when FUN calls Winsock
493 functions, which is how run_with_timeout is used in Wget.
495 [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
496 the default (wcc386 -3r). */
499 thread_helper (void *arg)
501 struct thread_data *td = (struct thread_data *) arg;
503 /* Initialize Winsock error to what it was in the parent. That way
504 the subsequent call to WSAGetLastError will return the same value
505 if td->fun doesn't change Winsock error state. */
506 WSASetLastError (td->ws_error);
510 /* Return Winsock error to the caller, in case FUN ran Winsock
512 td->ws_error = WSAGetLastError ();
516 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
517 seconds. Returns true if the function was interrupted with a
518 timeout, false otherwise.
520 This works by running FUN in a separate thread and terminating the
521 thread if it doesn't finish in the specified time. */
524 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
526 static HANDLE thread_hnd = NULL;
527 struct thread_data thread_arg;
531 DEBUGP (("seconds %.2f, ", seconds));
540 /* Should never happen, but test for recursivety anyway. */
541 assert (thread_hnd == NULL);
543 thread_arg.fun = fun;
544 thread_arg.arg = arg;
545 thread_arg.ws_error = WSAGetLastError ();
546 thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
547 &thread_arg, 0, &thread_id);
550 DEBUGP (("CreateThread() failed; [0x%x]\n", GetLastError ()));
551 goto blocking_fallback;
554 if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
557 /* Propagate error state (which is per-thread) to this thread,
558 so the caller can inspect it. */
559 WSASetLastError (thread_arg.ws_error);
560 DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
565 TerminateThread (thread_hnd, 1);
569 CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
574 /* Wget expects network calls such as connect, recv, send, etc., to set
575 errno on failure. To achieve that, Winsock calls are wrapped with code
576 that, in case of error, sets errno to the value of WSAGetLastError().
577 In addition, we provide a wrapper around strerror, which recognizes
578 Winsock errors and prints the appropriate error message. */
580 /* Define a macro that creates a function definition that wraps FUN into
581 a function that sets errno the way the rest of the code expects. */
583 #define WRAP(fun, decl, call) int wrapped_##fun decl { \
584 int retval = fun call; \
586 errno = WSAGetLastError (); \
590 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
591 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
592 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
593 WRAP (listen, (int s, int backlog), (s, backlog))
594 WRAP (accept, (int s, struct sockaddr *a, int *alen), (s, a, alen))
595 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
596 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
597 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
599 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
600 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
601 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
602 (s, level, opt, val, len))
603 WRAP (closesocket, (int s), (s))
605 /* Return the text of the error message for Winsock error WSERR. */
608 get_winsock_error (int wserr)
611 case WSAEINTR: return "Interrupted system call";
612 case WSAEBADF: return "Bad file number";
613 case WSAEACCES: return "Permission denied";
614 case WSAEFAULT: return "Bad address";
615 case WSAEINVAL: return "Invalid argument";
616 case WSAEMFILE: return "Too many open files";
617 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
618 case WSAEINPROGRESS: return "Operation now in progress";
619 case WSAEALREADY: return "Operation already in progress";
620 case WSAENOTSOCK: return "Socket operation on nonsocket";
621 case WSAEDESTADDRREQ: return "Destination address required";
622 case WSAEMSGSIZE: return "Message too long";
623 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
624 case WSAENOPROTOOPT: return "Bad protocol option";
625 case WSAEPROTONOSUPPORT: return "Protocol not supported";
626 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
627 case WSAEOPNOTSUPP: return "Operation not supported";
628 case WSAEPFNOSUPPORT: return "Protocol family not supported";
629 case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
630 case WSAEADDRINUSE: return "Address already in use";
631 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
632 case WSAENETDOWN: return "Network is down";
633 case WSAENETUNREACH: return "Network is unreachable";
634 case WSAENETRESET: return "Network dropped connection on reset";
635 case WSAECONNABORTED: return "Software caused connection abort";
636 case WSAECONNRESET: return "Connection reset by peer";
637 case WSAENOBUFS: return "No buffer space available";
638 case WSAEISCONN: return "Socket is already connected";
639 case WSAENOTCONN: return "Socket is not connected";
640 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
641 case WSAETOOMANYREFS: return "Too many references";
642 case WSAETIMEDOUT: return "Connection timed out";
643 case WSAECONNREFUSED: return "Connection refused";
644 case WSAELOOP: return "Too many levels of symbolic links";
645 case WSAENAMETOOLONG: return "File name too long";
646 case WSAEHOSTDOWN: return "Host is down";
647 case WSAEHOSTUNREACH: return "No route to host";
648 case WSAENOTEMPTY: return "Not empty";
649 case WSAEPROCLIM: return "Too many processes";
650 case WSAEUSERS: return "Too many users";
651 case WSAEDQUOT: return "Bad quota";
652 case WSAESTALE: return "Something is stale";
653 case WSAEREMOTE: return "Remote error";
654 case WSAEDISCON: return "Disconnected";
656 /* Extended Winsock errors */
657 case WSASYSNOTREADY: return "Winsock library is not ready";
658 case WSANOTINITIALISED: return "Winsock library not initalised";
659 case WSAVERNOTSUPPORTED: return "Winsock version not supported";
661 case WSAHOST_NOT_FOUND: return "Host not found";
662 case WSATRY_AGAIN: return "Host not found, try again";
663 case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
664 case WSANO_DATA: return "No data record of requested type";
671 /* Return the error message corresponding to ERR. This is different
672 from Windows libc strerror() in that it handles Winsock errors
676 windows_strerror (int err)
679 if (err >= 0 && err < sys_nerr)
680 return strerror (err);
681 else if ((p = get_winsock_error (err)) != NULL)
686 snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
692 /* An inet_ntop implementation that uses WSAAddressToString.
693 Prototype complies with POSIX 1003.1-2004. This is only used under
694 IPv6 because Wget prints IPv4 addresses using inet_ntoa. */
697 inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
699 /* struct sockaddr can't accomodate struct sockaddr_in6. */
701 struct sockaddr_in6 sin6;
702 struct sockaddr_in sin;
711 sa.sin.sin_family = AF_INET;
712 sa.sin.sin_addr = *(struct in_addr *) src;
713 srcsize = sizeof (sa.sin);
716 sa.sin6.sin6_family = AF_INET6;
717 sa.sin6.sin6_addr = *(struct in6_addr *) src;
718 srcsize = sizeof (sa.sin6);
724 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
726 errno = WSAGetLastError();
729 return (const char *) dst;