/[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.1 - (show annotations) (download) (as text)
Thu Oct 18 09:06:43 2001 UTC (18 years ago) by stdarg
Branch: MAIN
File MIME type: text/x-chdr
Fixed a bug in msprintf.
Added SCRIPT_FREE_VAR flag, to automatically free a script_var_t.
Added first config variables (for logging) via tclscript.mod.
Separated the logging stuff into logfile.c.
Added a command, "stoplog", which lets you close a logfile.
Removed "max-logs" since the logfiles are in a linked list (it was kind of pointless).

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23