Mercurial > hg > toybox
annotate toys/pending/syslogd.c @ 1024:63b8e54d2c6f
syslogd: cleanup
- remove flag macros
- remove some unecessary gotos
- inline open_udp_socks() and getport()
- simplify resulting open_logfiles()
Now in the syslog.conf the port numbers for remote hosts are no
longer allowed to be hexadecimal. If there is need for hexadecimal
port numbers, one can as well accept octal ones and use base 0
in strtoul.
author | Felix Janda <felix.janda@posteo.de> |
---|---|
date | Wed, 21 Aug 2013 21:24:45 +0200 |
parents | 773e4862e790 |
children | f19286ac3e7f |
rev | line source |
---|---|
960 | 1 /* syslogd.c - a system logging utility. |
2 * | |
3 * Copyright 2013 Madhur Verma <mad.flexi@gmail.com> | |
997
8b1814e4c987
Ashwini Sharma said that Kyungwan Han should be in the contact info for the commands he sent recently.
Rob Landley <rob@landley.net>
parents:
995
diff
changeset
|
4 * Copyright 2013 Kyungwan Han <asura321@gmail.com> |
960 | 5 * |
6 * No Standard | |
7 | |
8 USE_SYSLOGD(NEWTOY(syslogd,">0l#<1>8=8R:b#<0>99=1s#<0=200m#<0>71582787=20O:p:f:a:nSKLD", TOYFLAG_SBIN|TOYFLAG_STAYROOT)) | |
9 | |
10 config SYSLOGD | |
11 bool "syslogd" | |
12 default n | |
13 help | |
1021 | 14 Usage: syslogd [-a socket] [-O logfile] [-f config file] [-m interval] |
960 | 15 [-p socket] [-s SIZE] [-b N] [-R HOST] [-l N] [-nSLKD] |
16 | |
17 System logging utility | |
18 | |
19 -a Extra unix socket for listen | |
20 -O FILE Default log file <DEFAULT: /var/log/messages> | |
21 -f FILE Config file <DEFAULT: /etc/syslog.conf> | |
22 -p Alternative unix domain socket <DEFAULT : /dev/log> | |
23 -n Avoid auto-backgrounding. | |
24 -S Smaller output | |
25 -m MARK interval <DEFAULT: 20 minutes> (RANGE: 0 to 71582787) | |
26 -R HOST Log to IP or hostname on PORT (default PORT=514/UDP)" | |
27 -L Log locally and via network (default is network only if -R)" | |
28 -s SIZE Max size (KB) before rotation (default:200KB, 0=off) | |
29 -b N rotated logs to keep (default:1, max=99, 0=purge) | |
30 -K Log to kernel printk buffer (use dmesg to read it) | |
31 -l N Log only messages more urgent than prio(default:8 max:8 min:1) | |
32 -D Drop duplicates | |
33 */ | |
34 | |
35 #define FOR_syslogd | |
1019
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
36 #define SYSLOG_NAMES |
960 | 37 #include "toys.h" |
38 #include "toynet.h" | |
39 | |
40 GLOBALS( | |
41 char *socket; | |
42 char *config_file; | |
43 char *unix_socket; | |
44 char *logfile; | |
45 long interval; | |
46 long rot_size; | |
47 long rot_count; | |
48 char *remote_log; | |
49 long log_prio; | |
50 | |
51 struct arg_list *lsocks; // list of listen sockets | |
52 struct arg_list *lfiles; // list of write logfiles | |
53 fd_set rfds; // fds for reading | |
54 int sd; // socket for logging remote messeges. | |
1021 | 55 int sigfd[2]; |
960 | 56 ) |
57 | |
58 | |
59 // UNIX Sockets for listening | |
1021 | 60 struct unsocks { |
960 | 61 char *path; |
62 struct sockaddr_un sdu; | |
63 int sd; | |
1021 | 64 }; |
960 | 65 |
66 // Log file entry to log into. | |
1021 | 67 struct logfile { |
960 | 68 char *filename; |
69 char *config; | |
1024 | 70 int isNetwork; |
960 | 71 uint32_t facility[8]; |
72 uint8_t level[LOG_NFACILITIES]; | |
73 int logfd; | |
74 struct sockaddr_in saddr; | |
1021 | 75 }; |
960 | 76 |
77 // Adds opened socks to rfds for select() | |
78 static int addrfds(void) | |
79 { | |
1021 | 80 struct unsocks *sock; |
960 | 81 int ret = 0; |
82 struct arg_list *node = TT.lsocks; | |
83 FD_ZERO(&TT.rfds); | |
84 | |
85 while (node) { | |
1021 | 86 sock = (struct unsocks*) node->arg; |
960 | 87 if (sock->sd > 2) { |
88 FD_SET(sock->sd, &TT.rfds); | |
89 ret = sock->sd; | |
90 } | |
91 node = node->next; | |
92 } | |
1021 | 93 FD_SET(TT.sigfd[0], &TT.rfds); |
94 return (TT.sigfd[0] > ret) ? TT.sigfd[0] : ret; | |
960 | 95 } |
96 | |
97 /* | |
98 * initializes unsock_t structure | |
99 * and opens socket for reading | |
100 * and adds to global lsock list. | |
101 */ | |
102 static int open_unix_socks(void) | |
103 { | |
104 struct arg_list *node; | |
1021 | 105 struct unsocks *sock; |
960 | 106 int ret = 0; |
107 | |
108 for(node = TT.lsocks; node; node = node->next) { | |
1021 | 109 sock = (struct unsocks*) node->arg; |
960 | 110 sock->sdu.sun_family = AF_UNIX; |
111 strcpy(sock->sdu.sun_path, sock->path); | |
112 sock->sd = socket(AF_UNIX, SOCK_DGRAM, 0); | |
113 if (sock->sd < 0) { | |
114 perror_msg("OPEN SOCKS : failed"); | |
115 continue; | |
116 } | |
117 unlink(sock->sdu.sun_path); | |
118 if (bind(sock->sd, (struct sockaddr *) &sock->sdu, sizeof(sock->sdu))) { | |
119 perror_msg("BIND SOCKS : failed sock : %s", sock->sdu.sun_path); | |
120 close(sock->sd); | |
121 continue; | |
122 } | |
123 chmod(sock->path, 0777); | |
124 ret++; | |
125 } | |
126 return ret; | |
127 } | |
128 | |
129 // Returns node having filename | |
130 static struct arg_list *get_file_node(char *filename, struct arg_list *list) | |
131 { | |
132 while (list) { | |
1021 | 133 if (!strcmp(((struct logfile*) list->arg)->filename, filename)) return list; |
960 | 134 list = list->next; |
135 } | |
136 return list; | |
137 } | |
138 | |
139 /* | |
140 * recurses the logfile list and resolves config | |
141 * for evry file and updates facilty and log level bits. | |
142 */ | |
1021 | 143 static int resolve_config(struct logfile *file) |
960 | 144 { |
145 char *tk, *fac, *lvl, *tmp, *nfac; | |
146 int count = 0; | |
147 unsigned facval = 0; | |
148 uint8_t set, levval, neg; | |
149 CODE *val = NULL; | |
150 | |
151 tmp = xstrdup(file->config); | |
152 for (tk = strtok(tmp, "; \0"); tk; tk = strtok(NULL, "; \0")) { | |
153 fac = tk; | |
154 tk = strchr(fac, '.'); | |
155 if (!tk) return -1; | |
156 *tk = '\0'; | |
157 lvl = tk + 1; | |
158 | |
159 while(1) { | |
160 count = 0; | |
161 if (*fac == '*') { | |
162 facval = 0xFFFFFFFF; | |
163 fac++; | |
164 } | |
165 nfac = strchr(fac, ','); | |
166 if (nfac) *nfac = '\0'; | |
167 while (*fac && ((CODE*) &facilitynames[count])->c_name) { | |
168 val = (CODE*) &facilitynames[count]; | |
169 if (!strcmp(fac, val->c_name)) { | |
170 facval |= (1<<LOG_FAC(val->c_val)); | |
171 break; | |
172 } | |
173 count++; | |
174 } | |
175 if (((CODE*) &facilitynames[count])->c_val == -1) | |
176 return -1; | |
177 | |
178 if (nfac) fac = nfac+1; | |
179 else break; | |
180 } | |
181 | |
182 count = 0; | |
183 set = 0; | |
184 levval = 0; | |
185 neg = 0; | |
186 if (*lvl == '!') { | |
187 neg = 1; | |
188 lvl++; | |
189 } | |
190 if (*lvl == '=') { | |
191 set = 1; | |
192 lvl++; | |
193 } | |
194 if (*lvl == '*') { | |
195 levval = 0xFF; | |
196 lvl++; | |
197 } | |
198 while (*lvl && ((CODE*) &prioritynames[count])->c_name) { | |
199 val = (CODE*) &prioritynames[count]; | |
200 if (!strcmp(lvl, val->c_name)) { | |
201 levval |= set ? LOG_MASK(val->c_val):LOG_UPTO(val->c_val); | |
202 if (neg) levval = ~levval; | |
203 break; | |
204 } | |
205 count++; | |
206 } | |
207 if (((CODE*) &prioritynames[count])->c_val == -1) return -1; | |
208 | |
209 count = 0; | |
210 set = levval; | |
211 while(set) { | |
212 if (set & 0x1) file->facility[count] |= facval; | |
213 set >>= 1; | |
214 count++; | |
215 } | |
216 for (count = 0; count < LOG_NFACILITIES; count++) { | |
217 if (facval & 0x1) file->level[count] |= levval; | |
218 facval >>= 1; | |
219 } | |
220 } | |
221 free(tmp); | |
222 | |
223 return 0; | |
224 } | |
225 | |
226 // Parse config file and update the log file list. | |
227 static int parse_config_file(void) | |
228 { | |
1021 | 229 struct logfile *file; |
960 | 230 FILE *fp = NULL; |
231 char *confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL}; | |
232 int len, linelen, tcount, lineno = 0; | |
233 struct arg_list *node; | |
234 /* | |
235 * if -K then open only /dev/kmsg | |
236 * all other log files are neglected | |
237 * thus no need to open config either. | |
238 */ | |
1024 | 239 if (toys.optflags & FLAG_K) { |
960 | 240 node = xzalloc(sizeof(struct arg_list)); |
1021 | 241 file = xzalloc(sizeof(struct logfile)); |
960 | 242 file->filename = "/dev/kmsg"; |
243 file->config = "*.*"; | |
244 memset(file->level, 0xFF, sizeof(file->level)); | |
245 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); | |
246 node->arg = (char*) file; | |
247 TT.lfiles = node; | |
248 return 0; | |
249 } | |
250 /* | |
251 * if -R then add remote host to log list | |
252 * if -L is not provided all other log | |
253 * files are neglected thus no need to | |
254 * open config either so just return. | |
255 */ | |
1024 | 256 if (toys.optflags & FLAG_R) { |
960 | 257 node = xzalloc(sizeof(struct arg_list)); |
1021 | 258 file = xzalloc(sizeof(struct logfile)); |
960 | 259 file->filename = xmsprintf("@%s",TT.remote_log); |
260 file->isNetwork = 1; | |
261 file->config = "*.*"; | |
262 memset(file->level, 0xFF, sizeof(file->level)); | |
263 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); | |
264 node->arg = (char*) file; | |
265 TT.lfiles = node; | |
1024 | 266 if (!(toys.optflags & FLAG_L))return 0; |
960 | 267 } |
268 /* | |
269 * Read config file and add logfiles to the list | |
270 * with their configuration. | |
271 */ | |
272 fp = fopen(TT.config_file, "r"); | |
1024 | 273 if (!fp && (toys.optflags & FLAG_f)) |
960 | 274 perror_exit("can't open '%s'", TT.config_file); |
275 | |
276 for (len = 0, linelen = 0; fp;) { | |
277 len = getline(&confline, (size_t*) &linelen, fp); | |
278 if (len <= 0) break; | |
279 lineno++; | |
280 for (; *confline == ' '; confline++, len--) ; | |
281 if ((confline[0] == '#') || (confline[0] == '\n')) continue; | |
282 for (tcount = 0, tk = strtok(confline, " \t"); tk && (tcount < 2); tk = | |
283 strtok(NULL, " \t"), tcount++) { | |
284 if (tcount == 2) { | |
285 error_msg("error in '%s' at line %d", TT.config_file, lineno); | |
286 return -1; | |
287 } | |
288 tokens[tcount] = xstrdup(tk); | |
289 } | |
290 if (tcount <= 1 || tcount > 2) { | |
291 if (tokens[0]) free(tokens[0]); | |
292 error_msg("bad line %d: 1 tokens found, 2 needed", lineno); | |
293 return -1; | |
294 } | |
295 tk = (tokens[1] + (strlen(tokens[1]) - 1)); | |
296 if (*tk == '\n') *tk = '\0'; | |
297 if (*tokens[1] == '\0') { | |
298 error_msg("bad line %d: 1 tokens found, 2 needed", lineno); | |
299 return -1; | |
300 } | |
1024 | 301 if (*tokens[1] != '*') { |
302 node = get_file_node(tokens[1], TT.lfiles); | |
303 if (!node) { | |
304 node = xzalloc(sizeof(struct arg_list)); | |
305 file = xzalloc(sizeof(struct logfile)); | |
306 file->config = xstrdup(tokens[0]); | |
307 if (resolve_config(file)==-1) { | |
308 error_msg("error in '%s' at line %d", TT.config_file, lineno); | |
309 return -1; | |
310 } | |
311 file->filename = xstrdup(tokens[1]); | |
312 if (*file->filename == '@') file->isNetwork = 1; | |
313 node->arg = (char*) file; | |
314 node->next = TT.lfiles; | |
315 TT.lfiles = node; | |
316 } else { | |
317 file = (struct logfile*) node->arg; | |
318 int rel = strlen(file->config) + strlen(tokens[0]) + 2; | |
319 file->config = xrealloc(file->config, rel); | |
320 sprintf(file->config, "%s;%s", file->config, tokens[0]); | |
960 | 321 } |
322 } | |
323 if (tokens[0]) free(tokens[0]); | |
324 if (tokens[1]) free(tokens[1]); | |
325 free(confline); | |
326 confline = NULL; | |
327 } | |
328 /* | |
329 * Can't open config file or support is not enabled | |
330 * adding default logfile to the head of list. | |
331 */ | |
332 if (!fp){ | |
333 node = xzalloc(sizeof(struct arg_list)); | |
1021 | 334 file = xzalloc(sizeof(struct logfile)); |
1024 | 335 file->filename = (toys.optflags & FLAG_O) ? |
336 TT.logfile : "/var/log/messages"; //DEFLOGFILE | |
960 | 337 file->isNetwork = 0; |
338 file->config = "*.*"; | |
339 memset(file->level, 0xFF, sizeof(file->level)); | |
340 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); | |
341 node->arg = (char*) file; | |
342 node->next = TT.lfiles; | |
343 TT.lfiles = node; | |
344 } | |
345 if (fp) { | |
346 fclose(fp); | |
347 fp = NULL; | |
348 } | |
349 return 0; | |
350 } | |
351 | |
352 // open every log file in list. | |
353 static void open_logfiles(void) | |
354 { | |
1024 | 355 struct arg_list *node; |
356 | |
357 for (node = TT.lfiles; node; node = node->next) { | |
358 struct logfile *tfd = (struct logfile*) node->arg; | |
359 char *p, *tmpfile; | |
360 long port = 514; | |
361 | |
362 if (tfd->isNetwork) { | |
363 struct addrinfo *info, rp; | |
364 | |
365 tmpfile = xstrdup(tfd->filename + 1); | |
366 if ((p = strchr(tmpfile, ':'))) { | |
367 char *endptr; | |
960 | 368 |
369 *p = '\0'; | |
1024 | 370 port = strtol(++p, &endptr, 10); |
371 if (*endptr || endptr == p || port < 0 || port > 65535) | |
372 error_exit("bad port in %s", tfd->filename); | |
960 | 373 } |
1024 | 374 memset(&rp, 0, sizeof(rp)); |
375 rp.ai_family = AF_INET; | |
376 rp.ai_socktype = SOCK_DGRAM; | |
377 rp.ai_protocol = IPPROTO_UDP; | |
378 | |
379 if (getaddrinfo(tmpfile, NULL, &rp, &info) || !info) | |
380 perror_exit("BAD ADDRESS: can't find : %s ", tmpfile); | |
381 ((struct sockaddr_in*)info->ai_addr)->sin_port = htons(port); | |
382 memcpy(&tfd->saddr, info->ai_addr, info->ai_addrlen); | |
383 freeaddrinfo(info); | |
384 | |
385 tfd->logfd = xsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
960 | 386 free(tmpfile); |
387 } else tfd->logfd = open(tfd->filename, O_CREAT | O_WRONLY | O_APPEND, 0666); | |
388 if (tfd->logfd < 0) { | |
389 tfd->filename = "/dev/console"; | |
390 tfd->logfd = open(tfd->filename, O_APPEND); | |
391 } | |
392 } | |
393 } | |
394 | |
395 //write to file with rotation | |
1021 | 396 static int write_rotate(struct logfile *tf, int len) |
960 | 397 { |
398 int size, isreg; | |
399 struct stat statf; | |
400 isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode)); | |
401 size = statf.st_size; | |
402 | |
1024 | 403 if ((toys.optflags & FLAG_s) || (toys.optflags & FLAG_b)) { |
960 | 404 if (TT.rot_size && isreg && (size + len) > (TT.rot_size*1024)) { |
405 if (TT.rot_count) { /* always 0..99 */ | |
406 int i = strlen(tf->filename) + 3 + 1; | |
407 char old_file[i]; | |
408 char new_file[i]; | |
409 i = TT.rot_count - 1; | |
410 while (1) { | |
411 sprintf(new_file, "%s.%d", tf->filename, i); | |
412 if (!i) break; | |
413 sprintf(old_file, "%s.%d", tf->filename, --i); | |
414 rename(old_file, new_file); | |
415 } | |
416 rename(tf->filename, new_file); | |
417 unlink(tf->filename); | |
418 close(tf->logfd); | |
419 tf->logfd = open(tf->filename, O_CREAT | O_WRONLY | O_APPEND, 0666); | |
420 } | |
421 ftruncate(tf->logfd, 0); | |
422 } | |
423 } | |
424 return write(tf->logfd, toybuf, len); | |
425 } | |
426 | |
1019
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
427 // Lookup numerical code from name |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
428 // Only used in logger |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
429 int logger_lookup(int where, char *key) |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
430 { |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
431 CODE *w = ((CODE *[]){facilitynames, prioritynames})[where]; |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
432 |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
433 for (; w->c_name; w++) |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
434 if (!strcasecmp(key, w->c_name)) return w->c_val; |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
435 |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
436 return -1; |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
437 } |
f9271a80fedc
In logger and syslogd remove duplicated definitions of facilities and priorities
Felix Janda <felix.janda@posteo.de>
parents:
997
diff
changeset
|
438 |
960 | 439 //search the given name and return its value |
440 static char *dec(int val, CODE *clist) | |
441 { | |
442 const CODE *c; | |
443 | |
444 for (c = clist; c->c_name; c++) | |
445 if (val == c->c_val) return c->c_name; | |
446 return itoa(val); | |
447 } | |
448 | |
449 // Compute priority from "facility.level" pair | |
450 static void priority_to_string(int pri, char **facstr, char **lvlstr) | |
451 { | |
452 int fac,lev; | |
453 | |
454 fac = LOG_FAC(pri); | |
455 lev = LOG_PRI(pri); | |
456 *facstr = dec(fac<<3, facilitynames); | |
457 *lvlstr = dec(lev, prioritynames); | |
458 } | |
459 | |
460 //Parse messege and write to file. | |
461 static void logmsg(char *msg, int len) | |
462 { | |
463 time_t now; | |
464 char *p, *ts, *lvlstr, *facstr; | |
465 struct utsname uts; | |
466 int pri = 0; | |
467 struct arg_list *lnode = TT.lfiles; | |
468 | |
469 char *omsg = msg; | |
470 int olen = len, fac, lvl; | |
471 | |
472 if (*msg == '<') { // Extract the priority no. | |
473 pri = (int) strtoul(msg + 1, &p, 10); | |
474 if (*p == '>') msg = p + 1; | |
475 } | |
476 /* Jan 18 00:11:22 msg... | |
477 * 01234567890123456 | |
478 */ | |
479 if (len < 16 || msg[3] != ' ' || msg[6] != ' ' || msg[9] != ':' | |
480 || msg[12] != ':' || msg[15] != ' ') { | |
481 time(&now); | |
482 ts = ctime(&now) + 4; /* skip day of week */ | |
483 } else { | |
484 now = 0; | |
485 ts = msg; | |
486 msg += 16; | |
487 } | |
488 ts[15] = '\0'; | |
489 fac = LOG_FAC(pri); | |
490 lvl = LOG_PRI(pri); | |
491 | |
1024 | 492 if (toys.optflags & FLAG_K) len = sprintf(toybuf, "<%d> %s\n", pri, msg); |
493 else { | |
494 priority_to_string(pri, &facstr, &lvlstr); | |
960 | 495 |
1024 | 496 p = "local"; |
497 if (!uname(&uts)) p = uts.nodename; | |
498 if (toys.optflags & FLAG_S) len = sprintf(toybuf, "%s %s\n", ts, msg); | |
499 else len = sprintf(toybuf, "%s %s %s.%s %s\n", ts, p, facstr, lvlstr, msg); | |
500 } | |
960 | 501 if (lvl >= TT.log_prio) return; |
502 | |
503 while (lnode) { | |
1021 | 504 struct logfile *tf = (struct logfile*) lnode->arg; |
960 | 505 if (tf->logfd > 0) { |
506 if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) { | |
507 int wlen; | |
508 if (tf->isNetwork) | |
509 wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr)); | |
510 else wlen = write_rotate(tf, len); | |
1024 | 511 if (wlen < 0) perror_msg("write failed file : %s ", tf->filename + tf->isNetwork); |
960 | 512 } |
513 } | |
514 lnode = lnode->next; | |
515 } | |
516 } | |
517 | |
518 /* | |
519 * closes all read and write fds | |
520 * and frees all nodes and lists | |
521 */ | |
522 static void cleanup(void) | |
523 { | |
524 struct arg_list *fnode; | |
525 while (TT.lsocks) { | |
526 fnode = TT.lsocks; | |
1021 | 527 if (((struct unsocks*) fnode->arg)->sd >= 0) |
528 close(((struct unsocks*) fnode->arg)->sd); | |
960 | 529 free(fnode->arg); |
530 TT.lsocks = fnode->next; | |
531 free(fnode); | |
532 } | |
533 unlink("/dev/log"); | |
534 | |
535 while (TT.lfiles) { | |
536 fnode = TT.lfiles; | |
1021 | 537 if (((struct logfile*) fnode->arg)->logfd >= 0) |
538 close(((struct logfile*) fnode->arg)->logfd); | |
960 | 539 free(fnode->arg); |
540 TT.lfiles = fnode->next; | |
541 free(fnode); | |
542 } | |
543 } | |
544 | |
545 static void signal_handler(int sig) | |
546 { | |
547 unsigned char ch = sig; | |
1021 | 548 if (write(TT.sigfd[1], &ch, 1) != 1) error_msg("can't send signal"); |
960 | 549 } |
550 | |
551 void syslogd_main(void) | |
552 { | |
1021 | 553 struct unsocks *tsd; |
960 | 554 int maxfd, retval, last_len=0; |
555 struct timeval tv; | |
556 struct arg_list *node; | |
557 char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each | |
558 | |
1024 | 559 if ((toys.optflags & FLAG_p) && (strlen(TT.unix_socket) > 108)) |
960 | 560 error_exit("Socket path should not be more than 108"); |
561 | |
1024 | 562 TT.config_file = (toys.optflags & FLAG_f) ? |
563 TT.config_file : "/etc/syslog.conf"; //DEFCONFFILE | |
960 | 564 init_jumpin: |
565 TT.lsocks = xzalloc(sizeof(struct arg_list)); | |
1021 | 566 tsd = xzalloc(sizeof(struct unsocks)); |
960 | 567 |
1024 | 568 tsd->path = (toys.optflags & FLAG_p) ? TT.unix_socket : "/dev/log"; // DEFLOGSOCK |
960 | 569 TT.lsocks->arg = (char*) tsd; |
570 | |
1024 | 571 if (toys.optflags & FLAG_a) { |
960 | 572 for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) { |
573 struct arg_list *ltemp = xzalloc(sizeof(struct arg_list)); | |
574 if (strlen(temp) > 107) temp[108] = '\0'; | |
1021 | 575 tsd = xzalloc(sizeof(struct unsocks)); |
960 | 576 tsd->path = temp; |
577 ltemp->arg = (char*) tsd; | |
578 ltemp->next = TT.lsocks; | |
579 TT.lsocks = ltemp; | |
580 } | |
581 } | |
582 if (!open_unix_socks()) { | |
583 error_msg("Can't open single socket for listenning."); | |
584 goto clean_and_exit; | |
585 } | |
1021 | 586 |
587 // Setup signals | |
588 if (pipe(TT.sigfd) < 0) error_exit("pipe failed\n"); | |
589 | |
590 fcntl(TT.sigfd[1] , F_SETFD, FD_CLOEXEC); | |
591 fcntl(TT.sigfd[0] , F_SETFD, FD_CLOEXEC); | |
592 int flags = fcntl(TT.sigfd[1], F_GETFL); | |
593 fcntl(TT.sigfd[1], F_SETFL, flags | O_NONBLOCK); | |
594 signal(SIGHUP, signal_handler); | |
595 signal(SIGTERM, signal_handler); | |
596 signal(SIGINT, signal_handler); | |
597 signal(SIGQUIT, signal_handler); | |
598 | |
960 | 599 if (parse_config_file() == -1) goto clean_and_exit; |
600 open_logfiles(); | |
1024 | 601 if (!(toys.optflags & FLAG_n)) { |
995
893c86bbe452
Add daemonize function to lib for klogd and syslogd
Felix Janda <felix.janda@posteo.de>
parents:
960
diff
changeset
|
602 //don't daemonize again if SIGHUP received. |
893c86bbe452
Add daemonize function to lib for klogd and syslogd
Felix Janda <felix.janda@posteo.de>
parents:
960
diff
changeset
|
603 toys.optflags |= FLAG_n; |
893c86bbe452
Add daemonize function to lib for klogd and syslogd
Felix Janda <felix.janda@posteo.de>
parents:
960
diff
changeset
|
604 } |
960 | 605 { |
606 int pid_fd = open("/var/run/syslogd.pid", O_CREAT | O_WRONLY | O_TRUNC, 0666); | |
607 if (pid_fd > 0) { | |
608 unsigned pid = getpid(); | |
609 int len = sprintf(toybuf, "%u\n", pid); | |
610 write(pid_fd, toybuf, len); | |
611 close(pid_fd); | |
612 } | |
613 } | |
614 | |
615 logmsg("<46>Toybox: syslogd started", 27); //27 : the length of message | |
616 for (;;) { | |
617 maxfd = addrfds(); | |
618 tv.tv_usec = 0; | |
619 tv.tv_sec = TT.interval*60; | |
620 | |
621 retval = select(maxfd + 1, &TT.rfds, NULL, NULL, (TT.interval)?&tv:NULL); | |
622 if (retval < 0) { /* Some error. */ | |
623 if (errno == EINTR) continue; | |
624 perror_msg("Error in select "); | |
625 continue; | |
626 } | |
627 if (!retval) { /* Timed out */ | |
628 logmsg("<46>-- MARK --", 14); | |
629 continue; | |
630 } | |
1021 | 631 if (FD_ISSET(TT.sigfd[0], &TT.rfds)) { /* May be a signal */ |
960 | 632 unsigned char sig; |
633 | |
1021 | 634 if (read(TT.sigfd[0], &sig, 1) != 1) { |
960 | 635 error_msg("signal read failed.\n"); |
636 continue; | |
637 } | |
638 switch(sig) { | |
639 case SIGTERM: /* FALLTHROUGH */ | |
640 case SIGINT: /* FALLTHROUGH */ | |
641 case SIGQUIT: | |
642 logmsg("<46>syslogd exiting", 19); | |
643 if (CFG_TOYBOX_FREE ) cleanup(); | |
644 signal(sig, SIG_DFL); | |
645 sigset_t ss; | |
646 sigemptyset(&ss); | |
647 sigaddset(&ss, sig); | |
648 sigprocmask(SIG_UNBLOCK, &ss, NULL); | |
649 raise(sig); | |
650 _exit(1); /* Should not reach it */ | |
651 break; | |
652 case SIGHUP: | |
653 logmsg("<46>syslogd exiting", 19); | |
654 cleanup(); //cleanup is done, as we restart syslog. | |
655 goto init_jumpin; | |
656 default: break; | |
657 } | |
658 } | |
659 if (retval > 0) { /* Some activity on listen sockets. */ | |
660 node = TT.lsocks; | |
661 while (node) { | |
1021 | 662 int sd = ((struct unsocks*) node->arg)->sd; |
960 | 663 if (FD_ISSET(sd, &TT.rfds)) { |
664 int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL | |
665 if (len > 0) { | |
666 buffer[len] = '\0'; | |
1024 | 667 if((toys.optflags & FLAG_D) && (len == last_len)) |
960 | 668 if (!memcmp(last_buf, buffer, len)) break; |
669 | |
670 memcpy(last_buf, buffer, len); | |
671 last_len = len; | |
672 logmsg(buffer, len); | |
673 } | |
674 break; | |
675 } | |
676 node = node->next; | |
677 } | |
678 } | |
679 } | |
680 clean_and_exit: | |
681 logmsg("<46>syslogd exiting", 19); | |
682 if (CFG_TOYBOX_FREE ) cleanup(); | |
683 } |