Removing obsolete Win32 GUI files
[privoxy.git] / errlog.c
1 const char errlog_rcs[] = "$Id: errlog.c,v 1.15 2001/07/29 17:41:10 jongfoster Exp $";
2 /*********************************************************************
3  *
4  * File        :  $Source: /cvsroot/ijbswa/current/errlog.c,v $
5  *
6  * Purpose     :  Log errors to a designated destination in an elegant,
7  *                printf-like fashion.
8  *
9  * Copyright   :  Written by and Copyright (C) 2001 the SourceForge
10  *                IJBSWA team.  http://ijbswa.sourceforge.net
11  *
12  *                Based on the Internet Junkbuster originally written
13  *                by and Copyright (C) 1997 Anonymous Coders and 
14  *                Junkbusters Corporation.  http://www.junkbusters.com
15  *
16  *                This program is free software; you can redistribute it 
17  *                and/or modify it under the terms of the GNU General
18  *                Public License as published by the Free Software
19  *                Foundation; either version 2 of the License, or (at
20  *                your option) any later version.
21  *
22  *                This program is distributed in the hope that it will
23  *                be useful, but WITHOUT ANY WARRANTY; without even the
24  *                implied warranty of MERCHANTABILITY or FITNESS FOR A
25  *                PARTICULAR PURPOSE.  See the GNU General Public
26  *                License for more details.
27  *
28  *                The GNU General Public License should be included with
29  *                this file.  If not, you can view it at
30  *                http://www.gnu.org/copyleft/gpl.html
31  *                or write to the Free Software Foundation, Inc., 59
32  *                Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33  *
34  * Revisions   :
35  *    $Log: errlog.c,v $
36  *    Revision 1.15  2001/07/29 17:41:10  jongfoster
37  *    Now prints thread ID for each message (pthreads only)
38  *
39  *    Revision 1.14  2001/07/19 19:03:48  haroon
40  *    - Added case for LOG_LEVEL_POPUPS
41  *
42  *    Revision 1.13  2001/07/13 13:58:58  oes
43  *     - Added case for LOG_LEVEL_DEANIMATE
44  *     - Removed all #ifdef PCRS
45  *
46  *    Revision 1.12  2001/06/09 10:55:28  jongfoster
47  *    Changing BUFSIZ ==> BUFFER_SIZE
48  *
49  *    Revision 1.11  2001/06/01 18:14:49  jongfoster
50  *    Changing the calls to strerr() to check HAVE_STRERR (which is defined
51  *    in config.h if appropriate) rather than the NO_STRERR macro.
52  *
53  *    Revision 1.10  2001/05/29 11:52:21  oes
54  *    Conditional compilation of w32_socket_error
55  *
56  *    Revision 1.9  2001/05/28 16:15:17  jongfoster
57  *    Improved reporting of errors under Win32.
58  *
59  *    Revision 1.8  2001/05/26 17:25:14  jongfoster
60  *    Added support for CLF (Common Log Format) and fixed LOG_LEVEL_LOG
61  *
62  *    Revision 1.7  2001/05/26 15:21:28  jongfoster
63  *    Activity animation in Win32 GUI now works even if debug==0
64  *
65  *    Revision 1.6  2001/05/25 21:55:08  jongfoster
66  *    Now cleans up properly on FATAL (removes taskbar icon etc)
67  *
68  *    Revision 1.5  2001/05/22 18:46:04  oes
69  *
70  *    - Enabled filtering banners by size rather than URL
71  *      by adding patterns that replace all standard banner
72  *      sizes with the "Junkbuster" gif to the re_filterfile
73  *
74  *    - Enabled filtering WebBugs by providing a pattern
75  *      which kills all 1x1 images
76  *
77  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
78  *      which is selected by the (nonstandard and therefore
79  *      capital) letter 'U' in the option string.
80  *      It causes the quantifiers to be ungreedy by default.
81  *      Appending a ? turns back to greedy (!).
82  *
83  *    - Added a new interceptor ijb-send-banner, which
84  *      sends back the "Junkbuster" gif. Without imagelist or
85  *      MSIE detection support, or if tinygif = 1, or the
86  *      URL isn't recognized as an imageurl, a lame HTML
87  *      explanation is sent instead.
88  *
89  *    - Added new feature, which permits blocking remote
90  *      script redirects and firing back a local redirect
91  *      to the browser.
92  *      The feature is conditionally compiled, i.e. it
93  *      can be disabled with --disable-fast-redirects,
94  *      plus it must be activated by a "fast-redirects"
95  *      line in the config file, has its own log level
96  *      and of course wants to be displayed by show-proxy-args
97  *      Note: Boy, all the #ifdefs in 1001 locations and
98  *      all the fumbling with configure.in and acconfig.h
99  *      were *way* more work than the feature itself :-(
100  *
101  *    - Because a generic redirect template was needed for
102  *      this, tinygif = 3 now uses the same.
103  *
104  *    - Moved GIFs, and other static HTTP response templates
105  *      to project.h
106  *
107  *    - Some minor fixes
108  *
109  *    - Removed some >400 CRs again (Jon, you really worked
110  *      a lot! ;-)
111  *
112  *    Revision 1.4  2001/05/21 19:32:54  jongfoster
113  *    Added another #ifdef _WIN_CONSOLE
114  *
115  *    Revision 1.3  2001/05/20 01:11:40  jongfoster
116  *    Added support for LOG_LEVEL_FATAL
117  *    Renamed LOG_LEVEL_FRC to LOG_LEVEL_FORCE,
118  *    and LOG_LEVEL_REF to LOG_LEVEL_RE_FILTER
119  *
120  *    Revision 1.2  2001/05/17 22:42:01  oes
121  *     - Cleaned CRLF's from the sources and related files
122  *     - Repaired logging for REF and FRC
123  *
124  *    Revision 1.1.1.1  2001/05/15 13:58:51  oes
125  *    Initial import of version 2.9.3 source tree
126  *
127  *
128  *********************************************************************/
129 \f
130
131 #include "config.h"
132
133 #include <stdlib.h>
134 #include <stdio.h>
135 #include <stdarg.h>
136 #include <string.h>
137
138 #ifndef _WIN32
139 #include <unistd.h>
140 #endif /* ndef _WIN32 */
141
142 #include <errno.h>
143 #ifdef FEATURE_PTHREAD
144 #include <pthread.h>
145 #endif /* def FEATURE_PTHREAD */
146
147 #ifdef _WIN32
148 #include <windows.h>
149 #ifndef _WIN_CONSOLE
150 #include "w32log.h"
151 #endif /* ndef _WIN_CONSOLE */
152 #endif /* def _WIN32 */
153
154 #include "errlog.h"
155 #include "project.h"
156
157 const char errlog_h_rcs[] = ERRLOG_H_VERSION;
158
159
160 /*
161  * LOG_LEVEL_FATAL cannot be turned off.  (There are
162  * some exceptional situations where we need to get a
163  * message to the user).
164  */
165 #define LOG_LEVEL_MINIMUM  LOG_LEVEL_FATAL
166
167 /* where to log (default: stderr) */
168 static FILE *logfp = NULL;
169
170 /* where to log (NULL == stderr) */
171 static char * logfilename = NULL;
172
173 /* logging detail level.  */
174 static int debug = (LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);  
175
176 /* static functions */
177 static void fatal_error(const char * error_message);
178 static char * w32_socket_strerr(int errcode, char * tmp_buf);
179
180
181 /*********************************************************************
182  *
183  * Function    :  fatal_error
184  *
185  * Description :  Displays a fatal error to standard error (or, on 
186  *                a WIN32 GUI, to a dialog box), and exits
187  *                JunkBuster with status code 1.
188  *
189  * Parameters  :
190  *          1  :  error_message = The error message to display.
191  *
192  * Returns     :  Does not return.
193  *
194  *********************************************************************/
195 static void fatal_error(const char * error_message)
196 {
197 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
198    MessageBox(g_hwndLogFrame, error_message, "Internet JunkBuster Error", 
199       MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);  
200
201    /* Cleanup - remove taskbar icon etc. */
202    TermLogWindow();
203
204 #else /* if !defined(_WIN32) || defined(_WIN_CONSOLE) */
205    fputs(error_message, stderr);
206 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
207
208    exit(1);
209 }
210
211
212 /*********************************************************************
213  *
214  * Function    :  init_errlog
215  *
216  * Description :  Initializes the logging module.  Must call before
217  *                calling log_error.
218  *
219  * Parameters  :
220  *          1  :  prog_name  = The program name.
221  *          2  :  logfname   = The logfile name, or NULL for stderr.
222  *          3  :  debuglevel = The debugging level.
223  *
224  * Returns     :  N/A
225  *
226  *********************************************************************/
227 void init_error_log(const char *prog_name, const char *logfname, int debuglevel)
228 {
229    FILE *fp;
230
231    /* FIXME RACE HAZARD: should start critical section error_log_use here */
232
233    /* set the logging detail level */
234    debug = debuglevel | LOG_LEVEL_MINIMUM;
235
236    if ((logfp != NULL) && (logfp != stderr))
237    {
238       fclose(logfp);
239    }
240    logfp = stderr;
241
242    /* set the designated log file */
243    if( logfname )
244    {
245       if( !(fp = fopen(logfname, "a")) )
246       {
247          log_error(LOG_LEVEL_FATAL, "init_errlog(): can't open logfile: %s", logfname);
248       }
249
250       /* set logging to be completely unbuffered */
251       setbuf(fp, NULL);
252
253       logfp = fp;
254    }
255
256    log_error(LOG_LEVEL_INFO, "Internet JunkBuster version " VERSION);
257    if (prog_name != NULL)
258    {
259       log_error(LOG_LEVEL_INFO, "Program name: %s", prog_name);
260    }
261
262    /* FIXME RACE HAZARD: should end critical section error_log_use here */
263
264 } /* init_error_log */
265
266
267 /*********************************************************************
268  *
269  * Function    :  log_error
270  *
271  * Description :  This is the error-reporting and logging function.
272  *
273  * Parameters  :
274  *          1  :  loglevel  = the type of message to be logged
275  *          2  :  fmt       = the main string we want logged, printf-like
276  *          3  :  ...       = arguments to be inserted in fmt (printf-like).
277  *
278  * Returns     :  N/A
279  *
280  *********************************************************************/
281 void log_error(int loglevel, char *fmt, ...)
282 {
283    va_list ap;
284    char outbuf[BUFFER_SIZE];
285    char * src = fmt;
286    int outc = 0;
287    long this_thread = 1;  /* was: pthread_t this_thread;*/
288
289 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
290    /*
291     * Irrespective of debug setting, a GET/POST/CONNECT makes
292     * the taskbar icon animate.  (There is an option to disable
293     * this but checking that is handled inside LogShowActivity()).
294     */
295    if (loglevel == LOG_LEVEL_GPC)
296    {
297       LogShowActivity();
298    }
299 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
300
301    /* verify if loglevel applies to current settings and bail out if negative */
302    if ((loglevel & debug) == 0)
303    {
304       return;
305    }
306
307    /* FIXME get current thread id */
308 #ifdef FEATURE_PTHREAD
309    this_thread = (long)pthread_self();
310 #endif /* def FEATURE_PTHREAD */
311
312    switch (loglevel)
313    {
314       case LOG_LEVEL_ERROR:
315          outc = sprintf(outbuf, "IJB(%d) Error: ", this_thread);
316          break;
317       case LOG_LEVEL_FATAL:
318          outc = sprintf(outbuf, "IJB(%d) Fatal error: ", this_thread);
319          break;
320       case LOG_LEVEL_GPC:
321          outc = sprintf(outbuf, "IJB(%d) Request: ", this_thread);
322          break;
323       case LOG_LEVEL_CONNECT:
324          outc = sprintf(outbuf, "IJB(%d) Connect: ", this_thread);
325          break;
326       case LOG_LEVEL_LOG:
327          outc = sprintf(outbuf, "IJB(%d) Writing: ", this_thread);
328          break;
329       case LOG_LEVEL_HEADER:
330          outc = sprintf(outbuf, "IJB(%d) Header: ", this_thread);
331          break;
332       case LOG_LEVEL_INFO:
333          outc = sprintf(outbuf, "IJB(%d) Info: ", this_thread);
334          break;
335       case LOG_LEVEL_RE_FILTER:
336          outc = sprintf(outbuf, "IJB(%d) Re-Filter: ", this_thread);
337          break;
338 #ifdef FEATURE_FORCE_LOAD
339       case LOG_LEVEL_FORCE:
340          outc = sprintf(outbuf, "IJB(%d) Force: ", this_thread);
341          break;
342 #endif /* def FEATURE_FORCE_LOAD */
343 #ifdef FEATURE_FAST_REDIRECTS
344       case LOG_LEVEL_REDIRECTS:
345          outc = sprintf(outbuf, "IJB(%d) Redirect: ", this_thread);
346          break;
347 #endif /* def FEATURE_FAST_REDIRECTS */
348       case LOG_LEVEL_DEANIMATE:
349          outc = sprintf(outbuf, "IJB(%d) Gif-Deanimate: ", this_thread);
350          break;
351       case LOG_LEVEL_CLF:
352          outc = 0;
353          outbuf[0] = '\0';
354          break;
355 #ifdef FEATURE_KILL_POPUPS
356       case LOG_LEVEL_POPUPS:
357          outc = sprintf(outbuf, "IJB(%d) Kill-Popups: ", this_thread);
358          break;
359 #endif /* def FEATURE_KILL_POPUPS */
360       default:
361          outc = sprintf(outbuf, "IJB(%d) UNKNOWN LOG TYPE(%d): ", this_thread, loglevel);
362          break;
363    }
364    
365    /* get ready to scan var. args. */
366    va_start( ap, fmt );
367
368    /* build formatted message from fmt and var-args */
369    while ((*src) && (outc < BUFFER_SIZE-2))
370    {
371       char tempbuf[BUFFER_SIZE];
372       char *sval;
373       int ival;
374       unsigned uval;
375       long lval;
376       unsigned long ulval;
377       int oldoutc;
378       char ch;
379       
380       ch = *src++;
381       if( ch != '%' )
382       {
383          outbuf[outc++] = ch;
384          continue;
385       }
386
387       ch = *src++;
388       switch (ch) {
389          case '%':
390             outbuf[outc++] = '%';
391             break;
392          case 'd':
393             ival = va_arg( ap, int );
394             oldoutc = outc;
395             outc += sprintf(tempbuf, "%d", ival);
396             if (outc < BUFFER_SIZE-1) 
397             {
398                strcpy(outbuf + oldoutc, tempbuf);
399             }
400             else
401             {
402                outbuf[oldoutc] = '\0';
403             }
404             break;
405          case 'u':
406             uval = va_arg( ap, unsigned );
407             oldoutc = outc;
408             outc += sprintf(tempbuf, "%u", uval);
409             if (outc < BUFFER_SIZE-1) 
410             {
411                strcpy(outbuf + oldoutc, tempbuf);
412             }
413             else
414             {
415                outbuf[oldoutc] = '\0';
416             }
417             break;
418          case 'l':
419             /* this is a modifier that must be followed by u or d */
420             ch = *src++;
421             if (ch == 'd')
422             {
423                lval = va_arg( ap, long );
424                oldoutc = outc;
425                outc += sprintf(tempbuf, "%ld", lval);
426             }
427             else if (ch == 'u')
428             {
429                ulval = va_arg( ap, unsigned long );
430                oldoutc = outc;
431                outc += sprintf(tempbuf, "%lu", ulval);
432             }
433             else
434             {
435                /* Error */
436                sprintf(outbuf, "IJB(%d) Error: log_error(): Bad format string:\n"
437                                "Format = \"%s\"\n"
438                                "Exiting.", this_thread, fmt);
439                /* FIXME RACE HAZARD: should start critical section error_log_use here */
440                if( !logfp )
441                {
442                   logfp = stderr;
443                }
444                fputs(outbuf, logfp);
445                /* FIXME RACE HAZARD: should end critical section error_log_use here */
446                fatal_error(outbuf);
447                /* Never get here */
448                break;
449             }
450             if (outc < BUFFER_SIZE-1) 
451             {
452                strcpy(outbuf + oldoutc, tempbuf);
453             }
454             else
455             {
456                outbuf[oldoutc] = '\0';
457             }
458             break;
459          case 'c':
460             /*
461              * Note that char paramaters are converted to int, so we need to
462              * pass "int" to va_arg.  (See K&R, 2nd ed, section A7.3.2, page 202)
463              */
464             outbuf[outc++] = (char) va_arg( ap, int );
465             break;
466          case 's':
467             sval = va_arg( ap, char * );
468             oldoutc = outc;
469             outc += strlen(sval);
470             if (outc < BUFFER_SIZE-1) 
471             {
472                strcpy(outbuf + oldoutc, sval);
473             }
474             else
475             {
476                outbuf[oldoutc] = '\0';
477             }
478             break;
479          case 'N':
480             /* Non-standard: Print a counted string.  Takes 2 parameters:
481              * int length, const char * string
482              */
483             ival = va_arg( ap, int );
484             sval = va_arg( ap, char * );
485             if (ival < 0)
486             {
487                ival = 0;
488             }
489             oldoutc = outc;
490             outc += ival;
491             if (outc < BUFFER_SIZE-1)
492             {
493                memcpy(outbuf + oldoutc, sval, ival);
494             }
495             else
496             {
497                outbuf[oldoutc] = '\0';
498             }
499             break;
500          case 'E':
501             /* Non-standard: Print error code from errno */
502 #ifdef _WIN32
503             ival = WSAGetLastError();
504             sval = w32_socket_strerr(ival, tempbuf);
505 #else /* ifndef _WIN32 */
506             ival = errno; 
507 #ifdef HAVE_STRERROR
508             sval = strerror(ival);
509 #else /* ifndef HAVE_STRERROR */
510             sval = NULL;
511 #endif /* ndef HAVE_STRERROR */
512             if (sval == NULL)
513             {
514                sprintf(tempbuf, "(errno = %d)", ival);
515                sval = tempbuf;
516             }
517 #endif /* ndef _WIN32 */
518             oldoutc = outc;
519             outc += strlen(sval);
520             if (outc < BUFFER_SIZE-1) 
521             {
522                strcpy(outbuf + oldoutc, sval);
523             }
524             else
525             {
526                outbuf[oldoutc] = '\0';
527             }
528             break;
529          case 'T':
530             /* Non-standard: Print a Common Log File timestamp */
531             {
532                /*
533                 * Write timestamp into tempbuf.
534                 *
535                 * Complex because not all OSs have tm_gmtoff or
536                 * the %z field in strftime()
537                 */
538                time_t now; 
539                struct tm *tm_now; 
540                struct tm gmt; 
541                int days, hrs, mins; 
542                time (&now); 
543                gmt = *gmtime (&now); 
544                tm_now = localtime (&now); 
545                days = tm_now->tm_yday - gmt.tm_yday; 
546                hrs = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + tm_now->tm_hour - gmt.tm_hour); 
547                mins = hrs * 60 + tm_now->tm_min - gmt.tm_min; 
548                strftime (tempbuf, BUFFER_SIZE-6, "%d/%b/%Y:%H:%M:%S ", tm_now); 
549                sprintf (tempbuf + strlen(tempbuf), "%+03d%02d", mins / 60, abs(mins) % 60); 
550             }
551             oldoutc = outc;
552             outc += strlen(tempbuf);
553             if (outc < BUFFER_SIZE-1) 
554             {
555                strcpy(outbuf + oldoutc, tempbuf);
556             }
557             else
558             {
559                outbuf[oldoutc] = '\0';
560             }
561             break;
562          default:
563             sprintf(outbuf, "IJB(%d) Error: log_error(): Bad format string:\n"
564                             "Format = \"%s\"\n"
565                             "Exiting.", this_thread, fmt);
566             /* FIXME RACE HAZARD: should start critical section error_log_use here */
567             if( !logfp )
568             {
569                logfp = stderr;
570             }
571             fputs(outbuf, logfp);
572             /* FIXME RACE HAZARD: should end critical section error_log_use here */
573             fatal_error(outbuf);
574             /* Never get here */
575             break;
576
577       } /* switch( p ) */
578
579    } /* for( p ... ) */
580    
581    /* done with var. args */
582    va_end( ap );
583    
584    if (outc >= BUFFER_SIZE-2)
585    {
586       /* insufficient room for newline and trailing null. */
587
588       static const char warning[] = "... [too long, truncated]\n";
589
590       if (outc < BUFFER_SIZE)
591       {
592          /* Need to add terminating null in this case. */
593          outbuf[outc] = '\0';
594       }
595
596       /* Truncate output */
597       outbuf[BUFFER_SIZE - sizeof(warning)] = '\0';
598
599       /* Append warning */
600       strcat(outbuf, warning);
601    }
602    else
603    {
604       /* Add terminating newline and null */
605       outbuf[outc++] = '\n';
606       outbuf[outc] = '\0';
607    }
608
609    /* FIXME RACE HAZARD: should start critical section error_log_use here */
610
611    /* deal with glibc stupidity - it won't let you initialize logfp */
612    if( !logfp )
613    {
614       logfp = stderr;
615    }
616
617    fputs(outbuf, logfp);
618
619    if (loglevel == LOG_LEVEL_FATAL)
620    {
621       fatal_error(outbuf);
622       /* Never get here */
623    }
624
625    /* FIXME RACE HAZARD: should end critical section error_log_use here */
626
627 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
628    /* Write to display */
629    LogPutString(outbuf);
630 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
631
632 }
633
634
635 #ifdef _WIN32
636 /*********************************************************************
637  *
638  * Function    :  w32_socket_strerr
639  *
640  * Description :  Translate the return value from WSAGetLastError()
641  *                into a string.
642  *
643  * Parameters  :
644  *          1  :  errcode = The return value from WSAGetLastError().
645  *          2  :  tmp_buf = A temporary buffer that might be used to
646  *                          store the string.
647  *
648  * Returns     :  String representing the error code.  This may be
649  *                a global string constant or a string stored in
650  *                tmp_buf.
651  *
652  *********************************************************************/
653 static char * w32_socket_strerr(int errcode, char * tmp_buf)
654 {
655 #define TEXT_FOR_ERROR(code,text) \
656    if (errcode == code)           \
657    {                              \
658       return #code " - " text;    \
659    }
660
661    TEXT_FOR_ERROR(WSAEACCES, "Permission denied")
662    TEXT_FOR_ERROR(WSAEADDRINUSE, "Address already in use.")
663    TEXT_FOR_ERROR(WSAEADDRNOTAVAIL, "Cannot assign requested address.");
664    TEXT_FOR_ERROR(WSAEAFNOSUPPORT, "Address family not supported by protocol family.");
665    TEXT_FOR_ERROR(WSAEALREADY, "Operation already in progress.");
666    TEXT_FOR_ERROR(WSAECONNABORTED, "Software caused connection abort.");
667    TEXT_FOR_ERROR(WSAECONNREFUSED, "Connection refused.");
668    TEXT_FOR_ERROR(WSAECONNRESET, "Connection reset by peer.");
669    TEXT_FOR_ERROR(WSAEDESTADDRREQ, "Destination address required.");
670    TEXT_FOR_ERROR(WSAEFAULT, "Bad address.");
671    TEXT_FOR_ERROR(WSAEHOSTDOWN, "Host is down.");
672    TEXT_FOR_ERROR(WSAEHOSTUNREACH, "No route to host.");
673    TEXT_FOR_ERROR(WSAEINPROGRESS, "Operation now in progress.");
674    TEXT_FOR_ERROR(WSAEINTR, "Interrupted function call.");
675    TEXT_FOR_ERROR(WSAEINVAL, "Invalid argument.");
676    TEXT_FOR_ERROR(WSAEISCONN, "Socket is already connected.");
677    TEXT_FOR_ERROR(WSAEMFILE, "Too many open sockets.");
678    TEXT_FOR_ERROR(WSAEMSGSIZE, "Message too long.");
679    TEXT_FOR_ERROR(WSAENETDOWN, "Network is down.");
680    TEXT_FOR_ERROR(WSAENETRESET, "Network dropped connection on reset.");
681    TEXT_FOR_ERROR(WSAENETUNREACH, "Network is unreachable.");
682    TEXT_FOR_ERROR(WSAENOBUFS, "No buffer space available.");
683    TEXT_FOR_ERROR(WSAENOPROTOOPT, "Bad protocol option.");
684    TEXT_FOR_ERROR(WSAENOTCONN, "Socket is not connected.");
685    TEXT_FOR_ERROR(WSAENOTSOCK, "Socket operation on non-socket.");
686    TEXT_FOR_ERROR(WSAEOPNOTSUPP, "Operation not supported.");
687    TEXT_FOR_ERROR(WSAEPFNOSUPPORT, "Protocol family not supported.");
688    TEXT_FOR_ERROR(WSAEPROCLIM, "Too many processes.");
689    TEXT_FOR_ERROR(WSAEPROTONOSUPPORT, "Protocol not supported.");
690    TEXT_FOR_ERROR(WSAEPROTOTYPE, "Protocol wrong type for socket.");
691    TEXT_FOR_ERROR(WSAESHUTDOWN, "Cannot send after socket shutdown.");
692    TEXT_FOR_ERROR(WSAESOCKTNOSUPPORT, "Socket type not supported.");
693    TEXT_FOR_ERROR(WSAETIMEDOUT, "Connection timed out.");
694    TEXT_FOR_ERROR(WSAEWOULDBLOCK, "Resource temporarily unavailable.");
695    TEXT_FOR_ERROR(WSAHOST_NOT_FOUND, "Host not found.");
696    TEXT_FOR_ERROR(WSANOTINITIALISED, "Successful WSAStartup not yet performed.");
697    TEXT_FOR_ERROR(WSANO_DATA, "Valid name, no data record of requested type.");
698    TEXT_FOR_ERROR(WSANO_RECOVERY, "This is a non-recoverable error.");
699    TEXT_FOR_ERROR(WSASYSNOTREADY, "Network subsystem is unavailable.");
700    TEXT_FOR_ERROR(WSATRY_AGAIN, "Non-authoritative host not found.");
701    TEXT_FOR_ERROR(WSAVERNOTSUPPORTED, "WINSOCK.DLL version out of range.");
702    TEXT_FOR_ERROR(WSAEDISCON, "Graceful shutdown in progress.");
703    /*
704     * The following error codes are documented in the Microsoft WinSock
705     * reference guide, but don't actually exist.
706     *
707     * TEXT_FOR_ERROR(WSA_INVALID_HANDLE, "Specified event object handle is invalid.");
708     * TEXT_FOR_ERROR(WSA_INVALID_PARAMETER, "One or more parameters are invalid.");
709     * TEXT_FOR_ERROR(WSAINVALIDPROCTABLE, "Invalid procedure table from service provider.");
710     * TEXT_FOR_ERROR(WSAINVALIDPROVIDER, "Invalid service provider version number.");
711     * TEXT_FOR_ERROR(WSA_IO_PENDING, "Overlapped operations will complete later.");
712     * TEXT_FOR_ERROR(WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state.");
713     * TEXT_FOR_ERROR(WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available.");
714     * TEXT_FOR_ERROR(WSAPROVIDERFAILEDINIT, "Unable to initialize a service provider.");
715     * TEXT_FOR_ERROR(WSASYSCALLFAILURE, "System call failure.");
716     * TEXT_FOR_ERROR(WSA_OPERATION_ABORTED, "Overlapped operation aborted.");
717     */
718
719    sprintf(tmp_buf, "(error number %d)", errcode);
720    return tmp_buf;
721 }
722 #endif /* def _WIN32 */
723
724
725 /*
726   Local Variables:
727   tab-width: 3
728   end:
729 */
730