log.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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; /* the *nprintf funcs return how many bytes they
  49. * _would_ print, if the output is truncated */
  50. if (funcname) {
  51. n += snprintf(buf+n, buf_len-n, "%s(): ", funcname);
  52. if(n > buf_len)
  53. n = buf_len;
  54. }
  55. n += vsnprintf(buf+n,buf_len-n,format,ap);
  56. if(n > buf_len)
  57. n = buf_len;
  58. buf[n]='\n';
  59. buf[n+1]='\0';
  60. }
  61. static void
  62. logv(int severity, const char *funcname, const char *format, va_list ap)
  63. {
  64. char buf[1024];
  65. int formatted = 0;
  66. logfile_t *lf;
  67. assert(format);
  68. if (severity < loglevel)
  69. return;
  70. if (!logfiles) {
  71. /* XXX This is a temporary measure until we get configuration support
  72. for logfiles. */
  73. add_stream_log(loglevel, "<stdout>", stdout);
  74. }
  75. for (lf = logfiles; lf; lf = lf->next) {
  76. if (severity < lf->loglevel || severity > lf->max_loglevel)
  77. continue;
  78. if (!lf->file)
  79. continue;
  80. if (!formatted) {
  81. format_msg(buf, 1024, severity, funcname, format, ap);
  82. formatted = 1;
  83. }
  84. fputs(buf, lf->file);
  85. }
  86. }
  87. void
  88. log_set_severity(int severity)
  89. {
  90. loglevel = severity;
  91. }
  92. /* Outputs a message to stdout */
  93. void log(int severity, const char *format, ...)
  94. {
  95. va_list ap;
  96. va_start(ap,format);
  97. logv(severity, NULL, format, ap);
  98. va_end(ap);
  99. }
  100. void _log_fn(int severity, const char *fn, const char *format, ...)
  101. {
  102. va_list ap;
  103. va_start(ap,format);
  104. logv(severity, fn, format, ap);
  105. va_end(ap);
  106. }
  107. void close_logs()
  108. {
  109. logfile_t *next, *lf;
  110. for (lf = logfiles; lf; lf = lf->next) {
  111. if (lf->needs_close)
  112. fclose(lf->file);
  113. next = lf->next;
  114. free(lf);
  115. }
  116. logfiles = NULL;
  117. }
  118. void reset_logs()
  119. {
  120. logfile_t *lf;
  121. for (lf = logfiles; lf; lf = lf->next) {
  122. if (lf->needs_close) {
  123. fclose(lf->file);
  124. lf->file = fopen(lf->filename, "a");
  125. }
  126. }
  127. }
  128. void add_stream_log(int loglevel, const char *name, FILE *stream)
  129. {
  130. logfile_t *lf;
  131. lf = tor_malloc(sizeof(logfile_t));
  132. lf->filename = name;
  133. lf->needs_close = 0;
  134. lf->loglevel = loglevel;
  135. lf->max_loglevel = LOG_EMERG;
  136. lf->file = stream;
  137. lf->next = logfiles;
  138. logfiles = lf;
  139. }
  140. void add_file_log(int loglevel, const char *filename)
  141. {
  142. FILE *f;
  143. f = fopen(filename, "a");
  144. if (!f) return;
  145. add_stream_log(loglevel, filename, f);
  146. logfiles->needs_close = 1;
  147. }