log.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. /**
  5. * \file log.c
  6. *
  7. * \brief Functions to send messages to log files or the console.
  8. */
  9. #include <stdarg.h>
  10. #include <assert.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "orconfig.h"
  14. #include "./util.h"
  15. #include "./log.h"
  16. #ifdef MS_WINDOWS
  17. #define vsnprintf _vsnprintf
  18. #define snprintf _snprintf
  19. #endif
  20. /** Information for a single logfile; only used in log.c */
  21. typedef struct logfile_t {
  22. struct logfile_t *next; /**< Next logfile_t in the linked list. */
  23. const char *filename; /**< Filename to open. */
  24. FILE *file; /**< Stream to receive log messages. */
  25. int needs_close; /**< Boolean: true if the stream gets closed on shutdown. */
  26. int loglevel; /**< Lowest severity level to send to this stream. */
  27. int max_loglevel; /**< Highest severity level to send to this stream. */
  28. } logfile_t;
  29. /** Helper: map a log severity to descriptive string. */
  30. static INLINE const char *sev_to_string(int severity) {
  31. switch(severity) {
  32. case LOG_DEBUG: return "debug";
  33. case LOG_INFO: return "info";
  34. case LOG_NOTICE: return "notice";
  35. case LOG_WARN: return "warn";
  36. case LOG_ERR: return "err";
  37. default: assert(0); return "UNKNOWN";
  38. }
  39. }
  40. /** Linked list of logfile_t. */
  41. static logfile_t *logfiles = NULL;
  42. /** Helper: Format a log message into a fixed-sized buffer. (This is
  43. * factored out of <b>logv</b> so that we never format a message more
  44. * than once.)
  45. */
  46. static INLINE void format_msg(char *buf, size_t buf_len,
  47. int severity, const char *funcname,
  48. const char *format, va_list ap)
  49. {
  50. time_t t;
  51. struct timeval now;
  52. size_t n;
  53. buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
  54. tor_gettimeofday(&now);
  55. t = (time_t)now.tv_sec;
  56. n = strftime(buf, buf_len, "%b %d %H:%M:%S", localtime(&t));
  57. n += snprintf(buf+n, buf_len-n,
  58. ".%.3ld [%s] ",
  59. (long)now.tv_usec / 1000, sev_to_string(severity));
  60. if(n > buf_len)
  61. n = buf_len-1; /* the *nprintf funcs return how many bytes they
  62. * _would_ print, if the output is truncated.
  63. * Subtract one because the count doesn't include the \0 */
  64. if (funcname) {
  65. n += snprintf(buf+n, buf_len-n, "%s(): ", funcname);
  66. if(n > buf_len)
  67. n = buf_len-1;
  68. }
  69. n += vsnprintf(buf+n,buf_len-n,format,ap);
  70. if(n > buf_len)
  71. n = buf_len-1;
  72. buf[n]='\n';
  73. buf[n+1]='\0';
  74. }
  75. /** Helper: sends a message to the appropriate logfiles, at loglevel
  76. * <b>severity</b>. If provided, <b>funcname</b> is prepended to the
  77. * message. The actual message is derived as from vsprintf(format,ap).
  78. */
  79. static void
  80. logv(int severity, const char *funcname, const char *format, va_list ap)
  81. {
  82. char buf[10024];
  83. int formatted = 0;
  84. logfile_t *lf;
  85. assert(format);
  86. for (lf = logfiles; lf; lf = lf->next) {
  87. if (severity < lf->loglevel || severity > lf->max_loglevel)
  88. continue;
  89. if (!lf->file)
  90. continue;
  91. if (!formatted) {
  92. format_msg(buf, 10024, severity, funcname, format, ap);
  93. formatted = 1;
  94. }
  95. if(fputs(buf, lf->file) == EOF) { /* error */
  96. assert(0); /* XXX */
  97. }
  98. if(fflush(lf->file) == EOF) { /* error */
  99. /* don't log the error! */
  100. assert(0); /* XXX fail for now. what's better to do? */
  101. }
  102. }
  103. }
  104. /** Output a message to the log. */
  105. void _log(int severity, const char *format, ...)
  106. {
  107. va_list ap;
  108. va_start(ap,format);
  109. logv(severity, NULL, format, ap);
  110. va_end(ap);
  111. }
  112. /** Output a message to the log, prefixed with a function name <b>fn</b>. */
  113. void _log_fn(int severity, const char *fn, const char *format, ...)
  114. {
  115. va_list ap;
  116. va_start(ap,format);
  117. logv(severity, fn, format, ap);
  118. va_end(ap);
  119. }
  120. /** Close all open log files. */
  121. void close_logs()
  122. {
  123. logfile_t *victim;
  124. while(logfiles) {
  125. victim = logfiles;
  126. logfiles = logfiles->next;
  127. if (victim->needs_close)
  128. fclose(victim->file);
  129. free(victim);
  130. }
  131. }
  132. /** Close and re-open all log files; used to rotate logs on SIGHUP. */
  133. void reset_logs()
  134. {
  135. logfile_t *lf;
  136. for (lf = logfiles; lf; lf = lf->next) {
  137. if (lf->needs_close) {
  138. fclose(lf->file);
  139. lf->file = fopen(lf->filename, "a");
  140. }
  141. }
  142. }
  143. /** Add a log handler to send all messages of severity <b>loglevel</b>
  144. * or higher to <b>stream</b>. */
  145. void add_stream_log(int loglevelMin, int loglevelMax, const char *name, FILE *stream)
  146. {
  147. logfile_t *lf;
  148. lf = tor_malloc(sizeof(logfile_t));
  149. lf->filename = name;
  150. lf->needs_close = 0;
  151. lf->loglevel = loglevelMin;
  152. lf->max_loglevel = loglevelMax;
  153. lf->file = stream;
  154. lf->next = logfiles;
  155. logfiles = lf;
  156. }
  157. /**
  158. * Add a log handler to send messages to <b>filename</b>. If opening
  159. * the logfile fails, -1 is returned and errno is set appropriately
  160. * (by fopen).
  161. */
  162. int add_file_log(int loglevelMin, int loglevelMax, const char *filename)
  163. {
  164. FILE *f;
  165. f = fopen(filename, "a");
  166. if (!f) return -1;
  167. add_stream_log(loglevelMin, loglevelMax, filename, f);
  168. logfiles->needs_close = 1;
  169. return 0;
  170. }
  171. /** If <b>level</b> is a valid log severity, return the corresponding
  172. * numeric value. Otherwise, return -1. */
  173. int parse_log_level(const char *level) {
  174. if (!strcasecmp(level, "err"))
  175. return LOG_ERR;
  176. else if (!strcasecmp(level, "notice"))
  177. return LOG_NOTICE;
  178. else if (!strcasecmp(level, "info"))
  179. return LOG_INFO;
  180. else if (!strcasecmp(level, "debug"))
  181. return LOG_DEBUG;
  182. else
  183. return -1;
  184. }
  185. int get_min_log_level(void)
  186. {
  187. logfile_t *lf;
  188. int min = LOG_ERR;
  189. for (lf = logfiles; lf; lf = lf->next) {
  190. if (lf->loglevel < min)
  191. min = lf->loglevel;
  192. }
  193. return min;
  194. }
  195. /*
  196. Local Variables:
  197. mode:c
  198. indent-tabs-mode:nil
  199. c-basic-offset:2
  200. End:
  201. */