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 INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
46 #ifndef ES_SYSTEM_REQUIRED
47 #define ES_SYSTEM_REQUIRED 0x00000001
51 #define ES_CONTINUOUS 0x80000000
55 /* Defined in log.c. */
56 void log_request_redirect_output (const char *);
58 /* Windows version of xsleep in utils.c. */
61 xsleep (double seconds)
66 /* Explained in utils.c. */
68 seconds -= (long) seconds;
70 usleep (seconds * 1000000);
71 #else /* not HAVE_USLEEP */
72 SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
73 #endif /* not HAVE_USLEEP */
77 windows_main (char **exec_name)
81 /* Remove .EXE from filename if it has one. */
82 *exec_name = xstrdup (*exec_name);
83 p = strrchr (*exec_name, '.');
91 xfree ((char*)exec_name);
95 #if defined(CTRLBREAK_BACKGND) || defined(CTRLC_BACKGND)
97 ws_hangup (const char *reason)
99 fprintf (stderr, _("Continuing in background.\n"));
100 log_request_redirect_output (reason);
102 /* Detach process from the current console. Under Windows 9x, if we
103 were launched from a 16-bit process (which is usually the case;
104 command.com is 16-bit) the parent process should resume right away.
105 Under NT or if launched from a 32-process under 9x, this is a futile
106 gesture as the parent will wait for us to terminate before resuming. */
111 /* Construct the name for a named section (a.k.a. `file mapping') object.
112 The returned string is dynamically allocated and needs to be xfree()'d. */
114 make_section_name (DWORD pid)
116 return aprintf ("gnu_wget_fake_fork_%lu", pid);
119 /* This structure is used to hold all the data that is exchanged between
121 struct fake_fork_info
124 bool logfile_changed;
125 char lfilename[MAX_PATH + 1];
128 /* Determines if we are the child and if so performs the child logic.
135 fake_fork_child (void)
137 HANDLE section, event;
138 struct fake_fork_info *info;
141 name = make_section_name (GetCurrentProcessId ());
142 section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
144 /* It seems that Windows 9x and NT set last-error inconsistently when
145 OpenFileMapping() fails; so we assume it failed because the section
146 object does not exist. */
148 return 0; /* We are the parent. */
150 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
153 CloseHandle (section);
159 info->logfile_changed = false;
160 if (opt.quiet && !opt.server_response)
166 /* See utils:fork_to_background for explanation. */
167 FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, false, &opt.lfilename);
170 info->logfile_changed = true;
171 strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
172 info->lfilename[sizeof (info->lfilename) - 1] = '\0';
177 UnmapViewOfFile (info);
178 CloseHandle (section);
180 /* Inform the parent that we've done our part. */
181 if (!SetEvent (event))
185 return 1; /* We are the child. */
188 /* Windows doesn't support the fork() call; so we fake it by invoking
189 another copy of Wget with the same arguments with which we were
190 invoked. The child copy of Wget should perform the same initialization
191 sequence as the parent; so we should have two processes that are
192 essentially identical. We create a specially named section object that
193 allows the child to distinguish itself from the parent and is used to
194 exchange information between the two processes. We use an event object
195 for synchronization. */
199 char exe[MAX_PATH + 1];
201 SECURITY_ATTRIBUTES sa;
202 HANDLE section, event, h[2];
204 PROCESS_INFORMATION pi;
205 struct fake_fork_info *info;
209 section = pi.hProcess = pi.hThread = NULL;
211 /* Get the fully qualified name of our executable. This is more reliable
212 than using argv[0]. */
213 exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
214 if (!exe_len || (exe_len >= sizeof (exe)))
217 sa.nLength = sizeof (sa);
218 sa.lpSecurityDescriptor = NULL;
219 sa.bInheritHandle = TRUE;
221 /* Create an anonymous inheritable event object that starts out
223 event = CreateEvent (&sa, FALSE, FALSE, NULL);
227 /* Create the child process detached form the current console and in a
231 rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
232 CREATE_SUSPENDED | DETACHED_PROCESS,
233 NULL, NULL, &si, &pi);
237 /* Create a named section object with a name based on the process id of
239 name = make_section_name (pi.dwProcessId);
241 CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
242 sizeof (struct fake_fork_info), name);
245 /* Fail if the section object already exists (should not happen). */
246 if (!section || (le == ERROR_ALREADY_EXISTS))
252 /* Copy the event handle into the section object. */
253 info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
262 UnmapViewOfFile (info);
264 /* Start the child process. */
265 rv = ResumeThread (pi.hThread);
268 TerminateProcess (pi.hProcess, (DWORD) -1);
272 /* Wait for the child to signal to us that it has done its part. If it
273 terminates before signaling us it's an error. */
277 rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
281 info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
288 /* Ensure string is properly terminated. */
289 if (info->logfile_changed &&
290 !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
297 printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
298 if (info->logfile_changed)
299 printf (_("Output will be written to `%s'.\n"), info->lfilename);
301 UnmapViewOfFile (info);
308 CloseHandle (section);
310 CloseHandle (pi.hThread);
312 CloseHandle (pi.hProcess);
314 /* We're the parent. If all is well, terminate. */
318 /* We failed, return. */
321 /* This is the corresponding Windows implementation of the
322 fork_to_background() function in utils.c. */
324 fork_to_background (void)
328 rv = fake_fork_child ();
331 fprintf (stderr, "fake_fork_child() failed\n");
336 /* We're the parent. */
338 /* If fake_fork() returns, it failed. */
339 fprintf (stderr, "fake_fork() failed\n");
342 /* If we get here, we're the child. */
346 ws_handler (DWORD dwEvent)
352 ws_hangup ("CTRL+C");
355 #ifdef CTRLBREAK_BACKGND
356 case CTRL_BREAK_EVENT:
357 ws_hangup ("CTRL+Break");
365 static char *title_buf = NULL;
366 static char *curr_url = NULL;
367 static int old_percentage = -1;
369 /* Updates the console title with the URL of the current file being
372 ws_changetitle (const char *url)
374 xfree_null (title_buf);
375 xfree_null (curr_url);
376 title_buf = xmalloc (strlen (url) + 20);
377 curr_url = xstrdup (url);
379 sprintf (title_buf, "Wget %s", curr_url);
380 SetConsoleTitle (title_buf);
383 /* Updates the console title with the percentage of the current file
386 ws_percenttitle (double percentage_float)
390 if (!title_buf || !curr_url)
393 percentage = (int) percentage_float;
395 /* Clamp percentage value. */
398 if (percentage > 100)
401 /* Only update the title when the percentage has changed. */
402 if (percentage == old_percentage)
405 old_percentage = percentage;
407 sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
408 SetConsoleTitle (title_buf);
411 /* Returns a pointer to the fully qualified name of the directory that
412 contains the Wget binary (wget.exe). The returned path does not have a
413 trailing path separator. Returns NULL on failure. */
417 static char *wspathsave = NULL;
421 char buf[MAX_PATH + 1];
425 len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
426 if (!len || (len >= sizeof (buf)))
429 p = strrchr (buf, PATH_SEPARATOR);
434 wspathsave = xstrdup (buf);
440 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
441 a lengthy transfer. Windows does not, by default, consider network
442 activity in console-programs as activity! Works on Win-98/ME/2K
445 set_sleep_mode (void)
447 typedef DWORD (WINAPI *func_t) (DWORD);
448 func_t set_exec_state;
451 (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
452 "SetThreadExecutionState");
455 set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
458 /* Perform Windows specific initialization. */
463 WORD requested = MAKEWORD (1, 1);
464 int err = WSAStartup (requested, &data);
467 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
472 if (data.wVersion < requested)
474 fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
482 SetConsoleCtrlHandler (ws_handler, TRUE);
485 /* run_with_timeout Windows implementation. */
487 /* Stack size 0 uses default thread stack-size (reserve+commit).
488 Determined by what's in the PE header. */
489 #define THREAD_STACK_SIZE 0
493 void (*fun) (void *);
498 /* The callback that runs FUN(ARG) in a separate thread. This
499 function exists for two reasons: a) to not require FUN to be
500 declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
501 which are per-thread. The latter is useful when FUN calls Winsock
502 functions, which is how run_with_timeout is used in Wget.
504 [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
505 the default (wcc386 -3r). */
508 thread_helper (void *arg)
510 struct thread_data *td = (struct thread_data *) arg;
512 /* Initialize Winsock error to what it was in the parent. That way
513 the subsequent call to WSAGetLastError will return the same value
514 if td->fun doesn't change Winsock error state. */
515 WSASetLastError (td->ws_error);
519 /* Return Winsock error to the caller, in case FUN ran Winsock
521 td->ws_error = WSAGetLastError ();
525 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
526 seconds. Returns true if the function was interrupted with a
527 timeout, false otherwise.
529 This works by running FUN in a separate thread and terminating the
530 thread if it doesn't finish in the specified time. */
533 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
536 struct thread_data thread_arg;
540 DEBUGP (("seconds %.2f, ", seconds));
549 thread_arg.fun = fun;
550 thread_arg.arg = arg;
551 thread_arg.ws_error = WSAGetLastError ();
552 thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
553 &thread_arg, 0, &thread_id);
556 DEBUGP (("CreateThread() failed; [%#lx]\n",
557 (unsigned long) GetLastError ()));
558 goto blocking_fallback;
561 if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
564 /* Propagate error state (which is per-thread) to this thread,
565 so the caller can inspect it. */
566 WSASetLastError (thread_arg.ws_error);
567 DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
572 TerminateThread (thread_hnd, 1);
576 CloseHandle (thread_hnd); /* Clear-up after TerminateThread(). */
581 /* Wget expects network calls such as connect, recv, send, etc., to set
582 errno on failure. To achieve that, Winsock calls are wrapped with code
583 that, in case of error, sets errno to the value of WSAGetLastError().
584 In addition, we provide a wrapper around strerror, which recognizes
585 Winsock errors and prints the appropriate error message. */
587 /* Define a macro that creates a function definition that wraps FUN into
588 a function that sets errno the way the rest of the code expects. */
590 #define WRAP(fun, decl, call) int wrapped_##fun decl { \
591 int retval = fun call; \
593 errno = WSAGetLastError (); \
597 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
598 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
599 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
600 WRAP (listen, (int s, int backlog), (s, backlog))
601 WRAP (accept, (int s, struct sockaddr *a, int *alen), (s, a, alen))
602 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
603 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
604 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
606 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
607 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
608 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
609 (s, level, opt, val, len))
610 WRAP (closesocket, (int s), (s))
612 /* Return the text of the error message for Winsock error WSERR. */
615 get_winsock_error (int wserr)
618 case WSAEINTR: return "Interrupted system call";
619 case WSAEBADF: return "Bad file number";
620 case WSAEACCES: return "Permission denied";
621 case WSAEFAULT: return "Bad address";
622 case WSAEINVAL: return "Invalid argument";
623 case WSAEMFILE: return "Too many open files";
624 case WSAEWOULDBLOCK: return "Resource temporarily unavailable";
625 case WSAEINPROGRESS: return "Operation now in progress";
626 case WSAEALREADY: return "Operation already in progress";
627 case WSAENOTSOCK: return "Socket operation on nonsocket";
628 case WSAEDESTADDRREQ: return "Destination address required";
629 case WSAEMSGSIZE: return "Message too long";
630 case WSAEPROTOTYPE: return "Protocol wrong type for socket";
631 case WSAENOPROTOOPT: return "Bad protocol option";
632 case WSAEPROTONOSUPPORT: return "Protocol not supported";
633 case WSAESOCKTNOSUPPORT: return "Socket type not supported";
634 case WSAEOPNOTSUPP: return "Operation not supported";
635 case WSAEPFNOSUPPORT: return "Protocol family not supported";
636 case WSAEAFNOSUPPORT: return "Address family not supported by protocol family";
637 case WSAEADDRINUSE: return "Address already in use";
638 case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
639 case WSAENETDOWN: return "Network is down";
640 case WSAENETUNREACH: return "Network is unreachable";
641 case WSAENETRESET: return "Network dropped connection on reset";
642 case WSAECONNABORTED: return "Software caused connection abort";
643 case WSAECONNRESET: return "Connection reset by peer";
644 case WSAENOBUFS: return "No buffer space available";
645 case WSAEISCONN: return "Socket is already connected";
646 case WSAENOTCONN: return "Socket is not connected";
647 case WSAESHUTDOWN: return "Cannot send after socket shutdown";
648 case WSAETOOMANYREFS: return "Too many references";
649 case WSAETIMEDOUT: return "Connection timed out";
650 case WSAECONNREFUSED: return "Connection refused";
651 case WSAELOOP: return "Too many levels of symbolic links";
652 case WSAENAMETOOLONG: return "File name too long";
653 case WSAEHOSTDOWN: return "Host is down";
654 case WSAEHOSTUNREACH: return "No route to host";
655 case WSAENOTEMPTY: return "Not empty";
656 case WSAEPROCLIM: return "Too many processes";
657 case WSAEUSERS: return "Too many users";
658 case WSAEDQUOT: return "Bad quota";
659 case WSAESTALE: return "Something is stale";
660 case WSAEREMOTE: return "Remote error";
661 case WSAEDISCON: return "Disconnected";
663 /* Extended Winsock errors */
664 case WSASYSNOTREADY: return "Winsock library is not ready";
665 case WSANOTINITIALISED: return "Winsock library not initalised";
666 case WSAVERNOTSUPPORTED: return "Winsock version not supported";
668 case WSAHOST_NOT_FOUND: return "Host not found";
669 case WSATRY_AGAIN: return "Host not found, try again";
670 case WSANO_RECOVERY: return "Unrecoverable error in call to nameserver";
671 case WSANO_DATA: return "No data record of requested type";
678 /* Return the error message corresponding to ERR. This is different
679 from Windows libc strerror() in that it handles Winsock errors
683 windows_strerror (int err)
686 if (err >= 0 && err < sys_nerr)
687 return strerror (err);
688 else if ((p = get_winsock_error (err)) != NULL)
693 snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
699 /* An inet_ntop implementation that uses WSAAddressToString.
700 Prototype complies with POSIX 1003.1-2004. This is only used under
701 IPv6 because Wget prints IPv4 addresses using inet_ntoa. */
704 inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
706 /* struct sockaddr can't accomodate struct sockaddr_in6. */
708 struct sockaddr_in6 sin6;
709 struct sockaddr_in sin;
718 sa.sin.sin_family = AF_INET;
719 sa.sin.sin_addr = *(struct in_addr *) src;
720 srcsize = sizeof (sa.sin);
723 sa.sin6.sin6_family = AF_INET6;
724 sa.sin6.sin6_addr = *(struct in6_addr *) src;
725 srcsize = sizeof (sa.sin6);
731 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
733 errno = WSAGetLastError();
736 return (const char *) dst;