/[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.15 - (show annotations) (download) (as text)
Sat Jan 19 20:08:58 2002 UTC (17 years, 9 months ago) by ite
Branch: MAIN
Changes since 1.14: +2 -5 lines
File MIME type: text/x-chdr
* varoius header inclusion cleanups
* moved FILEDB* defines from src/egg.h to a more suitable place in modules/filesys/filesys.h
* moved NORMAL and QUICK defines from src/egg.h to a more suitable place in modules/irc/irc.h
* fixed a warning in modules/perlscript/perlscript.c
* created src/misc.h and src/logfile.h. Moved in them the respective prototypes from src/proto.h, and the respective defines from src/egg.h
* moved private structures from src/dns.h to src/dns.c
* moved src/dns.c's related prototypes from src/egg.h to src/dns.h
* moved RES_* defines from src/egg.h to dns.h
* removed some unneeded defines here and there
* moved LOG_* defines from src/egg.h to src/logfile.h
* dns_events wasn't static

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23