/[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.29 - (show annotations) (download) (as text)
Mon Feb 17 10:22:30 2003 UTC (16 years, 8 months ago) by stdarg
Branch: MAIN
Changes since 1.28: +0 -1 lines
File MIME type: text/x-chdr
* Moved irccmp to libeggdrop
* Initial support for 005 numeric

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23