Anope IRC Services  Version 1.8
log.c
Go to the documentation of this file.
1 /* Logging routines.
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 
14 #include "services.h"
15 #include "pseudo.h"
16 
17 static FILE *logfile;
18 
19 static int curday = 0;
20 
21 /*************************************************************************/
22 
23 static int get_logname(char *name, int count, struct tm *tm)
24 {
25  char timestamp[32];
26  time_t t;
27 
28 
29  if (!tm) {
30  time(&t);
31  tm = localtime(&t);
32  }
33 
34  /* fix bug 577 */
35  strftime(timestamp, sizeof(timestamp), "%Y%m%d", tm);
36  snprintf(name, count, "logs/%s.%s", log_filename, timestamp);
37  curday = tm->tm_yday;
38 
39  return 1;
40 }
41 
42 /*************************************************************************/
43 
44 static void remove_log(void)
45 {
46  time_t t;
47  struct tm tm;
48 
49  char name[PATH_MAX];
50 
51  if (!KeepLogs)
52  return;
53 
54  time(&t);
55  t -= (60 * 60 * 24 * KeepLogs);
56  tm = *localtime(&t);
57 
58  /* removed if from here cause get_logchan is always 1 */
59  get_logname(name, sizeof(name), &tm);
60 #ifndef _WIN32
61  unlink(name);
62 #else
63  DeleteFile(name);
64 #endif
65 }
66 
67 /*************************************************************************/
68 
69 static void checkday(void)
70 {
71  time_t t;
72  struct tm tm;
73 
74  time(&t);
75  tm = *localtime(&t);
76 
77  if (curday != tm.tm_yday) {
78  close_log();
79  remove_log();
80  open_log();
81  }
82 }
83 
84 /*************************************************************************/
85 
86 /* Open the log file. Return -1 if the log file could not be opened, else
87  * return 0. */
88 
89 int open_log(void)
90 {
91  char name[PATH_MAX];
92 
93  if (logfile)
94  return 0;
95 
96  /* if removed again.. get_logname is always 1 */
97  get_logname(name, sizeof(name), NULL);
98  logfile = fopen(name, "a");
99 
100  if (logfile)
101  setbuf(logfile, NULL);
102  return logfile != NULL ? 0 : -1;
103 }
104 
105 /*************************************************************************/
106 
107 /* Close the log file. */
108 
109 void close_log(void)
110 {
111  if (!logfile)
112  return;
113  fclose(logfile);
114  logfile = NULL;
115 }
116 
117 /*************************************************************************/
118 
119 /* added cause this is used over and over in the code */
120 char *log_gettimestamp(void)
121 {
122  time_t t;
123  struct tm tm;
124  static char tbuf[256];
125 
126  time(&t);
127  tm = *localtime(&t);
128 #if HAVE_GETTIMEOFDAY
129  if (debug) {
130  char *s;
131  struct timeval tv;
132  gettimeofday(&tv, NULL);
133  strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S", &tm);
134  s = tbuf + strlen(tbuf);
135  s += snprintf(s, sizeof(tbuf) - (s - tbuf), ".%06d",
136  (int) tv.tv_usec);
137  strftime(s, sizeof(tbuf) - (s - tbuf) - 1, " %Y]", &tm);
138  } else {
139 #endif
140  strftime(tbuf, sizeof(tbuf) - 1, "[%b %d %H:%M:%S %Y]", &tm);
141 #if HAVE_GETTIMEOFDAY
142  }
143 #endif
144  return tbuf;
145 }
146 
147 /*************************************************************************/
148 
149 /* Log stuff to the log file with a datestamp. Note that errno is
150  * preserved by this routine and log_perror().
151  */
152 
153 void alog(const char *fmt, ...)
154 {
155  va_list args;
156  char *buf;
157  int errno_save = errno;
158  char str[BUFSIZE];
159 
160  checkday();
161 
162  if (!fmt) {
163  return;
164  }
165 
166  va_start(args, fmt);
167  vsnprintf(str, sizeof(str), fmt, args);
168  va_end(args);
169 
170  buf = log_gettimestamp();
171 
172  if (logfile) {
173  fprintf(logfile, "%s %s\n", buf, str);
174  }
175  if (nofork) {
176  fprintf(stderr, "%s %s\n", buf, str);
177  }
178  if (LogChannel && logchan && !debug && findchan(LogChannel)) {
179  privmsg(s_GlobalNoticer, LogChannel, "%s", str);
180  }
181  errno = errno_save;
182 }
183 
184 /*************************************************************************/
185 
186 /* Like alog(), but tack a ": " and a system error message (as returned by
187  * strerror()) onto the end.
188  */
189 
190 void log_perror(const char *fmt, ...)
191 {
192  va_list args;
193  char *buf;
194  int errno_save = errno;
195  char str[BUFSIZE];
196 
197  checkday();
198 
199  if (!fmt) {
200  return;
201  }
202 
203  va_start(args, fmt);
204  vsnprintf(str, sizeof(str), fmt, args);
205  va_end(args);
206 
207  buf = log_gettimestamp();
208 
209  if (logfile) {
210  fprintf(logfile, "%s %s : %s\n", buf, str, strerror(errno_save));
211  }
212  if (nofork) {
213  fprintf(stderr, "%s %s : %s\n", buf, str, strerror(errno_save));
214  }
215  errno = errno_save;
216 }
217 
218 /*************************************************************************/
219 
220 /* We've hit something we can't recover from. Let people know what
221  * happened, then go down.
222  */
223 
224 void fatal(const char *fmt, ...)
225 {
226  va_list args;
227  char *buf;
228  char buf2[4096];
229 
230  checkday();
231 
232  if (!fmt) {
233  return;
234  }
235 
236  va_start(args, fmt);
237  vsnprintf(buf2, sizeof(buf2), fmt, args);
238  va_end(args);
239 
240  buf = log_gettimestamp();
241 
242  if (logfile)
243  fprintf(logfile, "%s FATAL: %s\n", buf, buf2);
244  if (nofork)
245  fprintf(stderr, "%s FATAL: %s\n", buf, buf2);
246  if (servsock >= 0)
247  anope_cmd_global(NULL, "FATAL ERROR! %s", buf2);
248 
249  /* one of the many places this needs to be called from */
251 
252  exit(1);
253 }
254 
255 /*************************************************************************/
256 
257 /* Same thing, but do it like perror(). */
258 
259 void fatal_perror(const char *fmt, ...)
260 {
261  va_list args;
262  char *buf;
263  char buf2[4096];
264  int errno_save = errno;
265 
266  checkday();
267 
268  if (!fmt) {
269  return;
270  }
271 
272  va_start(args, fmt);
273  vsnprintf(buf2, sizeof(buf2), fmt, args);
274  va_end(args);
275 
276  buf = log_gettimestamp();
277 
278  if (logfile)
279  fprintf(logfile, "%s FATAL: %s: %s\n", buf, buf2,
280  strerror(errno_save));
281  if (nofork)
282  fprintf(stderr, "%s FATAL: %s: %s\n", buf, buf2,
283  strerror(errno_save));
284  if (servsock >= 0)
285  anope_cmd_global(NULL, "FATAL ERROR! %s: %s", buf2,
286  strerror(errno_save));
287 
288  /* one of the many places this needs to be called from */
290 
291  exit(1);
292 }
293 
294 /*************************************************************************/
295 
296 /* Same thing, but do it like perror().
297  * This is for socket errors. On *nix, it works just like fatal_perror,
298  * on Win32, it uses the socket error code and formatting functions.
299  */
300 
301 void fatal_sockerror(const char *fmt, ...)
302 {
303  va_list args;
304  char *buf;
305  char buf2[4096];
306  int errno_save = ano_sockgeterr();
307 
308  if (!fmt) {
309  return;
310  }
311 
312  checkday();
313 
314  /* this will fix 581 */
315  va_start(args, fmt);
316  vsnprintf(buf2, sizeof(buf2), fmt, args);
317  va_end(args);
318 
319  buf = log_gettimestamp();
320 
321  if (logfile)
322  fprintf(logfile, "%s FATAL: %s: %s\n", buf, buf2,
323  ano_sockstrerror(errno_save));
324  if (stderr)
325  fprintf(stderr, "%s FATAL: %s: %s\n", buf, buf2,
326  ano_sockstrerror(errno_save));
327  if (servsock >= 0)
328  anope_cmd_global(NULL, "FATAL ERROR! %s: %s", buf2,
329  strerror(errno_save));
330 
331  /* one of the many places this needs to be called from */
333 
334  exit(1);
335 }
static FILE * logfile
Definition: log.c:17
int open_log(void)
Definition: log.c:89
void fatal_perror(const char *fmt,...)
Definition: log.c:259
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
void close_log(void)
Definition: log.c:109
#define ano_sockgeterr()
Definition: sockets.h:36
E int nofork
Definition: extern.h:779
E Channel * findchan(const char *chan)
Definition: channels.c:394
static int curday
Definition: log.c:19
void fatal_sockerror(const char *fmt,...)
Definition: log.c:301
E int servsock
Definition: extern.h:794
E char * log_filename
Definition: extern.h:774
E char * strerror(int errnum)
Definition: compat.c:123
void fatal(const char *fmt,...)
Definition: log.c:224
E void privmsg(char *source, char *dest, const char *fmt,...)
Definition: send.c:303
void alog(const char *fmt,...)
Definition: log.c:153
E int debug
Definition: extern.h:775
static void remove_log(void)
Definition: log.c:44
E int logchan
Definition: extern.h:777
#define ano_sockstrerror(err)
Definition: sockets.h:38
E int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
E void ModuleRunTimeDirCleanUp(void)
Definition: modules.c:2880
void log_perror(const char *fmt,...)
Definition: log.c:190
E char * LogChannel
Definition: extern.h:280
E int KeepLogs
Definition: extern.h:349
char * log_gettimestamp(void)
Definition: log.c:120
static int get_logname(char *name, int count, struct tm *tm)
Definition: log.c:23
static void checkday(void)
Definition: log.c:69
#define BUFSIZE
Definition: config.h:47
E char * s_GlobalNoticer
Definition: extern.h:290
E void anope_cmd_global(char *source, const char *fmt,...)
Definition: ircd.c:506