comparison 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
comparison
equal deleted inserted replaced
1023:97383e221a4a 1024:63b8e54d2c6f
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 int sigfd[2];
56 ) 56 )
57 57
58 #define flag_get(f,v,d) ((toys.optflags & f) ? v : d)
59 #define flag_chk(f) ((toys.optflags & f) ? 1 : 0)
60
61 58
62 // UNIX Sockets for listening 59 // UNIX Sockets for listening
63 struct unsocks { 60 struct unsocks {
64 char *path; 61 char *path;
65 struct sockaddr_un sdu; 62 struct sockaddr_un sdu;
68 65
69 // Log file entry to log into. 66 // Log file entry to log into.
70 struct logfile { 67 struct logfile {
71 char *filename; 68 char *filename;
72 char *config; 69 char *config;
73 uint8_t isNetwork; 70 int isNetwork;
74 uint32_t facility[8]; 71 uint32_t facility[8];
75 uint8_t level[LOG_NFACILITIES]; 72 uint8_t level[LOG_NFACILITIES];
76 int logfd; 73 int logfd;
77 struct sockaddr_in saddr; 74 struct sockaddr_in saddr;
78 }; 75 };
125 } 122 }
126 chmod(sock->path, 0777); 123 chmod(sock->path, 0777);
127 ret++; 124 ret++;
128 } 125 }
129 return ret; 126 return ret;
130 }
131
132 /*
133 * creates a socket of family INET and protocol UDP
134 * if successful then returns SOCK othrwise error
135 */
136 static int open_udp_socks(char *host, int port, struct sockaddr_in *sadd)
137 {
138 struct addrinfo *info, rp;
139
140 memset(&rp, 0, sizeof(rp));
141 rp.ai_family = AF_INET;
142 rp.ai_socktype = SOCK_DGRAM;
143 rp.ai_protocol = IPPROTO_UDP;
144
145 if (getaddrinfo(host, NULL, &rp, &info) || !info)
146 perror_exit("BAD ADDRESS: can't find : %s ", host);
147 ((struct sockaddr_in*)info->ai_addr)->sin_port = htons(port);
148 memcpy(sadd, info->ai_addr, info->ai_addrlen);
149 freeaddrinfo(info);
150
151 return xsocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
152 } 127 }
153 128
154 // Returns node having filename 129 // Returns node having filename
155 static struct arg_list *get_file_node(char *filename, struct arg_list *list) 130 static struct arg_list *get_file_node(char *filename, struct arg_list *list)
156 { 131 {
259 /* 234 /*
260 * if -K then open only /dev/kmsg 235 * if -K then open only /dev/kmsg
261 * all other log files are neglected 236 * all other log files are neglected
262 * thus no need to open config either. 237 * thus no need to open config either.
263 */ 238 */
264 if (flag_chk(FLAG_K)) { 239 if (toys.optflags & FLAG_K) {
265 node = xzalloc(sizeof(struct arg_list)); 240 node = xzalloc(sizeof(struct arg_list));
266 file = xzalloc(sizeof(struct logfile)); 241 file = xzalloc(sizeof(struct logfile));
267 file->filename = "/dev/kmsg"; 242 file->filename = "/dev/kmsg";
268 file->config = "*.*"; 243 file->config = "*.*";
269 memset(file->level, 0xFF, sizeof(file->level)); 244 memset(file->level, 0xFF, sizeof(file->level));
276 * if -R then add remote host to log list 251 * if -R then add remote host to log list
277 * if -L is not provided all other log 252 * if -L is not provided all other log
278 * files are neglected thus no need to 253 * files are neglected thus no need to
279 * open config either so just return. 254 * open config either so just return.
280 */ 255 */
281 if (flag_chk(FLAG_R)) { 256 if (toys.optflags & FLAG_R) {
282 node = xzalloc(sizeof(struct arg_list)); 257 node = xzalloc(sizeof(struct arg_list));
283 file = xzalloc(sizeof(struct logfile)); 258 file = xzalloc(sizeof(struct logfile));
284 file->filename = xmsprintf("@%s",TT.remote_log); 259 file->filename = xmsprintf("@%s",TT.remote_log);
285 file->isNetwork = 1; 260 file->isNetwork = 1;
286 file->config = "*.*"; 261 file->config = "*.*";
287 memset(file->level, 0xFF, sizeof(file->level)); 262 memset(file->level, 0xFF, sizeof(file->level));
288 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); 263 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
289 node->arg = (char*) file; 264 node->arg = (char*) file;
290 TT.lfiles = node; 265 TT.lfiles = node;
291 if (!flag_chk(FLAG_L))return 0; 266 if (!(toys.optflags & FLAG_L))return 0;
292 } 267 }
293 /* 268 /*
294 * Read config file and add logfiles to the list 269 * Read config file and add logfiles to the list
295 * with their configuration. 270 * with their configuration.
296 */ 271 */
297 fp = fopen(TT.config_file, "r"); 272 fp = fopen(TT.config_file, "r");
298 if (!fp && flag_chk(FLAG_f)) 273 if (!fp && (toys.optflags & FLAG_f))
299 perror_exit("can't open '%s'", TT.config_file); 274 perror_exit("can't open '%s'", TT.config_file);
300 275
301 for (len = 0, linelen = 0; fp;) { 276 for (len = 0, linelen = 0; fp;) {
302 len = getline(&confline, (size_t*) &linelen, fp); 277 len = getline(&confline, (size_t*) &linelen, fp);
303 if (len <= 0) break; 278 if (len <= 0) break;
321 if (*tk == '\n') *tk = '\0'; 296 if (*tk == '\n') *tk = '\0';
322 if (*tokens[1] == '\0') { 297 if (*tokens[1] == '\0') {
323 error_msg("bad line %d: 1 tokens found, 2 needed", lineno); 298 error_msg("bad line %d: 1 tokens found, 2 needed", lineno);
324 return -1; 299 return -1;
325 } 300 }
326 if (*tokens[1] == '*') goto loop_again; 301 if (*tokens[1] != '*') {
327 302 node = get_file_node(tokens[1], TT.lfiles);
328 node = get_file_node(tokens[1], TT.lfiles); 303 if (!node) {
329 if (!node) { 304 node = xzalloc(sizeof(struct arg_list));
330 node = xzalloc(sizeof(struct arg_list)); 305 file = xzalloc(sizeof(struct logfile));
331 file = xzalloc(sizeof(struct logfile)); 306 file->config = xstrdup(tokens[0]);
332 file->config = xstrdup(tokens[0]); 307 if (resolve_config(file)==-1) {
333 if (resolve_config(file)==-1) { 308 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); 309 return -1;
335 return -1; 310 }
336 } 311 file->filename = xstrdup(tokens[1]);
337 file->filename = xstrdup(tokens[1]); 312 if (*file->filename == '@') file->isNetwork = 1;
338 if (*file->filename == '@') file->isNetwork = 1; 313 node->arg = (char*) file;
339 node->arg = (char*) file; 314 node->next = TT.lfiles;
340 node->next = TT.lfiles; 315 TT.lfiles = node;
341 TT.lfiles = node; 316 } else {
342 } else { 317 file = (struct logfile*) node->arg;
343 file = (struct logfile*) node->arg; 318 int rel = strlen(file->config) + strlen(tokens[0]) + 2;
344 int rel = strlen(file->config) + strlen(tokens[0]) + 2; 319 file->config = xrealloc(file->config, rel);
345 file->config = xrealloc(file->config, rel); 320 sprintf(file->config, "%s;%s", file->config, tokens[0]);
346 sprintf(file->config, "%s;%s", file->config, tokens[0]); 321 }
347 } 322 }
348 loop_again:
349 if (tokens[0]) free(tokens[0]); 323 if (tokens[0]) free(tokens[0]);
350 if (tokens[1]) free(tokens[1]); 324 if (tokens[1]) free(tokens[1]);
351 free(confline); 325 free(confline);
352 confline = NULL; 326 confline = NULL;
353 } 327 }
356 * adding default logfile to the head of list. 330 * adding default logfile to the head of list.
357 */ 331 */
358 if (!fp){ 332 if (!fp){
359 node = xzalloc(sizeof(struct arg_list)); 333 node = xzalloc(sizeof(struct arg_list));
360 file = xzalloc(sizeof(struct logfile)); 334 file = xzalloc(sizeof(struct logfile));
361 file->filename = flag_get(FLAG_O, TT.logfile, "/var/log/messages"); //DEFLOGFILE 335 file->filename = (toys.optflags & FLAG_O) ?
336 TT.logfile : "/var/log/messages"; //DEFLOGFILE
362 file->isNetwork = 0; 337 file->isNetwork = 0;
363 file->config = "*.*"; 338 file->config = "*.*";
364 memset(file->level, 0xFF, sizeof(file->level)); 339 memset(file->level, 0xFF, sizeof(file->level));
365 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility)); 340 memset(file->facility, 0xFFFFFFFF, sizeof(file->facility));
366 node->arg = (char*) file; 341 node->arg = (char*) file;
372 fp = NULL; 347 fp = NULL;
373 } 348 }
374 return 0; 349 return 0;
375 } 350 }
376 351
377 static int getport(char *str, char *filename)
378 {
379 char *endptr = NULL;
380 int base = 10;
381 errno = 0;
382 if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
383 base = 16;
384 str += 2;
385 }
386 long port = strtol(str, &endptr, base);
387 if (errno || *endptr!='\0'|| endptr == str
388 || port < 0 || port > 65535) error_exit("wrong port no in %s", filename);
389 return (int)port;
390 }
391
392 // open every log file in list. 352 // open every log file in list.
393 static void open_logfiles(void) 353 static void open_logfiles(void)
394 { 354 {
395 struct logfile *tfd; 355 struct arg_list *node;
396 char *p, *tmpfile; 356
397 int port = -1; 357 for (node = TT.lfiles; node; node = node->next) {
398 struct arg_list *node = TT.lfiles; 358 struct logfile *tfd = (struct logfile*) node->arg;
399 359 char *p, *tmpfile;
400 while (node) { 360 long port = 514;
401 tfd = (struct logfile*) node->arg; 361
402 if (tfd->isNetwork) { 362 if (tfd->isNetwork) {
403 tmpfile = xstrdup(tfd->filename +1); 363 struct addrinfo *info, rp;
364
365 tmpfile = xstrdup(tfd->filename + 1);
404 if ((p = strchr(tmpfile, ':'))) { 366 if ((p = strchr(tmpfile, ':'))) {
367 char *endptr;
368
405 *p = '\0'; 369 *p = '\0';
406 port = getport(p + 1, tfd->filename); 370 port = strtol(++p, &endptr, 10);
407 } 371 if (*endptr || endptr == p || port < 0 || port > 65535)
408 tfd->logfd = open_udp_socks(tmpfile, (port>=0)?port:514, &tfd->saddr); 372 error_exit("bad port in %s", tfd->filename);
373 }
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);
409 free(tmpfile); 386 free(tmpfile);
410 } else tfd->logfd = open(tfd->filename, O_CREAT | O_WRONLY | O_APPEND, 0666); 387 } else tfd->logfd = open(tfd->filename, O_CREAT | O_WRONLY | O_APPEND, 0666);
411 if (tfd->logfd < 0) { 388 if (tfd->logfd < 0) {
412 tfd->filename = "/dev/console"; 389 tfd->filename = "/dev/console";
413 tfd->logfd = open(tfd->filename, O_APPEND); 390 tfd->logfd = open(tfd->filename, O_APPEND);
414 } 391 }
415 node = node->next;
416 } 392 }
417 } 393 }
418 394
419 //write to file with rotation 395 //write to file with rotation
420 static int write_rotate(struct logfile *tf, int len) 396 static int write_rotate(struct logfile *tf, int len)
422 int size, isreg; 398 int size, isreg;
423 struct stat statf; 399 struct stat statf;
424 isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode)); 400 isreg = (!fstat(tf->logfd, &statf) && S_ISREG(statf.st_mode));
425 size = statf.st_size; 401 size = statf.st_size;
426 402
427 if (flag_chk(FLAG_s) || flag_chk(FLAG_b)) { 403 if ((toys.optflags & FLAG_s) || (toys.optflags & FLAG_b)) {
428 if (TT.rot_size && isreg && (size + len) > (TT.rot_size*1024)) { 404 if (TT.rot_size && isreg && (size + len) > (TT.rot_size*1024)) {
429 if (TT.rot_count) { /* always 0..99 */ 405 if (TT.rot_count) { /* always 0..99 */
430 int i = strlen(tf->filename) + 3 + 1; 406 int i = strlen(tf->filename) + 3 + 1;
431 char old_file[i]; 407 char old_file[i];
432 char new_file[i]; 408 char new_file[i];
511 } 487 }
512 ts[15] = '\0'; 488 ts[15] = '\0';
513 fac = LOG_FAC(pri); 489 fac = LOG_FAC(pri);
514 lvl = LOG_PRI(pri); 490 lvl = LOG_PRI(pri);
515 491
516 if (flag_chk(FLAG_K)) { 492 if (toys.optflags & FLAG_K) len = sprintf(toybuf, "<%d> %s\n", pri, msg);
517 len = sprintf(toybuf, "<%d> %s\n", pri, msg); 493 else {
518 goto do_log; 494 priority_to_string(pri, &facstr, &lvlstr);
519 } 495
520 priority_to_string(pri, &facstr, &lvlstr); 496 p = "local";
521 497 if (!uname(&uts)) p = uts.nodename;
522 p = "local"; 498 if (toys.optflags & FLAG_S) len = sprintf(toybuf, "%s %s\n", ts, msg);
523 if (!uname(&uts)) p = uts.nodename; 499 else len = sprintf(toybuf, "%s %s %s.%s %s\n", ts, p, facstr, lvlstr, msg);
524 if (flag_chk(FLAG_S)) len = sprintf(toybuf, "%s %s\n", ts, msg); 500 }
525 else len = sprintf(toybuf, "%s %s %s.%s %s\n", ts, p, facstr, lvlstr, msg);
526
527 do_log:
528 if (lvl >= TT.log_prio) return; 501 if (lvl >= TT.log_prio) return;
529 502
530 while (lnode) { 503 while (lnode) {
531 struct logfile *tf = (struct logfile*) lnode->arg; 504 struct logfile *tf = (struct logfile*) lnode->arg;
532 if (tf->logfd > 0) { 505 if (tf->logfd > 0) {
533 if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) { 506 if ((tf->facility[lvl] & (1 << fac)) && (tf->level[fac] & (1<<lvl))) {
534 int wlen; 507 int wlen;
535 if (tf->isNetwork) 508 if (tf->isNetwork)
536 wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr)); 509 wlen = sendto(tf->logfd, omsg, olen, 0, (struct sockaddr*)&tf->saddr, sizeof(tf->saddr));
537 else wlen = write_rotate(tf, len); 510 else wlen = write_rotate(tf, len);
538 if (wlen < 0) perror_msg("write failed file : %s ", (tf->isNetwork)?(tf->filename+1):tf->filename); 511 if (wlen < 0) perror_msg("write failed file : %s ", tf->filename + tf->isNetwork);
539 } 512 }
540 } 513 }
541 lnode = lnode->next; 514 lnode = lnode->next;
542 } 515 }
543 } 516 }
581 int maxfd, retval, last_len=0; 554 int maxfd, retval, last_len=0;
582 struct timeval tv; 555 struct timeval tv;
583 struct arg_list *node; 556 struct arg_list *node;
584 char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each 557 char *temp, *buffer = (toybuf +2048), *last_buf = (toybuf + 3072); //these two buffs are of 1K each
585 558
586 if (flag_chk(FLAG_p) && strlen(TT.unix_socket) > 108) 559 if ((toys.optflags & FLAG_p) && (strlen(TT.unix_socket) > 108))
587 error_exit("Socket path should not be more than 108"); 560 error_exit("Socket path should not be more than 108");
588 561
589 TT.config_file = flag_get(FLAG_f, TT.config_file, "/etc/syslog.conf"); //DEFCONFFILE 562 TT.config_file = (toys.optflags & FLAG_f) ?
563 TT.config_file : "/etc/syslog.conf"; //DEFCONFFILE
590 init_jumpin: 564 init_jumpin:
591 TT.lsocks = xzalloc(sizeof(struct arg_list)); 565 TT.lsocks = xzalloc(sizeof(struct arg_list));
592 tsd = xzalloc(sizeof(struct unsocks)); 566 tsd = xzalloc(sizeof(struct unsocks));
593 567
594 tsd->path = flag_get(FLAG_p, TT.unix_socket , "/dev/log"); // DEFLOGSOCK 568 tsd->path = (toys.optflags & FLAG_p) ? TT.unix_socket : "/dev/log"; // DEFLOGSOCK
595 TT.lsocks->arg = (char*) tsd; 569 TT.lsocks->arg = (char*) tsd;
596 570
597 if (flag_chk(FLAG_a)) { 571 if (toys.optflags & FLAG_a) {
598 for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) { 572 for (temp = strtok(TT.socket, ":"); temp; temp = strtok(NULL, ":")) {
599 struct arg_list *ltemp = xzalloc(sizeof(struct arg_list)); 573 struct arg_list *ltemp = xzalloc(sizeof(struct arg_list));
600 if (strlen(temp) > 107) temp[108] = '\0'; 574 if (strlen(temp) > 107) temp[108] = '\0';
601 tsd = xzalloc(sizeof(struct unsocks)); 575 tsd = xzalloc(sizeof(struct unsocks));
602 tsd->path = temp; 576 tsd->path = temp;
622 signal(SIGINT, signal_handler); 596 signal(SIGINT, signal_handler);
623 signal(SIGQUIT, signal_handler); 597 signal(SIGQUIT, signal_handler);
624 598
625 if (parse_config_file() == -1) goto clean_and_exit; 599 if (parse_config_file() == -1) goto clean_and_exit;
626 open_logfiles(); 600 open_logfiles();
627 if (!flag_chk(FLAG_n)) { 601 if (!(toys.optflags & FLAG_n)) {
628 //don't daemonize again if SIGHUP received. 602 //don't daemonize again if SIGHUP received.
629 toys.optflags |= FLAG_n; 603 toys.optflags |= FLAG_n;
630 } 604 }
631 { 605 {
632 int pid_fd = open("/var/run/syslogd.pid", O_CREAT | O_WRONLY | O_TRUNC, 0666); 606 int pid_fd = open("/var/run/syslogd.pid", O_CREAT | O_WRONLY | O_TRUNC, 0666);
688 int sd = ((struct unsocks*) node->arg)->sd; 662 int sd = ((struct unsocks*) node->arg)->sd;
689 if (FD_ISSET(sd, &TT.rfds)) { 663 if (FD_ISSET(sd, &TT.rfds)) {
690 int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL 664 int len = read(sd, buffer, 1023); //buffer is of 1K, hence readingonly 1023 bytes, 1 for NUL
691 if (len > 0) { 665 if (len > 0) {
692 buffer[len] = '\0'; 666 buffer[len] = '\0';
693 if(flag_chk(FLAG_D) && (len == last_len)) 667 if((toys.optflags & FLAG_D) && (len == last_len))
694 if (!memcmp(last_buf, buffer, len)) break; 668 if (!memcmp(last_buf, buffer, len)) break;
695 669
696 memcpy(last_buf, buffer, len); 670 memcpy(last_buf, buffer, len);
697 last_len = len; 671 last_len = len;
698 logmsg(buffer, len); 672 logmsg(buffer, len);