/[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.17 - (show annotations) (download) (as text)
Tue Mar 26 01:06:22 2002 UTC (17 years, 7 months ago) by ite
Branch: MAIN
Changes since 1.16: +0 -2 lines
File MIME type: text/x-chdr
* moved script API to libeggdrop (without using the bot context)
* fixed a wrong function name in perlscript
* do not use the bot context in registry for now

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23