log.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. #include "../or/or.h"
  5. #include "util.h"
  6. struct logfile_t;
  7. typedef struct logfile_t {
  8. struct logfile_t *next;
  9. const char *filename;
  10. FILE *file;
  11. int needs_close;
  12. int loglevel;
  13. int max_loglevel;
  14. } logfile_t;
  15. static INLINE const char *sev_to_string(int severity) {
  16. switch(severity) {
  17. case LOG_DEBUG: return "debug";
  18. case LOG_INFO: return "info";
  19. case LOG_NOTICE: return "notice";
  20. case LOG_WARNING: return "warn";
  21. case LOG_ERR: return "err";
  22. case LOG_CRIT: return "crit";
  23. case LOG_ALERT: return "alert";
  24. case LOG_EMERG: return "emerg";
  25. default: return "UNKNOWN";
  26. }
  27. }
  28. static int loglevel = LOG_DEBUG;
  29. static logfile_t *logfiles = NULL;
  30. /* Format a log message into a fixed-sized buffer. (This is factored out
  31. * of 'logv' so that we never format a message more than once.
  32. */
  33. static INLINE void format_msg(char *buf, size_t buf_len,
  34. int severity, const char *funcname,
  35. const char *format, va_list ap)
  36. {
  37. time_t t;
  38. struct timeval now;
  39. int n;
  40. buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
  41. my_gettimeofday(&now);
  42. t = (time_t)now.tv_sec;
  43. n = strftime(buf, buf_len, "%b %d %H:%M:%S", localtime(&t));
  44. n += snprintf(buf+n, buf_len-n,
  45. ".%.3ld [%s] ",
  46. (long)now.tv_usec / 1000, sev_to_string(severity));
  47. if(n > buf_len)
  48. n = buf_len-1; /* the *nprintf funcs return how many bytes they
  49. * _would_ print, if the output is truncated.
  50. * Subtract one because the count doesn't include the \0 */
  51. if (funcname) {
  52. n += snprintf(buf+n, buf_len-n, "%s(): ", funcname);
  53. if(n > buf_len)
  54. n = buf_len-1;
  55. }
  56. n += vsnprintf(buf+n,buf_len-n,format,ap);
  57. if(n > buf_len)
  58. n = buf_len-1;
  59. buf[n]='\n';
  60. buf[n+1]='\0';
  61. }
  62. static void
  63. logv(int severity, const char *funcname, const char *format, va_list ap)
  64. {
  65. char buf[1024];
  66. int formatted = 0;
  67. logfile_t *lf;
  68. assert(format);
  69. if (severity < loglevel)
  70. return;
  71. if (!logfiles) {
  72. /* XXX This is a temporary measure until we get configuration support
  73. for logfiles. */
  74. add_stream_log(loglevel, "<stdout>", stdout);
  75. }
  76. for (lf = logfiles; lf; lf = lf->next) {
  77. if (severity < lf->loglevel || severity > lf->max_loglevel)
  78. continue;
  79. if (!lf->file)
  80. continue;
  81. if (!formatted) {
  82. format_msg(buf, 1024, severity, funcname, format, ap);
  83. formatted = 1;
  84. }
  85. fputs(buf, lf->file);
  86. }
  87. }
  88. void
  89. log_set_severity(int severity)
  90. {
  91. loglevel = severity;
  92. }
  93. /* Outputs a message to stdout */
  94. void log(int severity, const char *format, ...)
  95. {
  96. va_list ap;
  97. va_start(ap,format);
  98. logv(severity, NULL, format, ap);
  99. va_end(ap);
  100. }
  101. void _log_fn(int severity, const char *fn, const char *format, ...)
  102. {
  103. va_list ap;
  104. va_start(ap,format);
  105. logv(severity, fn, format, ap);
  106. va_end(ap);
  107. }
  108. void close_logs()
  109. {
  110. logfile_t *next, *lf;
  111. for (lf = logfiles; lf; lf = lf->next) {
  112. if (lf->needs_close)
  113. fclose(lf->file);
  114. next = lf->next;
  115. free(lf);
  116. }
  117. logfiles = NULL;
  118. }
  119. void reset_logs()
  120. {
  121. logfile_t *lf;
  122. for (lf = logfiles; lf; lf = lf->next) {
  123. if (lf->needs_close) {
  124. fclose(lf->file);
  125. lf->file = fopen(lf->filename, "a");
  126. }
  127. }
  128. }
  129. void add_stream_log(int loglevel, const char *name, FILE *stream)
  130. {
  131. logfile_t *lf;
  132. lf = tor_malloc(sizeof(logfile_t));
  133. lf->filename = name;
  134. lf->needs_close = 0;
  135. lf->loglevel = loglevel;
  136. lf->max_loglevel = LOG_EMERG;
  137. lf->file = stream;
  138. lf->next = logfiles;
  139. logfiles = lf;
  140. }
  141. void add_file_log(int loglevel, const char *filename)
  142. {
  143. FILE *f;
  144. f = fopen(filename, "a");
  145. if (!f) return;
  146. add_stream_log(loglevel, filename, f);
  147. logfiles->needs_close = 1;
  148. }