/[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.49 - (show annotations) (download) (as text)
Mon Oct 4 15:48:30 2004 UTC (15 years ago) by stdarg
Branch: MAIN
Changes since 1.48: +2 -1 lines
File MIME type: text/x-chdr
* Reorganized channel functions into several files to aid readability
* Got rid of separate "static" channels since it was confusing

1 /* logfile.c: logging
2 *
3 * Copyright (C) 2001, 2002, 2003, 2004 Eggheads Development Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21 #ifndef lint
22 static const char rcsid[] = "$Id: logfile.c,v 1.48 2004/09/26 09:42:09 stdarg Exp $";
23 #endif
24
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <eggdrop/eggdrop.h>
30 #include "core_config.h"
31 #include "terminal.h" /* TERMINAL_NICK */
32 #include "logfile.h"
33
34
35 static logfile_t *logfiles = NULL;
36 static int nlogfiles = 0;
37
38 extern int backgrd, use_stderr, terminal_mode;
39 int terminal_enabled = 0;
40 extern time_t now;
41
42 static int logfile_minutely();
43 static int logfile_5minutely();
44 static int logfile_cycle();
45 static void check_logsizes();
46 static void flushlog(logfile_t *log, char *timestamp);
47
48 /* Bind for the log table. The core does logging to files and the partyline, but
49 * modules may implement sql logging or whatever. */
50 static int on_putlog(int flags, const char *chan, const char *text, int len);
51
52 static script_command_t log_script_cmds[] = {
53 {"", "logfile", logfile_add, NULL, 3, "sss", "modes chan filename", SCRIPT_STRING, 0}, /* DDD */
54 {0}
55 };
56
57 void logfile_init(void)
58 {
59 void *root, *node;
60 char *filename, *chname, *mask;
61 int i;
62
63 script_create_commands(log_script_cmds);
64 bind_add_simple("log", NULL, NULL, on_putlog);
65 bind_add_simple("event", NULL, "minutely", logfile_minutely);
66 bind_add_simple("event", NULL, "5minutely", logfile_5minutely);
67
68 root = config_get_root("eggdrop");
69 node = config_lookup_section(root, "eggdrop.logging.logfiles", 0, NULL);
70 for (i = 0; ; i++) {
71 config_get_str(&filename, node, "logfile", i, "filename", 0, NULL);
72 config_get_str(&chname, node, "logfile", i, "channel", 0, NULL);
73 config_get_str(&mask, node, "logfile", i, "mask", 0, NULL);
74 if (!filename || !chname || !mask) break;
75 logfile_add(mask, chname, filename);
76 }
77 }
78
79 void logfile_shutdown(void)
80 {
81 void *root, *node;
82 int i;
83
84 flushlogs();
85
86 root = config_get_root("eggdrop");
87 node = config_lookup_section(root, "eggdrop.logging.logfiles", 0, NULL);
88 for (i = 0; i < nlogfiles; i++) {
89 config_set_str(logfiles[i].filename, node, "logfile", i, "filename", 0, NULL);
90 config_set_str(logfiles[i].chname, node, "logfile", i, "channel", 0, NULL);
91 config_set_str("*", node, "logfile", i, "mask", 0, NULL);
92 }
93
94 bind_rem_simple("log", NULL, NULL, on_putlog);
95 bind_rem_simple("event", NULL, "minutely", logfile_minutely);
96 bind_rem_simple("event", NULL, "5minutely", logfile_5minutely);
97 script_delete_commands(log_script_cmds);
98 }
99
100 static int logfile_minutely()
101 {
102 struct tm *nowtm;
103 int miltime;
104
105 if (core_config.logging.quick) {
106 flushlogs();
107 check_logsizes();
108 }
109
110 nowtm = localtime(&now);
111 miltime = 100 * nowtm->tm_hour + nowtm->tm_min;
112
113 if (miltime == core_config.logging.switch_at) logfile_cycle();
114
115 return(0);
116 }
117
118 static int logfile_5minutely()
119 {
120 if (!core_config.logging.quick) {
121 flushlogs();
122 check_logsizes();
123 }
124 return(0);
125 }
126
127 static int logfile_cycle()
128 {
129 logfile_t *log;
130 int i;
131 char suffix[32];
132 char *newfname;
133
134 putlog(LOG_MISC, "*", _("Cycling logfiles..."));
135 flushlogs();
136
137 /* Determine suffix for cycled logfiles. */
138 if (core_config.logging.keep_all) {
139 strftime(suffix, 32, core_config.logging.suffix, localtime(&now));
140 }
141
142 for (i = nlogfiles - 1; i >= 0; i--) {
143 log = &logfiles[i];
144
145 fclose(log->fp);
146
147 if (core_config.logging.keep_all) newfname = egg_mprintf("%s%s", log->filename, suffix);
148 else newfname = egg_mprintf("%s.yesterday", log->filename);
149
150 unlink(newfname);
151 movefile(log->filename, newfname);
152 free(newfname);
153
154 log->fp = fopen(log->filename, "a");
155 if (!log->fp) logfile_del(log->filename);
156 }
157
158 return(0);
159 }
160
161 char *logfile_add(char *modes, char *chan, char *fname)
162 {
163 FILE *fp;
164 logfile_t *log;
165
166 /* Get rid of any duplicates. */
167 logfile_del(fname);
168
169 /* Test the filename. */
170 fp = fopen(fname, "a");
171 if (!fp) return("");
172
173 logfiles = realloc(logfiles, (nlogfiles + 1) * sizeof(*logfiles));
174
175 log = &logfiles[nlogfiles++];
176 memset(log, 0, sizeof(*log));
177 log->filename = strdup(fname);
178 log->chname = strdup(chan);
179 log->last_msg = strdup("");
180 log->mask = LOG_ALL;
181 log->fp = fp;
182
183 return (log->filename);
184 }
185
186 int logfile_del(char *filename)
187 {
188 logfile_t *log;
189 int i;
190
191 log = NULL;
192 for (i = 0; i < nlogfiles; i++) {
193 log = &logfiles[i];
194 if (!strcmp(log->filename, filename)) break;
195 log = NULL;
196 }
197
198 if (log == NULL) return(-1);
199
200 if (log->fp) {
201 flushlog(log, timer_get_timestamp());
202 fclose(log->fp);
203 }
204
205 if (log->last_msg) free(log->last_msg);
206 if (log->filename) free(log->filename);
207
208 if (nlogfiles == 1) {
209 free(logfiles);
210 logfiles = NULL;
211 } else {
212 memmove(logfiles + i, logfiles + i + 1, (nlogfiles - i - 1) * sizeof(logfile_t));
213 logfiles = realloc(logfiles, (nlogfiles - 1) * sizeof(logfile_t));
214 }
215
216 nlogfiles--;
217
218 return(0);
219 }
220
221 static int on_putlog(int flags, const char *chan, const char *text, int len)
222 {
223 char *ts;
224 int i;
225
226 ts = timer_get_timestamp();
227 for (i = nlogfiles - 1; i >= 0; i--) {
228 logfile_t *log = &logfiles[i];
229
230 /* If this log is disabled, skip it */
231 if (log->state != LOG_STATE_ENABLED)
232 continue;
233
234 /* If this log doesn't match, skip it. */
235 if (!(log->mask & flags)) {
236 continue;
237 }
238
239 if (chan[0] != '*' && log->chname[0] != '*' && irccmp(chan, log->chname)) continue;
240
241 /* If it's a repeat message, don't write it again. */
242 if (log->last_msg && !strcasecmp(text, log->last_msg)) {
243 log->repeats++;
244 continue;
245 }
246
247
248 /* If there was a repeated message, write the count. */
249 if (log->repeats) {
250 fprintf(log->fp, "%s", ts);
251 fprintf(log->fp, _("Last message repeated %d time(s).\n"), log->repeats);
252 log->repeats = 0;
253 }
254
255 /* Save this msg to check for repeats next time. */
256 str_redup(&log->last_msg, text);
257
258 if (log->fp == NULL) {
259 if (log->fname == NULL) {
260 char buf[1024];
261 time_t now;
262
263 now = time(NULL);
264 strftime(buf, sizeof(buf), log->filename, localtime(&now));
265 log->fname = strdup(buf);
266 }
267
268 log->fp = fopen(log->fname, "a+");
269 if (log->fp == NULL) {
270 log->state = LOG_STATE_DISABLED;
271 putlog(LOG_MISC, "*", _("Failed to open log file: %s"), log->fname);
272 putlog(LOG_MISC, "*", _(" Check if directory (if any) exists and is read- and writeable."));
273 continue;
274 }
275 }
276
277 /* Now output to the file. */
278 fprintf(log->fp, "%s%s\n", ts, text);
279 }
280
281 if (!backgrd || use_stderr) {
282
283 if (terminal_mode) {
284 /* check if HQ is on console. If yes we disable
285 * output to stdout since otherwise everything would
286 * be printed out twice. */
287 if (!terminal_enabled) {
288 terminal_enabled = (
289 partymember_lookup_nick (TERMINAL_NICK) != NULL);
290 }
291 if (terminal_enabled)
292 return 0;
293
294 }
295
296 fprintf (stdout, "%s %s%s\n", chan, ts, text);
297 }
298
299 return(0);
300 }
301
302 static void check_logsizes()
303 {
304 int size, i;
305 char *newfname;
306
307 if (core_config.logging.keep_all || core_config.logging.max_size <= 0) return;
308
309 for (i = 0; i < nlogfiles; i++) {
310 logfile_t *log = &logfiles[i];
311
312 size = ftell(log->fp) / 1024; /* Size in kilobytes. */
313 if (size < core_config.logging.max_size) continue;
314
315 /* It's too big. */
316 putlog(LOG_MISC, "*", _("Cycling logfile %s: over max-logsize (%d kilobytes)."), log->filename, size);
317 fclose(log->fp);
318
319 newfname = egg_mprintf("%s.yesterday", log->filename);
320 unlink(newfname);
321 movefile(log->filename, newfname);
322 free(newfname);
323 }
324 }
325
326 static void flushlog(logfile_t *log, char *timestamp)
327 {
328 if (log->repeats) {
329 fprintf(log->fp, "%s", timestamp);
330 fprintf(log->fp, _("Last message repeated %d time(s).\n"), log->repeats);
331 log->repeats = 0;
332 realloc_strcpy(log->last_msg, "");
333 }
334 fflush(log->fp);
335 }
336
337 /* Flush the logfiles to disk
338 */
339 void flushlogs()
340 {
341 char *ts;
342 int i;
343
344 ts = timer_get_timestamp();
345 for (i = 0; i < nlogfiles; i++) {
346 flushlog(&logfiles[i], ts);
347 }
348 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23