Fix a comment typo.
[privoxy.git] / errlog.c
1 const char errlog_rcs[] = "$Id: errlog.c,v 1.71 2008/06/28 17:17:15 fabiankeil 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-2007 the SourceForge
10  *                Privoxy team. http://www.privoxy.org/
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.71  2008/06/28 17:17:15  fabiankeil
37  *    Remove another stray semicolon.
38  *
39  *    Revision 1.70  2008/06/28 17:10:29  fabiankeil
40  *    Remove stray semicolon in get_log_timestamp().
41  *    Reported by Jochen Voss in #2005221.
42  *
43  *    Revision 1.69  2008/05/30 15:55:25  fabiankeil
44  *    Declare variable "debug" static and complain about its name.
45  *
46  *    Revision 1.68  2008/04/27 16:50:46  fabiankeil
47  *    Remove an incorrect assertion. The value of debug may change if
48  *    the configuration is reloaded in another thread. While we could
49  *    cache the initial value, the assertion doesn't seem worth it.
50  *
51  *    Revision 1.67  2008/03/27 18:27:23  fabiankeil
52  *    Remove kill-popups action.
53  *
54  *    Revision 1.66  2008/01/31 15:38:14  fabiankeil
55  *    - Make the logfp assertion more strict. As of 1.63, the "||" could
56  *      have been an "&&", which means we can use two separate assertions
57  *      and skip on of them on Windows.
58  *    - Break a long commit message line in two.
59  *
60  *    Revision 1.65  2008/01/31 14:44:33  fabiankeil
61  *    Use (a != b) instead of !(a == b) so the sanity check looks less insane.
62  *
63  *    Revision 1.64  2008/01/21 18:56:46  david__schmidt
64  *    Swap #def from negative to positive, re-joined it so it didn't
65  *    span an assertion (compilation failure on OS/2)
66  *
67  *    Revision 1.63  2007/12/15 19:49:32  fabiankeil
68  *    Stop overloading logfile to control the mingw32 log window as well.
69  *    It's no longer necessary now that we disable all debug lines by default
70  *    and at least one user perceived it as a regression (added in 1.55).
71  *
72  *    Revision 1.62  2007/11/30 15:33:46  fabiankeil
73  *    Unbreak LOG_LEVEL_FATAL. It wasn't fatal with logging disabled
74  *    and on mingw32 fatal log messages didn't end up in the log file.
75  *
76  *    Revision 1.61  2007/11/04 19:03:01  fabiankeil
77  *    Fix another deadlock Hal spotted and that mysteriously didn't affect FreeBSD.
78  *
79  *    Revision 1.60  2007/11/03 19:03:31  fabiankeil
80  *    - Prevent the Windows GUI from showing the version two times in a row.
81  *    - Stop using the imperative in the "(Re-)Open logfile" message.
82  *    - Ditch the "Switching to daemon mode" message as the detection
83  *      whether or not we're already in daemon mode doesn't actually work.
84  *
85  *    Revision 1.59  2007/11/01 12:50:56  fabiankeil
86  *    Here's looking at you, deadlock.
87  *
88  *    Revision 1.58  2007/10/28 19:04:21  fabiankeil
89  *    Don't mention daemon mode in "Logging disabled" message. Some
90  *    platforms call it differently and it's not really relevant anyway.
91  *
92  *    Revision 1.57  2007/10/27 13:02:26  fabiankeil
93  *    Relocate daemon-mode-related log messages to make sure
94  *    they aren't shown again in case of configuration reloads.
95  *
96  *    Revision 1.56  2007/10/14 14:26:56  fabiankeil
97  *    Remove the old log_error() version.
98  *
99  *    Revision 1.55  2007/10/14 14:12:41  fabiankeil
100  *    When in daemon mode, close stderr after the configuration file has been
101  *    parsed the first time. If logfile isn't set, stop logging. Fixes BR#897436.
102  *
103  *    Revision 1.54  2007/09/22 16:15:34  fabiankeil
104  *    - Let it compile with pcc.
105  *    - Move our includes below system includes to prevent macro conflicts.
106  *
107  *    Revision 1.53  2007/08/05 13:53:14  fabiankeil
108  *    #1763173 from Stefan Huehner: declare some more functions
109  *    static and use void instead of empty parameter lists.
110  *
111  *    Revision 1.52  2007/07/14 07:28:47  fabiankeil
112  *    Add translation function for JB_ERR_FOO codes.
113  *
114  *    Revision 1.51  2007/05/11 11:51:34  fabiankeil
115  *    Fix a type mismatch warning.
116  *
117  *    Revision 1.50  2007/04/11 10:55:44  fabiankeil
118  *    Enforce some assertions that could be triggered
119  *    on mingw32 and other systems where we use threads
120  *    but no locks.
121  *
122  *    Revision 1.49  2007/04/08 16:44:15  fabiankeil
123  *    We need <sys/time.h> for gettimeofday(), not <time.h>.
124  *
125  *    Revision 1.48  2007/03/31 13:33:28  fabiankeil
126  *    Add alternative log_error() with timestamps
127  *    that contain milliseconds and without using
128  *    strcpy(), strcat() or sprintf().
129  *
130  *    Revision 1.47  2006/11/28 15:25:15  fabiankeil
131  *    Only unlink the pidfile if it's actually used.
132  *
133  *    Revision 1.46  2006/11/13 19:05:51  fabiankeil
134  *    Make pthread mutex locking more generic. Instead of
135  *    checking for OSX and OpenBSD, check for FEATURE_PTHREAD
136  *    and use mutex locking unless there is an _r function
137  *    available. Better safe than sorry.
138  *
139  *    Fixes "./configure --disable-pthread" and should result
140  *    in less threading-related problems on pthread-using platforms,
141  *    but it still doesn't fix BR#1122404.
142  *
143  *    Revision 1.45  2006/08/21 11:15:54  david__schmidt
144  *    MS Visual C++ build updates
145  *
146  *    Revision 1.44  2006/08/18 16:03:16  david__schmidt
147  *    Tweak for OS/2 build happiness.
148  *
149  *    Revision 1.43  2006/08/03 02:46:41  david__schmidt
150  *    Incorporate Fabian Keil's patch work:
151  *    http://www.fabiankeil.de/sourcecode/privoxy/
152  *
153  *    Revision 1.42  2006/07/18 14:48:46  david__schmidt
154  *    Reorganizing the repository: swapping out what was HEAD (the old 3.1 branch)
155  *    with what was really the latest development (the v_3_0_branch branch)
156  *
157  *    Revision 1.40.2.4  2005/04/03 20:10:50  david__schmidt
158  *    Thanks to Jindrich Makovicka for a race condition fix for the log
159  *    file.  The race condition remains for non-pthread implementations.
160  *    Reference patch #1175720.
161  *
162  *    Revision 1.40.2.3  2003/03/07 03:41:04  david__schmidt
163  *    Wrapping all *_r functions (the non-_r versions of them) with mutex 
164  *    semaphores for OSX.  Hopefully this will take care of all of those pesky
165  *    crash reports.
166  *
167  *    Revision 1.40.2.2  2002/09/28 00:30:57  david__schmidt
168  *    Update error logging to give sane values for thread IDs on Mach kernels.
169  *    It's still a hack, but at least it looks farily normal.  We print the
170  *    absolute value of the first 4 bytes of the pthread_t modded with 1000.
171  *
172  *    Revision 1.40.2.1  2002/09/25 12:47:42  oes
173  *    Make log_error safe against NULL string arguments
174  *
175  *    Revision 1.40  2002/05/22 01:27:27  david__schmidt
176  *
177  *    Add os2_socket_strerr mirroring w32_socket_strerr.
178  *
179  *    Revision 1.39  2002/04/03 17:15:27  gliptak
180  *    zero padding thread ids in log
181  *
182  *    Revision 1.38  2002/03/31 17:18:59  jongfoster
183  *    Win32 only: Enabling STRICT to fix a VC++ compile warning.
184  *
185  *    Revision 1.37  2002/03/27 14:32:43  david__schmidt
186  *    More compiler warning message maintenance
187  *
188  *    Revision 1.36  2002/03/26 22:29:54  swa
189  *    we have a new homepage!
190  *
191  *    Revision 1.35  2002/03/24 15:23:33  jongfoster
192  *    Name changes
193  *
194  *    Revision 1.34  2002/03/24 13:25:43  swa
195  *    name change related issues
196  *
197  *    Revision 1.33  2002/03/13 00:27:04  jongfoster
198  *    Killing warnings
199  *
200  *    Revision 1.32  2002/03/07 03:46:17  oes
201  *    Fixed compiler warnings
202  *
203  *    Revision 1.31  2002/03/06 23:02:57  jongfoster
204  *    Removing tabs
205  *
206  *    Revision 1.30  2002/03/05 22:43:45  david__schmidt
207  *    - Better error reporting on OS/2
208  *    - Fix double-slash comment (oops)
209  *
210  *    Revision 1.29  2002/03/04 23:45:13  jongfoster
211  *    Printing thread ID if using Win32 native threads
212  *
213  *    Revision 1.28  2002/03/04 17:59:59  oes
214  *    Deleted deletePidFile(), cosmetics
215  *
216  *    Revision 1.27  2002/03/04 02:08:01  david__schmidt
217  *    Enable web editing of actions file on OS/2 (it had been broken all this time!)
218  *
219  *    Revision 1.26  2002/01/09 19:05:45  steudten
220  *    Fix big memory leak.
221  *
222  *    Revision 1.25  2002/01/09 14:32:08  oes
223  *    Added support for gmtime_r and localtime_r.
224  *
225  *    Revision 1.24  2001/12/30 14:07:32  steudten
226  *    - Add signal handling (unix)
227  *    - Add SIGHUP handler (unix)
228  *    - Add creation of pidfile (unix)
229  *    - Add action 'top' in rc file (RH)
230  *    - Add entry 'SIGNALS' to manpage
231  *    - Add exit message to logfile (unix)
232  *
233  *    Revision 1.23  2001/11/07 00:02:13  steudten
234  *    Add line number in error output for lineparsing for
235  *    actionsfile and configfile.
236  *    Special handling for CLF added.
237  *
238  *    Revision 1.22  2001/11/05 23:43:05  steudten
239  *    Add time+date to log files.
240  *
241  *    Revision 1.21  2001/10/25 03:40:47  david__schmidt
242  *    Change in porting tactics: OS/2's EMX porting layer doesn't allow multiple
243  *    threads to call select() simultaneously.  So, it's time to do a real, live,
244  *    native OS/2 port.  See defines for __EMX__ (the porting layer) vs. __OS2__
245  *    (native). Both versions will work, but using __OS2__ offers multi-threading.
246  *
247  *    Revision 1.20  2001/09/16 23:04:34  jongfoster
248  *    Fixing a warning
249  *
250  *    Revision 1.19  2001/09/13 20:08:06  jongfoster
251  *    Adding support for LOG_LEVEL_CGI
252  *
253  *    Revision 1.18  2001/09/10 11:27:24  oes
254  *    Declaration of w32_socket_strerr now conditional
255  *
256  *    Revision 1.17  2001/09/10 10:17:13  oes
257  *    Removed unused variable; Fixed sprintf format
258  *
259  *    Revision 1.16  2001/07/30 22:08:36  jongfoster
260  *    Tidying up #defines:
261  *    - All feature #defines are now of the form FEATURE_xxx
262  *    - Permanently turned off WIN_GUI_EDIT
263  *    - Permanently turned on WEBDAV and SPLIT_PROXY_ARGS
264  *
265  *    Revision 1.15  2001/07/29 17:41:10  jongfoster
266  *    Now prints thread ID for each message (pthreads only)
267  *
268  *    Revision 1.14  2001/07/19 19:03:48  haroon
269  *    - Added case for LOG_LEVEL_POPUPS
270  *
271  *    Revision 1.13  2001/07/13 13:58:58  oes
272  *     - Added case for LOG_LEVEL_DEANIMATE
273  *     - Removed all #ifdef PCRS
274  *
275  *    Revision 1.12  2001/06/09 10:55:28  jongfoster
276  *    Changing BUFSIZ ==> BUFFER_SIZE
277  *
278  *    Revision 1.11  2001/06/01 18:14:49  jongfoster
279  *    Changing the calls to strerr() to check HAVE_STRERR (which is defined
280  *    in config.h if appropriate) rather than the NO_STRERR macro.
281  *
282  *    Revision 1.10  2001/05/29 11:52:21  oes
283  *    Conditional compilation of w32_socket_error
284  *
285  *    Revision 1.9  2001/05/28 16:15:17  jongfoster
286  *    Improved reporting of errors under Win32.
287  *
288  *    Revision 1.8  2001/05/26 17:25:14  jongfoster
289  *    Added support for CLF (Common Log Format) and fixed LOG_LEVEL_LOG
290  *
291  *    Revision 1.7  2001/05/26 15:21:28  jongfoster
292  *    Activity animation in Win32 GUI now works even if debug==0
293  *
294  *    Revision 1.6  2001/05/25 21:55:08  jongfoster
295  *    Now cleans up properly on FATAL (removes taskbar icon etc)
296  *
297  *    Revision 1.5  2001/05/22 18:46:04  oes
298  *
299  *    - Enabled filtering banners by size rather than URL
300  *      by adding patterns that replace all standard banner
301  *      sizes with the "Junkbuster" gif to the re_filterfile
302  *
303  *    - Enabled filtering WebBugs by providing a pattern
304  *      which kills all 1x1 images
305  *
306  *    - Added support for PCRE_UNGREEDY behaviour to pcrs,
307  *      which is selected by the (nonstandard and therefore
308  *      capital) letter 'U' in the option string.
309  *      It causes the quantifiers to be ungreedy by default.
310  *      Appending a ? turns back to greedy (!).
311  *
312  *    - Added a new interceptor ijb-send-banner, which
313  *      sends back the "Junkbuster" gif. Without imagelist or
314  *      MSIE detection support, or if tinygif = 1, or the
315  *      URL isn't recognized as an imageurl, a lame HTML
316  *      explanation is sent instead.
317  *
318  *    - Added new feature, which permits blocking remote
319  *      script redirects and firing back a local redirect
320  *      to the browser.
321  *      The feature is conditionally compiled, i.e. it
322  *      can be disabled with --disable-fast-redirects,
323  *      plus it must be activated by a "fast-redirects"
324  *      line in the config file, has its own log level
325  *      and of course wants to be displayed by show-proxy-args
326  *      Note: Boy, all the #ifdefs in 1001 locations and
327  *      all the fumbling with configure.in and acconfig.h
328  *      were *way* more work than the feature itself :-(
329  *
330  *    - Because a generic redirect template was needed for
331  *      this, tinygif = 3 now uses the same.
332  *
333  *    - Moved GIFs, and other static HTTP response templates
334  *      to project.h
335  *
336  *    - Some minor fixes
337  *
338  *    - Removed some >400 CRs again (Jon, you really worked
339  *      a lot! ;-)
340  *
341  *    Revision 1.4  2001/05/21 19:32:54  jongfoster
342  *    Added another #ifdef _WIN_CONSOLE
343  *
344  *    Revision 1.3  2001/05/20 01:11:40  jongfoster
345  *    Added support for LOG_LEVEL_FATAL
346  *    Renamed LOG_LEVEL_FRC to LOG_LEVEL_FORCE,
347  *    and LOG_LEVEL_REF to LOG_LEVEL_RE_FILTER
348  *
349  *    Revision 1.2  2001/05/17 22:42:01  oes
350  *     - Cleaned CRLF's from the sources and related files
351  *     - Repaired logging for REF and FRC
352  *
353  *    Revision 1.1.1.1  2001/05/15 13:58:51  oes
354  *    Initial import of version 2.9.3 source tree
355  *
356  *
357  *********************************************************************/
358 \f
359
360 #include <stdlib.h>
361 #include <stdio.h>
362 #include <stdarg.h>
363 #include <string.h>
364
365 #include "config.h"
366 #include "miscutil.h"
367
368 /* For gettimeofday() */
369 #include <sys/time.h>
370
371 #if !defined(_WIN32) && !defined(__OS2__)
372 #include <unistd.h>
373 #endif /* !defined(_WIN32) && !defined(__OS2__) */
374
375 #include <errno.h>
376 #include <assert.h>
377
378 #ifdef _WIN32
379 #ifndef STRICT
380 #define STRICT
381 #endif
382 #include <windows.h>
383 #ifndef _WIN_CONSOLE
384 #include "w32log.h"
385 #endif /* ndef _WIN_CONSOLE */
386 #endif /* def _WIN32 */
387 #ifdef _MSC_VER
388 #define inline __inline
389 #endif /* def _MSC_VER */
390
391 #ifdef __OS2__
392 #include <sys/socket.h> /* For sock_errno */
393 #define INCL_DOS
394 #include <os2.h>
395 #endif
396
397 #include "errlog.h"
398 #include "project.h"
399 #include "jcc.h"
400
401 const char errlog_h_rcs[] = ERRLOG_H_VERSION;
402
403
404 /*
405  * LOG_LEVEL_FATAL cannot be turned off.  (There are
406  * some exceptional situations where we need to get a
407  * message to the user).
408  */
409 #define LOG_LEVEL_MINIMUM  LOG_LEVEL_FATAL
410
411 /* where to log (default: stderr) */
412 static FILE *logfp = NULL;
413
414 /* logging detail level. XXX: stupid name. */
415 static int debug = (LOG_LEVEL_FATAL | LOG_LEVEL_ERROR | LOG_LEVEL_INFO);  
416
417 /* static functions */
418 static void fatal_error(const char * error_message);
419 #ifdef _WIN32
420 static char *w32_socket_strerr(int errcode, char *tmp_buf);
421 #endif
422 #ifdef __OS2__
423 static char *os2_socket_strerr(int errcode, char *tmp_buf);
424 #endif
425
426 #ifdef FEATURE_PTHREAD
427 static inline void lock_logfile(void)
428 {
429    pthread_mutex_lock(&log_mutex);
430 }
431 static inline void unlock_logfile(void)
432 {
433    pthread_mutex_unlock(&log_mutex);
434 }
435 static inline void lock_loginit(void)
436 {
437    pthread_mutex_lock(&log_init_mutex);
438 }
439 static inline void unlock_loginit(void)
440 {
441    pthread_mutex_unlock(&log_init_mutex);
442 }
443 #else /* ! FEATURE_PTHREAD */
444 /*
445  * FIXME we need a cross-platform locking mechanism.
446  * The locking/unlocking functions below should be 
447  * fleshed out for non-pthread implementations.
448  */ 
449 static inline void lock_logfile() {}
450 static inline void unlock_logfile() {}
451 static inline void lock_loginit() {}
452 static inline void unlock_loginit() {}
453 #endif
454
455 /*********************************************************************
456  *
457  * Function    :  fatal_error
458  *
459  * Description :  Displays a fatal error to standard error (or, on 
460  *                a WIN32 GUI, to a dialog box), and exits
461  *                JunkBuster with status code 1.
462  *
463  * Parameters  :
464  *          1  :  error_message = The error message to display.
465  *
466  * Returns     :  Does not return.
467  *
468  *********************************************************************/
469 static void fatal_error(const char * error_message)
470 {
471 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
472    MessageBox(g_hwndLogFrame, error_message, "Privoxy Error", 
473       MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);  
474
475    /* Cleanup - remove taskbar icon etc. */
476    TermLogWindow();
477 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
478
479    if (logfp != NULL)
480    {
481       fputs(error_message, logfp);
482    }
483
484 #if defined(unix)
485    if (pidfile)
486    {
487       unlink(pidfile);
488    }
489 #endif /* unix */
490
491    exit(1);
492 }
493
494
495 /*********************************************************************
496  *
497  * Function    :  show_version
498  *
499  * Description :  Logs the Privoxy version and the program name.
500  *
501  * Parameters  :
502  *          1  :  prog_name = The program name.
503  *
504  * Returns     :  Nothing.
505  *
506  *********************************************************************/
507 static void show_version(const char *prog_name)
508 {
509    log_error(LOG_LEVEL_INFO, "Privoxy version " VERSION);
510    if (prog_name != NULL)
511    {
512       log_error(LOG_LEVEL_INFO, "Program name: %s", prog_name);
513    }
514 }
515
516
517 /*********************************************************************
518  *
519  * Function    :  init_log_module
520  *
521  * Description :  Initializes the logging module to log to stderr.
522  *                Can only be called while stderr hasn't been closed
523  *                yet and is only supposed to be called once.
524  *
525  * Parameters  :
526  *          1  :  prog_name = The program name.
527  *
528  * Returns     :  Nothing.
529  *
530  *********************************************************************/
531 void init_log_module(const char *prog_name)
532 {
533    lock_logfile();
534    logfp = stderr;
535    unlock_logfile();
536    set_debug_level(debug);
537    show_version(prog_name);
538 }
539
540
541 /*********************************************************************
542  *
543  * Function    :  set_debug_level
544  *
545  * Description :  Sets the debug level to the provided value
546  *                plus LOG_LEVEL_MINIMUM.
547  *
548  *                XXX: we should only use the LOG_LEVEL_MINIMUM
549  *                until the first time the configuration file has
550  *                been parsed.
551  *                
552  * Parameters  :  1: debug_level = The debug level to set.
553  *
554  * Returns     :  Nothing.
555  *
556  *********************************************************************/
557 void set_debug_level(int debug_level)
558 {
559    debug = debug_level | LOG_LEVEL_MINIMUM;
560 }
561
562
563 /*********************************************************************
564  *
565  * Function    :  disable_logging
566  *
567  * Description :  Disables logging.
568  *                
569  * Parameters  :  None.
570  *
571  * Returns     :  Nothing.
572  *
573  *********************************************************************/
574 void disable_logging(void)
575 {
576    if (logfp != NULL)
577    {
578       log_error(LOG_LEVEL_INFO,
579          "No logfile configured. Please enable it before reporting any problems.");
580       lock_logfile();
581       fclose(logfp);
582       logfp = NULL;
583       unlock_logfile();
584    }
585 }
586
587
588 /*********************************************************************
589  *
590  * Function    :  init_error_log
591  *
592  * Description :  Initializes the logging module to log to a file.
593  *
594  *                XXX: should be renamed.
595  *
596  * Parameters  :
597  *          1  :  prog_name  = The program name.
598  *          2  :  logfname   = The logfile name, or NULL for stderr.
599  *          3  :  debuglevel = The debugging level.
600  *
601  * Returns     :  N/A
602  *
603  *********************************************************************/
604 void init_error_log(const char *prog_name, const char *logfname)
605 {
606    FILE *fp;
607
608    assert(NULL != logfname);
609
610    lock_loginit();
611
612    if (logfp != NULL)
613    {
614       log_error(LOG_LEVEL_INFO, "(Re-)Opening logfile \'%s\'", logfname);
615    }
616
617    /* set the designated log file */
618    fp = fopen(logfname, "a");
619    if (NULL == fp)
620    {
621       log_error(LOG_LEVEL_FATAL, "init_error_log(): can't open logfile: \'%s\'", logfname);
622    }
623
624    /* set logging to be completely unbuffered */
625    setbuf(fp, NULL);
626
627    lock_logfile();
628    if (logfp != NULL)
629    {
630       fclose(logfp);
631    }
632    logfp = fp;
633    unlock_logfile();
634
635 #if !defined(_WIN32)
636    /*
637     * Prevent the Windows GUI from showing the version two
638     * times in a row on startup. It already displayed the show_version()
639     * call from init_log_module() that other systems write to stderr.
640     *
641     * This means mingw32 users will never see the version in their
642     * log file, but I assume they wouldn't look for it there anyway
643     * and simply use the "Help/About Privoxy" menu.
644     */
645    show_version(prog_name);
646 #endif /* def unix */
647
648    unlock_loginit();
649
650 } /* init_error_log */
651
652
653 /*********************************************************************
654  *
655  * Function    :  get_thread_id
656  *
657  * Description :  Returns a number that is different for each thread.
658  *
659  *                XXX: Should be moved elsewhere (miscutil.c?)
660  *                
661  * Parameters  :  None
662  *
663  * Returns     :  thread_id
664  *
665  *********************************************************************/
666 static long get_thread_id(void)
667 {
668    long this_thread = 1;  /* was: pthread_t this_thread;*/
669
670 #ifdef __OS2__
671    PTIB     ptib;
672    APIRET   ulrc; /* XXX: I have no clue what this does */
673 #endif /* __OS2__ */
674
675    /* FIXME get current thread id */
676 #ifdef FEATURE_PTHREAD
677    this_thread = (long)pthread_self();
678 #ifdef __MACH__
679    /*
680     * Mac OSX (and perhaps other Mach instances) doesn't have a debuggable
681     * value at the first 4 bytes of pthread_self()'s return value, a pthread_t.
682     * pthread_t is supposed to be opaque... but it's fairly random, though, so
683     * we make it mostly presentable.
684     */
685    this_thread = abs(this_thread % 1000);
686 #endif /* def __MACH__ */
687 #elif defined(_WIN32)
688    this_thread = GetCurrentThreadId();
689 #elif defined(__OS2__)
690    ulrc = DosGetInfoBlocks(&ptib, NULL);
691    if (ulrc == 0)
692      this_thread = ptib -> tib_ptib2 -> tib2_ultid;
693 #endif /* def FEATURE_PTHREAD */
694
695    return this_thread;
696 }
697
698
699 /*********************************************************************
700  *
701  * Function    :  get_log_timestamp
702  *
703  * Description :  Generates the time stamp for the log message prefix.
704  *
705  * Parameters  :
706  *          1  :  buffer = Storage buffer
707  *          2  :  buffer_size = Size of storage buffer
708  *
709  * Returns     :  Number of written characters or 0 for error.
710  *
711  *********************************************************************/
712 static inline size_t get_log_timestamp(char *buffer, size_t buffer_size)
713 {
714    size_t length;
715    time_t now; 
716    struct tm tm_now;
717    struct timeval tv_now; /* XXX: stupid name */
718    long msecs;
719    int msecs_length = 0;
720
721    gettimeofday(&tv_now, NULL);
722    msecs = tv_now.tv_usec / 1000;
723
724    time(&now);
725
726 #ifdef HAVE_LOCALTIME_R
727    tm_now = *localtime_r(&now, &tm_now);
728 #elif FEATURE_PTHREAD
729    pthread_mutex_lock(&localtime_mutex);
730    tm_now = *localtime(&now); 
731    pthread_mutex_unlock(&localtime_mutex);
732 #else
733    tm_now = *localtime(&now); 
734 #endif
735
736    length = strftime(buffer, buffer_size, "%b %d %H:%M:%S", &tm_now);
737    if (length > 0)
738    {
739       msecs_length = snprintf(buffer+length, buffer_size - length, ".%.3ld", msecs);               
740    }
741    if (msecs_length > 0)
742    {
743       length += (size_t)msecs_length;
744    }
745    else
746    {
747       length = 0;
748    }
749
750    return length;
751 }
752
753
754 /*********************************************************************
755  *
756  * Function    :  get_clf_timestamp
757  *
758  * Description :  Generates a Common Log Format time string.
759  *
760  * Parameters  :
761  *          1  :  buffer = Storage buffer
762  *          2  :  buffer_size = Size of storage buffer
763  *
764  * Returns     :  Number of written characters or 0 for error.
765  *
766  *********************************************************************/
767 static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size)
768 {
769    /*
770     * Complex because not all OSs have tm_gmtoff or
771     * the %z field in strftime()
772     */
773    time_t now;
774    struct tm *tm_now; 
775    struct tm gmt;
776 #ifdef HAVE_LOCALTIME_R
777    struct tm dummy;
778 #endif
779    int days, hrs, mins;
780    size_t length;
781    int tz_length = 0;
782
783    time (&now); 
784 #ifdef HAVE_GMTIME_R
785    gmt = *gmtime_r(&now, &gmt);
786 #elif FEATURE_PTHREAD
787    pthread_mutex_lock(&gmtime_mutex);
788    gmt = *gmtime(&now);
789    pthread_mutex_unlock(&gmtime_mutex);
790 #else
791    gmt = *gmtime(&now);
792 #endif
793 #ifdef HAVE_LOCALTIME_R
794    tm_now = localtime_r(&now, &dummy);
795 #elif FEATURE_PTHREAD
796    pthread_mutex_lock(&localtime_mutex);
797    tm_now = localtime(&now); 
798    pthread_mutex_unlock(&localtime_mutex);
799 #else
800    tm_now = localtime(&now); 
801 #endif
802    days = tm_now->tm_yday - gmt.tm_yday; 
803    hrs = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + tm_now->tm_hour - gmt.tm_hour); 
804    mins = hrs * 60 + tm_now->tm_min - gmt.tm_min; 
805
806    length = strftime(buffer, buffer_size, "%d/%b/%Y:%H:%M:%S ", tm_now);
807
808    if (length > 0)
809    {
810       tz_length = snprintf(buffer+length, buffer_size-length,
811                      "%+03d%02d", mins / 60, abs(mins) % 60);
812    }
813    if (tz_length > 0)
814    {
815       length += (size_t)tz_length;
816    }
817    else
818    {
819       length = 0;
820    }
821
822    return length;
823 }
824
825
826 /*********************************************************************
827  *
828  * Function    :  get_log_level_string
829  *
830  * Description :  Translates a numerical loglevel into a string.
831  *
832  * Parameters  :  
833  *          1  :  loglevel = LOG_LEVEL_FOO
834  *
835  * Returns     :  Log level string.
836  *
837  *********************************************************************/
838 static inline const char *get_log_level_string(int loglevel)
839 {
840    char *log_level_string = NULL;
841
842    assert(0 < loglevel);
843
844    switch (loglevel)
845    {
846       case LOG_LEVEL_ERROR:
847          log_level_string = "Error";
848          break;
849       case LOG_LEVEL_FATAL:
850          log_level_string = "Fatal error";
851          break;
852       case LOG_LEVEL_GPC:
853          log_level_string = "Request";
854          break;
855       case LOG_LEVEL_CONNECT:
856          log_level_string = "Connect";
857          break;
858       case LOG_LEVEL_LOG:
859          log_level_string = "Writing";
860          break;
861       case LOG_LEVEL_HEADER:
862          log_level_string = "Header";
863          break;
864       case LOG_LEVEL_INFO:
865          log_level_string = "Info";
866          break;
867       case LOG_LEVEL_RE_FILTER:
868          log_level_string = "Re-Filter";
869          break;
870 #ifdef FEATURE_FORCE_LOAD
871       case LOG_LEVEL_FORCE:
872          log_level_string = "Force";
873          break;
874 #endif /* def FEATURE_FORCE_LOAD */
875 #ifdef FEATURE_FAST_REDIRECTS
876       case LOG_LEVEL_REDIRECTS:
877          log_level_string = "Redirect";
878          break;
879 #endif /* def FEATURE_FAST_REDIRECTS */
880       case LOG_LEVEL_DEANIMATE:
881          log_level_string = "Gif-Deanimate";
882          break;
883       case LOG_LEVEL_CGI:
884          log_level_string = "CGI";
885          break;
886       default:
887          log_level_string = "Unknown log level";
888          break;
889    }
890    assert(NULL != log_level_string);
891
892    return log_level_string;
893 }
894
895
896 /*********************************************************************
897  *
898  * Function    :  log_error
899  *
900  * Description :  This is the error-reporting and logging function.
901  *
902  * Parameters  :
903  *          1  :  loglevel  = the type of message to be logged
904  *          2  :  fmt       = the main string we want logged, printf-like
905  *          3  :  ...       = arguments to be inserted in fmt (printf-like).
906  *
907  * Returns     :  N/A
908  *
909  *********************************************************************/
910 void log_error(int loglevel, const char *fmt, ...)
911 {
912    va_list ap;
913    char *outbuf = NULL;
914    static char *outbuf_save = NULL;
915    char tempbuf[BUFFER_SIZE];
916    size_t length = 0;
917    const char * src = fmt;
918    long thread_id;
919    char timestamp[30];
920    /*
921     * XXX: Make this a config option,
922     * why else do we allocate instead of using
923     * an array?
924     */
925    size_t log_buffer_size = BUFFER_SIZE;
926
927 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
928    /*
929     * Irrespective of debug setting, a GET/POST/CONNECT makes
930     * the taskbar icon animate.  (There is an option to disable
931     * this but checking that is handled inside LogShowActivity()).
932     */
933    if (loglevel == LOG_LEVEL_GPC)
934    {
935       LogShowActivity();
936    }
937 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
938
939    /*
940     * verify that the loglevel applies to current
941     * settings and that logging is enabled.
942     * Bail out otherwise.
943     */
944    if ((0 == (loglevel & debug))
945 #ifndef _WIN32
946       || (logfp == NULL)
947 #endif
948       )
949    {
950       return;
951    }
952
953    thread_id = get_thread_id();
954    get_log_timestamp(timestamp, sizeof(timestamp));
955
956    /* protect the whole function because of the static buffer (outbuf) */
957    lock_logfile();
958
959    if (NULL == outbuf_save) 
960    {
961       outbuf_save = (char*)zalloc(log_buffer_size + 1); /* +1 for paranoia */
962       if (NULL == outbuf_save)
963       {
964          snprintf(tempbuf, sizeof(tempbuf),
965             "%s Privoxy(%08lx) Fatal error: log_error() failed to allocate buffer memory.\n"
966             "\nExiting.", timestamp, thread_id);
967          fatal_error(tempbuf); /* Exit */
968       }
969    }
970    outbuf = outbuf_save;
971
972    /*
973     * Memsetting the whole buffer to zero (in theory)
974     * makes things easier later on.
975     */
976    memset(outbuf, 0, log_buffer_size);
977
978    /* Add prefix for everything but Common Log Format messages */
979    if (loglevel != LOG_LEVEL_CLF)
980    {
981       length = (size_t)snprintf(outbuf, log_buffer_size, "%s Privoxy(%08lx) %s: ",
982                                 timestamp, thread_id, get_log_level_string(loglevel));
983    }
984
985    /* get ready to scan var. args. */
986    va_start(ap, fmt);
987
988    /* build formatted message from fmt and var-args */
989    while ((*src) && (length < log_buffer_size-2))
990    {
991       const char *sval = NULL; /* %N string  */
992       int ival;                /* %N string length or an error code */
993       unsigned uval;           /* %u value */
994       long lval;               /* %l value */
995       unsigned long ulval;     /* %ul value */
996       char ch;
997       const char *format_string = tempbuf;
998
999       ch = *src++;
1000       if (ch != '%')
1001       {
1002          outbuf[length++] = ch;
1003          /*
1004           * XXX: Only necessary on platforms which don't use pthread
1005           * mutexes (mingw32 for example), where multiple threads can
1006           * write to the buffer at the same time.
1007           */
1008          outbuf[length] = '\0';
1009          continue;
1010       }
1011       outbuf[length] = '\0';
1012       ch = *src++;
1013       switch (ch) {
1014          case '%':
1015             tempbuf[0] = '%';
1016             tempbuf[1] = '\0';
1017             break;
1018          case 'd':
1019             ival = va_arg( ap, int );
1020             snprintf(tempbuf, sizeof(tempbuf), "%d", ival);
1021             break;
1022          case 'u':
1023             uval = va_arg( ap, unsigned );
1024             snprintf(tempbuf, sizeof(tempbuf), "%u", uval);
1025             break;
1026          case 'l':
1027             /* this is a modifier that must be followed by u or d */
1028             ch = *src++;
1029             if (ch == 'd')
1030             {
1031                lval = va_arg( ap, long );
1032                snprintf(tempbuf, sizeof(tempbuf), "%ld", lval);
1033             }
1034             else if (ch == 'u')
1035             {
1036                ulval = va_arg( ap, unsigned long );
1037                snprintf(tempbuf, sizeof(tempbuf), "%lu", ulval);
1038             }
1039             else
1040             {
1041                snprintf(tempbuf, sizeof(tempbuf), "Bad format string: \"%s\"", fmt);
1042                loglevel = LOG_LEVEL_FATAL;
1043             }
1044             break;
1045          case 'c':
1046             /*
1047              * Note that char paramaters are converted to int, so we need to
1048              * pass "int" to va_arg.  (See K&R, 2nd ed, section A7.3.2, page 202)
1049              */
1050             tempbuf[0] = (char) va_arg(ap, int);
1051             tempbuf[1] = '\0';
1052             break;
1053          case 's':
1054             format_string = va_arg(ap, char *);
1055             if (format_string == NULL)
1056             {
1057                format_string = "[null]";
1058             }
1059             break;
1060          case 'N':
1061             /*
1062              * Non-standard: Print a counted unterminated string.
1063              * Takes 2 parameters: int length, const char * string.
1064              */
1065             ival = va_arg(ap, int);
1066             sval = va_arg(ap, char *);
1067             if (sval == NULL)
1068             {
1069                format_string = "[null]";
1070             }
1071             else if (ival <= 0)
1072             {
1073                if (0 == ival)
1074                {
1075                   /* That's ok (but stupid) */
1076                   tempbuf[0] = '\0';
1077                }
1078                else
1079                {
1080                   /*
1081                    * That's not ok (and even more stupid)
1082                    */
1083                   assert(ival >= 0);
1084                   format_string = "[counted string lenght < 0]";
1085                }
1086             }
1087             else if (ival >= sizeof(tempbuf))
1088             {
1089                /*
1090                 * String is too long, copy as much as possible.
1091                 * It will be further truncated later.
1092                 */
1093                memcpy(tempbuf, sval, sizeof(tempbuf)-1);
1094                tempbuf[sizeof(tempbuf)-1] = '\0';
1095             }
1096             else
1097             {
1098                memcpy(tempbuf, sval, (size_t) ival);
1099                tempbuf[ival] = '\0';
1100             }
1101             break;
1102          case 'E':
1103             /* Non-standard: Print error code from errno */
1104 #ifdef _WIN32
1105             ival = WSAGetLastError();
1106             format_string = w32_socket_strerr(ival, tempbuf);
1107 #elif __OS2__
1108             ival = sock_errno();
1109             if (ival != 0)
1110             {
1111                format_string = os2_socket_strerr(ival, tempbuf);
1112             }
1113             else
1114             {
1115                ival = errno;
1116                format_string = strerror(ival);
1117             }
1118 #else /* ifndef _WIN32 */
1119             ival = errno; 
1120 #ifdef HAVE_STRERROR
1121             format_string = strerror(ival);
1122 #else /* ifndef HAVE_STRERROR */
1123             format_string = NULL;
1124 #endif /* ndef HAVE_STRERROR */
1125             if (sval == NULL)
1126             {
1127                snprintf(tempbuf, sizeof(tempbuf), "(errno = %d)", ival);
1128             }
1129 #endif /* ndef _WIN32 */
1130             break;
1131          case 'T':
1132             /* Non-standard: Print a Common Log File timestamp */
1133             get_clf_timestamp(tempbuf, sizeof(tempbuf));
1134             break;
1135          default:
1136             snprintf(tempbuf, sizeof(tempbuf), "Bad format string: \"%s\"", fmt);
1137             loglevel = LOG_LEVEL_FATAL;
1138             break;
1139       } /* switch( p ) */
1140
1141       assert(length < log_buffer_size);
1142       length += strlcpy(outbuf + length, format_string, log_buffer_size - length);
1143
1144       if (length >= log_buffer_size-2)
1145       {
1146          static char warning[] = "... [too long, truncated]";
1147
1148          length = log_buffer_size - sizeof(warning) - 1;
1149          length += strlcpy(outbuf + length, warning, log_buffer_size - length);
1150          assert(length < log_buffer_size);
1151
1152          break;
1153       }
1154    } /* for( p ... ) */
1155
1156    /* done with var. args */
1157    va_end(ap);
1158
1159    assert(length < log_buffer_size);
1160    length += strlcpy(outbuf + length, "\n", log_buffer_size - length);
1161
1162    /* Some sanity checks */
1163    if ((length >= log_buffer_size)
1164     || (outbuf[log_buffer_size-1] != '\0')
1165     || (outbuf[log_buffer_size] != '\0')
1166       )
1167    {
1168       /* Repeat as assertions */
1169       assert(length < log_buffer_size);
1170       assert(outbuf[log_buffer_size-1] == '\0');
1171       /*
1172        * outbuf's real size is log_buffer_size+1,
1173        * so while this looks like an off-by-one,
1174        * we're only checking our paranoia byte.
1175        */
1176       assert(outbuf[log_buffer_size] == '\0');
1177
1178       snprintf(outbuf, log_buffer_size,
1179          "%s Privoxy(%08lx) Fatal error: log_error()'s sanity checks failed. length: %d\n"
1180          "Exiting.", timestamp, thread_id, (int)length);
1181       loglevel = LOG_LEVEL_FATAL;
1182    }
1183
1184 #ifndef _WIN32
1185    /*
1186     * On Windows this is acceptable in case
1187     * we are logging to the GUI window only.
1188     */
1189    assert(NULL != logfp);
1190 #endif
1191
1192    if (loglevel == LOG_LEVEL_FATAL)
1193    {
1194       fatal_error(outbuf_save);
1195       /* Never get here */
1196    }
1197    if (logfp != NULL)
1198    {
1199       fputs(outbuf_save, logfp);
1200    }
1201    unlock_logfile();
1202
1203 #if defined(_WIN32) && !defined(_WIN_CONSOLE)
1204    /* Write to display */
1205    LogPutString(outbuf_save);
1206 #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
1207
1208 }
1209
1210
1211 /*********************************************************************
1212  *
1213  * Function    :  jb_err_to_string
1214  *
1215  * Description :  Translates JB_ERR_FOO codes into strings.
1216  *
1217  *                XXX: the type of error codes is jb_err
1218  *                but the typedef'inition is currently not
1219  *                visible to all files that include errlog.h.
1220  *
1221  * Parameters  :
1222  *          1  :  error = a valid jb_err code
1223  *
1224  * Returns     :  A string with the jb_err translation
1225  *
1226  *********************************************************************/
1227 const char *jb_err_to_string(int error)
1228 {
1229    switch (error)
1230    {
1231       case JB_ERR_OK:
1232          return "Success, no error";
1233       case JB_ERR_MEMORY:
1234          return "Out of memory";
1235       case JB_ERR_CGI_PARAMS:
1236          return "Missing or corrupt CGI parameters";
1237       case JB_ERR_FILE:
1238          return "Error opening, reading or writing a file";
1239       case JB_ERR_PARSE:
1240          return "Parse error";
1241       case JB_ERR_MODIFIED:
1242          return "File has been modified outside of the CGI actions editor.";
1243       case JB_ERR_COMPRESS:
1244          return "(De)compression failure";
1245       default:
1246          assert(0);
1247          return "Unknown error";
1248    }
1249    assert(0);
1250    return "Internal error";
1251 }
1252
1253 #ifdef _WIN32
1254 /*********************************************************************
1255  *
1256  * Function    :  w32_socket_strerr
1257  *
1258  * Description :  Translate the return value from WSAGetLastError()
1259  *                into a string.
1260  *
1261  * Parameters  :
1262  *          1  :  errcode = The return value from WSAGetLastError().
1263  *          2  :  tmp_buf = A temporary buffer that might be used to
1264  *                          store the string.
1265  *
1266  * Returns     :  String representing the error code.  This may be
1267  *                a global string constant or a string stored in
1268  *                tmp_buf.
1269  *
1270  *********************************************************************/
1271 static char *w32_socket_strerr(int errcode, char *tmp_buf)
1272 {
1273 #define TEXT_FOR_ERROR(code,text) \
1274    if (errcode == code)           \
1275    {                              \
1276       return #code " - " text;    \
1277    }
1278
1279    TEXT_FOR_ERROR(WSAEACCES, "Permission denied")
1280    TEXT_FOR_ERROR(WSAEADDRINUSE, "Address already in use.")
1281    TEXT_FOR_ERROR(WSAEADDRNOTAVAIL, "Cannot assign requested address.");
1282    TEXT_FOR_ERROR(WSAEAFNOSUPPORT, "Address family not supported by protocol family.");
1283    TEXT_FOR_ERROR(WSAEALREADY, "Operation already in progress.");
1284    TEXT_FOR_ERROR(WSAECONNABORTED, "Software caused connection abort.");
1285    TEXT_FOR_ERROR(WSAECONNREFUSED, "Connection refused.");
1286    TEXT_FOR_ERROR(WSAECONNRESET, "Connection reset by peer.");
1287    TEXT_FOR_ERROR(WSAEDESTADDRREQ, "Destination address required.");
1288    TEXT_FOR_ERROR(WSAEFAULT, "Bad address.");
1289    TEXT_FOR_ERROR(WSAEHOSTDOWN, "Host is down.");
1290    TEXT_FOR_ERROR(WSAEHOSTUNREACH, "No route to host.");
1291    TEXT_FOR_ERROR(WSAEINPROGRESS, "Operation now in progress.");
1292    TEXT_FOR_ERROR(WSAEINTR, "Interrupted function call.");
1293    TEXT_FOR_ERROR(WSAEINVAL, "Invalid argument.");
1294    TEXT_FOR_ERROR(WSAEISCONN, "Socket is already connected.");
1295    TEXT_FOR_ERROR(WSAEMFILE, "Too many open sockets.");
1296    TEXT_FOR_ERROR(WSAEMSGSIZE, "Message too long.");
1297    TEXT_FOR_ERROR(WSAENETDOWN, "Network is down.");
1298    TEXT_FOR_ERROR(WSAENETRESET, "Network dropped connection on reset.");
1299    TEXT_FOR_ERROR(WSAENETUNREACH, "Network is unreachable.");
1300    TEXT_FOR_ERROR(WSAENOBUFS, "No buffer space available.");
1301    TEXT_FOR_ERROR(WSAENOPROTOOPT, "Bad protocol option.");
1302    TEXT_FOR_ERROR(WSAENOTCONN, "Socket is not connected.");
1303    TEXT_FOR_ERROR(WSAENOTSOCK, "Socket operation on non-socket.");
1304    TEXT_FOR_ERROR(WSAEOPNOTSUPP, "Operation not supported.");
1305    TEXT_FOR_ERROR(WSAEPFNOSUPPORT, "Protocol family not supported.");
1306    TEXT_FOR_ERROR(WSAEPROCLIM, "Too many processes.");
1307    TEXT_FOR_ERROR(WSAEPROTONOSUPPORT, "Protocol not supported.");
1308    TEXT_FOR_ERROR(WSAEPROTOTYPE, "Protocol wrong type for socket.");
1309    TEXT_FOR_ERROR(WSAESHUTDOWN, "Cannot send after socket shutdown.");
1310    TEXT_FOR_ERROR(WSAESOCKTNOSUPPORT, "Socket type not supported.");
1311    TEXT_FOR_ERROR(WSAETIMEDOUT, "Connection timed out.");
1312    TEXT_FOR_ERROR(WSAEWOULDBLOCK, "Resource temporarily unavailable.");
1313    TEXT_FOR_ERROR(WSAHOST_NOT_FOUND, "Host not found.");
1314    TEXT_FOR_ERROR(WSANOTINITIALISED, "Successful WSAStartup not yet performed.");
1315    TEXT_FOR_ERROR(WSANO_DATA, "Valid name, no data record of requested type.");
1316    TEXT_FOR_ERROR(WSANO_RECOVERY, "This is a non-recoverable error.");
1317    TEXT_FOR_ERROR(WSASYSNOTREADY, "Network subsystem is unavailable.");
1318    TEXT_FOR_ERROR(WSATRY_AGAIN, "Non-authoritative host not found.");
1319    TEXT_FOR_ERROR(WSAVERNOTSUPPORTED, "WINSOCK.DLL version out of range.");
1320    TEXT_FOR_ERROR(WSAEDISCON, "Graceful shutdown in progress.");
1321    /*
1322     * The following error codes are documented in the Microsoft WinSock
1323     * reference guide, but don't actually exist.
1324     *
1325     * TEXT_FOR_ERROR(WSA_INVALID_HANDLE, "Specified event object handle is invalid.");
1326     * TEXT_FOR_ERROR(WSA_INVALID_PARAMETER, "One or more parameters are invalid.");
1327     * TEXT_FOR_ERROR(WSAINVALIDPROCTABLE, "Invalid procedure table from service provider.");
1328     * TEXT_FOR_ERROR(WSAINVALIDPROVIDER, "Invalid service provider version number.");
1329     * TEXT_FOR_ERROR(WSA_IO_PENDING, "Overlapped operations will complete later.");
1330     * TEXT_FOR_ERROR(WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state.");
1331     * TEXT_FOR_ERROR(WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available.");
1332     * TEXT_FOR_ERROR(WSAPROVIDERFAILEDINIT, "Unable to initialize a service provider.");
1333     * TEXT_FOR_ERROR(WSASYSCALLFAILURE, "System call failure.");
1334     * TEXT_FOR_ERROR(WSA_OPERATION_ABORTED, "Overlapped operation aborted.");
1335     */
1336
1337    sprintf(tmp_buf, "(error number %d)", errcode);
1338    return tmp_buf;
1339 }
1340 #endif /* def _WIN32 */
1341
1342
1343 #ifdef __OS2__
1344 /*********************************************************************
1345  *
1346  * Function    :  os2_socket_strerr
1347  *
1348  * Description :  Translate the return value from sock_errno()
1349  *                into a string.
1350  *
1351  * Parameters  :
1352  *          1  :  errcode = The return value from sock_errno().
1353  *          2  :  tmp_buf = A temporary buffer that might be used to
1354  *                          store the string.
1355  *
1356  * Returns     :  String representing the error code.  This may be
1357  *                a global string constant or a string stored in
1358  *                tmp_buf.
1359  *
1360  *********************************************************************/
1361 static char *os2_socket_strerr(int errcode, char *tmp_buf)
1362 {
1363 #define TEXT_FOR_ERROR(code,text) \
1364    if (errcode == code)           \
1365    {                              \
1366       return #code " - " text;    \
1367    }
1368
1369    TEXT_FOR_ERROR(SOCEPERM          , "Not owner.")
1370    TEXT_FOR_ERROR(SOCESRCH          , "No such process.")
1371    TEXT_FOR_ERROR(SOCEINTR          , "Interrupted system call.")
1372    TEXT_FOR_ERROR(SOCENXIO          , "No such device or address.")
1373    TEXT_FOR_ERROR(SOCEBADF          , "Bad file number.")
1374    TEXT_FOR_ERROR(SOCEACCES         , "Permission denied.")
1375    TEXT_FOR_ERROR(SOCEFAULT         , "Bad address.")
1376    TEXT_FOR_ERROR(SOCEINVAL         , "Invalid argument.")
1377    TEXT_FOR_ERROR(SOCEMFILE         , "Too many open files.")
1378    TEXT_FOR_ERROR(SOCEPIPE          , "Broken pipe.")
1379    TEXT_FOR_ERROR(SOCEWOULDBLOCK    , "Operation would block.")
1380    TEXT_FOR_ERROR(SOCEINPROGRESS    , "Operation now in progress.")
1381    TEXT_FOR_ERROR(SOCEALREADY       , "Operation already in progress.")
1382    TEXT_FOR_ERROR(SOCENOTSOCK       , "Socket operation on non-socket.")
1383    TEXT_FOR_ERROR(SOCEDESTADDRREQ   , "Destination address required.")
1384    TEXT_FOR_ERROR(SOCEMSGSIZE       , "Message too long.")
1385    TEXT_FOR_ERROR(SOCEPROTOTYPE     , "Protocol wrong type for socket.")
1386    TEXT_FOR_ERROR(SOCENOPROTOOPT    , "Protocol not available.")
1387    TEXT_FOR_ERROR(SOCEPROTONOSUPPORT, "Protocol not supported.")
1388    TEXT_FOR_ERROR(SOCESOCKTNOSUPPORT, "Socket type not supported.")
1389    TEXT_FOR_ERROR(SOCEOPNOTSUPP     , "Operation not supported.")
1390    TEXT_FOR_ERROR(SOCEPFNOSUPPORT   , "Protocol family not supported.")
1391    TEXT_FOR_ERROR(SOCEAFNOSUPPORT   , "Address family not supported by protocol family.")
1392    TEXT_FOR_ERROR(SOCEADDRINUSE     , "Address already in use.")
1393    TEXT_FOR_ERROR(SOCEADDRNOTAVAIL  , "Can't assign requested address.")
1394    TEXT_FOR_ERROR(SOCENETDOWN       , "Network is down.")
1395    TEXT_FOR_ERROR(SOCENETUNREACH    , "Network is unreachable.")
1396    TEXT_FOR_ERROR(SOCENETRESET      , "Network dropped connection on reset.")
1397    TEXT_FOR_ERROR(SOCECONNABORTED   , "Software caused connection abort.")
1398    TEXT_FOR_ERROR(SOCECONNRESET     , "Connection reset by peer.")
1399    TEXT_FOR_ERROR(SOCENOBUFS        , "No buffer space available.")
1400    TEXT_FOR_ERROR(SOCEISCONN        , "Socket is already connected.")
1401    TEXT_FOR_ERROR(SOCENOTCONN       , "Socket is not connected.")
1402    TEXT_FOR_ERROR(SOCESHUTDOWN      , "Can't send after socket shutdown.")
1403    TEXT_FOR_ERROR(SOCETOOMANYREFS   , "Too many references: can't splice.")
1404    TEXT_FOR_ERROR(SOCETIMEDOUT      , "Operation timed out.")
1405    TEXT_FOR_ERROR(SOCECONNREFUSED   , "Connection refused.")
1406    TEXT_FOR_ERROR(SOCELOOP          , "Too many levels of symbolic links.")
1407    TEXT_FOR_ERROR(SOCENAMETOOLONG   , "File name too long.")
1408    TEXT_FOR_ERROR(SOCEHOSTDOWN      , "Host is down.")
1409    TEXT_FOR_ERROR(SOCEHOSTUNREACH   , "No route to host.")
1410    TEXT_FOR_ERROR(SOCENOTEMPTY      , "Directory not empty.")
1411    TEXT_FOR_ERROR(SOCEOS2ERR        , "OS/2 Error.")
1412
1413    sprintf(tmp_buf, "(error number %d)", errcode);
1414    return tmp_buf;
1415 }
1416 #endif /* def __OS2__ */
1417
1418
1419 /*
1420   Local Variables:
1421   tab-width: 3
1422   end:
1423 */