Mercurial > hg > toybox
annotate toys/pending/syslogd.c @ 1025:f19286ac3e7f draft
syslogd: cleanup
- simplify resolveconfig() -> now logger_lookup is also used in syslogd.c
- inline addrfds
- small cosmetical changes in parse_config_file()
author | Felix Janda <felix.janda at posteo.de> |
---|---|
date | Fri, 23 Aug 2013 22:19:55 +0200 |
parents | 63b8e54d2c6f |
children | 09cc81f6e411 |
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 |
1025 | 77 // Lookup numerical code from name |
78 // Also used in logger | |
79 int logger_lookup(int where, char *key) | |
80 { | |
81 CODE *w = ((CODE *[]){facilitynames, prioritynames})[where]; | |
82 | |
83 for (; w->c_name; w++) | |
84 if (!strcasecmp(key, w->c_name)) return w->c_val; | |
85 | |
86 return -1; | |
87 } | |
88 | |
89 //search the given name and return its value | |
90 static char *dec(int val, CODE *clist) | |
91 { | |
92 for (; clist->c_name; clist++) | |
93 if (val == clist->c_val) return clist->c_name; | |
94 return itoa(val); | |
95 } | |
96 | |
960 | 97 // Adds opened socks to rfds for select() |
98 static int addrfds(void) | |
99 { | |
1021 | 100 struct unsocks *sock; |
960 | 101 int ret = 0; |
102 struct arg_list *node = TT.lsocks; | |
103 FD_ZERO(&TT.rfds); | |
104 | |
105 while (node) { | |
1021 | 106 sock = (struct unsocks*) node->arg; |
960 | 107 if (sock->sd > 2) { |
108 FD_SET(sock->sd, &TT.rfds); | |
109 ret = sock->sd; | |
110 } | |
111 node = node->next; | |
112 } | |
1021 | 113 FD_SET(TT.sigfd[0], &TT.rfds); |
114 return (TT.sigfd[0] > ret) ? TT.sigfd[0] : ret; | |
960 | 115 } |
116 | |
117 /* | |
118 * initializes unsock_t structure | |
119 * and opens socket for reading | |
120 * and adds to global lsock list. | |
121 */ | |
122 static int open_unix_socks(void) | |
123 { | |
124 struct arg_list *node; | |
1021 | 125 struct unsocks *sock; |
960 | 126 int ret = 0; |
127 | |
128 for(node = TT.lsocks; node; node = node->next) { | |
1021 | 129 sock = (struct unsocks*) node->arg; |
960 | 130 sock->sdu.sun_family = AF_UNIX; |
131 strcpy(sock->sdu.sun_path, sock->path); | |
132 sock->sd = socket(AF_UNIX, SOCK_DGRAM, 0); | |
133 if (sock->sd < 0) { | |
134 perror_msg("OPEN SOCKS : failed"); | |
135 continue; | |
136 } | |
137 unlink(sock->sdu.sun_path); | |
138 if (bind(sock->sd, (struct sockaddr *) &sock->sdu, sizeof(sock->sdu))) { | |
139 perror_msg("BIND SOCKS : failed sock : %s", sock->sdu.sun_path); | |
140 close(sock->sd); | |
141 continue; | |
142 } | |
143 chmod(sock->path, 0777); | |
144 ret++; | |
145 } | |
146 return ret; | |
147 } | |
148 | |
149 // Returns node having filename | |
150 static struct arg_list *get_file_node(char *filename, struct arg_list *list) | |
151 { | |
152 while (list) { | |
1021 | 153 if (!strcmp(((struct logfile*) list->arg)->filename, filename)) return list; |
960 | 154 list = list->next; |
155 } | |
156 return list; | |
157 } | |
158 | |
159 /* | |
160 * recurses the logfile list and resolves config | |
161 * for evry file and updates facilty and log level bits. | |
162 */ | |
1021 | 163 static int resolve_config(struct logfile *file) |
960 | 164 { |
1025 | 165 char *tk, *tmp = xstrdup(file->config); |
960 | 166 |
167 for (tk = strtok(tmp, "; \0"); tk; tk = strtok(NULL, "; \0")) { | |
1025 | 168 char *fac = tk, *lvl; |
169 int i = 0; | |
170 unsigned facval = 0; | |
171 uint8_t set, levval, bits = 0; | |
172 | |
960 | 173 tk = strchr(fac, '.'); |
174 if (!tk) return -1; | |
175 *tk = '\0'; | |
176 lvl = tk + 1; | |
177 | |
1025 | 178 for (;;) { |
179 char *nfac = strchr(fac, ','); | |
180 | |
181 if (nfac) *nfac = '\0'; | |
960 | 182 if (*fac == '*') { |
183 facval = 0xFFFFFFFF; | |
1025 | 184 if (fac[1]) return -1; |
185 } else { | |
186 if ((i = logger_lookup(0, fac)) == -1) return -1; | |
187 facval |= (1 << LOG_FAC(i)); | |
960 | 188 } |
1025 | 189 if (nfac) fac = nfac + 1; |
960 | 190 else break; |
191 } | |
192 | |
193 levval = 0; | |
1025 | 194 for (tk = "!=*"; tk; tk++, bits <<= 1) { |
195 if (*lvl == *tk) { | |
196 bits++; | |
197 lvl++; | |
198 } | |
960 | 199 } |
1025 | 200 if (bits & 1) levval = 0xff; |
201 if (lvl) { | |
202 if ((i = logger_lookup(1, lvl)) == -1) return -1; | |
203 levval |= (bits & 2) ? LOG_MASK(i) : LOG_UPTO(i); | |
204 if (bits & 4) levval = ~levval; | |
960 | 205 } |
206 | |
1025 | 207 for (i = 0, set = levval; set; set >>= 1, i++) |
208 if (set & 0x1) file->facility[i] |= facval; | |
209 for (i = 0; i < LOG_NFACILITIES; facval >>= 1, i++) | |
210 if (facval & 0x1) file->level[i] |= levval; | |
960 | 211 } |
212 free(tmp); | |
213 | |
214 return 0; | |
215 } | |
216 | |
217 // Parse config file and update the log file list. | |
218 static int parse_config_file(void) | |
219 { | |
1021 | 220 struct logfile *file; |
1025 | 221 FILE *fp; |
960 | 222 char *confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL}; |
1025 | 223 int len, tcount, lineno = 0; |
224 size_t linelen; | |
960 | 225 struct arg_list *node; |
226 /* | |
227 * if -K then open only /dev/kmsg | |
228 * all other log files are neglected | |
229 * thus no need to open config either. | |
230 */ | |
1024 | 231 if (toys.optflags & FLAG_K) { |
960 | 232 node = xzalloc(sizeof(struct arg_list)); |
1021 | 233 file = xzalloc(sizeof(struct logfile)); |
960 | 234 file->filename = "/dev/kmsg"; |
235 file->config = "*.*"; | |
236 memset(file->level, 0xFF, sizeof(file->level)); | |
237 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); | |
238 node->arg = (char*) file; | |
239 TT.lfiles = node; | |
240 return 0; | |
241 } | |
242 /* | |
243 * if -R then add remote host to log list | |
244 * if -L is not provided all other log | |
245 * files are neglected thus no need to | |
246 * open config either so just return. | |
247 */ | |
1025 | 248 if (toys.optflags & FLAG_R) { |
249 node = xzalloc(sizeof(struct arg_list)); | |
250 file = xzalloc(sizeof(struct logfile)); | |
251 file->filename = xmsprintf("@%s",TT.remote_log); | |
252 file->isNetwork = 1; | |
253 file->config = "*.*"; | |
254 memset(file->level, 0xFF, sizeof(file->level)); | |
255 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); | |
256 node->arg = (char*) file; | |
257 TT.lfiles = node; | |
258 if (!(toys.optflags & FLAG_L)) return 0; | |
259 } | |
960 | 260 /* |
261 * Read config file and add logfiles to the list | |
262 * with their configuration. | |
263 */ | |
264 fp = fopen(TT.config_file, "r"); | |
1024 | 265 if (!fp && (toys.optflags & FLAG_f)) |
960 | 266 perror_exit("can't open '%s'", TT.config_file); |
267 | |
268 for (len = 0, linelen = 0; fp;) { | |
1025 | 269 len = getline(&confline, &linelen, fp); |
960 | 270 if (len <= 0) break; |
271 lineno++; | |
272 for (; *confline == ' '; confline++, len--) ; | |
273 if ((confline[0] == '#') || (confline[0] == '\n')) continue; | |
274 for (tcount = 0, tk = strtok(confline, " \t"); tk && (tcount < 2); tk = | |
275 strtok(NULL, " \t"), tcount++) { | |
276 if (tcount == 2) { | |
277 error_msg("error in '%s' at line %d", TT.config_file, lineno); | |
278 return -1; | |
279 } | |
280 tokens[tcount] = xstrdup(tk); | |
281 } | |
282 if (tcount <= 1 || tcount > 2) { | |
283 if (tokens[0]) free(tokens[0]); | |
284 error_msg("bad line %d: 1 tokens found, 2 needed", lineno); | |
285 return -1; | |
286 } | |
287 tk = (tokens[1] + (strlen(tokens[1]) - 1)); | |
288 if (*tk == '\n') *tk = '\0'; | |
289 if (*tokens[1] == '\0') { | |
290 error_msg("bad line %d: 1 tokens found, 2 needed", lineno); | |
291 return -1; | |
292 } | |
1024 | 293 if (*tokens[1] != '*') { |
294 node = get_file_node(tokens[1], TT.lfiles); | |
295 if (!node) { | |
296 node = xzalloc(sizeof(struct arg_list)); | |
297 file = xzalloc(sizeof(struct logfile)); | |
298 file->config = xstrdup(tokens[0]); | |
299 if (resolve_config(file)==-1) { | |
300 error_msg("error in '%s' at line %d", TT.config_file, lineno); | |
301 return -1; | |
302 } | |
303 file->filename = xstrdup(tokens[1]); | |
304 if (*file->filename == '@') file->isNetwork = 1; | |
305 node->arg = (char*) file; | |
306 node->next = TT.lfiles; | |
307 TT.lfiles = node; | |
308 } else { | |
309 file = (struct logfile*) node->arg; | |
310 int rel = strlen(file->config) + strlen(tokens[0]) + 2; | |
311 file->config = xrealloc(file->config, rel); | |
312 sprintf(file->config, "%s;%s", file->config, tokens[0]); | |
960 | 313 } |
314 } | |
315 if (tokens[0]) free(tokens[0]); | |
316 if (tokens[1]) free(tokens[1]); | |
317 free(confline); | |
318 confline = NULL; | |
319 } | |
320 /* | |
321 * Can't open config file or support is not enabled | |
322 * adding default logfile to the head of list. | |
323 */ | |
324 if (!fp){ | |
325 node = xzalloc(sizeof(struct arg_list)); | |
1021 | 326 file = xzalloc(sizeof(struct logfile)); |
1024 | 327 file->filename = (toys.optflags & FLAG_O) ? |
328 TT.logfile : "/var/log/messages"; //DEFLOGFILE | |
960 | 329 file->config = "*.*"; |
330 memset(file->level, 0xFF, sizeof(file->level)); | |
331 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); | |
332 node->arg = (char*) file; | |
333 node->next = TT.lfiles; | |
334 TT.lfiles = node; | |
1025 | 335 } else fclose(fp); |
960 | 336 return 0; |
337 } | |
338 | |
339 // open every log file in list. | |
340 static void open_logfiles(void) | |
341 { | |
1024 | 342 struct arg_list *node; |
343 | |
344 for (node = TT.lfiles; node; node = node->next) { | |
345 struct logfile *tfd = (struct logfile*) node->arg; | |
346 char *p, *tmpfile; | |
347 long port = 514; | |
348 | |
349 if (tfd->isNetwork) { | |
350 struct addrinfo *info, rp; | |
351 | |
352 tmpfile = xstrdup(tfd->filename + 1); | |
353 if ((p = strchr(tmpfile, ':'))) { | |
354 char *endptr; | |
960 | 355 |
356 *p = '\0'; | |
1024 | 357 port = strtol(++p, &endptr, 10); |
358 if (*endptr || endptr == p || port < 0 || port > 65535) | |
359 error_exit("bad port in %s", tfd->filename); | |
960 | 360 } |
1024 | 361 memset(&rp, 0, sizeof(rp)); |
362 rp.ai_family = AF_INET; | |
363 rp.ai_socktype = SOCK_DGRAM; | |
364 rp.ai_protocol = IPPROTO_UDP; | |
365 | |
366 if (getaddrinfo(tmpfile, NULL, &rp, &info) || !info) | |
367 perror_exit("BAD ADDRESS: can't find : %s ", tmpfile); | |
368 ((struct sockaddr_in*)info->ai_addr)->sin_port = htons(port); | |
369 memcpy(&tfd->saddr, info->ai_addr, info->ai_addrlen); | |
370 freeaddrinfo(info); | |
371 | |
372 tfd->logfd = xsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
960 | 373 free(tmpfile); |
374 } else tfd->logfd = open(tfd->filename, O_CREAT | O_WRONLY | O_APPEND, 0666); | |
375 if (tfd->logfd < 0) { | |
376 tfd->filename = "/dev/console"; | |
377 tfd->logfd = open(tfd->filename, O_APPEND); | |
378 } | |
379 } | |
380 } | |
381 | |
382 //write to file with rotation | |
1021 | 383 static int write_rotate(struct logfile *tf, int len) |
960 | 384 { |
385 int size, isreg; | |
386 struct stat statf; | |
387 isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode)); | |
388 size = statf.st_size; | |
389 | |
1024 | 390 if ((toys.optflags & FLAG_s) || (toys.optflags & FLAG_b)) { |
960 | 391 if (TT.rot_size && isreg && (size + len) > (TT.rot_size*1024)) { |
392 if (TT.rot_count) { /* always 0..99 */ | |
393 int i = strlen(tf->filename) + 3 + 1; | |
394 char old_file[i]; | |
395 char new_file[i]; | |
396 i = TT.rot_count - 1; | |
397 while (1) { | |
398 sprintf(new_file, "%s.%d", tf->filename, i); | |
399 if (!i) break; | |
400 sprintf(old_file, "%s.%d", tf->filename, --i); | |
401 rename(old_file, new_file); | |
402 } | |
403 rename(tf->filename, new_file); | |
404 unlink(tf->filename); | |
405 close(tf->logfd); | |
406 tf->logfd = open(tf->filename, O_CREAT | O_WRONLY | O_APPEND, 0666); | |
407 } | |
408 ftruncate(tf->logfd, 0); | |
409 } | |
410 } | |
411 return write(tf->logfd, toybuf, len); | |
412 } | |
413 | |
414 //Parse messege and write to file. | |
415 static void logmsg(char *msg, int len) | |
416 { | |
417 time_t now; | |
418 char *p, *ts, *lvlstr, *facstr; | |
419 struct utsname uts; | |
420 int pri = 0; | |
421 struct arg_list *lnode = TT.lfiles; | |
422 | |
423 char *omsg = msg; | |
424 int olen = len, fac, lvl; | |
425 | |
426 if (*msg == '<') { // Extract the priority no. | |
427 pri = (int) strtoul(msg + 1, &p, 10); | |
428 if (*p == '>') msg = p + 1; | |
429 } | |
430 /* Jan 18 00:11:22 msg... | |
431 * 01234567890123456 | |
432 */ | |
433 if (len < 16 || msg[3] != ' ' || msg[6] != ' ' || msg[9] != ':' | |
434 || msg[12] != ':' || msg[15] != ' ') { | |
435 time(&now); | |
436 ts = ctime(&now) + 4; /* skip day of week */ | |
437 } else { | |
438 now = 0; | |
439 ts = msg; | |
440 msg += 16; | |
441 } | |
442 ts[15] = '\0'; | |
443 fac = LOG_FAC(pri); | |
444 lvl = LOG_PRI(pri); | |
445 | |
1024 | 446 if (toys.optflags & FLAG_K) len = sprintf(toybuf, "<%d> %s\n", pri, msg); |
447 else { | |
1025 | 448 facstr = dec(LOG_FAC(pri), facilitynames); |
449 lvlstr = dec(LOG_PRI(pri), prioritynames); | |
960 | 450 |
1024 | 451 p = "local"; |
452 if (!uname(&uts)) p = uts.nodename; | |
453 if (toys.optflags & FLAG_S) len = sprintf(toybuf, "%s %s\n", ts, msg); | |
454 else len = sprintf(toybuf, "%s %s %s.%s %s\n", ts, p, facstr, lvlstr, msg); | |
455 } | |
960 | 456 if (lvl >= TT.log_prio) return; |
457 | |
458 while (lnode) { | |
1021 | 459 struct logfile *tf = (struct logfile*) lnode->arg; |
960 | 460 if (tf->logfd > 0) { |
461 if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) { | |
462 int wlen; | |
463 if (tf->isNetwork) | |
464 wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr)); | |
465 else wlen = write_rotate(tf, len); | |
1024 | 466 if (wlen < 0) perror_msg("write failed file : %s ", tf->filename + tf->isNetwork); |
960 | 467 } |
468 } | |
469 lnode = lnode->next; | |
470 } | |
471 } | |
472 | |
473 /* | |
474 * closes all read and write fds | |
475 * and frees all nodes and lists | |
476 */ | |
477 static void cleanup(void) | |
478 { | |
479 struct arg_list *fnode; | |
480 while (TT.lsocks) { | |
481 fnode = TT.lsocks; | |
1021 | 482 if (((struct unsocks*) fnode->arg)->sd >= 0) |
483 close(((struct unsocks*) fnode->arg)->sd); | |
960 | 484 free(fnode->arg); |
485 TT.lsocks = fnode->next; | |
486 free(fnode); | |
487 } | |
488 unlink("/dev/log"); | |
489 | |
490 while (TT.lfiles) { | |
491 fnode = TT.lfiles; | |
1021 | 492 if (((struct logfile*) fnode->arg)->logfd >= 0) |
493 close(((struct logfile*) fnode->arg)->logfd); | |
960 | 494 free(fnode->arg); |
495 TT.lfiles = fnode->next; | |
496 free(fnode); | |
497 } | |
498 } | |
499 | |
500 static void signal_handler(int sig) | |
501 { | |
502 unsigned char ch = sig; | |
1021 | 503 if (write(TT.sigfd[1], &ch, 1) != 1) error_msg("can't send signal"); |
960 | 504 } |
505 | |
506 void syslogd_main(void) | |
507 { | |
1021 | 508 struct unsocks *tsd; |
960 | 509 int maxfd, retval, last_len=0; |
510 struct timeval tv; | |
511 struct arg_list *node; | |
512 char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each | |
513 | |
1024 | 514 if ((toys.optflags & FLAG_p) && (strlen(TT.unix_socket) > 108)) |
960 | 515 error_exit("Socket path should not be more than 108"); |
516 | |
1024 | 517 TT.config_file = (toys.optflags & FLAG_f) ? |
518 TT.config_file : "/etc/syslog.conf"; //DEFCONFFILE | |
960 | 519 init_jumpin: |
520 TT.lsocks = xzalloc(sizeof(struct arg_list)); | |
1021 | 521 tsd = xzalloc(sizeof(struct unsocks)); |
960 | 522 |
1024 | 523 tsd->path = (toys.optflags & FLAG_p) ? TT.unix_socket : "/dev/log"; // DEFLOGSOCK |
960 | 524 TT.lsocks->arg = (char*) tsd; |
525 | |
1024 | 526 if (toys.optflags & FLAG_a) { |
960 | 527 for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) { |
528 struct arg_list *ltemp = xzalloc(sizeof(struct arg_list)); | |
529 if (strlen(temp) > 107) temp[108] = '\0'; | |
1021 | 530 tsd = xzalloc(sizeof(struct unsocks)); |
960 | 531 tsd->path = temp; |
532 ltemp->arg = (char*) tsd; | |
533 ltemp->next = TT.lsocks; | |
534 TT.lsocks = ltemp; | |
535 } | |
536 } | |
537 if (!open_unix_socks()) { | |
538 error_msg("Can't open single socket for listenning."); | |
539 goto clean_and_exit; | |
540 } | |
1021 | 541 |
542 // Setup signals | |
543 if (pipe(TT.sigfd) < 0) error_exit("pipe failed\n"); | |
544 | |
545 fcntl(TT.sigfd[1] , F_SETFD, FD_CLOEXEC); | |
546 fcntl(TT.sigfd[0] , F_SETFD, FD_CLOEXEC); | |
547 int flags = fcntl(TT.sigfd[1], F_GETFL); | |
548 fcntl(TT.sigfd[1], F_SETFL, flags | O_NONBLOCK); | |
549 signal(SIGHUP, signal_handler); | |
550 signal(SIGTERM, signal_handler); | |
551 signal(SIGINT, signal_handler); | |
552 signal(SIGQUIT, signal_handler); | |
553 | |
960 | 554 if (parse_config_file() == -1) goto clean_and_exit; |
555 open_logfiles(); | |
1024 | 556 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
|
557 //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
|
558 toys.optflags |= FLAG_n; |
893c86bbe452
Add daemonize function to lib for klogd and syslogd
Felix Janda <felix.janda@posteo.de>
parents:
960
diff
changeset
|
559 } |
960 | 560 { |
561 int pid_fd = open("/var/run/syslogd.pid", O_CREAT | O_WRONLY | O_TRUNC, 0666); | |
562 if (pid_fd > 0) { | |
563 unsigned pid = getpid(); | |
564 int len = sprintf(toybuf, "%u\n", pid); | |
565 write(pid_fd, toybuf, len); | |
566 close(pid_fd); | |
567 } | |
568 } | |
569 | |
570 logmsg("<46>Toybox: syslogd started", 27); //27 : the length of message | |
571 for (;;) { | |
572 maxfd = addrfds(); | |
573 tv.tv_usec = 0; | |
574 tv.tv_sec = TT.interval*60; | |
575 | |
576 retval = select(maxfd + 1, &TT.rfds, NULL, NULL, (TT.interval)?&tv:NULL); | |
577 if (retval < 0) { /* Some error. */ | |
578 if (errno == EINTR) continue; | |
579 perror_msg("Error in select "); | |
580 continue; | |
581 } | |
582 if (!retval) { /* Timed out */ | |
583 logmsg("<46>-- MARK --", 14); | |
584 continue; | |
585 } | |
1021 | 586 if (FD_ISSET(TT.sigfd[0], &TT.rfds)) { /* May be a signal */ |
960 | 587 unsigned char sig; |
588 | |
1021 | 589 if (read(TT.sigfd[0], &sig, 1) != 1) { |
960 | 590 error_msg("signal read failed.\n"); |
591 continue; | |
592 } | |
593 switch(sig) { | |
594 case SIGTERM: /* FALLTHROUGH */ | |
595 case SIGINT: /* FALLTHROUGH */ | |
596 case SIGQUIT: | |
597 logmsg("<46>syslogd exiting", 19); | |
598 if (CFG_TOYBOX_FREE ) cleanup(); | |
599 signal(sig, SIG_DFL); | |
600 sigset_t ss; | |
601 sigemptyset(&ss); | |
602 sigaddset(&ss, sig); | |
603 sigprocmask(SIG_UNBLOCK, &ss, NULL); | |
604 raise(sig); | |
605 _exit(1); /* Should not reach it */ | |
606 break; | |
607 case SIGHUP: | |
608 logmsg("<46>syslogd exiting", 19); | |
609 cleanup(); //cleanup is done, as we restart syslog. | |
610 goto init_jumpin; | |
611 default: break; | |
612 } | |
613 } | |
614 if (retval > 0) { /* Some activity on listen sockets. */ | |
615 node = TT.lsocks; | |
616 while (node) { | |
1021 | 617 int sd = ((struct unsocks*) node->arg)->sd; |
960 | 618 if (FD_ISSET(sd, &TT.rfds)) { |
619 int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL | |
620 if (len > 0) { | |
621 buffer[len] = '\0'; | |
1024 | 622 if((toys.optflags & FLAG_D) && (len == last_len)) |
960 | 623 if (!memcmp(last_buf, buffer, len)) break; |
624 | |
625 memcpy(last_buf, buffer, len); | |
626 last_len = len; | |
627 logmsg(buffer, len); | |
628 } | |
629 break; | |
630 } | |
631 node = node->next; | |
632 } | |
633 } | |
634 } | |
635 clean_and_exit: | |
636 logmsg("<46>syslogd exiting", 19); | |
637 if (CFG_TOYBOX_FREE ) cleanup(); | |
638 } |