📄 syslogd.c
字号:
* Convert to lower case to recognize the correct domain laterly */ for (p = (char *)LocalDomain; *p ; p++) if (isupper(*p)) *p = tolower(*p); (void) signal(SIGTERM, die); (void) signal(SIGINT, Debug ? die : SIG_IGN); (void) signal(SIGQUIT, Debug ? die : SIG_IGN); (void) signal(SIGCHLD, reapchild); (void) signal(SIGALRM, domark); (void) signal(SIGUSR1, Debug ? debug_switch : SIG_IGN); (void) alarm(TIMERINTVL); /* Create a partial message table for all file descriptors. */ num_fds = getdtablesize(); dprintf("Allocated parts table for %d file descriptors.\n", num_fds); if ( (parts = (char **) malloc(num_fds * sizeof(char *))) == \ (char **) 0 ) { logerror("Cannot allocate memory for message parts table."); die(0); } for(i= 0; i < num_fds; ++i) parts[i] = (char *) 0; dprintf("Starting.\n"); init();#ifndef TESTING if ( Debug ) { dprintf("Debugging disabled, SIGUSR1 to turn on debugging.\n"); debugging_on = 0; } /* * Send a signal to the parent to it can terminate. */ if (getpid() != ppid) kill (ppid, SIGTERM);#endif /* Main loop begins here. */ for (;;) { int nfds; errno = 0; FD_ZERO(&readfds); maxfds = 0;#ifdef SYSLOG_UNIXAF#ifndef TESTING /* * Add the Unix Domain Sockets to the list of read * descriptors. */ /* Copy master connections */ for (i = 0; i < nfunix; i++) { if (funix[i] != -1) { FD_SET(funix[i], &readfds); if (funix[i]>maxfds) maxfds=funix[i]; } }#endif#endif#ifdef SYSLOG_INET#ifndef TESTING /* * Add the Internet Domain Socket to the list of read * descriptors. */ if ( InetInuse && AcceptRemote ) { FD_SET(inetm, &readfds); if (inetm>maxfds) maxfds=inetm; dprintf("Listening on syslog UDP port.\n"); }#endif#endif#ifdef TESTING FD_SET(fileno(stdin), &readfds); if (fileno(stdin) > maxfds) maxfds = fileno(stdin); dprintf("Listening on stdin. Press Ctrl-C to interrupt.\n");#endif if ( debugging_on ) { dprintf("Calling select, active file descriptors (max %d): ", maxfds); for (nfds= 0; nfds <= maxfds; ++nfds) if ( FD_ISSET(nfds, &readfds) ) dprintf("%d ", nfds); dprintf("\n"); } nfds = select(maxfds+1, (fd_set *) &readfds, (fd_set *) NULL, (fd_set *) NULL, (struct timeval *) NULL); if ( restart ) { dprintf("\nReceived SIGHUP, reloading syslogd.\n"); init(); restart = 0; continue; } if (nfds == 0) { dprintf("No select activity.\n"); continue; } if (nfds < 0) { if (errno != EINTR) logerror("select"); dprintf("Select interrupted.\n"); continue; } if ( debugging_on ) { dprintf("\nSuccessful select, descriptor count = %d, " \ "Activity on: ", nfds); for (nfds= 0; nfds <= maxfds; ++nfds) if ( FD_ISSET(nfds, &readfds) ) dprintf("%d ", nfds); dprintf(("\n")); }#ifndef TESTING#ifdef SYSLOG_UNIXAF for (i = 0; i < nfunix; i++) { if ((fd = funix[i]) != -1 && FD_ISSET(fd, &readfds)) { memset(line, '\0', sizeof(line)); i = recv(fd, line, MAXLINE - 2, 0); dprintf("Message from UNIX socket: #%d\n", fd); if (i > 0) { line[i] = line[i+1] = '\0'; printchopped(LocalHostName, line, i + 2, fd); } else if (i < 0 && errno != EINTR) { dprintf("UNIX socket error: %d = %s.\n", \ errno, strerror(errno)); logerror("recvfrom UNIX"); } } }#endif#ifdef SYSLOG_INET if (InetInuse && AcceptRemote && FD_ISSET(inetm, &readfds)) { len = sizeof(frominet); memset(line, '\0', sizeof(line)); i = recvfrom(finet, line, MAXLINE - 2, 0, \ (struct sockaddr *) &frominet, &len); dprintf("Message from inetd socket: #%d, host: %s\n", inetm, inet_ntoa(frominet.sin_addr)); if (i > 0) { line[i] = line[i+1] = '\0'; from = (char *)cvthname(&frominet); /* * Here we could check if the host is permitted * to send us syslog messages. We just have to * catch the result of cvthname, look for a dot * and if that doesn't exist, replace the first * '\0' with '.' and we have the fqdn in lowercase * letters so we could match them against whatever. * -Joey */ printchopped(from, line, \ i + 2, finet); } else if (i < 0 && errno != EINTR) { dprintf("INET socket error: %d = %s.\n", \ errno, strerror(errno)); logerror("recvfrom inet"); /* should be harmless now that we set * BSDCOMPAT on the socket */ sleep(10); } }#endif#else if ( FD_ISSET(fileno(stdin), &readfds) ) { dprintf("Message from stdin.\n"); memset(line, '\0', sizeof(line)); line[0] = '.'; parts[fileno(stdin)] = (char *) 0; i = read(fileno(stdin), line, MAXLINE); if (i > 0) { printchopped(LocalHostName, line, i+1, fileno(stdin)); } else if (i < 0) { if (errno != EINTR) { logerror("stdin"); } } FD_CLR(fileno(stdin), &readfds); }#endif }}int usage(){ fprintf(stderr, "usage: syslogd [-drvh] [-l hostlist] [-m markinterval] [-n] [-p path]\n" \ " [-s domainlist] [-f conffile]\n"); exit(1);}#ifdef SYSLOG_UNIXAFstatic int create_unix_socket(const char *path){ struct sockaddr_un sunx; int fd; char line[MAXLINE +1]; if (path[0] == '\0') return -1; (void) unlink(path); memset(&sunx, 0, sizeof(sunx)); sunx.sun_family = AF_UNIX; (void) strncpy(sunx.sun_path, path, sizeof(sunx.sun_path)); fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (fd < 0 || bind(fd, (struct sockaddr *) &sunx, sizeof(sunx.sun_family)+strlen(sunx.sun_path)) < 0 || chmod(path, 0666) < 0) { (void) snprintf(line, sizeof(line), "cannot create %s", path); logerror(line); dprintf("cannot create %s (%d).\n", path, errno); close(fd);#ifndef SYSV die(0);#endif return -1; } return fd;}#endif#ifdef SYSLOG_INETstatic int create_inet_socket(){ int fd, on = 1; struct sockaddr_in sin; fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { logerror("syslog: Unknown protocol, suspending inet service."); return fd; } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = LogPort; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \ (char *) &on, sizeof(on)) < 0 ) { logerror("setsockopt(REUSEADDR), suspending inet"); close(fd); return -1; } /* We need to enable BSD compatibility. Otherwise an attacker * could flood our log files by sending us tons of ICMP errors. */ if (setsockopt(fd, SOL_SOCKET, SO_BSDCOMPAT, \ (char *) &on, sizeof(on)) < 0) { logerror("setsockopt(BSDCOMPAT), suspending inet"); close(fd); return -1; } if (bind(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { logerror("bind, suspending inet"); close(fd); return -1; } return fd;}#endifchar **crunch_list(list) char *list;{ int count, i; char *p, *q; char **result = NULL; p = list; /* strip off trailing delimiters */ while (p[strlen(p)-1] == LIST_DELIMITER) { count--; p[strlen(p)-1] = '\0'; } /* cut off leading delimiters */ while (p[0] == LIST_DELIMITER) { count--; p++; } /* count delimiters to calculate elements */ for (count=i=0; p[i]; i++) if (p[i] == LIST_DELIMITER) count++; if ((result = (char **)malloc(sizeof(char *) * count+2)) == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); exit(0); } /* * We now can assume that the first and last * characters are different from any delimiters, * so we don't have to care about this. */ count = 0; while ((q=strchr(p, LIST_DELIMITER))) { result[count] = (char *) malloc((q - p + 1) * sizeof(char)); if (result[count] == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); exit(0); } strncpy(result[count], p, q - p); result[count][q - p] = '\0'; p = q; p++; count++; } if ((result[count] = \ (char *)malloc(sizeof(char) * strlen(p) + 1)) == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); exit(0); } strcpy(result[count],p); result[++count] = NULL;#if 0 count=0; while (result[count]) dprintf ("#%d: %s\n", count, StripDomains[count++]);#endif return result;}void untty()#ifdef SYSV{ if ( !Debug ) { setsid(); } return;}#else{ int i; if ( !Debug ) { i = open(_PATH_TTY, O_RDWR); if (i >= 0) { (void) ioctl(i, (int) TIOCNOTTY, (char *)0); (void) close(i); } }}#endif/* * Parse the line to make sure that the msg is not a composite of more * than one message. */void printchopped(hname, msg, len, fd) const char *hname; char *msg; int len; int fd;{ auto int ptlngth; auto char *start = msg, *p, *end, tmpline[MAXLINE + 1]; dprintf("Message length: %d, File descriptor: %d.\n", len, fd); tmpline[0] = '\0'; if ( parts[fd] != (char *) 0 ) { dprintf("Including part from messages.\n"); strcpy(tmpline, parts[fd]); free(parts[fd]); parts[fd] = (char *) 0; if ( (strlen(msg) + strlen(tmpline)) > MAXLINE ) { logerror("Cannot glue message parts together"); printline(hname, tmpline); start = msg; } else { dprintf("Previous: %s\n", tmpline); dprintf("Next: %s\n", msg); strcat(tmpline, msg); /* length checked above */ printline(hname, tmpline); if ( (strlen(msg) + 1) == len ) return; else start = strchr(msg, '\0') + 1; } } if ( msg[len-1] != '\0' ) { msg[len] = '\0'; for(p= msg+len-1; *p != '\0' && p > msg; ) --p; if(*p == '\0') p++; ptlngth = strlen(p); if ( (parts[fd] = malloc(ptlngth + 1)) == (char *) 0 ) logerror("Cannot allocate memory for message part."); else { strcpy(parts[fd], p); dprintf("Saving partial msg: %s\n", parts[fd]); memset(p, '\0', ptlngth); } } do { end = strchr(start + 1, '\0'); printline(hname, start); start = end + 1; } while ( *start != '\0' ); return;}/* * Take a raw input line, decode the message, and print the message * on the appropriate log files. */void printline(hname, msg) const char *hname; char *msg;{ register char *p, *q; register unsigned char c; char line[MAXLINE + 1]; int pri; /* test for special codes */ pri = DEFUPRI; p = msg; if (*p == '<') { pri = 0; while (isdigit(*++p)) { pri = 10 * pri + (*p - '0'); } if (*p == '>') ++p; } if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) pri = DEFUPRI; memset (line, 0, sizeof(line)); q = line; while ((c = *p++) && q < &line[sizeof(line) - 4]) { if (c == '\n') *q++ = ' '; else if (c < 040) { *q++ = '^'; *q++ = c ^ 0100; } else if (c == 0177 || (c & 0177) < 040) { *q++ = '\\'; *q++ = '0' + ((c & 0300) >> 6); *q++ = '0' + ((c & 0070) >> 3); *q++ = '0' + (c & 0007); } else *q++ = c; } *q = '\0'; logmsg(pri, line, hname, SYNC_FILE); return;}/* * Take a raw input line from /dev/klog, split and format similar to syslog(). */void printsys(msg) char *msg;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -