/[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.26 - (show annotations) (download) (as text)
Mon Feb 3 01:01:07 2003 UTC (16 years, 8 months ago) by stdarg
Branch: MAIN
Changes since 1.25: +31 -95 lines
File MIME type: text/x-chdr
* Let me know if there are any missing files!

1 /*
2 * logfile.c --
3 *
4 */
5
6 #include "main.h"
7 #include "modules.h" /* add_hook() */
8 #include "logfile.h" /* prototypes */
9 #include "dccutil.h" /* dprintf_eggdrop */
10 #include "irccmp.h" /* irccmp */
11 #include "chanprog.h" /* logmodes */
12 #include <eggdrop/eggdrop.h>
13
14 typedef struct log_b {
15 struct log_b *next;
16 char *filename;
17 int mask;
18 char *chname;
19 char *last_msg;
20 int repeats;
21 int flags;
22 FILE *fp;
23 } log_t;
24
25 extern int use_stderr; /* From main.c, while we're starting eggdrop. */
26 extern int term_z;
27 extern int backgrd;
28 extern int con_chan;
29 extern time_t now;
30
31 extern int dcc_total;
32 extern struct dcc_t *dcc;
33
34 #ifndef MAKING_MODS
35 extern struct dcc_table DCC_CHAT;
36 #endif /* MAKING_MODS */
37
38 static int cycle_at = 300; /* Military time where we cycle logfiles. */
39 static int keep_all_logs = 0; /* Keep all logs? */
40 static int max_logsize = 0; /* Max log size in kilobytes. */
41 static int quick_logs = 0; /* Check size more often? */
42 static char *logfile_suffix = NULL; /* Suffix for old logfiles. */
43
44 static log_t *log_list_head = NULL; /* Linked list of logfiles. */
45
46 static int logfile_minutely();
47 static int logfile_5minutely();
48 static int logfile_cycle();
49 static void check_logsizes();
50 static void flushlog(log_t *log, char *timestamp);
51
52 /* Functions for accessing the logfiles via scripts. */
53 static int script_putlog(char *text);
54 static int script_putloglev(char *level, char *chan, char *text);
55
56 /* Bind for the log table. The core does logging to files and the partyline, but
57 * modules may implement sql logging or whatever. */
58 static int on_putlog(int flags, const char *chan, const char *text, int len);
59
60 static script_linked_var_t log_script_vars[] = {
61 {"", "logfile_suffix", &logfile_suffix, SCRIPT_STRING, NULL},
62 {"", "max_logsize", &max_logsize, SCRIPT_INTEGER, NULL},
63 {"", "switch_logfiles_at", &cycle_at, SCRIPT_INTEGER, NULL},
64 {"", "keep_all_logs", &keep_all_logs, SCRIPT_INTEGER, NULL},
65 {"", "quick_logs", &quick_logs, SCRIPT_INTEGER, NULL},
66 {0}
67 };
68
69 static bind_list_t log_binds[] = {
70 {"", on_putlog},
71 {0}
72 };
73
74 void logfile_init()
75 {
76 logfile_suffix = strdup(".%d%b%Y");
77 script_link_vars(log_script_vars);
78 add_hook(HOOK_MINUTELY, logfile_minutely);
79 add_hook(HOOK_5MINUTELY, logfile_5minutely);
80 bind_add_list("log", log_binds);
81 }
82
83 static int get_timestamp(char *t)
84 {
85 time_t now2 = time(NULL);
86
87 /* Calculate timestamp. */
88 strftime(t, 32, "[%H:%M] ", localtime(&now2));
89 return(0);
90 }
91
92 static int logfile_minutely()
93 {
94 struct tm *nowtm;
95 int miltime;
96
97 if (quick_logs) {
98 flushlogs();
99 check_logsizes();
100 }
101
102 nowtm = localtime(&now);
103 miltime = 100 * nowtm->tm_hour + nowtm->tm_min;
104
105 if (miltime == cycle_at) logfile_cycle();
106
107 return(0);
108 }
109
110 static int logfile_5minutely()
111 {
112 if (!quick_logs) {
113 flushlogs();
114 check_logsizes();
115 }
116 return(0);
117 }
118
119 static int logfile_cycle()
120 {
121 log_t *log, *prev;
122 char suffix[32];
123 char *newfname;
124
125 putlog(LOG_MISC, "*", _("Cycling logfiles"));
126 flushlogs();
127
128 /* Determine suffix for cycled logfiles. */
129 if (keep_all_logs) {
130 strftime(suffix, 32, logfile_suffix, localtime(&now));
131 }
132
133 prev = NULL;
134 for (log = log_list_head; log; log = log->next) {
135 fclose(log->fp);
136
137 if (keep_all_logs) newfname = egg_mprintf("%s%s", log->filename, suffix);
138 else newfname = egg_mprintf("%s.yesterday", log->filename);
139
140 unlink(newfname);
141 movefile(log->filename, newfname);
142 free(newfname);
143
144 log->fp = fopen(log->filename, "a");
145 if (!log->fp) {
146 logfile_del(log->filename);
147 if (prev) log = prev;
148 else log = log_list_head;
149 }
150 else prev = log;
151 }
152 return(0);
153 }
154
155 char *logfile_add(char *modes, char *chan, char *fname)
156 {
157 FILE *fp;
158 log_t *log;
159
160 /* Get rid of any duplicates. */
161 logfile_del(fname);
162
163 /* Test the filename. */
164 fp = fopen(fname, "a");
165 if (!fp) return("");
166
167 log = (log_t *)calloc(1, sizeof(*log));
168 log->filename = strdup(fname);
169 log->chname = strdup(chan);
170 log->last_msg = strdup("");
171 log->mask = logmodes(modes);
172 log->fp = fp;
173
174 log->next = log_list_head;
175 log_list_head = log;
176
177 return(log->filename);
178 }
179
180 int logfile_del(char *filename)
181 {
182 log_t *log, *prev;
183 char timestamp[32];
184
185 prev = NULL;
186 for (log = log_list_head; log; log = log->next) {
187 if (!strcmp(log->filename, filename)) break;
188 prev = log;
189 }
190 if (!log) return(1);
191 if (prev) prev->next = log->next;
192 else log_list_head = log->next;
193 if (log->fp) {
194 get_timestamp(timestamp);
195 flushlog(log, timestamp);
196 fclose(log->fp);
197 }
198 free(log->last_msg);
199 free(log->filename);
200 free(log);
201 return(0);
202 }
203
204 static int on_putlog(int flags, const char *chan, const char *text, int len)
205 {
206 log_t *log;
207 char timestamp[32];
208 int i;
209
210 get_timestamp(timestamp);
211 for (log = log_list_head; log; log = log->next) {
212 /* If this log doesn't match, skip it. */
213 if (!(log->mask & flags)) continue;
214 if (chan[0] != '*' && log->chname[0] != '*' && irccmp(chan, log->chname)) continue;
215
216 /* If it's a repeat message, don't write it again. */
217 if (!strcasecmp(text, log->last_msg)) {
218 log->repeats++;
219 continue;
220 }
221
222 /* If there was a repeated message, write the count. */
223 if (log->repeats) {
224 fprintf(log->fp, "%s", timestamp);
225 fprintf(log->fp, _("Last message repeated %d time(s).\n"), log->repeats);
226 log->repeats = 0;
227 }
228
229 /* Save this msg to check for repeats next time. */
230 str_redup(&log->last_msg, text);
231
232 /* Now output to the file. */
233 fprintf(log->fp, "%s%s\n", timestamp, text);
234 }
235
236 for (i = 0; i < dcc_total; i++)
237 if ((dcc[i].type == &DCC_CHAT)) {
238 dprintf(i, "%s%s\n", timestamp, text);
239 }
240 if ((!backgrd) && (!con_chan) && (!term_z))
241 dprintf(DP_STDOUT, "%s%s\n", timestamp, text);
242 else if (use_stderr) {
243 dprintf(DP_STDERR, "%s%s\n", timestamp, text);
244 }
245
246 return(0);
247 }
248
249 static void check_logsizes()
250 {
251 int size;
252 char *newfname;
253 log_t *log;
254
255 if (keep_all_logs || max_logsize <= 0) return;
256
257 for (log = log_list_head; log; log = log->next) {
258 size = ftell(log->fp) / 1024; /* Size in kilobytes. */
259 if (size < max_logsize) continue;
260
261 /* It's too big. */
262 putlog(LOG_MISC, "*", _("Cycling logfile %s, over max-logsize (%d kilobytes)"), log->filename, size);
263 fclose(log->fp);
264
265 newfname = egg_mprintf("%s.yesterday", log->filename);
266 unlink(newfname);
267 movefile(log->filename, newfname);
268 free(newfname);
269 }
270 }
271
272 static void flushlog(log_t *log, char *timestamp)
273 {
274 if (log->repeats) {
275 fprintf(log->fp, "%s", timestamp);
276 fprintf(log->fp, _("Last message repeated %d time(s).\n"), log->repeats);
277 log->repeats = 0;
278 realloc_strcpy(log->last_msg, "");
279 }
280 fflush(log->fp);
281 }
282
283 /* Flush the logfiles to disk
284 */
285 void flushlogs()
286 {
287 char timestamp[32];
288 log_t *log;
289
290 get_timestamp(timestamp);
291 for (log = log_list_head; log; log = log->next) {
292 flushlog(log, timestamp);
293 }
294 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23