/[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.10 - (show annotations) (download) (as text)
Tue Nov 13 04:50:40 2001 UTC (17 years, 11 months ago) by stdarg
Branch: MAIN
Changes since 1.9: +1 -0 lines
File MIME type: text/x-chdr
* Added convenience functions for script_var_t's.
* Converted a bunch of functions in tcldcc.c.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23