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 USE_GNULIB_ALLOC
33 #define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
48 #ifndef ES_SYSTEM_REQUIRED
49 #define ES_SYSTEM_REQUIRED 0x00000001
53 #define ES_CONTINUOUS 0x80000000
57 /* Defined in log.c. */
58 void log_request_redirect_output (const char *);
60 /* Windows version of xsleep in utils.c. */
63 xsleep (double seconds)
68 /* Explained in utils.c. */
70 seconds -= (long) seconds;
72 usleep (seconds * 1000000);
73 #else /* not HAVE_USLEEP */
74 SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
75 #endif /* not HAVE_USLEEP */
79 windows_main (char **exec_name)
83 /* Remove .EXE from filename if it has one. */
84 *exec_name = xstrdup (*exec_name);
85 p = strrchr (*exec_name, '.');
93 xfree ((char*)exec_name);
97 #if defined(CTRLBREAK_BACKGND) || defined(CTRLC_BACKGND)
99 ws_hangup (const char *reason)
101 fprintf (stderr, _("Continuing in background.\n"));
102 log_request_redirect_output (reason);
104 /* Detach process from the current console. Under Windows 9x, if we
105 were launched from a 16-bit process (which is usually the case;
106 command.com is 16-bit) the parent process should resume right away.
107 Under NT or if launched from a 32-process under 9x, this is a futile
108 gesture as the parent will wait for us to terminate before resuming. */
113 /* Construct the name for a named section (a.k.a. `file mapping') object.
114 The returned string is dynamically allocated and needs to be xfree()'d. */
116 make_section_name (DWORD pid)
118 return aprintf ("gnu_wget_fake_fork_%lu", pid);
121 /* This structure is used to hold all the data that is exchanged between
123 struct fake_fork_info
126 bool logfile_changed;
127 char lfilename[MAX_PATH + 1];
130 /* Determines if we are the child and if so performs the child logic.
137 fake_fork_child (void)
139 HANDLE section, event;
140 struct fake_fork_info *info;
143 name = make_section_name (GetCurrentProcessId ());
144 section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
146 /* It seems that Windows 9x and NT set last-error inconsistently when
147 OpenFileMapping() fails; so we assume it failed because the section
148 object does not exist. */
150 return 0; /* We are the parent. */
152 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
155 CloseHandle (section);
161 info->logfile_changed = false;
162 if (!opt.lfilename && (!opt.quiet || opt.server_response))
164 /* See utils:fork_to_background for explanation. */
165 FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
168 info->logfile_changed = true;
169 strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
170 info->lfilename[sizeof (info->lfilename) - 1] = '\0';
175 UnmapViewOfFile (info);
176 CloseHandle (section);
178 /* Inform the parent that we've done our part. */
179 if (!SetEvent (event))
183 return 1; /* We are the child. */
186 /* Windows doesn't support the fork() call; so we fake it by invoking
187 another copy of Wget with the same arguments with which we were
188 invoked. The child copy of Wget should perform the same initialization
189 sequence as the parent; so we should have two processes that are
190 essentially identical. We create a specially named section object that
191 allows the child to distinguish itself from the parent and is used to
192 exchange information between the two processes. We use an event object
193 for synchronization. */
197 char exe[MAX_PATH + 1];
199 SECURITY_ATTRIBUTES sa;
200 HANDLE section, event, h[2];
202 PROCESS_INFORMATION pi;
203 struct fake_fork_info *info;
207 section = pi.hProcess = pi.hThread = NULL;
209 /* Get the fully qualified name of our executable. This is more reliable
210 than using argv[0]. */
211 exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
212 if (!exe_len || (exe_len >= sizeof (exe)))
215 sa.nLength = sizeof (sa);
216 sa.lpSecurityDescriptor = NULL;
217 sa.bInheritHandle = TRUE;
219 /* Create an anonymous inheritable event object that starts out
221 event = CreateEvent (&sa, FALSE, FALSE, NULL);
225 /* Create the child process detached form the current console and in a
229 rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
230 CREATE_SUSPENDED | DETACHED_PROCESS,
231 NULL, NULL, &si, &pi);
235 /* Create a named section object with a name based on the process id of
237 name = make_section_name (pi.dwProcessId);
239 CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
240 sizeof (struct fake_fork_info), name);
243 /* Fail if the section object already exists (should not happen). */
244 if (!section || (le == ERROR_ALREADY_EXISTS))
250 /* Copy the event handle into the section object. */
251 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
260 UnmapViewOfFile (info);
262 /* Start the child process. */
263 rv = ResumeThread (pi.hThread);
266 TerminateProcess (pi.hProcess, (DWORD) -1);
270 /* Wait for the child to signal to us that it has done its part. If it
271 terminates before signaling us it's an error. */
275 rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
279 info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
286 /* Ensure string is properly terminated. */
287 if (info->logfile_changed &&
288 !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
294 printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
295 if (info->logfile_changed)
296 printf (_("Output will be written to %s.\n"), quote (info->lfilename));
298 UnmapViewOfFile (info);
305 CloseHandle (section);
307 CloseHandle (pi.hThread);
309 CloseHandle (pi.hProcess);
311 /* We're the parent. If all is well, terminate. */
315 /* We failed, return. */
318 /* This is the corresponding Windows implementation of the
319 fork_to_background() function in utils.c. */
321 fork_to_background (void)
325 rv = fake_fork_child ();
328 fprintf (stderr, "fake_fork_child() failed\n");
333 /* We're the parent. */
335 /* If fake_fork() returns, it failed. */
336 fprintf (stderr, "fake_fork() failed\n");
339 /* If we get here, we're the child. */
343 ws_handler (DWORD dwEvent)
349 ws_hangup ("CTRL+C");
352 #ifdef CTRLBREAK_BACKGND
353 case CTRL_BREAK_EVENT:
354 ws_hangup ("CTRL+Break");
362 static char *title_buf = NULL;
363 static char *curr_url = NULL;
364 static int old_percentage = -1;
366 /* Updates the console title with the URL of the current file being
369 ws_changetitle (const char *url)
371 xfree_null (title_buf);
372 xfree_null (curr_url);
373 title_buf = xmalloc (strlen (url) + 20);
374 curr_url = xstrdup (url);
376 sprintf (title_buf, "Wget %s", curr_url);
377 SetConsoleTitle (title_buf);
380 /* Updates the console title with the percentage of the current file
383 ws_percenttitle (double percentage_float)
387 if (!title_buf || !curr_url)
390 percentage = (int) percentage_float;
392 /* Clamp percentage value. */
395 if (percentage > 100)
398 /* Only update the title when the percentage has changed. */
399 if (percentage == old_percentage)
402 old_percentage = percentage;
404 sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
405 SetConsoleTitle (title_buf);
408 /* Returns a pointer to the fully qualified name of the directory that
409 contains the Wget binary (wget.exe). The returned path does not have a
410 trailing path separator. Returns NULL on failure. */
414 static char *wspathsave = NULL;
418 char buf[MAX_PATH + 1];
422 len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
423 if (!len || (len >= sizeof (buf)))
426 p = strrchr (buf, PATH_SEPARATOR);
431 wspathsave = xstrdup (buf);
437 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
438 a lengthy transfer. Windows does not, by default, consider network
439 activity in console-programs as activity! Works on Win-98/ME/2K
442 set_sleep_mode (void)
444 typedef DWORD (WINAPI *func_t) (DWORD);
445 func_t set_exec_state;
448 (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
449 "SetThreadExecutionState");
452 set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
455 /* Perform Windows specific initialization. */
460 WORD requested = MAKEWORD (1, 1);
461 int err = WSAStartup (requested, &data);
464 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
469 if (data.wVersion < requested)
471 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
479 SetConsoleCtrlHandler (ws_handler, TRUE);
482 /* run_with_timeout Windows implementation. */
484 /* Stack size 0 uses default thread stack-size (reserve+commit).
485 Determined by what's in the PE header. */
486 #define THREAD_STACK_SIZE 0
490 void (*fun) (void *);
495 /* The callback that runs FUN(ARG) in a separate thread. This
496 function exists for two reasons: a) to not require FUN to be
497 declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
498 which are per-thread. The latter is useful when FUN calls Winsock
499 functions, which is how run_with_timeout is used in Wget.
501 [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
502 the default (wcc386 -3r). */
505 thread_helper (void *arg)
507 struct thread_data *td = (struct thread_data *) arg;
509 /* Initialize Winsock error to what it was in the parent. That way
510 the subsequent call to WSAGetLastError will return the same value
511 if td->fun doesn't change Winsock error state. */
512 WSASetLastError (td->ws_error);
516 /* Return Winsock error to the caller, in case FUN ran Winsock
518 td->ws_error = WSAGetLastError ();
522 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
523 seconds. Returns true if the function was interrupted with a
524 timeout, false otherwise.
526 This works by running FUN in a separate thread and terminating the
527 thread if it doesn't finish in the specified time. */
530 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
533 struct thread_data thread_arg;
537 DEBUGP (("seconds %.2f, ", seconds));
546 thread_arg.fun = fun;
547 thread_arg.arg = arg;
548 thread_arg.ws_error = WSAGetLastError ();
549 thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
550 &thread_arg, 0, &thread_id);
553 DEBUGP (("CreateThread() failed; [%#lx]\n",
554 (unsigned long) GetLastError ()));
555 goto blocking_fallback;
558 if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
561 /* Propagate error state (which is per-thread) to this thread,
562 so the caller can inspect it. */
563 WSASetLastError (thread_arg.ws_error);
564 DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
569 TerminateThread (thread_hnd, 1);
573 CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
578 /* Wget expects network calls such as connect, recv, send, etc., to set
579 errno on failure. To achieve that, Winsock calls are wrapped with code
580 that, in case of error, sets errno to the value of WSAGetLastError().
581 In addition, we provide a wrapper around strerror, which recognizes
582 Winsock errors and prints the appropriate error message. */
584 /* Define a macro that creates a function definition that wraps FUN into
585 a function that sets errno the way the rest of the code expects. */
587 #define WRAP(fun, decl, call) int wrapped_##fun decl { \
588 int retval = fun call; \
590 errno = WSAGetLastError (); \
594 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
595 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
596 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
597 WRAP (listen, (int s, int backlog), (s, backlog))
598 WRAP (accept, (int s, struct sockaddr *a, int *alen), (s, a, alen))
599 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
600 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
601 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
603 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
604 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
605 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
606 (s, level, opt, val, len))
607 WRAP (closesocket, (int s), (s))
609 /* Return the text of the error message for Winsock error WSERR. */
612 get_winsock_error (int wserr)
615 case WSAEINTR: return "Interrupted system call";
616 case WSAEBADF: return "Bad file number";
617 case WSAEACCES: return "Permission denied";
618 case WSAEFAULT: return "Bad address";
619 case WSAEINVAL: return "Invalid argument";
620 case WSAEMFILE: return "Too many open files";
621 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
622 case WSAEINPROGRESS: return "Operation now in progress";
623 case WSAEALREADY: return "Operation already in progress";
624 case WSAENOTSOCK: return "Socket operation on nonsocket";
625 case WSAEDESTADDRREQ: return "Destination address required";
626 case WSAEMSGSIZE: return "Message too long";
627 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
628 case WSAENOPROTOOPT: return "Bad protocol option";
629 case WSAEPROTONOSUPPORT: return "Protocol not supported";
630 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
631 case WSAEOPNOTSUPP: return "Operation not supported";
632 case WSAEPFNOSUPPORT: return "Protocol family not supported";
633 case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
634 case WSAEADDRINUSE: return "Address already in use";
635 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
636 case WSAENETDOWN: return "Network is down";
637 case WSAENETUNREACH: return "Network is unreachable";
638 case WSAENETRESET: return "Network dropped connection on reset";
639 case WSAECONNABORTED: return "Software caused connection abort";
640 case WSAECONNRESET: return "Connection reset by peer";
641 case WSAENOBUFS: return "No buffer space available";
642 case WSAEISCONN: return "Socket is already connected";
643 case WSAENOTCONN: return "Socket is not connected";
644 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
645 case WSAETOOMANYREFS: return "Too many references";
646 case WSAETIMEDOUT: return "Connection timed out";
647 case WSAECONNREFUSED: return "Connection refused";
648 case WSAELOOP: return "Too many levels of symbolic links";
649 case WSAENAMETOOLONG: return "File name too long";
650 case WSAEHOSTDOWN: return "Host is down";
651 case WSAEHOSTUNREACH: return "No route to host";
652 case WSAENOTEMPTY: return "Not empty";
653 case WSAEPROCLIM: return "Too many processes";
654 case WSAEUSERS: return "Too many users";
655 case WSAEDQUOT: return "Bad quota";
656 case WSAESTALE: return "Something is stale";
657 case WSAEREMOTE: return "Remote error";
658 case WSAEDISCON: return "Disconnected";
660 /* Extended Winsock errors */
661 case WSASYSNOTREADY: return "Winsock library is not ready";
662 case WSANOTINITIALISED: return "Winsock library not initalised";
663 case WSAVERNOTSUPPORTED: return "Winsock version not supported";
665 case WSAHOST_NOT_FOUND: return "Host not found";
666 case WSATRY_AGAIN: return "Host not found, try again";
667 case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
668 case WSANO_DATA: return "No data record of requested type";
675 /* Return the error message corresponding to ERR. This is different
676 from Windows libc strerror() in that it handles Winsock errors
680 windows_strerror (int err)
683 if (err >= 0 && err < sys_nerr)
684 return strerror (err);
685 else if ((p = get_winsock_error (err)) != NULL)
690 snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
696 /* An inet_ntop implementation that uses WSAAddressToString.
697 Prototype complies with POSIX 1003.1-2004. This is only used under
698 IPv6 because Wget prints IPv4 addresses using inet_ntoa. */
701 inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
703 /* struct sockaddr can't accomodate struct sockaddr_in6. */
705 struct sockaddr_in6 sin6;
706 struct sockaddr_in sin;
715 sa.sin.sin_family = AF_INET;
716 sa.sin.sin_addr = *(struct in_addr *) src;
717 srcsize = sizeof (sa.sin);
720 sa.sin6.sin6_family = AF_INET6;
721 sa.sin6.sin6_addr = *(struct in6_addr *) src;
722 srcsize = sizeof (sa.sin6);
728 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
730 errno = WSAGetLastError();
733 return (const char *) dst;