comparison toys/pending/syslogd.c @ 1021:773e4862e790

syslogd: cleanup - Remove structure fd_pair so that sigfd can go into GLOBALS - Remove struct typedefs - Inline setup_signal() - Small fix in Usage message
author Felix Janda <felix.janda@posteo.de>
date Tue, 20 Aug 2013 23:15:48 +0200
parents f9271a80fedc
children 63b8e54d2c6f
comparison
equal deleted inserted replaced
1020:fe7725c1819a 1021:773e4862e790
9 9
10 config SYSLOGD 10 config SYSLOGD
11 bool "syslogd" 11 bool "syslogd"
12 default n 12 default n
13 help 13 help
14 Usage: syslogd [-a socket] [-p socket] [-O logfile] [-f config file] [-m interval] 14 Usage: syslogd [-a socket] [-O logfile] [-f config file] [-m interval]
15 [-p socket] [-s SIZE] [-b N] [-R HOST] [-l N] [-nSLKD] 15 [-p socket] [-s SIZE] [-b N] [-R HOST] [-l N] [-nSLKD]
16 16
17 System logging utility 17 System logging utility
18 18
19 -a Extra unix socket for listen 19 -a Extra unix socket for listen
50 50
51 struct arg_list *lsocks; // list of listen sockets 51 struct arg_list *lsocks; // list of listen sockets
52 struct arg_list *lfiles; // list of write logfiles 52 struct arg_list *lfiles; // list of write logfiles
53 fd_set rfds; // fds for reading 53 fd_set rfds; // fds for reading
54 int sd; // socket for logging remote messeges. 54 int sd; // socket for logging remote messeges.
55 int sigfd[2];
55 ) 56 )
56 57
57 #define flag_get(f,v,d) ((toys.optflags & f) ? v : d) 58 #define flag_get(f,v,d) ((toys.optflags & f) ? v : d)
58 #define flag_chk(f) ((toys.optflags & f) ? 1 : 0) 59 #define flag_chk(f) ((toys.optflags & f) ? 1 : 0)
59 60
60 61
61 // Signal handling
62 struct fd_pair { int rd; int wr; };
63 static struct fd_pair sigfd;
64
65 // UNIX Sockets for listening 62 // UNIX Sockets for listening
66 typedef struct unsocks_s { 63 struct unsocks {
67 char *path; 64 char *path;
68 struct sockaddr_un sdu; 65 struct sockaddr_un sdu;
69 int sd; 66 int sd;
70 } unsocks_t; 67 };
71 68
72 // Log file entry to log into. 69 // Log file entry to log into.
73 typedef struct logfile_s { 70 struct logfile {
74 char *filename; 71 char *filename;
75 char *config; 72 char *config;
76 uint8_t isNetwork; 73 uint8_t isNetwork;
77 uint32_t facility[8]; 74 uint32_t facility[8];
78 uint8_t level[LOG_NFACILITIES]; 75 uint8_t level[LOG_NFACILITIES];
79 int logfd; 76 int logfd;
80 struct sockaddr_in saddr; 77 struct sockaddr_in saddr;
81 } logfile_t; 78 };
82 79
83 // Adds opened socks to rfds for select() 80 // Adds opened socks to rfds for select()
84 static int addrfds(void) 81 static int addrfds(void)
85 { 82 {
86 unsocks_t *sock; 83 struct unsocks *sock;
87 int ret = 0; 84 int ret = 0;
88 struct arg_list *node = TT.lsocks; 85 struct arg_list *node = TT.lsocks;
89 FD_ZERO(&TT.rfds); 86 FD_ZERO(&TT.rfds);
90 87
91 while (node) { 88 while (node) {
92 sock = (unsocks_t*) node->arg; 89 sock = (struct unsocks*) node->arg;
93 if (sock->sd > 2) { 90 if (sock->sd > 2) {
94 FD_SET(sock->sd, &TT.rfds); 91 FD_SET(sock->sd, &TT.rfds);
95 ret = sock->sd; 92 ret = sock->sd;
96 } 93 }
97 node = node->next; 94 node = node->next;
98 } 95 }
99 FD_SET(sigfd.rd, &TT.rfds); 96 FD_SET(TT.sigfd[0], &TT.rfds);
100 return (sigfd.rd > ret)?sigfd.rd:ret; 97 return (TT.sigfd[0] > ret) ? TT.sigfd[0] : ret;
101 } 98 }
102 99
103 /* 100 /*
104 * initializes unsock_t structure 101 * initializes unsock_t structure
105 * and opens socket for reading 102 * and opens socket for reading
106 * and adds to global lsock list. 103 * and adds to global lsock list.
107 */ 104 */
108 static int open_unix_socks(void) 105 static int open_unix_socks(void)
109 { 106 {
110 struct arg_list *node; 107 struct arg_list *node;
111 unsocks_t *sock; 108 struct unsocks *sock;
112 int ret = 0; 109 int ret = 0;
113 110
114 for(node = TT.lsocks; node; node = node->next) { 111 for(node = TT.lsocks; node; node = node->next) {
115 sock = (unsocks_t*) node->arg; 112 sock = (struct unsocks*) node->arg;
116 sock->sdu.sun_family = AF_UNIX; 113 sock->sdu.sun_family = AF_UNIX;
117 strcpy(sock->sdu.sun_path, sock->path); 114 strcpy(sock->sdu.sun_path, sock->path);
118 sock->sd = socket(AF_UNIX, SOCK_DGRAM, 0); 115 sock->sd = socket(AF_UNIX, SOCK_DGRAM, 0);
119 if (sock->sd < 0) { 116 if (sock->sd < 0) {
120 perror_msg("OPEN SOCKS : failed"); 117 perror_msg("OPEN SOCKS : failed");
156 153
157 // Returns node having filename 154 // Returns node having filename
158 static struct arg_list *get_file_node(char *filename, struct arg_list *list) 155 static struct arg_list *get_file_node(char *filename, struct arg_list *list)
159 { 156 {
160 while (list) { 157 while (list) {
161 if (!strcmp(((logfile_t*) list->arg)->filename, filename)) return list; 158 if (!strcmp(((struct logfile*) list->arg)->filename, filename)) return list;
162 list = list->next; 159 list = list->next;
163 } 160 }
164 return list; 161 return list;
165 } 162 }
166 163
167 /* 164 /*
168 * recurses the logfile list and resolves config 165 * recurses the logfile list and resolves config
169 * for evry file and updates facilty and log level bits. 166 * for evry file and updates facilty and log level bits.
170 */ 167 */
171 static int resolve_config(logfile_t *file) 168 static int resolve_config(struct logfile *file)
172 { 169 {
173 char *tk, *fac, *lvl, *tmp, *nfac; 170 char *tk, *fac, *lvl, *tmp, *nfac;
174 int count = 0; 171 int count = 0;
175 unsigned facval = 0; 172 unsigned facval = 0;
176 uint8_t set, levval, neg; 173 uint8_t set, levval, neg;
252 } 249 }
253 250
254 // Parse config file and update the log file list. 251 // Parse config file and update the log file list.
255 static int parse_config_file(void) 252 static int parse_config_file(void)
256 { 253 {
257 logfile_t *file; 254 struct logfile *file;
258 FILE *fp = NULL; 255 FILE *fp = NULL;
259 char *confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL}; 256 char *confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL};
260 int len, linelen, tcount, lineno = 0; 257 int len, linelen, tcount, lineno = 0;
261 struct arg_list *node; 258 struct arg_list *node;
262 /* 259 /*
264 * all other log files are neglected 261 * all other log files are neglected
265 * thus no need to open config either. 262 * thus no need to open config either.
266 */ 263 */
267 if (flag_chk(FLAG_K)) { 264 if (flag_chk(FLAG_K)) {
268 node = xzalloc(sizeof(struct arg_list)); 265 node = xzalloc(sizeof(struct arg_list));
269 file = xzalloc(sizeof(logfile_t)); 266 file = xzalloc(sizeof(struct logfile));
270 file->filename = "/dev/kmsg"; 267 file->filename = "/dev/kmsg";
271 file->config = "*.*"; 268 file->config = "*.*";
272 memset(file->level, 0xFF, sizeof(file->level)); 269 memset(file->level, 0xFF, sizeof(file->level));
273 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); 270 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
274 node->arg = (char*) file; 271 node->arg = (char*) file;
281 * files are neglected thus no need to 278 * files are neglected thus no need to
282 * open config either so just return. 279 * open config either so just return.
283 */ 280 */
284 if (flag_chk(FLAG_R)) { 281 if (flag_chk(FLAG_R)) {
285 node = xzalloc(sizeof(struct arg_list)); 282 node = xzalloc(sizeof(struct arg_list));
286 file = xzalloc(sizeof(logfile_t)); 283 file = xzalloc(sizeof(struct logfile));
287 file->filename = xmsprintf("@%s",TT.remote_log); 284 file->filename = xmsprintf("@%s",TT.remote_log);
288 file->isNetwork = 1; 285 file->isNetwork = 1;
289 file->config = "*.*"; 286 file->config = "*.*";
290 memset(file->level, 0xFF, sizeof(file->level)); 287 memset(file->level, 0xFF, sizeof(file->level));
291 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); 288 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
329 if (*tokens[1] == '*') goto loop_again; 326 if (*tokens[1] == '*') goto loop_again;
330 327
331 node = get_file_node(tokens[1], TT.lfiles); 328 node = get_file_node(tokens[1], TT.lfiles);
332 if (!node) { 329 if (!node) {
333 node = xzalloc(sizeof(struct arg_list)); 330 node = xzalloc(sizeof(struct arg_list));
334 file = xzalloc(sizeof(logfile_t)); 331 file = xzalloc(sizeof(struct logfile));
335 file->config = xstrdup(tokens[0]); 332 file->config = xstrdup(tokens[0]);
336 if (resolve_config(file)==-1) { 333 if (resolve_config(file)==-1) {
337 error_msg("error in '%s' at line %d", TT.config_file, lineno); 334 error_msg("error in '%s' at line %d", TT.config_file, lineno);
338 return -1; 335 return -1;
339 } 336 }
341 if (*file->filename == '@') file->isNetwork = 1; 338 if (*file->filename == '@') file->isNetwork = 1;
342 node->arg = (char*) file; 339 node->arg = (char*) file;
343 node->next = TT.lfiles; 340 node->next = TT.lfiles;
344 TT.lfiles = node; 341 TT.lfiles = node;
345 } else { 342 } else {
346 file = (logfile_t*) node->arg; 343 file = (struct logfile*) node->arg;
347 int rel = strlen(file->config) + strlen(tokens[0]) + 2; 344 int rel = strlen(file->config) + strlen(tokens[0]) + 2;
348 file->config = xrealloc(file->config, rel); 345 file->config = xrealloc(file->config, rel);
349 sprintf(file->config, "%s;%s", file->config, tokens[0]); 346 sprintf(file->config, "%s;%s", file->config, tokens[0]);
350 } 347 }
351 loop_again: 348 loop_again:
358 * Can't open config file or support is not enabled 355 * Can't open config file or support is not enabled
359 * adding default logfile to the head of list. 356 * adding default logfile to the head of list.
360 */ 357 */
361 if (!fp){ 358 if (!fp){
362 node = xzalloc(sizeof(struct arg_list)); 359 node = xzalloc(sizeof(struct arg_list));
363 file = xzalloc(sizeof(logfile_t)); 360 file = xzalloc(sizeof(struct logfile));
364 file->filename = flag_get(FLAG_O, TT.logfile, "/var/log/messages"); //DEFLOGFILE 361 file->filename = flag_get(FLAG_O, TT.logfile, "/var/log/messages"); //DEFLOGFILE
365 file->isNetwork = 0; 362 file->isNetwork = 0;
366 file->config = "*.*"; 363 file->config = "*.*";
367 memset(file->level, 0xFF, sizeof(file->level)); 364 memset(file->level, 0xFF, sizeof(file->level));
368 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); 365 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
393 } 390 }
394 391
395 // open every log file in list. 392 // open every log file in list.
396 static void open_logfiles(void) 393 static void open_logfiles(void)
397 { 394 {
398 logfile_t *tfd; 395 struct logfile *tfd;
399 char *p, *tmpfile; 396 char *p, *tmpfile;
400 int port = -1; 397 int port = -1;
401 struct arg_list *node = TT.lfiles; 398 struct arg_list *node = TT.lfiles;
402 399
403 while (node) { 400 while (node) {
404 tfd = (logfile_t*) node->arg; 401 tfd = (struct logfile*) node->arg;
405 if (tfd->isNetwork) { 402 if (tfd->isNetwork) {
406 tmpfile = xstrdup(tfd->filename +1); 403 tmpfile = xstrdup(tfd->filename +1);
407 if ((p = strchr(tmpfile, ':'))) { 404 if ((p = strchr(tmpfile, ':'))) {
408 *p = '\0'; 405 *p = '\0';
409 port = getport(p + 1, tfd->filename); 406 port = getport(p + 1, tfd->filename);
418 node = node->next; 415 node = node->next;
419 } 416 }
420 } 417 }
421 418
422 //write to file with rotation 419 //write to file with rotation
423 static int write_rotate( logfile_t *tf, int len) 420 static int write_rotate(struct logfile *tf, int len)
424 { 421 {
425 int size, isreg; 422 int size, isreg;
426 struct stat statf; 423 struct stat statf;
427 isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode)); 424 isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode));
428 size = statf.st_size; 425 size = statf.st_size;
529 526
530 do_log: 527 do_log:
531 if (lvl >= TT.log_prio) return; 528 if (lvl >= TT.log_prio) return;
532 529
533 while (lnode) { 530 while (lnode) {
534 logfile_t *tf = (logfile_t*) lnode->arg; 531 struct logfile *tf = (struct logfile*) lnode->arg;
535 if (tf->logfd > 0) { 532 if (tf->logfd > 0) {
536 if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) { 533 if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) {
537 int wlen; 534 int wlen;
538 if (tf->isNetwork) 535 if (tf->isNetwork)
539 wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr)); 536 wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr));
552 static void cleanup(void) 549 static void cleanup(void)
553 { 550 {
554 struct arg_list *fnode; 551 struct arg_list *fnode;
555 while (TT.lsocks) { 552 while (TT.lsocks) {
556 fnode = TT.lsocks; 553 fnode = TT.lsocks;
557 if (((unsocks_t*) fnode->arg)->sd >= 0) 554 if (((struct unsocks*) fnode->arg)->sd >= 0)
558 close(((unsocks_t*) fnode->arg)->sd); 555 close(((struct unsocks*) fnode->arg)->sd);
559 free(fnode->arg); 556 free(fnode->arg);
560 TT.lsocks = fnode->next; 557 TT.lsocks = fnode->next;
561 free(fnode); 558 free(fnode);
562 } 559 }
563 unlink("/dev/log"); 560 unlink("/dev/log");
564 561
565 while (TT.lfiles) { 562 while (TT.lfiles) {
566 fnode = TT.lfiles; 563 fnode = TT.lfiles;
567 if (((logfile_t*) fnode->arg)->logfd >= 0) 564 if (((struct logfile*) fnode->arg)->logfd >= 0)
568 close(((logfile_t*) fnode->arg)->logfd); 565 close(((struct logfile*) fnode->arg)->logfd);
569 free(fnode->arg); 566 free(fnode->arg);
570 TT.lfiles = fnode->next; 567 TT.lfiles = fnode->next;
571 free(fnode); 568 free(fnode);
572 } 569 }
573 } 570 }
574 571
575 static void signal_handler(int sig) 572 static void signal_handler(int sig)
576 { 573 {
577 unsigned char ch = sig; 574 unsigned char ch = sig;
578 if (write(sigfd.wr, &ch, 1) != 1) error_msg("can't send signal"); 575 if (write(TT.sigfd[1], &ch, 1) != 1) error_msg("can't send signal");
579 } 576 }
580 577
581 static void setup_signal() 578 void syslogd_main(void)
582 { 579 {
583 if (pipe((int *)&sigfd) < 0) error_exit("pipe failed\n"); 580 struct unsocks *tsd;
584 581 int maxfd, retval, last_len=0;
585 fcntl(sigfd.wr , F_SETFD, FD_CLOEXEC); 582 struct timeval tv;
586 fcntl(sigfd.rd , F_SETFD, FD_CLOEXEC); 583 struct arg_list *node;
587 int flags = fcntl(sigfd.wr, F_GETFL); 584 char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each
588 fcntl(sigfd.wr, F_SETFL, flags | O_NONBLOCK); 585
586 if (flag_chk(FLAG_p) && strlen(TT.unix_socket) > 108)
587 error_exit("Socket path should not be more than 108");
588
589 TT.config_file = flag_get(FLAG_f, TT.config_file, "/etc/syslog.conf"); //DEFCONFFILE
590 init_jumpin:
591 TT.lsocks = xzalloc(sizeof(struct arg_list));
592 tsd = xzalloc(sizeof(struct unsocks));
593
594 tsd->path = flag_get(FLAG_p, TT.unix_socket , "/dev/log"); // DEFLOGSOCK
595 TT.lsocks->arg = (char*) tsd;
596
597 if (flag_chk(FLAG_a)) {
598 for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) {
599 struct arg_list *ltemp = xzalloc(sizeof(struct arg_list));
600 if (strlen(temp) > 107) temp[108] = '\0';
601 tsd = xzalloc(sizeof(struct unsocks));
602 tsd->path = temp;
603 ltemp->arg = (char*) tsd;
604 ltemp->next = TT.lsocks;
605 TT.lsocks = ltemp;
606 }
607 }
608 if (!open_unix_socks()) {
609 error_msg("Can't open single socket for listenning.");
610 goto clean_and_exit;
611 }
612
613 // Setup signals
614 if (pipe(TT.sigfd) < 0) error_exit("pipe failed\n");
615
616 fcntl(TT.sigfd[1] , F_SETFD, FD_CLOEXEC);
617 fcntl(TT.sigfd[0] , F_SETFD, FD_CLOEXEC);
618 int flags = fcntl(TT.sigfd[1], F_GETFL);
619 fcntl(TT.sigfd[1], F_SETFL, flags | O_NONBLOCK);
589 signal(SIGHUP, signal_handler); 620 signal(SIGHUP, signal_handler);
590 signal(SIGTERM, signal_handler); 621 signal(SIGTERM, signal_handler);
591 signal(SIGINT, signal_handler); 622 signal(SIGINT, signal_handler);
592 signal(SIGQUIT, signal_handler); 623 signal(SIGQUIT, signal_handler);
593 } 624
594
595 void syslogd_main(void)
596 {
597 unsocks_t *tsd;
598 int maxfd, retval, last_len=0;
599 struct timeval tv;
600 struct arg_list *node;
601 char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each
602
603 if (flag_chk(FLAG_p) && strlen(TT.unix_socket) > 108)
604 error_exit("Socket path should not be more than 108");
605
606 TT.config_file = flag_get(FLAG_f, TT.config_file, "/etc/syslog.conf"); //DEFCONFFILE
607 init_jumpin:
608 TT.lsocks = xzalloc(sizeof(struct arg_list));
609 tsd = xzalloc(sizeof(unsocks_t));
610
611 tsd->path = flag_get(FLAG_p, TT.unix_socket , "/dev/log"); // DEFLOGSOCK
612 TT.lsocks->arg = (char*) tsd;
613
614 if (flag_chk(FLAG_a)) {
615 for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) {
616 struct arg_list *ltemp = xzalloc(sizeof(struct arg_list));
617 if (strlen(temp) > 107) temp[108] = '\0';
618 tsd = xzalloc(sizeof(unsocks_t));
619 tsd->path = temp;
620 ltemp->arg = (char*) tsd;
621 ltemp->next = TT.lsocks;
622 TT.lsocks = ltemp;
623 }
624 }
625 if (!open_unix_socks()) {
626 error_msg("Can't open single socket for listenning.");
627 goto clean_and_exit;
628 }
629 setup_signal();
630 if (parse_config_file() == -1) goto clean_and_exit; 625 if (parse_config_file() == -1) goto clean_and_exit;
631 open_logfiles(); 626 open_logfiles();
632 if (!flag_chk(FLAG_n)) { 627 if (!flag_chk(FLAG_n)) {
633 //don't daemonize again if SIGHUP received. 628 //don't daemonize again if SIGHUP received.
634 toys.optflags |= FLAG_n; 629 toys.optflags |= FLAG_n;
657 } 652 }
658 if (!retval) { /* Timed out */ 653 if (!retval) { /* Timed out */
659 logmsg("<46>-- MARK --", 14); 654 logmsg("<46>-- MARK --", 14);
660 continue; 655 continue;
661 } 656 }
662 if (FD_ISSET(sigfd.rd, &TT.rfds)) { /* May be a signal */ 657 if (FD_ISSET(TT.sigfd[0], &TT.rfds)) { /* May be a signal */
663 unsigned char sig; 658 unsigned char sig;
664 659
665 if (read(sigfd.rd, &sig, 1) != 1) { 660 if (read(TT.sigfd[0], &sig, 1) != 1) {
666 error_msg("signal read failed.\n"); 661 error_msg("signal read failed.\n");
667 continue; 662 continue;
668 } 663 }
669 switch(sig) { 664 switch(sig) {
670 case SIGTERM: /* FALLTHROUGH */ 665 case SIGTERM: /* FALLTHROUGH */
688 } 683 }
689 } 684 }
690 if (retval > 0) { /* Some activity on listen sockets. */ 685 if (retval > 0) { /* Some activity on listen sockets. */
691 node = TT.lsocks; 686 node = TT.lsocks;
692 while (node) { 687 while (node) {
693 int sd = ((unsocks_t*) node->arg)->sd; 688 int sd = ((struct unsocks*) node->arg)->sd;
694 if (FD_ISSET(sd, &TT.rfds)) { 689 if (FD_ISSET(sd, &TT.rfds)) {
695 int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL 690 int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL
696 if (len > 0) { 691 if (len > 0) {
697 buffer[len] = '\0'; 692 buffer[len] = '\0';
698 if(flag_chk(FLAG_D) && (len == last_len)) 693 if(flag_chk(FLAG_D) && (len == last_len))