/[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.28 - (show annotations) (download) (as text)
Tue Feb 11 06:59:43 2003 UTC (16 years, 8 months ago) by stdarg
Branch: MAIN
Changes since 1.27: +9 -25 lines
File MIME type: text/x-chdr
* A bit more to configure.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23