/[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.14 - (show annotations) (download) (as text)
Wed Jan 16 22:09:43 2002 UTC (17 years, 9 months ago) by ite
Branch: MAIN
Changes since 1.13: +4 -4 lines
File MIME type: text/x-chdr
Removed our malloc_strcpy macro sincw it had the same functionality of strdup (provided the respective fallback function)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23