Remove a possible source of error in circID picking.
[tor.git] / src / common / log.c
blob3a60d0576da26e97d24ea2eda4823a727f314bdb
1 /* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
2 /* See LICENSE for licensing information */
3 /* $Id$ */
5 #include "../or/or.h"
7 struct logfile_t;
8 typedef struct logfile_t {
9 struct logfile_t *next;
10 const char *filename;
11 FILE *file;
12 int needs_close;
13 int loglevel;
14 int max_loglevel;
15 } logfile_t;
17 static INLINE const char *sev_to_string(int severity) {
18 switch(severity) {
19 case LOG_DEBUG: return "debug";
20 case LOG_INFO: return "info";
21 case LOG_WARN: return "warn";
22 case LOG_ERR: return "err";
23 default: assert(0); return "UNKNOWN";
27 static int loglevel = LOG_DEBUG;
28 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.
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)
37 time_t t;
38 struct timeval now;
39 int n;
41 buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
43 tor_gettimeofday(&now);
44 t = (time_t)now.tv_sec;
46 n = strftime(buf, buf_len, "%b %d %H:%M:%S", localtime(&t));
47 n += snprintf(buf+n, buf_len-n,
48 ".%.3ld [%s] ",
49 (long)now.tv_usec / 1000, sev_to_string(severity));
50 if(n > buf_len)
51 n = buf_len-1; /* the *nprintf funcs return how many bytes they
52 * _would_ print, if the output is truncated.
53 * Subtract one because the count doesn't include the \0 */
55 if (funcname) {
56 n += snprintf(buf+n, buf_len-n, "%s(): ", funcname);
57 if(n > buf_len)
58 n = buf_len-1;
61 n += vsnprintf(buf+n,buf_len-n,format,ap);
62 if(n > buf_len)
63 n = buf_len-1;
64 buf[n]='\n';
65 buf[n+1]='\0';
68 static void
69 logv(int severity, const char *funcname, const char *format, va_list ap)
71 char buf[10024];
72 int formatted = 0;
73 logfile_t *lf;
75 assert(format);
76 if (severity < loglevel)
77 return;
78 for (lf = logfiles; lf; lf = lf->next) {
79 if (severity < lf->loglevel || severity > lf->max_loglevel)
80 continue;
81 if (!lf->file)
82 continue;
84 if (!formatted) {
85 format_msg(buf, 10024, severity, funcname, format, ap);
86 formatted = 1;
88 fputs(buf, lf->file);
89 fflush(lf->file);
90 /* XXX check for EOF */
94 void
95 log_set_severity(int severity)
97 loglevel = severity;
100 /* Outputs a message to stdout */
101 void _log(int severity, const char *format, ...)
103 va_list ap;
104 va_start(ap,format);
105 logv(severity, NULL, format, ap);
106 va_end(ap);
109 void _log_fn(int severity, const char *fn, const char *format, ...)
111 va_list ap;
112 va_start(ap,format);
113 logv(severity, fn, format, ap);
114 va_end(ap);
117 void close_logs()
119 logfile_t *victim;
120 while(logfiles) {
121 victim = logfiles;
122 logfiles = logfiles->next;
123 if (victim->needs_close)
124 fclose(victim->file);
125 free(victim);
129 void reset_logs()
131 logfile_t *lf;
132 for (lf = logfiles; lf; lf = lf->next) {
133 if (lf->needs_close) {
134 fclose(lf->file);
135 lf->file = fopen(lf->filename, "a");
140 void add_stream_log(int loglevel, const char *name, FILE *stream)
142 logfile_t *lf;
143 lf = tor_malloc(sizeof(logfile_t));
144 lf->filename = name;
145 lf->needs_close = 0;
146 lf->loglevel = loglevel;
147 lf->max_loglevel = LOG_ERR;
148 lf->file = stream;
149 lf->next = logfiles;
150 logfiles = lf;
153 int add_file_log(int loglevel, const char *filename)
155 FILE *f;
156 f = fopen(filename, "a");
157 if (!f) return -1;
158 add_stream_log(loglevel, filename, f);
159 logfiles->needs_close = 1;
160 return 0;