/[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.48 - (show annotations) (download) (as text)
Sun Sep 26 09:42:09 2004 UTC (15 years ago) by stdarg
Branch: MAIN
Changes since 1.47: +58 -47 lines
File MIME type: text/x-chdr
* module_load checks modname_LTX_start in addition to start.
* add linked list info to xml nodes
* there were some memory errors somewhere... no idea where... so for now I've changed it back to the old config api and commented out the help system

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.47 2004/06/28 17:36:34 wingman 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 log->filename = strdup(fname);
177 log->chname = strdup(chan);
178 log->last_msg = strdup("");
179 log->mask = LOG_ALL;
180 log->fp = fp;
181
182 return (log->filename);
183 }
184
185 int logfile_del(char *filename)
186 {
187 logfile_t *log;
188 int i;
189
190 log = NULL;
191 for (i = 0; i < nlogfiles; i++) {
192 log = &logfiles[i];
193 if (!strcmp(log->filename, filename)) break;
194 log = NULL;
195 }
196
197 if (log == NULL) return(-1);
198
199 if (log->fp) {
200 flushlog(log, timer_get_timestamp());
201 fclose(log->fp);
202 }
203
204 if (log->last_msg) free(log->last_msg);
205 if (log->filename) free(log->filename);
206
207 if (nlogfiles == 1) {
208 free(logfiles);
209 logfiles = NULL;
210 } else {
211 memmove(logfiles + i, logfiles + i + 1, (nlogfiles - i - 1) * sizeof(logfile_t));
212 logfiles = realloc(logfiles, (nlogfiles - 1) * sizeof(logfile_t));
213 }
214
215 nlogfiles--;
216
217 return(0);
218 }
219
220 static int on_putlog(int flags, const char *chan, const char *text, int len)
221 {
222 char *ts;
223 int i;
224
225 ts = timer_get_timestamp();
226 for (i = nlogfiles - 1; i >= 0; i--) {
227 logfile_t *log = &logfiles[i];
228
229 /* If this log is disabled, skip it */
230 if (log->state != LOG_STATE_ENABLED)
231 continue;
232
233 /* If this log doesn't match, skip it. */
234 if (!(log->mask & flags)) {
235 continue;
236 }
237
238 if (chan[0] != '*' && log->chname[0] != '*' && irccmp(chan, log->chname)) continue;
239
240 /* If it's a repeat message, don't write it again. */
241 if (log->last_msg && !strcasecmp(text, log->last_msg)) {
242 log->repeats++;
243 continue;
244 }
245
246
247 /* If there was a repeated message, write the count. */
248 if (log->repeats) {
249 fprintf(log->fp, "%s", ts);
250 fprintf(log->fp, _("Last message repeated %d time(s).\n"), log->repeats);
251 log->repeats = 0;
252 }
253
254 /* Save this msg to check for repeats next time. */
255 str_redup(&log->last_msg, text);
256
257 if (log->fp == NULL) {
258 if (log->fname == NULL) {
259 char buf[1024];
260 time_t now;
261
262 now = time(NULL);
263 strftime(buf, sizeof(buf), log->filename, localtime(&now));
264 log->fname = strdup(buf);
265 }
266
267 log->fp = fopen(log->fname, "a+");
268 if (log->fp == NULL) {
269 log->state = LOG_STATE_DISABLED;
270 putlog(LOG_MISC, "*", _("Failed to open log file: %s"), log->fname);
271 putlog(LOG_MISC, "*", _(" Check if directory (if any) exists and is read- and writeable."));
272 continue;
273 }
274 }
275
276 /* Now output to the file. */
277 fprintf(log->fp, "%s%s\n", ts, text);
278 }
279
280 if (!backgrd || use_stderr) {
281
282 if (terminal_mode) {
283 /* check if HQ is on console. If yes we disable
284 * output to stdout since otherwise everything would
285 * be printed out twice. */
286 if (!terminal_enabled) {
287 terminal_enabled = (
288 partymember_lookup_nick (TERMINAL_NICK) != NULL);
289 }
290 if (terminal_enabled)
291 return 0;
292
293 }
294
295 fprintf (stdout, "%s %s%s\n", chan, ts, text);
296 }
297
298 return(0);
299 }
300
301 static void check_logsizes()
302 {
303 int size, i;
304 char *newfname;
305
306 if (core_config.logging.keep_all || core_config.logging.max_size <= 0) return;
307
308 for (i = 0; i < nlogfiles; i++) {
309 logfile_t *log = &logfiles[i];
310
311 size = ftell(log->fp) / 1024; /* Size in kilobytes. */
312 if (size < core_config.logging.max_size) continue;
313
314 /* It's too big. */
315 putlog(LOG_MISC, "*", _("Cycling logfile %s: over max-logsize (%d kilobytes)."), log->filename, size);
316 fclose(log->fp);
317
318 newfname = egg_mprintf("%s.yesterday", log->filename);
319 unlink(newfname);
320 movefile(log->filename, newfname);
321 free(newfname);
322 }
323 }
324
325 static void flushlog(logfile_t *log, char *timestamp)
326 {
327 if (log->repeats) {
328 fprintf(log->fp, "%s", timestamp);
329 fprintf(log->fp, _("Last message repeated %d time(s).\n"), log->repeats);
330 log->repeats = 0;
331 realloc_strcpy(log->last_msg, "");
332 }
333 fflush(log->fp);
334 }
335
336 /* Flush the logfiles to disk
337 */
338 void flushlogs()
339 {
340 char *ts;
341 int i;
342
343 ts = timer_get_timestamp();
344 for (i = 0; i < nlogfiles; i++) {
345 flushlog(&logfiles[i], ts);
346 }
347 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23