comparison toys/pending/syslogd.c @ 1026:09cc81f6e411 draft

syslogd: stop abusing arg_list
author Felix Janda <felix.janda at posteo.de>
date Fri, 23 Aug 2013 22:50:29 +0200
parents f19286ac3e7f
children 4b0ad1c7af42
comparison
equal deleted inserted replaced
1025:f19286ac3e7f 1026:09cc81f6e411
35 #define FOR_syslogd 35 #define FOR_syslogd
36 #define SYSLOG_NAMES 36 #define SYSLOG_NAMES
37 #include "toys.h" 37 #include "toys.h"
38 #include "toynet.h" 38 #include "toynet.h"
39 39
40 // UNIX Sockets for listening
41 struct unsocks {
42 struct unsocks *next;
43 char *path;
44 struct sockaddr_un sdu;
45 int sd;
46 };
47
48 // Log file entry to log into.
49 struct logfile {
50 struct logfile *next;
51 char *filename;
52 char *config;
53 int isNetwork;
54 uint32_t facility[8];
55 uint8_t level[LOG_NFACILITIES];
56 int logfd;
57 struct sockaddr_in saddr;
58 };
59
40 GLOBALS( 60 GLOBALS(
41 char *socket; 61 char *socket;
42 char *config_file; 62 char *config_file;
43 char *unix_socket; 63 char *unix_socket;
44 char *logfile; 64 char *logfile;
46 long rot_size; 66 long rot_size;
47 long rot_count; 67 long rot_count;
48 char *remote_log; 68 char *remote_log;
49 long log_prio; 69 long log_prio;
50 70
51 struct arg_list *lsocks; // list of listen sockets 71 struct unsocks *lsocks; // list of listen sockets
52 struct arg_list *lfiles; // list of write logfiles 72 struct logfile *lfiles; // list of write logfiles
53 fd_set rfds; // fds for reading 73 fd_set rfds; // fds for reading
54 int sd; // socket for logging remote messeges. 74 int sd; // socket for logging remote messeges.
55 int sigfd[2]; 75 int sigfd[2];
56 ) 76 )
57 77
58
59 // UNIX Sockets for listening
60 struct unsocks {
61 char *path;
62 struct sockaddr_un sdu;
63 int sd;
64 };
65
66 // Log file entry to log into.
67 struct logfile {
68 char *filename;
69 char *config;
70 int isNetwork;
71 uint32_t facility[8];
72 uint8_t level[LOG_NFACILITIES];
73 int logfd;
74 struct sockaddr_in saddr;
75 };
76
77 // Lookup numerical code from name 78 // Lookup numerical code from name
78 // Also used in logger 79 // Also used in logger
79 int logger_lookup(int where, char *key) 80 int logger_lookup(int where, char *key)
80 { 81 {
81 CODE *w = ((CODE *[]){facilitynames, prioritynames})[where]; 82 CODE *w = ((CODE *[]){facilitynames, prioritynames})[where];
95 } 96 }
96 97
97 // Adds opened socks to rfds for select() 98 // Adds opened socks to rfds for select()
98 static int addrfds(void) 99 static int addrfds(void)
99 { 100 {
100 struct unsocks *sock; 101 struct unsocks *sock = TT.lsocks;
101 int ret = 0; 102 int ret = 0;
102 struct arg_list *node = TT.lsocks;
103 FD_ZERO(&TT.rfds); 103 FD_ZERO(&TT.rfds);
104 104
105 while (node) { 105 for (; sock; sock = sock->next) {
106 sock = (struct unsocks*) node->arg;
107 if (sock->sd > 2) { 106 if (sock->sd > 2) {
108 FD_SET(sock->sd, &TT.rfds); 107 FD_SET(sock->sd, &TT.rfds);
109 ret = sock->sd; 108 ret = sock->sd;
110 } 109 }
111 node = node->next;
112 } 110 }
113 FD_SET(TT.sigfd[0], &TT.rfds); 111 FD_SET(TT.sigfd[0], &TT.rfds);
114 return (TT.sigfd[0] > ret) ? TT.sigfd[0] : ret; 112 return (TT.sigfd[0] > ret) ? TT.sigfd[0] : ret;
115 } 113 }
116 114
119 * and opens socket for reading 117 * and opens socket for reading
120 * and adds to global lsock list. 118 * and adds to global lsock list.
121 */ 119 */
122 static int open_unix_socks(void) 120 static int open_unix_socks(void)
123 { 121 {
124 struct arg_list *node;
125 struct unsocks *sock; 122 struct unsocks *sock;
126 int ret = 0; 123 int ret = 0;
127 124
128 for(node = TT.lsocks; node; node = node->next) { 125 for(sock = TT.lsocks; sock; sock = sock->next) {
129 sock = (struct unsocks*) node->arg;
130 sock->sdu.sun_family = AF_UNIX; 126 sock->sdu.sun_family = AF_UNIX;
131 strcpy(sock->sdu.sun_path, sock->path); 127 strcpy(sock->sdu.sun_path, sock->path);
132 sock->sd = socket(AF_UNIX, SOCK_DGRAM, 0); 128 sock->sd = socket(AF_UNIX, SOCK_DGRAM, 0);
133 if (sock->sd < 0) { 129 if (sock->sd < 0) {
134 perror_msg("OPEN SOCKS : failed"); 130 perror_msg("OPEN SOCKS : failed");
142 } 138 }
143 chmod(sock->path, 0777); 139 chmod(sock->path, 0777);
144 ret++; 140 ret++;
145 } 141 }
146 return ret; 142 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) {
153 if (!strcmp(((struct logfile*) list->arg)->filename, filename)) return list;
154 list = list->next;
155 }
156 return list;
157 } 143 }
158 144
159 /* 145 /*
160 * recurses the logfile list and resolves config 146 * recurses the logfile list and resolves config
161 * for evry file and updates facilty and log level bits. 147 * for evry file and updates facilty and log level bits.
220 struct logfile *file; 206 struct logfile *file;
221 FILE *fp; 207 FILE *fp;
222 char *confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL}; 208 char *confline = NULL, *tk = NULL, *tokens[2] = {NULL, NULL};
223 int len, tcount, lineno = 0; 209 int len, tcount, lineno = 0;
224 size_t linelen; 210 size_t linelen;
225 struct arg_list *node;
226 /* 211 /*
227 * if -K then open only /dev/kmsg 212 * if -K then open only /dev/kmsg
228 * all other log files are neglected 213 * all other log files are neglected
229 * thus no need to open config either. 214 * thus no need to open config either.
230 */ 215 */
231 if (toys.optflags & FLAG_K) { 216 if (toys.optflags & FLAG_K) {
232 node = xzalloc(sizeof(struct arg_list));
233 file = xzalloc(sizeof(struct logfile)); 217 file = xzalloc(sizeof(struct logfile));
234 file->filename = "/dev/kmsg"; 218 file->filename = "/dev/kmsg";
235 file->config = "*.*"; 219 file->config = "*.*";
236 memset(file->level, 0xFF, sizeof(file->level)); 220 memset(file->level, 0xFF, sizeof(file->level));
237 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); 221 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
238 node->arg = (char*) file; 222 TT.lfiles = file;
239 TT.lfiles = node;
240 return 0; 223 return 0;
241 } 224 }
242 /* 225 /*
243 * if -R then add remote host to log list 226 * if -R then add remote host to log list
244 * if -L is not provided all other log 227 * if -L is not provided all other log
245 * files are neglected thus no need to 228 * files are neglected thus no need to
246 * open config either so just return. 229 * open config either so just return.
247 */ 230 */
248 if (toys.optflags & FLAG_R) { 231 if (toys.optflags & FLAG_R) {
249 node = xzalloc(sizeof(struct arg_list));
250 file = xzalloc(sizeof(struct logfile)); 232 file = xzalloc(sizeof(struct logfile));
251 file->filename = xmsprintf("@%s",TT.remote_log); 233 file->filename = xmsprintf("@%s",TT.remote_log);
252 file->isNetwork = 1; 234 file->isNetwork = 1;
253 file->config = "*.*"; 235 file->config = "*.*";
254 memset(file->level, 0xFF, sizeof(file->level)); 236 memset(file->level, 0xFF, sizeof(file->level));
255 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); 237 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
256 node->arg = (char*) file; 238 TT.lfiles = file;
257 TT.lfiles = node;
258 if (!(toys.optflags & FLAG_L)) return 0; 239 if (!(toys.optflags & FLAG_L)) return 0;
259 } 240 }
260 /* 241 /*
261 * Read config file and add logfiles to the list 242 * Read config file and add logfiles to the list
262 * with their configuration. 243 * with their configuration.
289 if (*tokens[1] == '\0') { 270 if (*tokens[1] == '\0') {
290 error_msg("bad line %d: 1 tokens found, 2 needed", lineno); 271 error_msg("bad line %d: 1 tokens found, 2 needed", lineno);
291 return -1; 272 return -1;
292 } 273 }
293 if (*tokens[1] != '*') { 274 if (*tokens[1] != '*') {
294 node = get_file_node(tokens[1], TT.lfiles); 275 file = TT.lfiles;
295 if (!node) { 276 while (file && !strcmp(file->filename, tokens[1])) file = file->next;
296 node = xzalloc(sizeof(struct arg_list)); 277 if (!file) {
297 file = xzalloc(sizeof(struct logfile)); 278 file = xzalloc(sizeof(struct logfile));
298 file->config = xstrdup(tokens[0]); 279 file->config = xstrdup(tokens[0]);
299 if (resolve_config(file)==-1) { 280 if (resolve_config(file)==-1) {
300 error_msg("error in '%s' at line %d", TT.config_file, lineno); 281 error_msg("error in '%s' at line %d", TT.config_file, lineno);
301 return -1; 282 return -1;
302 } 283 }
303 file->filename = xstrdup(tokens[1]); 284 file->filename = xstrdup(tokens[1]);
304 if (*file->filename == '@') file->isNetwork = 1; 285 if (*file->filename == '@') file->isNetwork = 1;
305 node->arg = (char*) file; 286 file->next = TT.lfiles;
306 node->next = TT.lfiles; 287 TT.lfiles = file;
307 TT.lfiles = node;
308 } else { 288 } else {
309 file = (struct logfile*) node->arg;
310 int rel = strlen(file->config) + strlen(tokens[0]) + 2; 289 int rel = strlen(file->config) + strlen(tokens[0]) + 2;
311 file->config = xrealloc(file->config, rel); 290 file->config = xrealloc(file->config, rel);
312 sprintf(file->config, "%s;%s", file->config, tokens[0]); 291 sprintf(file->config, "%s;%s", file->config, tokens[0]);
313 } 292 }
314 } 293 }
320 /* 299 /*
321 * Can't open config file or support is not enabled 300 * Can't open config file or support is not enabled
322 * adding default logfile to the head of list. 301 * adding default logfile to the head of list.
323 */ 302 */
324 if (!fp){ 303 if (!fp){
325 node = xzalloc(sizeof(struct arg_list));
326 file = xzalloc(sizeof(struct logfile)); 304 file = xzalloc(sizeof(struct logfile));
327 file->filename = (toys.optflags & FLAG_O) ? 305 file->filename = (toys.optflags & FLAG_O) ?
328 TT.logfile : "/var/log/messages"; //DEFLOGFILE 306 TT.logfile : "/var/log/messages"; //DEFLOGFILE
329 file->config = "*.*"; 307 file->config = "*.*";
330 memset(file->level, 0xFF, sizeof(file->level)); 308 memset(file->level, 0xFF, sizeof(file->level));
331 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); 309 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
332 node->arg = (char*) file; 310 file->next = TT.lfiles;
333 node->next = TT.lfiles; 311 TT.lfiles = file;
334 TT.lfiles = node;
335 } else fclose(fp); 312 } else fclose(fp);
336 return 0; 313 return 0;
337 } 314 }
338 315
339 // open every log file in list. 316 // open every log file in list.
340 static void open_logfiles(void) 317 static void open_logfiles(void)
341 { 318 {
342 struct arg_list *node; 319 struct logfile *tfd;
343 320
344 for (node = TT.lfiles; node; node = node->next) { 321 for (tfd = TT.lfiles; tfd; tfd = tfd->next) {
345 struct logfile *tfd = (struct logfile*) node->arg;
346 char *p, *tmpfile; 322 char *p, *tmpfile;
347 long port = 514; 323 long port = 514;
348 324
349 if (tfd->isNetwork) { 325 if (tfd->isNetwork) {
350 struct addrinfo *info, rp; 326 struct addrinfo *info, rp;
416 { 392 {
417 time_t now; 393 time_t now;
418 char *p, *ts, *lvlstr, *facstr; 394 char *p, *ts, *lvlstr, *facstr;
419 struct utsname uts; 395 struct utsname uts;
420 int pri = 0; 396 int pri = 0;
421 struct arg_list *lnode = TT.lfiles; 397 struct logfile *tf = TT.lfiles;
422 398
423 char *omsg = msg; 399 char *omsg = msg;
424 int olen = len, fac, lvl; 400 int olen = len, fac, lvl;
425 401
426 if (*msg == '<') { // Extract the priority no. 402 if (*msg == '<') { // Extract the priority no.
453 if (toys.optflags & FLAG_S) len = sprintf(toybuf, "%s %s\n", ts, msg); 429 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); 430 else len = sprintf(toybuf, "%s %s %s.%s %s\n", ts, p, facstr, lvlstr, msg);
455 } 431 }
456 if (lvl >= TT.log_prio) return; 432 if (lvl >= TT.log_prio) return;
457 433
458 while (lnode) { 434 for (; tf; tf = tf->next) {
459 struct logfile *tf = (struct logfile*) lnode->arg;
460 if (tf->logfd > 0) { 435 if (tf->logfd > 0) {
461 if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) { 436 if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) {
462 int wlen; 437 int wlen;
463 if (tf->isNetwork) 438 if (tf->isNetwork)
464 wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr)); 439 wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr));
465 else wlen = write_rotate(tf, len); 440 else wlen = write_rotate(tf, len);
466 if (wlen < 0) perror_msg("write failed file : %s ", tf->filename + tf->isNetwork); 441 if (wlen < 0) perror_msg("write failed file : %s ", tf->filename + tf->isNetwork);
467 } 442 }
468 } 443 }
469 lnode = lnode->next;
470 } 444 }
471 } 445 }
472 446
473 /* 447 /*
474 * closes all read and write fds 448 * closes all read and write fds
475 * and frees all nodes and lists 449 * and frees all nodes and lists
476 */ 450 */
477 static void cleanup(void) 451 static void cleanup(void)
478 { 452 {
479 struct arg_list *fnode;
480 while (TT.lsocks) { 453 while (TT.lsocks) {
481 fnode = TT.lsocks; 454 struct unsocks *fnode = TT.lsocks;
482 if (((struct unsocks*) fnode->arg)->sd >= 0) 455
483 close(((struct unsocks*) fnode->arg)->sd); 456 if (fnode->sd >= 0) close(fnode->sd);
484 free(fnode->arg);
485 TT.lsocks = fnode->next; 457 TT.lsocks = fnode->next;
486 free(fnode); 458 free(fnode);
487 } 459 }
488 unlink("/dev/log"); 460 unlink("/dev/log");
489 461
490 while (TT.lfiles) { 462 while (TT.lfiles) {
491 fnode = TT.lfiles; 463 struct logfile *fnode = TT.lfiles;
492 if (((struct logfile*) fnode->arg)->logfd >= 0) 464
493 close(((struct logfile*) fnode->arg)->logfd); 465 if (fnode->logfd >= 0) close(fnode->logfd);
494 free(fnode->arg);
495 TT.lfiles = fnode->next; 466 TT.lfiles = fnode->next;
496 free(fnode); 467 free(fnode);
497 } 468 }
498 } 469 }
499 470
506 void syslogd_main(void) 477 void syslogd_main(void)
507 { 478 {
508 struct unsocks *tsd; 479 struct unsocks *tsd;
509 int maxfd, retval, last_len=0; 480 int maxfd, retval, last_len=0;
510 struct timeval tv; 481 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 482 char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each
513 483
514 if ((toys.optflags & FLAG_p) && (strlen(TT.unix_socket) > 108)) 484 if ((toys.optflags & FLAG_p) && (strlen(TT.unix_socket) > 108))
515 error_exit("Socket path should not be more than 108"); 485 error_exit("Socket path should not be more than 108");
516 486
517 TT.config_file = (toys.optflags & FLAG_f) ? 487 TT.config_file = (toys.optflags & FLAG_f) ?
518 TT.config_file : "/etc/syslog.conf"; //DEFCONFFILE 488 TT.config_file : "/etc/syslog.conf"; //DEFCONFFILE
519 init_jumpin: 489 init_jumpin:
520 TT.lsocks = xzalloc(sizeof(struct arg_list));
521 tsd = xzalloc(sizeof(struct unsocks)); 490 tsd = xzalloc(sizeof(struct unsocks));
522 491
523 tsd->path = (toys.optflags & FLAG_p) ? TT.unix_socket : "/dev/log"; // DEFLOGSOCK 492 tsd->path = (toys.optflags & FLAG_p) ? TT.unix_socket : "/dev/log"; // DEFLOGSOCK
524 TT.lsocks->arg = (char*) tsd; 493 TT.lsocks = tsd;
525 494
526 if (toys.optflags & FLAG_a) { 495 if (toys.optflags & FLAG_a) {
527 for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) { 496 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'; 497 if (strlen(temp) > 107) temp[108] = '\0';
530 tsd = xzalloc(sizeof(struct unsocks)); 498 tsd = xzalloc(sizeof(struct unsocks));
531 tsd->path = temp; 499 tsd->path = temp;
532 ltemp->arg = (char*) tsd; 500 tsd->next = TT.lsocks;
533 ltemp->next = TT.lsocks; 501 TT.lsocks = tsd;
534 TT.lsocks = ltemp;
535 } 502 }
536 } 503 }
537 if (!open_unix_socks()) { 504 if (!open_unix_socks()) {
538 error_msg("Can't open single socket for listenning."); 505 error_msg("Can't open single socket for listenning.");
539 goto clean_and_exit; 506 goto clean_and_exit;
610 goto init_jumpin; 577 goto init_jumpin;
611 default: break; 578 default: break;
612 } 579 }
613 } 580 }
614 if (retval > 0) { /* Some activity on listen sockets. */ 581 if (retval > 0) { /* Some activity on listen sockets. */
615 node = TT.lsocks; 582 for (tsd = TT.lsocks; tsd; tsd = tsd->next) {
616 while (node) { 583 int sd = tsd->sd;
617 int sd = ((struct unsocks*) node->arg)->sd;
618 if (FD_ISSET(sd, &TT.rfds)) { 584 if (FD_ISSET(sd, &TT.rfds)) {
619 int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL 585 int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL
620 if (len > 0) { 586 if (len > 0) {
621 buffer[len] = '\0'; 587 buffer[len] = '\0';
622 if((toys.optflags & FLAG_D) && (len == last_len)) 588 if((toys.optflags & FLAG_D) && (len == last_len))
626 last_len = len; 592 last_len = len;
627 logmsg(buffer, len); 593 logmsg(buffer, len);
628 } 594 }
629 break; 595 break;
630 } 596 }
631 node = node->next;
632 } 597 }
633 } 598 }
634 } 599 }
635 clean_and_exit: 600 clean_and_exit:
636 logmsg("<46>syslogd exiting", 19); 601 logmsg("<46>syslogd exiting", 19);