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 */
75 #if !defined(HAVE_STRTOLL) && !defined(HAVE__STRTOI64)
78 char_value (char c, int base)
83 if ('0' <= c && c <= '9')
85 else if ('a' <= c && c <= 'z')
87 else if ('A' <= c && c <= 'Z')
96 /* A fairly simple strtoll replacement for MS VC versions that don't
100 str_to_int64 (const char *nptr, char **endptr, int base)
102 #define INT64_OVERFLOW 9223372036854775807I64
103 #define INT64_UNDERFLOW (-INT64_OVERFLOW - 1)
108 if (base != 0 && (base < 2 || base > 36))
114 while (*nptr == ' ' || *nptr == '\t')
121 else if (*nptr == '+')
129 /* If base is 0, determine the real base based on the beginning on
130 the number; octal numbers begin with "0", hexadecimal with "0x",
131 and the others are considered octal. */
134 if ((base == 0 || base == 16)
136 (*(nptr + 1) == 'x' || *(nptr + 1) == 'X'))
149 /* Parse positive number, checking for overflow. */
151 for (; (val = char_value (*nptr, base)) != -1; ++nptr)
153 __int64 newresult = base * result + val;
154 if (newresult < result)
156 result = INT64_OVERFLOW;
165 /* Parse negative number, checking for underflow. */
167 for (; (val = char_value (*nptr, base)) != -1; ++nptr)
169 __int64 newresult = base * result - val;
170 if (newresult > result)
172 result = INT64_UNDERFLOW;
180 *endptr = (char *) nptr;
186 windows_main (int *argc, char **argv, char **exec_name)
190 /* Remove .EXE from filename if it has one. */
191 *exec_name = xstrdup (*exec_name);
192 p = strrchr (*exec_name, '.');
204 ws_hangup (const char *reason)
206 fprintf (stderr, _("Continuing in background.\n"));
207 log_request_redirect_output (reason);
209 /* Detach process from the current console. Under Windows 9x, if we
210 were launched from a 16-bit process (which is usually the case;
211 command.com is 16-bit) the parent process should resume right away.
212 Under NT or if launched from a 32-process under 9x, this is a futile
213 gesture as the parent will wait for us to terminate before resuming. */
217 /* Construct the name for a named section (a.k.a. `file mapping') object.
218 The returned string is dynamically allocated and needs to be xfree()'d. */
220 make_section_name (DWORD pid)
222 return aprintf ("gnu_wget_fake_fork_%lu", pid);
225 /* This structure is used to hold all the data that is exchanged between
227 struct fake_fork_info
230 bool logfile_changed;
231 char lfilename[MAX_PATH + 1];
234 /* Determines if we are the child and if so performs the child logic.
241 fake_fork_child (void)
243 HANDLE section, event;
244 struct fake_fork_info *info;
247 name = make_section_name (GetCurrentProcessId ());
248 section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
250 /* It seems that Windows 9x and NT set last-error inconsistently when
251 OpenFileMapping() fails; so we assume it failed because the section
252 object does not exist. */
254 return 0; /* We are the parent. */
256 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
259 CloseHandle (section);
265 info->logfile_changed = false;
268 /* See utils:fork_to_background for explanation. */
269 FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
272 info->logfile_changed = true;
273 strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
274 info->lfilename[sizeof (info->lfilename) - 1] = '\0';
279 UnmapViewOfFile (info);
280 CloseHandle (section);
282 /* Inform the parent that we've done our part. */
283 if (!SetEvent (event))
287 return 1; /* We are the child. */
290 /* Windows doesn't support the fork() call; so we fake it by invoking
291 another copy of Wget with the same arguments with which we were
292 invoked. The child copy of Wget should perform the same initialization
293 sequence as the parent; so we should have two processes that are
294 essentially identical. We create a specially named section object that
295 allows the child to distinguish itself from the parent and is used to
296 exchange information between the two processes. We use an event object
297 for synchronization. */
301 char exe[MAX_PATH + 1];
303 SECURITY_ATTRIBUTES sa;
304 HANDLE section, event, h[2];
306 PROCESS_INFORMATION pi;
307 struct fake_fork_info *info;
311 section = pi.hProcess = pi.hThread = NULL;
313 /* Get the fully qualified name of our executable. This is more reliable
314 than using argv[0]. */
315 exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
316 if (!exe_len || (exe_len >= sizeof (exe)))
319 sa.nLength = sizeof (sa);
320 sa.lpSecurityDescriptor = NULL;
321 sa.bInheritHandle = TRUE;
323 /* Create an anonymous inheritable event object that starts out
325 event = CreateEvent (&sa, FALSE, FALSE, NULL);
329 /* Create the child process detached form the current console and in a
333 rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
334 CREATE_SUSPENDED | DETACHED_PROCESS,
335 NULL, NULL, &si, &pi);
339 /* Create a named section object with a name based on the process id of
341 name = make_section_name (pi.dwProcessId);
343 CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
344 sizeof (struct fake_fork_info), name);
347 /* Fail if the section object already exists (should not happen). */
348 if (!section || (le == ERROR_ALREADY_EXISTS))
354 /* Copy the event handle into the section object. */
355 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
364 UnmapViewOfFile (info);
366 /* Start the child process. */
367 rv = ResumeThread (pi.hThread);
370 TerminateProcess (pi.hProcess, (DWORD) -1);
374 /* Wait for the child to signal to us that it has done its part. If it
375 terminates before signaling us it's an error. */
379 rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
383 info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
390 /* Ensure string is properly terminated. */
391 if (info->logfile_changed &&
392 !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
398 printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
399 if (info->logfile_changed)
400 printf (_("Output will be written to `%s'.\n"), info->lfilename);
402 UnmapViewOfFile (info);
409 CloseHandle (section);
411 CloseHandle (pi.hThread);
413 CloseHandle (pi.hProcess);
415 /* We're the parent. If all is well, terminate. */
419 /* We failed, return. */
422 /* This is the corresponding Windows implementation of the
423 fork_to_background() function in utils.c. */
425 fork_to_background (void)
429 rv = fake_fork_child ();
432 fprintf (stderr, "fake_fork_child() failed\n");
437 /* We're the parent. */
439 /* If fake_fork() returns, it failed. */
440 fprintf (stderr, "fake_fork() failed\n");
443 /* If we get here, we're the child. */
447 ws_handler (DWORD dwEvent)
453 ws_hangup ("CTRL+C");
456 #ifdef CTRLBREAK_BACKGND
457 case CTRL_BREAK_EVENT:
458 ws_hangup ("CTRL+Break");
466 static char *title_buf = NULL;
467 static char *curr_url = NULL;
468 static int old_percentage = -1;
470 /* Updates the console title with the URL of the current file being
473 ws_changetitle (const char *url)
475 xfree_null (title_buf);
476 xfree_null (curr_url);
477 title_buf = xmalloc (strlen (url) + 20);
478 curr_url = xstrdup (url);
480 sprintf (title_buf, "Wget %s", curr_url);
481 SetConsoleTitle (title_buf);
484 /* Updates the console title with the percentage of the current file
487 ws_percenttitle (double percentage_float)
491 if (!title_buf || !curr_url)
494 percentage = (int) percentage_float;
496 /* Clamp percentage value. */
499 if (percentage > 100)
502 /* Only update the title when the percentage has changed. */
503 if (percentage == old_percentage)
506 old_percentage = percentage;
508 sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
509 SetConsoleTitle (title_buf);
512 /* Returns a pointer to the fully qualified name of the directory that
513 contains the Wget binary (wget.exe). The returned path does not have a
514 trailing path separator. Returns NULL on failure. */
518 static char *wspathsave = NULL;
522 char buf[MAX_PATH + 1];
526 len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
527 if (!len || (len >= sizeof (buf)))
530 p = strrchr (buf, PATH_SEPARATOR);
535 wspathsave = xstrdup (buf);
541 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
542 a lengthy transfer. Windows does not, by default, consider network
543 activity in console-programs as activity! Works on Win-98/ME/2K
546 set_sleep_mode (void)
548 typedef DWORD (WINAPI *func_t) (DWORD);
549 func_t set_exec_state;
552 (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
553 "SetThreadExecutionState");
556 set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
559 /* Perform Windows specific initialization. */
564 WORD requested = MAKEWORD (1, 1);
565 int err = WSAStartup (requested, &data);
568 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
573 if (data.wVersion < requested)
575 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
583 SetConsoleCtrlHandler (ws_handler, TRUE);
586 /* run_with_timeout Windows implementation. */
588 /* Stack size 0 uses default thread stack-size (reserve+commit).
589 Determined by what's in the PE header. */
590 #define THREAD_STACK_SIZE 0
594 void (*fun) (void *);
599 /* The callback that runs FUN(ARG) in a separate thread. This
600 function exists for two reasons: a) to not require FUN to be
601 declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
602 which are per-thread. The latter is useful when FUN calls Winsock
603 functions, which is how run_with_timeout is used in Wget.
605 [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
606 the default (wcc386 -3r). */
609 thread_helper (void *arg)
611 struct thread_data *td = (struct thread_data *) arg;
613 /* Initialize Winsock error to what it was in the parent. That way
614 the subsequent call to WSAGetLastError will return the same value
615 if td->fun doesn't change Winsock error state. */
616 WSASetLastError (td->ws_error);
620 /* Return Winsock error to the caller, in case FUN ran Winsock
622 td->ws_error = WSAGetLastError ();
626 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
627 seconds. Returns true if the function was interrupted with a
628 timeout, false otherwise.
630 This works by running FUN in a separate thread and terminating the
631 thread if it doesn't finish in the specified time. */
634 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
636 static HANDLE thread_hnd = NULL;
637 struct thread_data thread_arg;
641 DEBUGP (("seconds %.2f, ", seconds));
650 /* Should never happen, but test for recursivety anyway. */
651 assert (thread_hnd == NULL);
653 thread_arg.fun = fun;
654 thread_arg.arg = arg;
655 thread_arg.ws_error = WSAGetLastError ();
656 thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
657 &thread_arg, 0, &thread_id);
660 DEBUGP (("CreateThread() failed; [0x%x]\n", GetLastError ()));
661 goto blocking_fallback;
664 if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
667 /* Propagate error state (which is per-thread) to this thread,
668 so the caller can inspect it. */
669 WSASetLastError (thread_arg.ws_error);
670 DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
675 TerminateThread (thread_hnd, 1);
679 CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
684 /* Wget expects network calls such as connect, recv, send, etc., to set
685 errno on failure. To achieve that, Winsock calls are wrapped with code
686 that, in case of error, sets errno to the value of WSAGetLastError().
687 In addition, we provide a wrapper around strerror, which recognizes
688 Winsock errors and prints the appropriate error message. */
690 /* Define a macro that creates a function definition that wraps FUN into
691 a function that sets errno the way the rest of the code expects. */
693 #define WRAP(fun, decl, call) int wrapped_##fun decl { \
694 int retval = fun call; \
696 errno = WSAGetLastError (); \
700 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
701 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
702 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
703 WRAP (listen, (int s, int backlog), (s, backlog))
704 WRAP (accept, (int s, struct sockaddr *a, int *alen), (s, a, alen))
705 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
706 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
707 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
709 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
710 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
711 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
712 (s, level, opt, val, len))
713 WRAP (closesocket, (int s), (s))
715 /* Return the text of the error message for Winsock error WSERR. */
718 get_winsock_error (int wserr)
721 case WSAEINTR: return "Interrupted system call";
722 case WSAEBADF: return "Bad file number";
723 case WSAEACCES: return "Permission denied";
724 case WSAEFAULT: return "Bad address";
725 case WSAEINVAL: return "Invalid argument";
726 case WSAEMFILE: return "Too many open files";
727 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
728 case WSAEINPROGRESS: return "Operation now in progress";
729 case WSAEALREADY: return "Operation already in progress";
730 case WSAENOTSOCK: return "Socket operation on nonsocket";
731 case WSAEDESTADDRREQ: return "Destination address required";
732 case WSAEMSGSIZE: return "Message too long";
733 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
734 case WSAENOPROTOOPT: return "Bad protocol option";
735 case WSAEPROTONOSUPPORT: return "Protocol not supported";
736 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
737 case WSAEOPNOTSUPP: return "Operation not supported";
738 case WSAEPFNOSUPPORT: return "Protocol family not supported";
739 case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
740 case WSAEADDRINUSE: return "Address already in use";
741 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
742 case WSAENETDOWN: return "Network is down";
743 case WSAENETUNREACH: return "Network is unreachable";
744 case WSAENETRESET: return "Network dropped connection on reset";
745 case WSAECONNABORTED: return "Software caused connection abort";
746 case WSAECONNRESET: return "Connection reset by peer";
747 case WSAENOBUFS: return "No buffer space available";
748 case WSAEISCONN: return "Socket is already connected";
749 case WSAENOTCONN: return "Socket is not connected";
750 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
751 case WSAETOOMANYREFS: return "Too many references";
752 case WSAETIMEDOUT: return "Connection timed out";
753 case WSAECONNREFUSED: return "Connection refused";
754 case WSAELOOP: return "Too many levels of symbolic links";
755 case WSAENAMETOOLONG: return "File name too long";
756 case WSAEHOSTDOWN: return "Host is down";
757 case WSAEHOSTUNREACH: return "No route to host";
758 case WSAENOTEMPTY: return "Not empty";
759 case WSAEPROCLIM: return "Too many processes";
760 case WSAEUSERS: return "Too many users";
761 case WSAEDQUOT: return "Bad quota";
762 case WSAESTALE: return "Something is stale";
763 case WSAEREMOTE: return "Remote error";
764 case WSAEDISCON: return "Disconnected";
766 /* Extended Winsock errors */
767 case WSASYSNOTREADY: return "Winsock library is not ready";
768 case WSANOTINITIALISED: return "Winsock library not initalised";
769 case WSAVERNOTSUPPORTED: return "Winsock version not supported";
771 case WSAHOST_NOT_FOUND: return "Host not found";
772 case WSATRY_AGAIN: return "Host not found, try again";
773 case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
774 case WSANO_DATA: return "No data record of requested type";
781 /* Return the error message corresponding to ERR. This is different
782 from Windows libc strerror() in that it handles Winsock errors
786 windows_strerror (int err)
789 if (err >= 0 && err < sys_nerr)
790 return strerror (err);
791 else if ((p = get_winsock_error (err)) != NULL)
796 snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
802 /* An IPv6-only inet_ntop that prints with WSAAddressToString. (Wget
803 uses inet_ntoa for IPv4 addresses -- see print_address.) Prototype
804 complies with POSIX 1003.1-2004. */
807 inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
809 struct sockaddr_in6 sin6;
812 assert (af == AF_INET6);
814 sin6.sin6_family = AF_INET6;
815 sin6.sin6_addr = *(struct in6_addr *) src;
816 if (WSAAddressToString ((struct sockaddr *) &sin6, sizeof (sin6),
817 NULL, dst, &dstlen) != 0)
819 errno = WSAGetLastError();
822 return (const char *) dst;