/[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.12 - (show annotations) (download) (as text)
Sun Dec 9 21:43:36 2001 UTC (17 years, 10 months ago) by guppy
Branch: MAIN
Changes since 1.11: +1 -4 lines
File MIME type: text/x-chdr
log-time has been removed as a config setting

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23