errlog.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. /*********************************************************************
  2. *
  3. * File : $Source: /cvsroot/ijbswa/current/errlog.c,v $
  4. *
  5. * Purpose : Log errors to a designated destination in an elegant,
  6. * printf-like fashion.
  7. *
  8. * Copyright : Written by and Copyright (C) 2001-2014 the
  9. * Privoxy team. https://www.privoxy.org/
  10. *
  11. * Based on the Internet Junkbuster originally written
  12. * by and Copyright (C) 1997 Anonymous Coders and
  13. * Junkbusters Corporation. http://www.junkbusters.com
  14. *
  15. * This program is free software; you can redistribute it
  16. * and/or modify it under the terms of the GNU General
  17. * Public License as published by the Free Software
  18. * Foundation; either version 2 of the License, or (at
  19. * your option) any later version.
  20. *
  21. * This program is distributed in the hope that it will
  22. * be useful, but WITHOUT ANY WARRANTY; without even the
  23. * implied warranty of MERCHANTABILITY or FITNESS FOR A
  24. * PARTICULAR PURPOSE. See the GNU General Public
  25. * License for more details.
  26. *
  27. * The GNU General Public License should be included with
  28. * this file. If not, you can view it at
  29. * http://www.gnu.org/copyleft/gpl.html
  30. * or write to the Free Software Foundation, Inc., 59
  31. * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  32. *
  33. *********************************************************************/
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <stdarg.h>
  37. #include <string.h>
  38. #include <ctype.h>
  39. #include "config.h"
  40. #include "miscutil.h"
  41. /* For gettimeofday() */
  42. #include <sys/time.h>
  43. #if !defined(_WIN32)
  44. #include <unistd.h>
  45. #endif /* !defined(_WIN32) */
  46. #include <errno.h>
  47. #include <assert.h>
  48. #ifdef _WIN32
  49. #ifndef STRICT
  50. #define STRICT
  51. #endif
  52. #include <windows.h>
  53. #ifndef _WIN_CONSOLE
  54. #include "w32log.h"
  55. #endif /* ndef _WIN_CONSOLE */
  56. #endif /* def _WIN32 */
  57. #ifdef _MSC_VER
  58. #define inline __inline
  59. #endif /* def _MSC_VER */
  60. #include "errlog.h"
  61. #include "project.h"
  62. #include "jcc.h"
  63. #ifdef FEATURE_EXTERNAL_FILTERS
  64. #include "jbsockets.h"
  65. #endif
  66. /*
  67. * LOG_LEVEL_FATAL cannot be turned off. (There are
  68. * some exceptional situations where we need to get a
  69. * message to the user).
  70. */
  71. #define LOG_LEVEL_MINIMUM LOG_LEVEL_FATAL
  72. /* where to log (default: stderr) */
  73. static FILE *logfp = NULL;
  74. /* logging detail level. XXX: stupid name. */
  75. static int debug = (LOG_LEVEL_FATAL | LOG_LEVEL_ERROR);
  76. /* static functions */
  77. static void fatal_error(const char * error_message);
  78. #ifdef _WIN32
  79. static char *w32_socket_strerr(int errcode, char *tmp_buf);
  80. #endif
  81. #ifdef MUTEX_LOCKS_AVAILABLE
  82. static inline void lock_logfile(void)
  83. {
  84. privoxy_mutex_lock(&log_mutex);
  85. }
  86. static inline void unlock_logfile(void)
  87. {
  88. privoxy_mutex_unlock(&log_mutex);
  89. }
  90. static inline void lock_loginit(void)
  91. {
  92. privoxy_mutex_lock(&log_init_mutex);
  93. }
  94. static inline void unlock_loginit(void)
  95. {
  96. privoxy_mutex_unlock(&log_init_mutex);
  97. }
  98. #else /* ! MUTEX_LOCKS_AVAILABLE */
  99. /*
  100. * FIXME we need a cross-platform locking mechanism.
  101. * The locking/unlocking functions below should be
  102. * fleshed out for non-pthread implementations.
  103. */
  104. static inline void lock_logfile() {}
  105. static inline void unlock_logfile() {}
  106. static inline void lock_loginit() {}
  107. static inline void unlock_loginit() {}
  108. #endif
  109. /*********************************************************************
  110. *
  111. * Function : fatal_error
  112. *
  113. * Description : Displays a fatal error to standard error (or, on
  114. * a WIN32 GUI, to a dialog box), and exits Privoxy
  115. * with status code 1.
  116. *
  117. * Parameters :
  118. * 1 : error_message = The error message to display.
  119. *
  120. * Returns : Does not return.
  121. *
  122. *********************************************************************/
  123. static void fatal_error(const char *error_message)
  124. {
  125. if (logfp != NULL)
  126. {
  127. fputs(error_message, logfp);
  128. }
  129. #if defined(_WIN32) && !defined(_WIN_CONSOLE)
  130. {
  131. /* Skip timestamp and thread id for the message box. */
  132. const char *box_message = strstr(error_message, "Fatal error");
  133. if (NULL == box_message)
  134. {
  135. /* Shouldn't happen but ... */
  136. box_message = error_message;
  137. }
  138. MessageBox(g_hwndLogFrame, box_message, "Privoxy Error",
  139. MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND | MB_TOPMOST);
  140. /* Cleanup - remove taskbar icon etc. */
  141. TermLogWindow();
  142. }
  143. #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
  144. #if defined(unix)
  145. if (pidfile)
  146. {
  147. unlink(pidfile);
  148. }
  149. #endif /* unix */
  150. exit(1);
  151. }
  152. /*********************************************************************
  153. *
  154. * Function : show_version
  155. *
  156. * Description : Logs the Privoxy version and the program name.
  157. *
  158. * Parameters :
  159. * 1 : prog_name = The program name.
  160. *
  161. * Returns : Nothing.
  162. *
  163. *********************************************************************/
  164. void show_version(const char *prog_name)
  165. {
  166. log_error(LOG_LEVEL_INFO, "Privoxy version " VERSION);
  167. if (prog_name != NULL)
  168. {
  169. log_error(LOG_LEVEL_INFO, "Program name: %s", prog_name);
  170. }
  171. }
  172. /*********************************************************************
  173. *
  174. * Function : init_log_module
  175. *
  176. * Description : Initializes the logging module to log to stderr.
  177. * Can only be called while stderr hasn't been closed
  178. * yet and is only supposed to be called once.
  179. *
  180. * Parameters :
  181. * 1 : prog_name = The program name.
  182. *
  183. * Returns : Nothing.
  184. *
  185. *********************************************************************/
  186. void init_log_module(void)
  187. {
  188. lock_logfile();
  189. logfp = stderr;
  190. unlock_logfile();
  191. set_debug_level(debug);
  192. }
  193. /*********************************************************************
  194. *
  195. * Function : set_debug_level
  196. *
  197. * Description : Sets the debug level to the provided value
  198. * plus LOG_LEVEL_MINIMUM.
  199. *
  200. * XXX: we should only use the LOG_LEVEL_MINIMUM
  201. * until the first time the configuration file has
  202. * been parsed.
  203. *
  204. * Parameters : 1: debug_level = The debug level to set.
  205. *
  206. * Returns : Nothing.
  207. *
  208. *********************************************************************/
  209. void set_debug_level(int debug_level)
  210. {
  211. #ifdef FUZZ
  212. if (LOG_LEVEL_STFU == debug_level)
  213. {
  214. debug = LOG_LEVEL_STFU;
  215. }
  216. if (LOG_LEVEL_STFU == debug)
  217. {
  218. return;
  219. }
  220. #endif
  221. debug = debug_level | LOG_LEVEL_MINIMUM;
  222. }
  223. /*********************************************************************
  224. *
  225. * Function : debug_level_is_enabled
  226. *
  227. * Description : Checks if a certain debug level is enabled.
  228. *
  229. * Parameters : 1: debug_level = The debug level to check.
  230. *
  231. * Returns : Nothing.
  232. *
  233. *********************************************************************/
  234. int debug_level_is_enabled(int debug_level)
  235. {
  236. return (0 != (debug & debug_level));
  237. }
  238. /*********************************************************************
  239. *
  240. * Function : disable_logging
  241. *
  242. * Description : Disables logging.
  243. *
  244. * Parameters : None.
  245. *
  246. * Returns : Nothing.
  247. *
  248. *********************************************************************/
  249. void disable_logging(void)
  250. {
  251. if (logfp != NULL)
  252. {
  253. log_error(LOG_LEVEL_INFO,
  254. "No logfile configured. Please enable it before reporting any problems.");
  255. lock_logfile();
  256. fclose(logfp);
  257. logfp = NULL;
  258. unlock_logfile();
  259. }
  260. }
  261. /*********************************************************************
  262. *
  263. * Function : init_error_log
  264. *
  265. * Description : Initializes the logging module to log to a file.
  266. *
  267. * XXX: should be renamed.
  268. *
  269. * Parameters :
  270. * 1 : prog_name = The program name.
  271. * 2 : logfname = The logfile to (re)open.
  272. *
  273. * Returns : N/A
  274. *
  275. *********************************************************************/
  276. void init_error_log(const char *prog_name, const char *logfname)
  277. {
  278. FILE *fp;
  279. assert(NULL != logfname);
  280. lock_loginit();
  281. if ((logfp != NULL) && (logfp != stderr))
  282. {
  283. log_error(LOG_LEVEL_INFO, "(Re-)Opening logfile \'%s\'", logfname);
  284. }
  285. /* set the designated log file */
  286. fp = fopen(logfname, "a");
  287. if ((NULL == fp) && (logfp != NULL))
  288. {
  289. /*
  290. * Some platforms (like OS/2 (XXX: no longer supported)) don't
  291. * allow us to open the same file twice, therefore we give it
  292. * another shot after closing the old file descriptor first.
  293. *
  294. * We don't do it right away because it prevents us
  295. * from logging the "can't open logfile" message to
  296. * the old logfile.
  297. *
  298. * XXX: this is a lame workaround and once the next
  299. * release is out we should stop bothering reopening
  300. * the logfile unless we have to.
  301. *
  302. * Currently we reopen it every time the config file
  303. * has been reloaded, but actually we only have to
  304. * reopen it if the file name changed or if the
  305. * configuration reload was caused by a SIGHUP.
  306. */
  307. log_error(LOG_LEVEL_INFO, "Failed to reopen logfile: \'%s\'. "
  308. "Retrying after closing the old file descriptor first. If that "
  309. "doesn't work, Privoxy will exit without being able to log a message.",
  310. logfname);
  311. lock_logfile();
  312. fclose(logfp);
  313. logfp = NULL;
  314. unlock_logfile();
  315. fp = fopen(logfname, "a");
  316. }
  317. if (NULL == fp)
  318. {
  319. log_error(LOG_LEVEL_FATAL, "init_error_log(): can't open logfile: \'%s\'", logfname);
  320. }
  321. #ifdef FEATURE_EXTERNAL_FILTERS
  322. mark_socket_for_close_on_execute(3);
  323. #endif
  324. /* set logging to be completely unbuffered */
  325. setbuf(fp, NULL);
  326. lock_logfile();
  327. if (logfp != NULL)
  328. {
  329. fclose(logfp);
  330. }
  331. #ifdef unix
  332. if (daemon_mode && (logfp == stderr))
  333. {
  334. if (dup2(1, 2) == -1)
  335. {
  336. /*
  337. * We only use fatal_error() to clear the pid
  338. * file and to exit. Given that stderr has just
  339. * been closed, the user will not see the error
  340. * message.
  341. */
  342. fatal_error("Failed to reserve fd 2.");
  343. }
  344. }
  345. #endif
  346. logfp = fp;
  347. unlock_logfile();
  348. show_version(prog_name);
  349. unlock_loginit();
  350. } /* init_error_log */
  351. /*********************************************************************
  352. *
  353. * Function : get_thread_id
  354. *
  355. * Description : Returns a number that is different for each thread.
  356. *
  357. * XXX: Should be moved elsewhere (miscutil.c?)
  358. *
  359. * Parameters : None
  360. *
  361. * Returns : thread_id
  362. *
  363. *********************************************************************/
  364. static long get_thread_id(void)
  365. {
  366. long this_thread;
  367. /* FIXME get current thread id */
  368. #ifdef FEATURE_PTHREAD
  369. this_thread = (long)pthread_self();
  370. #ifdef __MACH__
  371. /*
  372. * Mac OSX (and perhaps other Mach instances) doesn't have a unique
  373. * value at the lowest order 4 bytes of pthread_self()'s return value, a pthread_t,
  374. * so trim the three lowest-order bytes from the value (16^3).
  375. */
  376. this_thread = this_thread / 4096;
  377. #endif /* def __MACH__ */
  378. #elif defined(_WIN32)
  379. this_thread = GetCurrentThreadId();
  380. #else
  381. /* Forking instead of threading. */
  382. this_thread = 1;
  383. #endif /* def FEATURE_PTHREAD */
  384. return this_thread;
  385. }
  386. /*********************************************************************
  387. *
  388. * Function : get_log_timestamp
  389. *
  390. * Description : Generates the time stamp for the log message prefix.
  391. *
  392. * Parameters :
  393. * 1 : buffer = Storage buffer
  394. * 2 : buffer_size = Size of storage buffer
  395. *
  396. * Returns : Number of written characters or 0 for error.
  397. *
  398. *********************************************************************/
  399. static inline size_t get_log_timestamp(char *buffer, size_t buffer_size)
  400. {
  401. size_t length;
  402. time_t now;
  403. struct tm tm_now;
  404. struct timeval tv_now; /* XXX: stupid name */
  405. long msecs;
  406. int msecs_length = 0;
  407. gettimeofday(&tv_now, NULL);
  408. msecs = tv_now.tv_usec / 1000;
  409. now = tv_now.tv_sec;
  410. #ifdef HAVE_LOCALTIME_R
  411. tm_now = *localtime_r(&now, &tm_now);
  412. #elif defined(MUTEX_LOCKS_AVAILABLE)
  413. privoxy_mutex_lock(&localtime_mutex);
  414. tm_now = *localtime(&now);
  415. privoxy_mutex_unlock(&localtime_mutex);
  416. #else
  417. tm_now = *localtime(&now);
  418. #endif
  419. length = strftime(buffer, buffer_size, "%Y-%m-%d %H:%M:%S", &tm_now);
  420. if (length > (size_t)0)
  421. {
  422. msecs_length = snprintf(buffer+length, buffer_size - length, ".%.3ld", msecs);
  423. }
  424. if (msecs_length > 0)
  425. {
  426. length += (size_t)msecs_length;
  427. }
  428. else
  429. {
  430. length = 0;
  431. }
  432. return length;
  433. }
  434. /*********************************************************************
  435. *
  436. * Function : get_clf_timestamp
  437. *
  438. * Description : Generates a Common Log Format time string.
  439. *
  440. * Parameters :
  441. * 1 : buffer = Storage buffer
  442. * 2 : buffer_size = Size of storage buffer
  443. *
  444. * Returns : Number of written characters or 0 for error.
  445. *
  446. *********************************************************************/
  447. static inline size_t get_clf_timestamp(char *buffer, size_t buffer_size)
  448. {
  449. /*
  450. * Complex because not all OSs have tm_gmtoff or
  451. * the %z field in strftime()
  452. */
  453. time_t now;
  454. struct tm *tm_now;
  455. struct tm gmt;
  456. #ifdef HAVE_LOCALTIME_R
  457. struct tm dummy;
  458. #endif
  459. int days, hrs, mins;
  460. size_t length;
  461. int tz_length = 0;
  462. time (&now);
  463. gmt = *privoxy_gmtime_r(&now, &gmt);
  464. #ifdef HAVE_LOCALTIME_R
  465. tm_now = localtime_r(&now, &dummy);
  466. #elif defined(MUTEX_LOCKS_AVAILABLE)
  467. privoxy_mutex_lock(&localtime_mutex);
  468. tm_now = localtime(&now);
  469. #else
  470. tm_now = localtime(&now);
  471. #endif
  472. days = tm_now->tm_yday - gmt.tm_yday;
  473. hrs = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) + tm_now->tm_hour - gmt.tm_hour);
  474. mins = hrs * 60 + tm_now->tm_min - gmt.tm_min;
  475. length = strftime(buffer, buffer_size, "%d/%b/%Y:%H:%M:%S ", tm_now);
  476. #if !defined(HAVE_LOCALTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
  477. privoxy_mutex_unlock(&localtime_mutex);
  478. #endif
  479. if (length > (size_t)0)
  480. {
  481. tz_length = snprintf(buffer+length, buffer_size-length,
  482. "%+03d%02d", mins / 60, abs(mins) % 60);
  483. }
  484. if (tz_length > 0)
  485. {
  486. length += (size_t)tz_length;
  487. }
  488. else
  489. {
  490. length = 0;
  491. }
  492. return length;
  493. }
  494. /*********************************************************************
  495. *
  496. * Function : get_log_level_string
  497. *
  498. * Description : Translates a numerical loglevel into a string.
  499. *
  500. * Parameters :
  501. * 1 : loglevel = LOG_LEVEL_FOO
  502. *
  503. * Returns : Log level string.
  504. *
  505. *********************************************************************/
  506. static inline const char *get_log_level_string(int loglevel)
  507. {
  508. char *log_level_string = NULL;
  509. assert(0 < loglevel);
  510. switch (loglevel)
  511. {
  512. case LOG_LEVEL_ERROR:
  513. log_level_string = "Error";
  514. break;
  515. case LOG_LEVEL_FATAL:
  516. log_level_string = "Fatal error";
  517. break;
  518. case LOG_LEVEL_REQUEST:
  519. log_level_string = "Request";
  520. break;
  521. case LOG_LEVEL_CONNECT:
  522. log_level_string = "Connect";
  523. break;
  524. case LOG_LEVEL_WRITING:
  525. log_level_string = "Writing";
  526. break;
  527. case LOG_LEVEL_RECEIVED:
  528. log_level_string = "Received";
  529. break;
  530. case LOG_LEVEL_HEADER:
  531. log_level_string = "Header";
  532. break;
  533. case LOG_LEVEL_INFO:
  534. log_level_string = "Info";
  535. break;
  536. case LOG_LEVEL_RE_FILTER:
  537. log_level_string = "Re-Filter";
  538. break;
  539. #ifdef FEATURE_FORCE_LOAD
  540. case LOG_LEVEL_FORCE:
  541. log_level_string = "Force";
  542. break;
  543. #endif /* def FEATURE_FORCE_LOAD */
  544. case LOG_LEVEL_REDIRECTS:
  545. log_level_string = "Redirect";
  546. break;
  547. case LOG_LEVEL_DEANIMATE:
  548. log_level_string = "Gif-Deanimate";
  549. break;
  550. case LOG_LEVEL_CRUNCH:
  551. log_level_string = "Crunch";
  552. break;
  553. case LOG_LEVEL_CGI:
  554. log_level_string = "CGI";
  555. break;
  556. case LOG_LEVEL_ACTIONS:
  557. log_level_string = "Actions";
  558. break;
  559. default:
  560. log_level_string = "Unknown log level";
  561. break;
  562. }
  563. assert(NULL != log_level_string);
  564. return log_level_string;
  565. }
  566. #define LOG_BUFFER_SIZE BUFFER_SIZE
  567. /*********************************************************************
  568. *
  569. * Function : log_error
  570. *
  571. * Description : This is the error-reporting and logging function.
  572. *
  573. * Parameters :
  574. * 1 : loglevel = the type of message to be logged
  575. * 2 : fmt = the main string we want logged, printf-like
  576. * 3 : ... = arguments to be inserted in fmt (printf-like).
  577. *
  578. * Returns : N/A
  579. *
  580. *********************************************************************/
  581. void log_error(int loglevel, const char *fmt, ...)
  582. {
  583. va_list ap;
  584. char outbuf[LOG_BUFFER_SIZE+1];
  585. char tempbuf[LOG_BUFFER_SIZE];
  586. size_t length = 0;
  587. const char * src = fmt;
  588. long thread_id;
  589. char timestamp[30];
  590. const size_t log_buffer_size = LOG_BUFFER_SIZE;
  591. #if defined(_WIN32) && !defined(_WIN_CONSOLE)
  592. /*
  593. * Irrespective of debug setting, a GET/POST/CONNECT makes
  594. * the taskbar icon animate. (There is an option to disable
  595. * this but checking that is handled inside LogShowActivity()).
  596. */
  597. if ((loglevel == LOG_LEVEL_REQUEST) || (loglevel == LOG_LEVEL_CRUNCH))
  598. {
  599. LogShowActivity();
  600. }
  601. #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
  602. /*
  603. * verify that the loglevel applies to current
  604. * settings and that logging is enabled.
  605. * Bail out otherwise.
  606. */
  607. if ((0 == (loglevel & debug))
  608. #ifndef _WIN32
  609. || (logfp == NULL)
  610. #endif
  611. )
  612. {
  613. #ifdef FUZZ
  614. if (debug == LOG_LEVEL_STFU)
  615. {
  616. return;
  617. }
  618. #endif
  619. if (loglevel == LOG_LEVEL_FATAL)
  620. {
  621. fatal_error("Fatal error. You're not supposed to"
  622. "see this message. Please file a bug report.");
  623. }
  624. return;
  625. }
  626. thread_id = get_thread_id();
  627. get_log_timestamp(timestamp, sizeof(timestamp));
  628. /*
  629. * Memsetting the whole buffer to zero (in theory)
  630. * makes things easier later on.
  631. */
  632. memset(outbuf, 0, sizeof(outbuf));
  633. /* Add prefix for everything but Common Log Format messages */
  634. if (loglevel != LOG_LEVEL_CLF)
  635. {
  636. length = (size_t)snprintf(outbuf, log_buffer_size, "%s %08lx %s: ",
  637. timestamp, thread_id, get_log_level_string(loglevel));
  638. }
  639. /* get ready to scan var. args. */
  640. va_start(ap, fmt);
  641. /* build formatted message from fmt and var-args */
  642. while ((*src) && (length < log_buffer_size-2))
  643. {
  644. const char *sval = NULL; /* %N string */
  645. int ival; /* %N string length or an error code */
  646. unsigned uval; /* %u value */
  647. long lval; /* %l value */
  648. unsigned long ulval; /* %ul value */
  649. char ch;
  650. const char *format_string = tempbuf;
  651. ch = *src++;
  652. if (ch != '%')
  653. {
  654. outbuf[length++] = ch;
  655. /*
  656. * XXX: Only necessary on platforms where multiple threads
  657. * can write to the buffer at the same time because we
  658. * don't support mutexes.
  659. * XXX: Are there any such platforms left now that OS/2 is gone?
  660. */
  661. outbuf[length] = '\0';
  662. continue;
  663. }
  664. outbuf[length] = '\0';
  665. ch = *src++;
  666. switch (ch) {
  667. case '%':
  668. tempbuf[0] = '%';
  669. tempbuf[1] = '\0';
  670. break;
  671. case 'd':
  672. ival = va_arg(ap, int);
  673. snprintf(tempbuf, sizeof(tempbuf), "%d", ival);
  674. break;
  675. case 'u':
  676. uval = va_arg(ap, unsigned);
  677. snprintf(tempbuf, sizeof(tempbuf), "%u", uval);
  678. break;
  679. case 'l':
  680. /* this is a modifier that must be followed by u, lu, or d */
  681. ch = *src++;
  682. if (ch == 'd')
  683. {
  684. lval = va_arg(ap, long);
  685. snprintf(tempbuf, sizeof(tempbuf), "%ld", lval);
  686. }
  687. else if (ch == 'u')
  688. {
  689. ulval = va_arg(ap, unsigned long);
  690. snprintf(tempbuf, sizeof(tempbuf), "%lu", ulval);
  691. }
  692. else if ((ch == 'l') && (*src == 'u'))
  693. {
  694. unsigned long long lluval = va_arg(ap, unsigned long long);
  695. snprintf(tempbuf, sizeof(tempbuf), "%llu", lluval);
  696. src++;
  697. }
  698. else
  699. {
  700. snprintf(tempbuf, sizeof(tempbuf), "Bad format string: \"%s\"", fmt);
  701. loglevel = LOG_LEVEL_FATAL;
  702. }
  703. break;
  704. case 'c':
  705. /*
  706. * Note that char parameters are converted to int, so we need to
  707. * pass "int" to va_arg. (See K&R, 2nd ed, section A7.3.2, page 202)
  708. */
  709. tempbuf[0] = (char) va_arg(ap, int);
  710. tempbuf[1] = '\0';
  711. break;
  712. case 's':
  713. format_string = va_arg(ap, char *);
  714. if (format_string == NULL)
  715. {
  716. format_string = "[null]";
  717. }
  718. break;
  719. case 'N':
  720. /*
  721. * Non-standard: Print a counted unterminated string,
  722. * replacing unprintable bytes with their hex value.
  723. * Takes 2 parameters: int length, const char * string.
  724. */
  725. ival = va_arg(ap, int);
  726. assert(ival >= 0);
  727. sval = va_arg(ap, char *);
  728. assert(sval != NULL);
  729. while ((ival-- > 0) && (length < log_buffer_size - 6))
  730. {
  731. if (isprint((int)*sval) && (*sval != '\\'))
  732. {
  733. outbuf[length++] = *sval;
  734. outbuf[length] = '\0';
  735. }
  736. else
  737. {
  738. int ret = snprintf(outbuf + length,
  739. log_buffer_size - length - 2, "\\x%.2x", (unsigned char)*sval);
  740. assert(ret == 4);
  741. length += 4;
  742. }
  743. sval++;
  744. }
  745. /*
  746. * XXX: In case of printable characters at the end of
  747. * the %N string, we're not using the whole buffer.
  748. */
  749. format_string = (length < log_buffer_size - 6) ? "" : "[too long]";
  750. break;
  751. case 'E':
  752. /* Non-standard: Print error code from errno */
  753. #ifdef _WIN32
  754. ival = WSAGetLastError();
  755. format_string = w32_socket_strerr(ival, tempbuf);
  756. #else /* ifndef _WIN32 */
  757. ival = errno;
  758. #ifdef HAVE_STRERROR
  759. format_string = strerror(ival);
  760. #else /* ifndef HAVE_STRERROR */
  761. format_string = NULL;
  762. #endif /* ndef HAVE_STRERROR */
  763. if (sval == NULL)
  764. {
  765. snprintf(tempbuf, sizeof(tempbuf), "(errno = %d)", ival);
  766. }
  767. #endif /* ndef _WIN32 */
  768. break;
  769. case 'T':
  770. /* Non-standard: Print a Common Log File timestamp */
  771. get_clf_timestamp(tempbuf, sizeof(tempbuf));
  772. break;
  773. default:
  774. snprintf(tempbuf, sizeof(tempbuf), "Bad format string: \"%s\"", fmt);
  775. loglevel = LOG_LEVEL_FATAL;
  776. break;
  777. }
  778. assert(length < log_buffer_size);
  779. length += strlcpy(outbuf + length, format_string, log_buffer_size - length);
  780. if (length >= log_buffer_size-2)
  781. {
  782. static const char warning[] = "... [too long, truncated]";
  783. length = log_buffer_size - sizeof(warning) - 1;
  784. length += strlcpy(outbuf + length, warning, log_buffer_size - length);
  785. assert(length < log_buffer_size);
  786. break;
  787. }
  788. }
  789. /* done with var. args */
  790. va_end(ap);
  791. assert(length < log_buffer_size);
  792. length += strlcpy(outbuf + length, "\n", log_buffer_size - length);
  793. /* Some sanity checks */
  794. if ((length >= log_buffer_size)
  795. || (outbuf[log_buffer_size-1] != '\0')
  796. || (outbuf[log_buffer_size] != '\0')
  797. )
  798. {
  799. /* Repeat as assertions */
  800. assert(length < log_buffer_size);
  801. assert(outbuf[log_buffer_size-1] == '\0');
  802. /*
  803. * outbuf's real size is log_buffer_size+1,
  804. * so while this looks like an off-by-one,
  805. * we're only checking our paranoia byte.
  806. */
  807. assert(outbuf[log_buffer_size] == '\0');
  808. snprintf(outbuf, log_buffer_size,
  809. "%s %08lx Fatal error: log_error()'s sanity checks failed."
  810. "length: %d. Exiting.",
  811. timestamp, thread_id, (int)length);
  812. loglevel = LOG_LEVEL_FATAL;
  813. }
  814. #ifndef _WIN32
  815. /*
  816. * On Windows this is acceptable in case
  817. * we are logging to the GUI window only.
  818. */
  819. assert(NULL != logfp);
  820. #endif
  821. lock_logfile();
  822. if (loglevel == LOG_LEVEL_FATAL)
  823. {
  824. fatal_error(outbuf);
  825. /* Never get here */
  826. }
  827. if (logfp != NULL)
  828. {
  829. fputs(outbuf, logfp);
  830. }
  831. #if defined(_WIN32) && !defined(_WIN_CONSOLE)
  832. /* Write to display */
  833. LogPutString(outbuf);
  834. #endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */
  835. unlock_logfile();
  836. }
  837. /*********************************************************************
  838. *
  839. * Function : jb_err_to_string
  840. *
  841. * Description : Translates JB_ERR_FOO codes into strings.
  842. *
  843. * Parameters :
  844. * 1 : jb_error = a valid jb_err code
  845. *
  846. * Returns : A string with the jb_err translation
  847. *
  848. *********************************************************************/
  849. const char *jb_err_to_string(jb_err jb_error)
  850. {
  851. switch (jb_error)
  852. {
  853. case JB_ERR_OK:
  854. return "Success, no error";
  855. case JB_ERR_MEMORY:
  856. return "Out of memory";
  857. case JB_ERR_CGI_PARAMS:
  858. return "Missing or corrupt CGI parameters";
  859. case JB_ERR_FILE:
  860. return "Error opening, reading or writing a file";
  861. case JB_ERR_PARSE:
  862. return "Parse error";
  863. case JB_ERR_MODIFIED:
  864. return "File has been modified outside of the CGI actions editor.";
  865. case JB_ERR_COMPRESS:
  866. return "(De)compression failure";
  867. }
  868. assert(0);
  869. return "Internal error";
  870. }
  871. #ifdef _WIN32
  872. /*********************************************************************
  873. *
  874. * Function : w32_socket_strerr
  875. *
  876. * Description : Translate the return value from WSAGetLastError()
  877. * into a string.
  878. *
  879. * Parameters :
  880. * 1 : errcode = The return value from WSAGetLastError().
  881. * 2 : tmp_buf = A temporary buffer that might be used to
  882. * store the string.
  883. *
  884. * Returns : String representing the error code. This may be
  885. * a global string constant or a string stored in
  886. * tmp_buf.
  887. *
  888. *********************************************************************/
  889. static char *w32_socket_strerr(int errcode, char *tmp_buf)
  890. {
  891. #define TEXT_FOR_ERROR(code,text) \
  892. if (errcode == code) \
  893. { \
  894. return #code " - " text; \
  895. }
  896. TEXT_FOR_ERROR(WSAEACCES, "Permission denied")
  897. TEXT_FOR_ERROR(WSAEADDRINUSE, "Address already in use.")
  898. TEXT_FOR_ERROR(WSAEADDRNOTAVAIL, "Cannot assign requested address.");
  899. TEXT_FOR_ERROR(WSAEAFNOSUPPORT, "Address family not supported by protocol family.");
  900. TEXT_FOR_ERROR(WSAEALREADY, "Operation already in progress.");
  901. TEXT_FOR_ERROR(WSAECONNABORTED, "Software caused connection abort.");
  902. TEXT_FOR_ERROR(WSAECONNREFUSED, "Connection refused.");
  903. TEXT_FOR_ERROR(WSAECONNRESET, "Connection reset by peer.");
  904. TEXT_FOR_ERROR(WSAEDESTADDRREQ, "Destination address required.");
  905. TEXT_FOR_ERROR(WSAEFAULT, "Bad address.");
  906. TEXT_FOR_ERROR(WSAEHOSTDOWN, "Host is down.");
  907. TEXT_FOR_ERROR(WSAEHOSTUNREACH, "No route to host.");
  908. TEXT_FOR_ERROR(WSAEINPROGRESS, "Operation now in progress.");
  909. TEXT_FOR_ERROR(WSAEINTR, "Interrupted function call.");
  910. TEXT_FOR_ERROR(WSAEINVAL, "Invalid argument.");
  911. TEXT_FOR_ERROR(WSAEISCONN, "Socket is already connected.");
  912. TEXT_FOR_ERROR(WSAEMFILE, "Too many open sockets.");
  913. TEXT_FOR_ERROR(WSAEMSGSIZE, "Message too long.");
  914. TEXT_FOR_ERROR(WSAENETDOWN, "Network is down.");
  915. TEXT_FOR_ERROR(WSAENETRESET, "Network dropped connection on reset.");
  916. TEXT_FOR_ERROR(WSAENETUNREACH, "Network is unreachable.");
  917. TEXT_FOR_ERROR(WSAENOBUFS, "No buffer space available.");
  918. TEXT_FOR_ERROR(WSAENOPROTOOPT, "Bad protocol option.");
  919. TEXT_FOR_ERROR(WSAENOTCONN, "Socket is not connected.");
  920. TEXT_FOR_ERROR(WSAENOTSOCK, "Socket operation on non-socket.");
  921. TEXT_FOR_ERROR(WSAEOPNOTSUPP, "Operation not supported.");
  922. TEXT_FOR_ERROR(WSAEPFNOSUPPORT, "Protocol family not supported.");
  923. TEXT_FOR_ERROR(WSAEPROCLIM, "Too many processes.");
  924. TEXT_FOR_ERROR(WSAEPROTONOSUPPORT, "Protocol not supported.");
  925. TEXT_FOR_ERROR(WSAEPROTOTYPE, "Protocol wrong type for socket.");
  926. TEXT_FOR_ERROR(WSAESHUTDOWN, "Cannot send after socket shutdown.");
  927. TEXT_FOR_ERROR(WSAESOCKTNOSUPPORT, "Socket type not supported.");
  928. TEXT_FOR_ERROR(WSAETIMEDOUT, "Connection timed out.");
  929. TEXT_FOR_ERROR(WSAEWOULDBLOCK, "Resource temporarily unavailable.");
  930. TEXT_FOR_ERROR(WSAHOST_NOT_FOUND, "Host not found.");
  931. TEXT_FOR_ERROR(WSANOTINITIALISED, "Successful WSAStartup not yet performed.");
  932. TEXT_FOR_ERROR(WSANO_DATA, "Valid name, no data record of requested type.");
  933. TEXT_FOR_ERROR(WSANO_RECOVERY, "This is a non-recoverable error.");
  934. TEXT_FOR_ERROR(WSASYSNOTREADY, "Network subsystem is unavailable.");
  935. TEXT_FOR_ERROR(WSATRY_AGAIN, "Non-authoritative host not found.");
  936. TEXT_FOR_ERROR(WSAVERNOTSUPPORTED, "WINSOCK.DLL version out of range.");
  937. TEXT_FOR_ERROR(WSAEDISCON, "Graceful shutdown in progress.");
  938. /*
  939. * The following error codes are documented in the Microsoft WinSock
  940. * reference guide, but don't actually exist.
  941. *
  942. * TEXT_FOR_ERROR(WSA_INVALID_HANDLE, "Specified event object handle is invalid.");
  943. * TEXT_FOR_ERROR(WSA_INVALID_PARAMETER, "One or more parameters are invalid.");
  944. * TEXT_FOR_ERROR(WSAINVALIDPROCTABLE, "Invalid procedure table from service provider.");
  945. * TEXT_FOR_ERROR(WSAINVALIDPROVIDER, "Invalid service provider version number.");
  946. * TEXT_FOR_ERROR(WSA_IO_PENDING, "Overlapped operations will complete later.");
  947. * TEXT_FOR_ERROR(WSA_IO_INCOMPLETE, "Overlapped I/O event object not in signaled state.");
  948. * TEXT_FOR_ERROR(WSA_NOT_ENOUGH_MEMORY, "Insufficient memory available.");
  949. * TEXT_FOR_ERROR(WSAPROVIDERFAILEDINIT, "Unable to initialize a service provider.");
  950. * TEXT_FOR_ERROR(WSASYSCALLFAILURE, "System call failure.");
  951. * TEXT_FOR_ERROR(WSA_OPERATION_ABORTED, "Overlapped operation aborted.");
  952. */
  953. sprintf(tmp_buf, "(error number %d)", errcode);
  954. return tmp_buf;
  955. }
  956. #endif /* def _WIN32 */
  957. /*
  958. Local Variables:
  959. tab-width: 3
  960. end:
  961. */