/[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.16 - (show annotations) (download) (as text)
Mon Feb 25 02:59:50 2002 UTC (17 years, 7 months ago) by stdarg
Branch: MAIN
Changes since 1.15: +1 -9 lines
File MIME type: text/x-chdr
* Added 'timers' and 'timer_info' commands
* Removed some unnecessary usage of time(NULL) in logfile.c
* New global variable egg_timeval_now (like 'now' but with microseconds)
* Fixed some bugs, cleaned up some code, in egg_timer.c

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23