/[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.47 - (show annotations) (download) (as text)
Mon Jun 28 17:36:34 2004 UTC (15 years, 3 months ago) by wingman
Branch: MAIN
Changes since 1.46: +97 -62 lines
File MIME type: text/x-chdr
* Added new datatype variant: supports common task of having one
  data structure supporting different types (int, bool, string, timestamp)

* Added a more fine graned config api, which allows us to use attributes,
  sub children, arrays and enum lookups in config files.

* Added logfile settings

* xml_*_lookup now can return attributes too (by using @ as starting
  char of name tokens)

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23