/[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.50 - (show annotations) (download) (as text)
Sun Oct 17 05:14:07 2004 UTC (15 years ago) by stdarg
Branch: MAIN
Changes since 1.49: +3 -6 lines
File MIME type: text/x-chdr
* Added a few includs to common.h
* Removed duplicate includes from a bunch of files
* Added tcl date parsing a la "clock scan"
* Fixed some issues with configure (maybe)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23