/[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.20 - (show annotations) (download) (as text)
Sun May 5 15:19:11 2002 UTC (17 years, 5 months ago) by wingman
Branch: MAIN
Changes since 1.19: +9 -5 lines
File MIME type: text/x-chdr
Changes:

 * removed patch.h
 * added proper <filename>.h to (nearly) all <filename.h>
 * moved fixcolon to server.mod and irc.mod
 * moved ip2long to net.h
 * removed some unused function (forgot the name :-P)

Todo:

 * move config.h #include's away from main.h to files which
   needs them
 * clean up lib/eggdrop/module.h
   (now not just main.h is included but nearly all .h files from
    the core, but i guess this fixes itself when the global func
    table is abandon - then the modules must be revised too and
    we can clean up module.h)

And i'll bet i forgot something... ;-)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23