/[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.37 - (show annotations) (download) (as text)
Wed Dec 17 08:12:43 2003 UTC (15 years, 10 months ago) by wcc
Branch: MAIN
Changes since 1.36: +3 -1 lines
File MIME type: text/x-chdr
* Should do it..

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23