]> sjero.net Git - wget/blob - src/mswindows.c
[svn] Renamed OVERFLOW and UNDERFLOW to INT64_OVERFLOW and INT64_UNDERFLOW.
[wget] / src / mswindows.c
1 /* mswindows.c -- Windows-specific support
2    Copyright (C) 1995, 1996, 1997, 1998, 2004
3    Free Software Foundation, Inc.
4
5 This file is part of GNU Wget.
6
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 2 of the License, or
10 (at your option) any later version.
11
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.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 In addition, as a special exception, the Free Software Foundation
22 gives permission to link the code of its release of Wget with the
23 OpenSSL project's "OpenSSL" library (or with modified versions of it
24 that use the same license as the "OpenSSL" library), and distribute
25 the linked executables.  You must obey the GNU General Public License
26 in all respects for all of the code used other than "OpenSSL".  If you
27 modify this file, you may extend this exception to your version of the
28 file, but you are not obligated to do so.  If you do not wish to do
29 so, delete this exception statement from your version.  */
30
31 #include <config.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <assert.h>
37 #include <errno.h>
38 #include <math.h>
39
40 #ifdef HACK_BCC_UTIME_BUG
41 # include <io.h>
42 # include <fcntl.h>
43 # ifdef HAVE_UTIME_H
44 #  include <utime.h>
45 # endif
46 # ifdef HAVE_SYS_UTIME_H
47 #  include <sys/utime.h>
48 # endif
49 #endif
50
51 #define INHIBIT_WRAP /* avoid wrapping of socket, bind, ... */
52
53 #include "wget.h"
54 #include "utils.h"
55 #include "url.h"
56
57 #ifndef errno
58 extern int errno;
59 #endif
60
61 #ifndef ES_SYSTEM_REQUIRED
62 #define ES_SYSTEM_REQUIRED  0x00000001
63 #endif
64
65 #ifndef ES_CONTINUOUS
66 #define ES_CONTINUOUS       0x80000000
67 #endif
68
69
70 /* Defined in log.c.  */
71 void log_request_redirect_output PARAMS ((const char *));
72
73 /* Windows version of xsleep in utils.c.  */
74
75 void
76 xsleep (double seconds)
77 {
78 #ifdef HAVE_USLEEP
79   if (seconds > 1000)
80     {
81       /* Explained in utils.c. */
82       sleep (seconds);
83       seconds -= (long) seconds;
84     }
85   usleep (seconds * 1000000L);
86 #else  /* not HAVE_USLEEP */
87   SleepEx ((DWORD) (seconds * 1000 + .5), FALSE);
88 #endif /* not HAVE_USLEEP */
89 }
90
91 #if defined(__BORLANDC__) || (defined(_MSC_VER) && _MSC_VER < 1300)
92
93 static inline int
94 char_value (char c, int base)
95 {
96   int value;
97   if (c < '0')
98     return -1;
99   if ('0' <= c && c <= '9')
100     value = c - '0';
101   else if ('a' <= c && c <= 'z')
102     value = c - 'a' + 10;
103   else if ('A' <= c && c <= 'Z')
104     value = c - 'A' + 10;
105   else
106     return -1;
107   if (value >= base)
108     return -1;
109   return value;
110 }
111
112 /* A fairly simple strtoll replacement for MS VC versions that don't
113    supply _strtoi64.  */
114
115 __int64
116 str_to_int64 (const char *nptr, char **endptr, int base)
117 {
118 #define INT64_OVERFLOW 9223372036854775807I64
119 #define INT64_UNDERFLOW (-INT64_OVERFLOW - 1)
120
121   __int64 result = 0;
122   int negative;
123
124   if (base != 0 && (base < 2 || base > 36))
125     {
126       errno = EINVAL;
127       return 0;
128     }
129
130   while (*nptr == ' ' || *nptr == '\t')
131     ++nptr;
132   if (*nptr == '-')
133     {
134       negative = 1;
135       ++nptr;
136     }
137   else if (*nptr == '+')
138     {
139       negative = 0;
140       ++nptr;
141     }
142   else
143     negative = 0;
144
145   /* If base is 0, determine the real base based on the beginning on
146      the number; octal numbers begin with "0", hexadecimal with "0x",
147      and the others are considered octal.  */
148   if (*nptr == '0')
149     {
150       if ((base == 0 || base == 16)
151           &&
152           (*(nptr + 1) == 'x' || *(nptr + 1) == 'X'))
153         {
154           base = 16;
155           nptr += 2;
156         }
157       else if (base == 0)
158         base = 8;
159     }
160   else if (base == 0)
161     base = 10;
162
163   if (!negative)
164     {
165       /* Parse positive number, checking for overflow. */
166       int val;
167       for (; (val = char_value (*nptr, base)) != -1; ++nptr)
168         {
169           __int64 newresult = base * result + val;
170           if (newresult < result)
171             {
172               result = INT64_OVERFLOW;
173               errno = ERANGE;
174               break;
175             }
176           result = newresult;
177         }
178     }
179   else
180     {
181       /* Parse negative number, checking for underflow. */
182       int val;
183       for (; (val = char_value (*nptr, base)) != -1; ++nptr)
184         {
185           __int64 newresult = base * result - val;
186           if (newresult > result)
187             {
188               result = INT64_UNDERFLOW;
189               errno = ERANGE;
190               break;
191             }
192           result = newresult;
193         }
194     }
195   if (endptr)
196     *endptr = (char *) nptr;
197   return result;
198 }
199
200 #else  /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
201
202 __int64
203 str_to_int64 (const char *nptr, char **endptr, int base)
204 {
205 #ifdef _MSC_VER
206   return _strtoi64 (nptr, endptr, base);
207 #else
208   return strtoll (nptr, endptr, base);
209 #endif
210 }
211
212 #endif /* !defined(__BORLANDC__) && (!defined(_MSC_VER) || _MSC_VER >= 1300) */
213
214 void
215 windows_main (int *argc, char **argv, char **exec_name)
216 {
217   char *p;
218
219   /* Remove .EXE from filename if it has one.  */
220   *exec_name = xstrdup (*exec_name);
221   p = strrchr (*exec_name, '.');
222   if (p)
223     *p = '\0';
224 }
225 \f
226 static void
227 ws_cleanup (void)
228 {
229   WSACleanup ();
230 }
231
232 static void
233 ws_hangup (const char *reason)
234 {
235   fprintf (stderr, _("Continuing in background.\n"));
236   log_request_redirect_output (reason);
237
238   /* Detach process from the current console.  Under Windows 9x, if we
239      were launched from a 16-bit process (which is usually the case;
240      command.com is 16-bit) the parent process should resume right away.
241      Under NT or if launched from a 32-process under 9x, this is a futile
242      gesture as the parent will wait for us to terminate before resuming.  */
243   FreeConsole ();
244 }
245
246 /* Construct the name for a named section (a.k.a. `file mapping') object.
247    The returned string is dynamically allocated and needs to be xfree()'d.  */
248 static char *
249 make_section_name (DWORD pid)
250 {
251   return aprintf ("gnu_wget_fake_fork_%lu", pid);
252 }
253
254 /* This structure is used to hold all the data that is exchanged between
255    parent and child.  */
256 struct fake_fork_info
257 {
258   HANDLE event;
259   int logfile_changed;
260   char lfilename[MAX_PATH + 1];
261 };
262
263 /* Determines if we are the child and if so performs the child logic.
264    Return values:
265      < 0  error
266        0  parent
267      > 0  child
268 */
269 static int
270 fake_fork_child (void)
271 {
272   HANDLE section, event;
273   struct fake_fork_info *info;
274   char *name;
275
276   name = make_section_name (GetCurrentProcessId ());
277   section = OpenFileMapping (FILE_MAP_WRITE, FALSE, name);
278   xfree (name);
279   /* It seems that Windows 9x and NT set last-error inconsistently when
280      OpenFileMapping() fails; so we assume it failed because the section
281      object does not exist.  */
282   if (!section)
283     return 0;                   /* We are the parent.  */
284
285   info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
286   if (!info)
287     {
288       CloseHandle (section);
289       return -1;
290     }
291
292   event = info->event;
293
294   info->logfile_changed = 0;
295   if (!opt.lfilename)
296     {
297       /* See utils:fork_to_background for explanation. */
298       FILE *new_log_fp = unique_create (DEFAULT_LOGFILE, 0, &opt.lfilename);
299       if (new_log_fp)
300         {
301           info->logfile_changed = 1;
302           strncpy (info->lfilename, opt.lfilename, sizeof (info->lfilename));
303           info->lfilename[sizeof (info->lfilename) - 1] = '\0';
304           fclose (new_log_fp);
305         }
306     }
307
308   UnmapViewOfFile (info);
309   CloseHandle (section);
310
311   /* Inform the parent that we've done our part.  */
312   if (!SetEvent (event))
313     return -1;
314
315   CloseHandle (event);
316   return 1;                     /* We are the child.  */
317 }
318
319 /* Windows doesn't support the fork() call; so we fake it by invoking
320    another copy of Wget with the same arguments with which we were
321    invoked.  The child copy of Wget should perform the same initialization
322    sequence as the parent; so we should have two processes that are
323    essentially identical.  We create a specially named section object that
324    allows the child to distinguish itself from the parent and is used to
325    exchange information between the two processes.  We use an event object
326    for synchronization.  */
327 static void
328 fake_fork (void)
329 {
330   char exe[MAX_PATH + 1];
331   DWORD exe_len, le;
332   SECURITY_ATTRIBUTES sa;
333   HANDLE section, event, h[2];
334   STARTUPINFO si;
335   PROCESS_INFORMATION pi;
336   struct fake_fork_info *info;
337   char *name;
338   BOOL rv;
339
340   section = pi.hProcess = pi.hThread = NULL;
341
342   /* Get the fully qualified name of our executable.  This is more reliable
343      than using argv[0].  */
344   exe_len = GetModuleFileName (GetModuleHandle (NULL), exe, sizeof (exe));
345   if (!exe_len || (exe_len >= sizeof (exe)))
346     return;
347
348   sa.nLength = sizeof (sa);
349   sa.lpSecurityDescriptor = NULL;
350   sa.bInheritHandle = TRUE;
351
352   /* Create an anonymous inheritable event object that starts out
353      non-signaled.  */
354   event = CreateEvent (&sa, FALSE, FALSE, NULL);
355   if (!event)
356     return;
357
358   /* Create the child process detached form the current console and in a
359      suspended state.  */
360   xzero (si);
361   si.cb = sizeof (si);
362   rv = CreateProcess (exe, GetCommandLine (), NULL, NULL, TRUE,
363                       CREATE_SUSPENDED | DETACHED_PROCESS,
364                       NULL, NULL, &si, &pi);
365   if (!rv)
366     goto cleanup;
367
368   /* Create a named section object with a name based on the process id of
369      the child.  */
370   name = make_section_name (pi.dwProcessId);
371   section =
372       CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
373                          sizeof (struct fake_fork_info), name);
374   le = GetLastError();
375   xfree (name);
376   /* Fail if the section object already exists (should not happen).  */
377   if (!section || (le == ERROR_ALREADY_EXISTS))
378     {
379       rv = FALSE;
380       goto cleanup;
381     }
382
383   /* Copy the event handle into the section object.  */
384   info = MapViewOfFile (section, FILE_MAP_WRITE, 0, 0, 0);
385   if (!info)
386     {
387       rv = FALSE;
388       goto cleanup;
389     }
390
391   info->event = event;
392
393   UnmapViewOfFile (info);
394
395   /* Start the child process.  */
396   rv = ResumeThread (pi.hThread);
397   if (!rv)
398     {
399       TerminateProcess (pi.hProcess, (DWORD) -1);
400       goto cleanup;
401     }
402
403   /* Wait for the child to signal to us that it has done its part.  If it
404      terminates before signaling us it's an error.  */
405
406   h[0] = event;
407   h[1] = pi.hProcess;
408   rv = WAIT_OBJECT_0 == WaitForMultipleObjects (2, h, FALSE, 5 * 60 * 1000);
409   if (!rv)
410     goto cleanup;
411
412   info = MapViewOfFile (section, FILE_MAP_READ, 0, 0, 0);
413   if (!info)
414     {
415       rv = FALSE;
416       goto cleanup;
417     }
418
419   /* Ensure string is properly terminated.  */
420   if (info->logfile_changed &&
421       !memchr (info->lfilename, '\0', sizeof (info->lfilename)))
422     {
423       rv = FALSE;
424       goto cleanup;
425     }
426
427   printf (_("Continuing in background, pid %lu.\n"), pi.dwProcessId);
428   if (info->logfile_changed)
429     printf (_("Output will be written to `%s'.\n"), info->lfilename);
430
431   UnmapViewOfFile (info);
432
433 cleanup:
434
435   if (event)
436     CloseHandle (event);
437   if (section)
438     CloseHandle (section);
439   if (pi.hThread)
440     CloseHandle (pi.hThread);
441   if (pi.hProcess)
442     CloseHandle (pi.hProcess);
443
444   /* We're the parent.  If all is well, terminate.  */
445   if (rv)
446     exit (0);
447
448   /* We failed, return.  */
449 }
450
451 /* This is the corresponding Windows implementation of the
452    fork_to_background() function in utils.c.  */
453 void
454 fork_to_background (void)
455 {
456   int rv;
457
458   rv = fake_fork_child ();
459   if (rv < 0)
460     {
461       fprintf (stderr, "fake_fork_child() failed\n");
462       abort ();
463     }
464   else if (rv == 0)
465     {
466       /* We're the parent.  */
467       fake_fork ();
468       /* If fake_fork() returns, it failed.  */
469       fprintf (stderr, "fake_fork() failed\n");
470       abort ();
471     }
472   /* If we get here, we're the child.  */
473 }
474
475 static BOOL WINAPI
476 ws_handler (DWORD dwEvent)
477 {
478   switch (dwEvent)
479     {
480 #ifdef CTRLC_BACKGND
481     case CTRL_C_EVENT:
482       ws_hangup ("CTRL+C");
483       return TRUE;
484 #endif
485 #ifdef CTRLBREAK_BACKGND
486     case CTRL_BREAK_EVENT:
487       ws_hangup ("CTRL+Break");
488       return TRUE;
489 #endif
490     default:
491       return FALSE;
492     }
493 }
494
495 static char *title_buf = NULL;
496 static char *curr_url  = NULL;
497 static int old_percentage = -1;
498
499 /* Updates the console title with the URL of the current file being
500    transferred.  */
501 void
502 ws_changetitle (const char *url)
503 {
504   xfree_null (title_buf);
505   xfree_null (curr_url);
506   title_buf = (char *)xmalloc (strlen (url) + 20);
507   curr_url = xstrdup (url);
508   old_percentage = -1;
509   sprintf (title_buf, "Wget %s", curr_url);
510   SetConsoleTitle (title_buf);
511 }
512
513 /* Updates the console title with the percentage of the current file
514    transferred.  */
515 void
516 ws_percenttitle (double percentage_float)
517 {
518   int percentage;
519
520   if (!title_buf || !curr_url)
521     return;
522
523   percentage = (int) percentage_float;
524
525   /* Clamp percentage value.  */
526   if (percentage < 0)
527     percentage = 0;
528   if (percentage > 100)
529     percentage = 100;
530
531   /* Only update the title when the percentage has changed.  */
532   if (percentage == old_percentage)
533     return;
534
535   old_percentage = percentage;
536
537   sprintf (title_buf, "Wget [%d%%] %s", percentage, curr_url);
538   SetConsoleTitle (title_buf);
539 }
540
541 /* Returns a pointer to the fully qualified name of the directory that
542    contains the Wget binary (wget.exe).  The returned path does not have a
543    trailing path separator.  Returns NULL on failure.  */
544 char *
545 ws_mypath (void)
546 {
547   static char *wspathsave = NULL;
548
549   if (!wspathsave)
550     {
551       char buf[MAX_PATH + 1];
552       char *p;
553       DWORD len;
554
555       len = GetModuleFileName (GetModuleHandle (NULL), buf, sizeof (buf));
556       if (!len || (len >= sizeof (buf)))
557         return NULL;
558
559       p = strrchr (buf, PATH_SEPARATOR);
560       if (!p)
561         return NULL;
562
563       *p = '\0';
564       wspathsave = xstrdup (buf);
565     }
566
567   return wspathsave;
568 }
569
570 /* Prevent Windows entering sleep/hibernation-mode while Wget is doing
571    a lengthy transfer.  Windows does not, by default, consider network
572    activity in console-programs as activity!  Works on Win-98/ME/2K
573    and up.  */
574 static void
575 set_sleep_mode (void)
576 {
577   typedef DWORD (WINAPI *func_t) (DWORD);
578   func_t set_exec_state;
579
580   set_exec_state =
581       (func_t) GetProcAddress (GetModuleHandle ("KERNEL32.DLL"),
582                                "SetThreadExecutionState");
583
584   if (set_exec_state)
585     set_exec_state (ES_SYSTEM_REQUIRED | ES_CONTINUOUS);
586 }
587
588 /* Perform Windows specific initialization.  */
589 void
590 ws_startup (void)
591 {
592   WSADATA data;
593   WORD requested = MAKEWORD (1, 1);
594   int err = WSAStartup (requested, &data);
595   if (err != 0)
596     {
597       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
598                exec_name);
599       exit (1);
600     }
601
602   if (data.wVersion < requested)
603     {
604       fprintf (stderr, _("%s: Couldn't find usable socket driver.\n"),
605                exec_name);
606       WSACleanup ();
607       exit (1);
608     }
609
610   atexit (ws_cleanup);
611   set_sleep_mode ();
612   SetConsoleCtrlHandler (ws_handler, TRUE);
613 }
614
615 /* Replacement utime function for buggy Borland C++Builder 5.5 compiler.
616    (The Borland utime function only works on Windows NT.)  */
617
618 #ifdef HACK_BCC_UTIME_BUG
619 int
620 borland_utime (const char *path, const struct utimbuf *times)
621 {
622   int fd;
623   int res;
624   struct ftime ft;
625   struct tm *ptr_tm;
626
627   if ((fd = open (path, O_RDWR)) < 0)
628     return -1;
629
630   ptr_tm = localtime (&times->modtime);
631   ft.ft_tsec = ptr_tm->tm_sec >> 1;
632   ft.ft_min = ptr_tm->tm_min;
633   ft.ft_hour = ptr_tm->tm_hour;
634   ft.ft_day = ptr_tm->tm_mday;
635   ft.ft_month = ptr_tm->tm_mon + 1;
636   ft.ft_year = ptr_tm->tm_year - 80;
637   res = setftime (fd, &ft);
638   close (fd);
639   return res;
640 }
641 #endif
642 \f
643 /* run_with_timeout Windows implementation.  */
644
645 /* Stack size 0 uses default thread stack-size (reserve+commit).
646    Determined by what's in the PE header.  */
647 #define THREAD_STACK_SIZE  0
648
649 struct thread_data
650 {
651   void (*fun) (void *);
652   void *arg;
653   DWORD ws_error;
654 };
655
656 /* The callback that runs FUN(ARG) in a separate thread.  This
657    function exists for two reasons: a) to not require FUN to be
658    declared WINAPI/__stdcall[1], and b) to retrieve Winsock errors,
659    which are per-thread.  The latter is useful when FUN calls Winsock
660    functions, which is how run_with_timeout is used in Wget.
661
662    [1] MSVC can use __fastcall globally (cl /Gr) and on Watcom this is
663    the default (wcc386 -3r).  */
664
665 static DWORD WINAPI
666 thread_helper (void *arg)
667 {
668   struct thread_data *td = (struct thread_data *) arg;
669
670   /* Initialize Winsock error to what it was in the parent.  That way
671      the subsequent call to WSAGetLastError will return the same value
672      if td->fun doesn't change Winsock error state.  */
673   WSASetLastError (td->ws_error);
674
675   td->fun (td->arg);
676
677   /* Return Winsock error to the caller, in case FUN ran Winsock
678      code.  */
679   td->ws_error = WSAGetLastError ();
680   return 0;
681 }
682
683 /* Call FUN(ARG), but don't allow it to run for more than TIMEOUT
684    seconds.  Returns non-zero if the function was interrupted with a
685    timeout, zero otherwise.
686
687    This works by running FUN in a separate thread and terminating the
688    thread if it doesn't finish in the specified time.  */
689
690 int
691 run_with_timeout (double seconds, void (*fun) (void *), void *arg)
692 {
693   static HANDLE thread_hnd = NULL;
694   struct thread_data thread_arg;
695   DWORD thread_id;
696   int rc;
697
698   DEBUGP (("seconds %.2f, ", seconds));
699
700   if (seconds == 0)
701     {
702     blocking_fallback:
703       fun (arg);
704       return 0;
705     }
706
707   /* Should never happen, but test for recursivety anyway.  */
708   assert (thread_hnd == NULL);
709
710   thread_arg.fun = fun;
711   thread_arg.arg = arg;
712   thread_arg.ws_error = WSAGetLastError ();
713   thread_hnd = CreateThread (NULL, THREAD_STACK_SIZE, thread_helper,
714                              &thread_arg, 0, &thread_id);
715   if (!thread_hnd)
716     {
717       DEBUGP (("CreateThread() failed; %s\n", strerror (GetLastError ())));
718       goto blocking_fallback;
719     }
720
721   if (WaitForSingleObject (thread_hnd, (DWORD)(1000 * seconds))
722       == WAIT_OBJECT_0)
723     {
724       /* Propagate error state (which is per-thread) to this thread,
725          so the caller can inspect it.  */
726       WSASetLastError (thread_arg.ws_error);
727       DEBUGP (("Winsock error: %d\n", WSAGetLastError ()));
728       rc = 0;
729     }
730   else
731     {
732       TerminateThread (thread_hnd, 1);
733       rc = 1;
734     }
735
736   CloseHandle (thread_hnd);     /* Clear-up after TerminateThread().  */
737   thread_hnd = NULL;
738   return rc;
739 }
740 \f
741 /* Wget expects network calls such as connect, recv, send, etc., to set
742    errno on failure.  To achieve that, Winsock calls are wrapped with code
743    that, in case of error, sets errno to the value of WSAGetLastError().
744    In addition, we provide a wrapper around strerror, which recognizes
745    Winsock errors and prints the appropriate error message. */
746
747 /* Define a macro that creates a function definition that wraps FUN into
748    a function that sets errno the way the rest of the code expects. */
749
750 #define WRAP(fun, decl, call) int wrapped_##fun decl {  \
751   int retval = fun call;                                \
752   if (retval < 0)                                       \
753     errno = WSAGetLastError ();                         \
754   return retval;                                        \
755 }
756
757 WRAP (socket, (int domain, int type, int protocol), (domain, type, protocol))
758 WRAP (bind, (int s, struct sockaddr *a, int alen), (s, a, alen))
759 WRAP (connect, (int s, const struct sockaddr *a, int alen), (s, a, alen))
760 WRAP (recv, (int s, void *buf, int len, int flags), (s, buf, len, flags))
761 WRAP (send, (int s, const void *buf, int len, int flags), (s, buf, len, flags))
762 WRAP (select, (int n, fd_set *r, fd_set *w, fd_set *e, const struct timeval *tm),
763               (n, r, w, e, tm))
764 WRAP (getsockname, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
765 WRAP (getpeername, (int s, struct sockaddr *n, int *nlen), (s, n, nlen))
766 WRAP (setsockopt, (int s, int level, int opt, const void *val, int len),
767                   (s, level, opt, val, len))
768 WRAP (closesocket, (int s), (s))
769
770 /* Return the text of the error message for Winsock error WSERR. */
771
772 static const char *
773 get_winsock_error (int wserr)
774 {
775   switch (wserr) {
776   case WSAEINTR:           return "Interrupted system call";
777   case WSAEBADF:           return "Bad file number";
778   case WSAEACCES:          return "Permission denied";
779   case WSAEFAULT:          return "Bad address";
780   case WSAEINVAL:          return "Invalid argument";
781   case WSAEMFILE:          return "Too many open files";
782   case WSAEWOULDBLOCK:     return "Resource temporarily unavailable";
783   case WSAEINPROGRESS:     return "Operation now in progress";
784   case WSAEALREADY:        return "Operation already in progress";
785   case WSAENOTSOCK:        return "Socket operation on nonsocket";
786   case WSAEDESTADDRREQ:    return "Destination address required";
787   case WSAEMSGSIZE:        return "Message too long";
788   case WSAEPROTOTYPE:      return "Protocol wrong type for socket";
789   case WSAENOPROTOOPT:     return "Bad protocol option";
790   case WSAEPROTONOSUPPORT: return "Protocol not supported";
791   case WSAESOCKTNOSUPPORT: return "Socket type not supported";
792   case WSAEOPNOTSUPP:      return "Operation not supported";
793   case WSAEPFNOSUPPORT:    return "Protocol family not supported";
794   case WSAEAFNOSUPPORT:    return "Address family not supported by protocol family";
795   case WSAEADDRINUSE:      return "Address already in use";
796   case WSAEADDRNOTAVAIL:   return "Cannot assign requested address";
797   case WSAENETDOWN:        return "Network is down";
798   case WSAENETUNREACH:     return "Network is unreachable";
799   case WSAENETRESET:       return "Network dropped connection on reset";
800   case WSAECONNABORTED:    return "Software caused connection abort";
801   case WSAECONNRESET:      return "Connection reset by peer";
802   case WSAENOBUFS:         return "No buffer space available";
803   case WSAEISCONN:         return "Socket is already connected";
804   case WSAENOTCONN:        return "Socket is not connected";
805   case WSAESHUTDOWN:       return "Cannot send after socket shutdown";
806   case WSAETOOMANYREFS:    return "Too many references";
807   case WSAETIMEDOUT:       return "Connection timed out";
808   case WSAECONNREFUSED:    return "Connection refused";
809   case WSAELOOP:           return "Too many levels of symbolic links";
810   case WSAENAMETOOLONG:    return "File name too long";
811   case WSAEHOSTDOWN:       return "Host is down";
812   case WSAEHOSTUNREACH:    return "No route to host";
813   case WSAENOTEMPTY:       return "Not empty";
814   case WSAEPROCLIM:        return "Too many processes";
815   case WSAEUSERS:          return "Too many users";
816   case WSAEDQUOT:          return "Bad quota";
817   case WSAESTALE:          return "Something is stale";
818   case WSAEREMOTE:         return "Remote error";
819   case WSAEDISCON:         return "Disconnected";
820
821   /* Extended Winsock errors */
822   case WSASYSNOTREADY:     return "Winsock library is not ready";
823   case WSANOTINITIALISED:  return "Winsock library not initalised";
824   case WSAVERNOTSUPPORTED: return "Winsock version not supported";
825
826   case WSAHOST_NOT_FOUND: return "Host not found";
827   case WSATRY_AGAIN:      return "Host not found, try again";
828   case WSANO_RECOVERY:    return "Unrecoverable error in call to nameserver";
829   case WSANO_DATA:        return "No data record of requested type";
830
831   default:
832     return NULL;
833   }
834 }
835
836 /* Return the error message corresponding to ERR.  This is different
837    from Windows libc strerror() in that it handles Winsock errors
838    correctly.  */
839
840 const char *
841 windows_strerror (int err)
842 {
843   const char *p;
844   if (err >= 0 && err < sys_nerr)
845     return strerror (err);
846   else if ((p = get_winsock_error (err)) != NULL)
847     return p;
848   else
849     {
850       static char buf[32];
851       snprintf (buf, sizeof (buf), "Unknown error %d (%#x)", err, err);
852       return buf;
853     }
854 }