/[cvs]/eggdrop1.9/src/logfile.c
ViewVC logotype

Contents of /eggdrop1.9/src/logfile.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.25 - (show annotations) (download) (as text)
Sat Jan 18 22:36:52 2003 UTC (16 years, 9 months ago) by wcc
Branch: MAIN
Changes since 1.24: +4 -2 lines
File MIME type: text/x-chdr
* Synch 1.6: nickbind, unixtime_incr, transfer-close, logblocking.

1 /*
2 * logfile.c --
3 *
4 */
5 /*
6 * Copyright (C) 2002, 2003 Eggheads Development Team
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 #ifndef lint
24 static const char rcsid[] = "$Id: logfile.c,v 1.24 2003/01/02 21:33:16 wcc Exp $";
25 #endif
26
27 #include "main.h"
28 //#include "chanprog.h" /* logmodes */
29 #include "modules.h" /* add_hook() */
30 #include "lib/egglib/msprintf.h"
31 #include "logfile.h" /* prototypes */
32 #include "dccutil.h" /* dprintf_eggdrop */
33 #include "irccmp.h" /* irccmp */
34
35 typedef struct log_b {
36 struct log_b *next;
37 char *filename;
38 int mask;
39 char *chname;
40 char *last_msg;
41 int repeats;
42 int flags;
43 FILE *fp;
44 } log_t;
45
46 extern int use_stderr; /* From main.c, while we're starting eggdrop. */
47 extern int term_z;
48 extern int backgrd;
49 extern int con_chan;
50 extern time_t now;
51
52 extern int dcc_total;
53 extern struct dcc_t *dcc;
54
55 #ifndef MAKING_MODS
56 extern struct dcc_table DCC_CHAT;
57 #endif /* MAKING_MODS */
58
59 static int cycle_at = 300; /* Military time where we cycle logfiles. */
60 static int keep_all_logs = 0; /* Keep all logs? */
61 static int max_logsize = 0; /* Max log size in kilobytes. */
62 static int quick_logs = 0; /* Check size more often? */
63 static char *logfile_suffix = NULL; /* Suffix for old logfiles. */
64
65 static log_t *log_list_head = NULL; /* Linked list of logfiles. */
66
67 static int logfile_minutely();
68 static int logfile_5minutely();
69 static int logfile_cycle();
70 static void check_logsizes();
71 static void flushlog(log_t *log, char *timestamp);
72
73 /* Functions for accessing the logfiles via scripts. */
74 static int script_putlog(void *cdata, char *text);
75 static int script_putloglev(char *level, char *chan, char *text);
76
77 static script_command_t log_script_cmds[] = {
78 {"", "putlog", script_putlog, (void *)LOG_MISC, 1, "s", "text", SCRIPT_INTEGER, SCRIPT_PASS_CDATA},
79 {"", "putcmdlog", script_putlog, (void *)LOG_CMDS, 1, "s", "text", SCRIPT_INTEGER, SCRIPT_PASS_CDATA},
80 {"", "putxferlog", script_putlog, (void *)LOG_FILES, 1, "s", "text", SCRIPT_INTEGER, SCRIPT_PASS_CDATA},
81 {"", "putloglev", script_putloglev, NULL, 3, "sss", "level channel text", SCRIPT_INTEGER, 0},
82 {"", "logfile", (Function) logfile_add, NULL, 3, "sss", "modes channel filename", SCRIPT_STRING, 0},
83 {"", "stoplog", logfile_del, NULL, 1, "s", "filename", SCRIPT_INTEGER, 0},
84 {0}
85 };
86
87 static script_linked_var_t log_script_vars[] = {
88 {"", "logfile_suffix", &logfile_suffix, SCRIPT_STRING, NULL},
89 {"", "max_logsize", &max_logsize, SCRIPT_INTEGER, NULL},
90 {"", "switch_logfiles_at", &cycle_at, SCRIPT_INTEGER, NULL},
91 {"", "keep_all_logs", &keep_all_logs, SCRIPT_INTEGER, NULL},
92 {"", "quick_logs", &quick_logs, SCRIPT_INTEGER, NULL},
93 {0}
94 };
95
96 void logfile_init()
97 {
98 logfile_suffix = strdup(".%d%b%Y");
99 script_create_commands(log_script_cmds);
100 script_link_vars(log_script_vars);
101 add_hook(HOOK_MINUTELY, logfile_minutely);
102 add_hook(HOOK_5MINUTELY, logfile_5minutely);
103 }
104
105 static int get_timestamp(char *t)
106 {
107 time_t now2 = time(NULL);
108
109 /* Calculate timestamp. */
110 strftime(t, 32, "[%H:%M] ", localtime(&now2));
111 return(0);
112 }
113
114 static int logfile_minutely()
115 {
116 struct tm *nowtm;
117 int miltime;
118
119 if (quick_logs) {
120 flushlogs();
121 check_logsizes();
122 }
123
124 nowtm = localtime(&now);
125 miltime = 100 * nowtm->tm_hour + nowtm->tm_min;
126
127 if (miltime == cycle_at) logfile_cycle();
128
129 return(0);
130 }
131
132 static int logfile_5minutely()
133 {
134 if (!quick_logs) {
135 flushlogs();
136 check_logsizes();
137 }
138 return(0);
139 }
140
141 static int logfile_cycle()
142 {
143 log_t *log, *prev;
144 char suffix[32];
145 char *newfname;
146
147 putlog(LOG_MISC, "*", _("Cycling logfiles"));
148 flushlogs();
149
150 /* Determine suffix for cycled logfiles. */
151 if (keep_all_logs) {
152 strftime(suffix, 32, logfile_suffix, localtime(&now));
153 }
154
155 prev = NULL;
156 for (log = log_list_head; log; log = log->next) {
157 fclose(log->fp);
158
159 if (keep_all_logs) newfname = msprintf("%s%s", log->filename, suffix);
160 else newfname = msprintf("%s.yesterday", log->filename);
161
162 unlink(newfname);
163 movefile(log->filename, newfname);
164 free(newfname);
165
166 log->fp = fopen(log->filename, "a");
167 if (!log->fp) {
168 logfile_del(log->filename);
169 if (prev) log = prev;
170 else log = log_list_head;
171 }
172 else prev = log;
173 }
174 return(0);
175 }
176
177 static int script_putlog(void *cdata, char *text)
178 {
179 return putlog((int) cdata, "*", "%s", text);
180 }
181
182 static int script_putloglev(char *level, char *chan, char *text)
183 {
184 int lev = 0;
185
186 //lev = logmodes(level);
187 //if (!lev) return(-1);
188 lev = LOG_MISC;
189 return putlog(lev, chan, "%s", text);
190 }
191
192 char *logfile_add(char *modes, char *chan, char *fname)
193 {
194 FILE *fp;
195 log_t *log;
196
197 /* Get rid of any duplicates. */
198 logfile_del(fname);
199
200 /* Test the filename. */
201 fp = fopen(fname, "a");
202 if (!fp) return("");
203
204 log = (log_t *)calloc(1, sizeof(*log));
205 log->filename = strdup(fname);
206 log->chname = strdup(chan);
207 log->last_msg = strdup("");
208 log->mask = LOG_MISC;
209 //log->mask = logmodes(modes);
210 log->fp = fp;
211
212 log->next = log_list_head;
213 log_list_head = log;
214
215 return(log->filename);
216 }
217
218 int logfile_del(char *filename)
219 {
220 log_t *log, *prev;
221 char timestamp[32];
222
223 prev = NULL;
224 for (log = log_list_head; log; log = log->next) {
225 if (!strcmp(log->filename, filename)) break;
226 prev = log;
227 }
228 if (!log) return(1);
229 if (prev) prev->next = log->next;
230 else log_list_head = log->next;
231 if (log->fp) {
232 get_timestamp(timestamp);
233 flushlog(log, timestamp);
234 fclose(log->fp);
235 }
236 free(log->last_msg);
237 free(log->filename);
238 free(log);
239 return(0);
240 }
241
242 /* Log something
243 * putlog(level,channel_name,format,...);
244 */
245 int putlog EGG_VARARGS_DEF(int, arg1)
246 {
247 int i, type, len;
248 log_t *log;
249 char *format, *chname, *out;
250 char timestamp[32];
251 va_list va;
252
253
254 len = 128;
255 out = (char *)malloc(len);
256 while (1) {
257 type = EGG_VARARGS_START(int, arg1, va);
258 chname = va_arg(va, char *);
259 format = va_arg(va, char *);
260 i = vsnprintf(out, len, format, va);
261 if (i > -1 && i < len) break; /* Done. */
262 if (i > len) len = i+1; /* Exact amount. */
263 else len *= 2; /* Just guessing. */
264 out = (char *)realloc(out, len);
265 }
266 len = i;
267
268 va_end(va);
269
270 get_timestamp(timestamp);
271 for (log = log_list_head; log; log = log->next) {
272 /* If this log doesn't match, skip it. */
273 if (!(log->mask & type)) continue;
274 if (chname[0] != '*' && log->chname[0] != '*' && irccmp(chname, log->chname)) continue;
275
276 /* If it's a repeat message, don't write it again. */
277 if (!strcasecmp(out, log->last_msg)) {
278 log->repeats++;
279 continue;
280 }
281
282 /* If there was a repeated message, write the count. */
283 if (log->repeats) {
284 fprintf(log->fp, "%s", timestamp);
285 fprintf(log->fp, _("Last message repeated %d time(s).\n"), log->repeats);
286 log->repeats = 0;
287 }
288
289 /* Save this msg to check for repeats next time. */
290 realloc_strcpy(log->last_msg, out);
291
292 /* Now output to the file. */
293 fprintf(log->fp, "%s%s\n", timestamp, out);
294 }
295
296 for (i = 0; i < dcc_total; i++)
297 if ((dcc[i].type == &DCC_CHAT) && (dcc[i].u.chat->con_flags & type)) {
298 if ((chname[0] == '*') || (dcc[i].u.chat->con_chan[0] == '*') ||
299 (!irccmp(chname, dcc[i].u.chat->con_chan)))
300 dprintf(i, "%s%s\n", timestamp, out);
301 }
302 if ((!backgrd) && (!con_chan) && (!term_z))
303 dprintf(DP_STDOUT, "%s%s\n", timestamp, out);
304 else if ((type & LOG_MISC) && use_stderr) {
305 dprintf(DP_STDERR, "%s%s\n", timestamp, out);
306 }
307
308 free(out);
309 return(len);
310 }
311
312 static void check_logsizes()
313 {
314 int size;
315 char *newfname;
316 log_t *log;
317
318 if (keep_all_logs || max_logsize <= 0) return;
319
320 for (log = log_list_head; log; log = log->next) {
321 size = ftell(log->fp) / 1024; /* Size in kilobytes. */
322 if (size < max_logsize) continue;
323
324 /* It's too big. */
325 putlog(LOG_MISC, "*", _("Cycling logfile %s, over max-logsize (%d kilobytes)"), log->filename, size);
326 fflush(log->fp);
327 fclose(log->fp);
328
329 newfname = msprintf("%s.yesterday", log->filename);
330 unlink(newfname);
331 movefile(log->filename, newfname);
332 free(newfname);
333 }
334 }
335
336 static void flushlog(log_t *log, char *timestamp)
337 {
338 if (log->repeats) {
339 fprintf(log->fp, "%s", timestamp);
340 fprintf(log->fp, _("Last message repeated %d time(s).\n"), log->repeats);
341 log->repeats = 0;
342 realloc_strcpy(log->last_msg, "");
343 }
344 fflush(log->fp);
345 }
346
347 /* Flush the logfiles to disk
348 */
349 void flushlogs()
350 {
351 char timestamp[32];
352 log_t *log;
353
354 get_timestamp(timestamp);
355 for (log = log_list_head; log; log = log->next) {
356 flushlog(log, timestamp);
357 }
358 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23