1 /* mswindows.c -- Windows-specific support
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008, 2009 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, ... */
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 (char **exec_name)
80 /* Remove .EXE from filename if it has one. */
81 *exec_name = xstrdup (*exec_name);
82 p = strrchr (*exec_name, '.');
90 xfree ((char*)exec_name);
94 #if defined(CTRLBREAK_BACKGND) || defined(CTRLC_BACKGND)
96 ws_hangup (const char *reason)
98 fprintf (stderr, _("Continuing in background.\n"));
99 log_request_redirect_output (reason);
101 /* Detach process from the current console. Under Windows 9x, if we
102 were launched from a 16-bit process (which is usually the case;
103 command.com is 16-bit) the parent process should resume right away.
104 Under NT or if launched from a 32-process under 9x, this is a futile
105 gesture as the parent will wait for us to terminate before resuming. */
110 /* Construct the name for a named section (a.k.a. `file mapping') object.
111 The returned string is dynamically allocated and needs to be xfree()'d. */
113 make_section_name (DWORD pid)
115 return aprintf ("gnu_wget_fake_fork_%lu", pid);
118 /* This structure is used to hold all the data that is exchanged between
120 struct fake_fork_info
123 bool logfile_changed;
124 char lfilename[MAX_PATH + 1];
127 /* Determines if we are the child and if so performs the child logic.
134 fake_fork_child (void)
136 HANDLE section, event;
137 struct fake_fork_info *info;
140 name = make_section_name (GetCurrentProcessId ());
141 section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
143 /* It seems that Windows 9x and NT set last-error inconsistently when
144 OpenFileMapping() fails; so we assume it failed because the section
145 object does not exist. */
147 return 0; /* We are the parent. */
149 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
152 CloseHandle (section);
158 info->logfile_changed = false;
159 if (!opt.lfilename && (!opt.quiet || opt.server_response))
161 /* See utils:fork_to_background for explanation. */
162 FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
165 info->logfile_changed = true;
166 strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
167 info->lfilename[sizeof (info->lfilename) - 1] = '\0';
172 UnmapViewOfFile (info);
173 CloseHandle (section);
175 /* Inform the parent that we've done our part. */
176 if (!SetEvent (event))
180 return 1; /* We are the child. */
183 /* Windows doesn't support the fork() call; so we fake it by invoking
184 another copy of Wget with the same arguments with which we were
185 invoked. The child copy of Wget should perform the same initialization
186 sequence as the parent; so we should have two processes that are
187 essentially identical. We create a specially named section object that
188 allows the child to distinguish itself from the parent and is used to
189 exchange information between the two processes. We use an event object
190 for synchronization. */
194 char exe[MAX_PATH + 1];
196 SECURITY_ATTRIBUTES sa;
197 HANDLE section, event, h[2];
199 PROCESS_INFORMATION pi;
200 struct fake_fork_info *info;
204 section = pi.hProcess = pi.hThread = NULL;
206 /* Get the fully qualified name of our executable. This is more reliable
207 than using argv[0]. */
208 exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
209 if (!exe_len || (exe_len >= sizeof (exe)))
212 sa.nLength = sizeof (sa);
213 sa.lpSecurityDescriptor = NULL;
214 sa.bInheritHandle = TRUE;
216 /* Create an anonymous inheritable event object that starts out
218 event = CreateEvent (&sa, FALSE, FALSE, NULL);
222 /* Create the child process detached form the current console and in a
226 rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
227 CREATE_SUSPENDED | DETACHED_PROCESS,
228 NULL, NULL, &si, &pi);
232 /* Create a named section object with a name based on the process id of
234 name = make_section_name (pi.dwProcessId);
236 CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
237 sizeof (struct fake_fork_info), name);
240 /* Fail if the section object already exists (should not happen). */
241 if (!section || (le == ERROR_ALREADY_EXISTS))
247 /* Copy the event handle into the section object. */
248 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
257 UnmapViewOfFile (info);
259 /* Start the child process. */
260 rv = ResumeThread (pi.hThread);
263 TerminateProcess (pi.hProcess, (DWORD) -1);
267 /* Wait for the child to signal to us that it has done its part. If it
268 terminates before signaling us it's an error. */
272 rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
276 info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
283 /* Ensure string is properly terminated. */
284 if (info->logfile_changed &&
285 !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
291 printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
292 if (info->logfile_changed)
293 printf (_("Output will be written to %s.\n"), quote (info->lfilename));
295 UnmapViewOfFile (info);
302 CloseHandle (section);
304 CloseHandle (pi.hThread);
306 CloseHandle (pi.hProcess);
308 /* We're the parent. If all is well, terminate. */
312 /* We failed, return. */
315 /* This is the corresponding Windows implementation of the
316 fork_to_background() function in utils.c. */
318 fork_to_background (void)
322 rv = fake_fork_child ();
325 fprintf (stderr, "fake_fork_child() failed\n");
330 /* We're the parent. */
332 /* If fake_fork() returns, it failed. */
333 fprintf (stderr, "fake_fork() failed\n");
336 /* If we get here, we're the child. */
340 ws_handler (DWORD dwEvent)
346 ws_hangup ("CTRL+C");
349 #ifdef CTRLBREAK_BACKGND
350 case CTRL_BREAK_EVENT:
351 ws_hangup ("CTRL+Break");
359 static char *title_buf = NULL;
360 static char *curr_url = NULL;
361 static int old_percentage = -1;
363 /* Updates the console title with the URL of the current file being
366 ws_changetitle (const char *url)
368 xfree_null (title_buf);
369 xfree_null (curr_url);
370 title_buf = xmalloc (strlen (url) + 20);
371 curr_url = xstrdup (url);
373 sprintf (title_buf, "Wget %s", curr_url);
374 SetConsoleTitle (title_buf);
377 /* Updates the console title with the percentage of the current file
380 ws_percenttitle (double percentage_float)
384 if (!title_buf || !curr_url)
387 percentage = (int) percentage_float;
389 /* Clamp percentage value. */
392 if (percentage > 100)
395 /* Only update the title when the percentage has changed. */
396 if (percentage == old_percentage)
399 old_percentage = percentage;
401 sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
402 SetConsoleTitle (title_buf);
405 /* Returns a pointer to the fully qualified name of the directory that
406 contains the Wget binary (wget.exe). The returned path does not have a
407 trailing path separator. Returns NULL on failure. */
411 static char *wspathsave = NULL;
415 char buf[MAX_PATH + 1];
419 len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
420 if (!len || (len >= sizeof (buf)))
423 p = strrchr (buf, PATH_SEPARATOR);
428 wspathsave = xstrdup (buf);
434 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
435 a lengthy transfer. Windows does not, by default, consider network
436 activity in console-programs as activity! Works on Win-98/ME/2K
439 set_sleep_mode (void)
441 typedef DWORD (WINAPI *func_t) (DWORD);
442 func_t set_exec_state;
445 (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
446 "SetThreadExecutionState");
449 set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
452 /* Perform Windows specific initialization. */
457 WORD requested = MAKEWORD (1, 1);
458 int err = WSAStartup (requested, &data);
461 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
466 if (data.wVersion < requested)
468 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
476 SetConsoleCtrlHandler (ws_handler, TRUE);
479 /* run_with_timeout Windows implementation. */
481 /* Stack size 0 uses default thread stack-size (reserve+commit).
482 Determined by what's in the PE header. */
483 #define THREAD_STACK_SIZE 0
487 void (*fun) (void *);
492 /* The callback that runs FUN(ARG) in a separate thread. This
493 function exists for two reasons: a) to not require FUN to be
494 declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
495 which are per-thread. The latter is useful when FUN calls Winsock
496 functions, which is how run_with_timeout is used in Wget.
498 [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
499 the default (wcc386 -3r). */
502 thread_helper (void *arg)
504 struct thread_data *td = (struct thread_data *) arg;
506 /* Initialize Winsock error to what it was in the parent. That way
507 the subsequent call to WSAGetLastError will return the same value
508 if td->fun doesn't change Winsock error state. */
509 WSASetLastError (td->ws_error);
513 /* Return Winsock error to the caller, in case FUN ran Winsock
515 td->ws_error = WSAGetLastError ();
519 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
520 seconds. Returns true if the function was interrupted with a
521 timeout, false otherwise.
523 This works by running FUN in a separate thread and terminating the
524 thread if it doesn't finish in the specified time. */
527 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
530 struct thread_data thread_arg;
534 DEBUGP (("seconds %.2f, ", seconds));
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; [%#lx]\n",
551 (unsigned long) GetLastError ()));
552 goto blocking_fallback;
555 if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
558 /* Propagate error state (which is per-thread) to this thread,
559 so the caller can inspect it. */
560 WSASetLastError (thread_arg.ws_error);
561 DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
566 TerminateThread (thread_hnd, 1);
570 CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
575 /* Wget expects network calls such as connect, recv, send, etc., to set
576 errno on failure. To achieve that, Winsock calls are wrapped with code
577 that, in case of error, sets errno to the value of WSAGetLastError().
578 In addition, we provide a wrapper around strerror, which recognizes
579 Winsock errors and prints the appropriate error message. */
581 /* Define a macro that creates a function definition that wraps FUN into
582 a function that sets errno the way the rest of the code expects. */
584 #define WRAP(fun, decl, call) int wrapped_##fun decl { \
585 int retval = fun call; \
587 errno = WSAGetLastError (); \
591 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
592 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
593 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
594 WRAP (listen, (int s, int backlog), (s, backlog))
595 WRAP (accept, (int s, struct sockaddr *a, int *alen), (s, a, alen))
596 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
597 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
598 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
600 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
601 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
602 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
603 (s, level, opt, val, len))
604 WRAP (closesocket, (int s), (s))
606 /* Return the text of the error message for Winsock error WSERR. */
609 get_winsock_error (int wserr)
612 case WSAEINTR: return "Interrupted system call";
613 case WSAEBADF: return "Bad file number";
614 case WSAEACCES: return "Permission denied";
615 case WSAEFAULT: return "Bad address";
616 case WSAEINVAL: return "Invalid argument";
617 case WSAEMFILE: return "Too many open files";
618 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
619 case WSAEINPROGRESS: return "Operation now in progress";
620 case WSAEALREADY: return "Operation already in progress";
621 case WSAENOTSOCK: return "Socket operation on nonsocket";
622 case WSAEDESTADDRREQ: return "Destination address required";
623 case WSAEMSGSIZE: return "Message too long";
624 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
625 case WSAENOPROTOOPT: return "Bad protocol option";
626 case WSAEPROTONOSUPPORT: return "Protocol not supported";
627 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
628 case WSAEOPNOTSUPP: return "Operation not supported";
629 case WSAEPFNOSUPPORT: return "Protocol family not supported";
630 case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
631 case WSAEADDRINUSE: return "Address already in use";
632 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
633 case WSAENETDOWN: return "Network is down";
634 case WSAENETUNREACH: return "Network is unreachable";
635 case WSAENETRESET: return "Network dropped connection on reset";
636 case WSAECONNABORTED: return "Software caused connection abort";
637 case WSAECONNRESET: return "Connection reset by peer";
638 case WSAENOBUFS: return "No buffer space available";
639 case WSAEISCONN: return "Socket is already connected";
640 case WSAENOTCONN: return "Socket is not connected";
641 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
642 case WSAETOOMANYREFS: return "Too many references";
643 case WSAETIMEDOUT: return "Connection timed out";
644 case WSAECONNREFUSED: return "Connection refused";
645 case WSAELOOP: return "Too many levels of symbolic links";
646 case WSAENAMETOOLONG: return "File name too long";
647 case WSAEHOSTDOWN: return "Host is down";
648 case WSAEHOSTUNREACH: return "No route to host";
649 case WSAENOTEMPTY: return "Not empty";
650 case WSAEPROCLIM: return "Too many processes";
651 case WSAEUSERS: return "Too many users";
652 case WSAEDQUOT: return "Bad quota";
653 case WSAESTALE: return "Something is stale";
654 case WSAEREMOTE: return "Remote error";
655 case WSAEDISCON: return "Disconnected";
657 /* Extended Winsock errors */
658 case WSASYSNOTREADY: return "Winsock library is not ready";
659 case WSANOTINITIALISED: return "Winsock library not initalised";
660 case WSAVERNOTSUPPORTED: return "Winsock version not supported";
662 case WSAHOST_NOT_FOUND: return "Host not found";
663 case WSATRY_AGAIN: return "Host not found, try again";
664 case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
665 case WSANO_DATA: return "No data record of requested type";
672 /* Return the error message corresponding to ERR. This is different
673 from Windows libc strerror() in that it handles Winsock errors
677 windows_strerror (int err)
680 if (err >= 0 && err < sys_nerr)
681 return strerror (err);
682 else if ((p = get_winsock_error (err)) != NULL)
687 snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
693 /* An inet_ntop implementation that uses WSAAddressToString.
694 Prototype complies with POSIX 1003.1-2004. This is only used under
695 IPv6 because Wget prints IPv4 addresses using inet_ntoa. */
698 inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
700 /* struct sockaddr can't accomodate struct sockaddr_in6. */
702 struct sockaddr_in6 sin6;
703 struct sockaddr_in sin;
712 sa.sin.sin_family = AF_INET;
713 sa.sin.sin_addr = *(struct in_addr *) src;
714 srcsize = sizeof (sa.sin);
717 sa.sin6.sin6_family = AF_INET6;
718 sa.sin6.sin6_addr = *(struct in6_addr *) src;
719 srcsize = sizeof (sa.sin6);
725 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
727 errno = WSAGetLastError();
730 return (const char *) dst;