📄 syslogd.c
字号:
sleep(300); /* * Not reached unless something major went wrong. 5 * minutes should be a fair amount of time to wait. * Please note that this procedure is important since * the father must not exit before syslogd isn't * initialized or the klogd won't be able to flush its * logs. -Joey */ exit(1); } signal (SIGTERM, SIG_DFL); num_fds = getdtablesize(); for (i= 0; i < num_fds; i++) (void) close(i); untty(); } else { fputs("syslogd: Already running.\n", stderr); exit(1); } } else#endif debugging_on = 1;#ifndef SYSV else setlinebuf(stdout);#endif#ifndef TESTING /* tuck my process id away */ if ( !Debug ) { dprintf("Writing pidfile.\n"); if (!check_pid(PidFile)) { if (!write_pid(PidFile)) { dprintf("Can't write pid.\n"); if (getpid() != ppid) kill (ppid, SIGTERM); exit(1); } } else { dprintf("Pidfile (and pid) already exist.\n"); if (getpid() != ppid) kill (ppid, SIGTERM); exit(1); } } /* if ( !Debug ) */#endif consfile.f_type = F_CONSOLE; (void) strcpy(consfile.f_un.f_fname, ctty); (void) gethostname(LocalHostName, sizeof(LocalHostName)); LocalDomain = emptystring; if ( (p = strchr(LocalHostName, '.')) ) { *p++ = '\0'; LocalDomain = p; } else if ( AcceptRemote ) { /* * It's not clearly defined whether gethostname() * should return the simple hostname or the fqdn. A * good piece of software should be aware of both and * we want to distribute good software. Joey * * Good software also always checks its return values... * If syslogd starts up before DNS is up & /etc/hosts * doesn't have LocalHostName listed, gethostbyname will * return NULL. */ hent = gethostbyname(LocalHostName); if ( hent ) snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name); if ( (p = strchr(LocalHostName, '.')) ) { *p++ = '\0'; LocalDomain = p; } } /* * 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) signal(SIGXFSZ, 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.");#ifndef TESTING if (getpid() != ppid) kill (ppid, SIGTERM);#endif 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 ) { restart = 0; dprintf("\nReceived SIGHUP, reloading syslogd.\n"); init(); 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)); msglen = recv(fd, line, MAXLINE - 2, 0); dprintf("Message from UNIX socket: #%d\n", fd); if (msglen > 0) printchopped(LocalHostName, line, msglen + 2, fd); else if (msglen < 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)); msglen = 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 (msglen > 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, \ msglen + 2, finet); } else if (msglen < 0 && errno != EINTR && errno != EAGAIN) { 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(1); } }#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; int sockflags; 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 must not block on the network socket, in case a packet * gets lost between select and recv, otherise the process * will stall until the timeout, and other processes trying to * log will also stall. */ if ((sockflags = fcntl(fd, F_GETFL)) != -1) { sockflags |= O_NONBLOCK; /* * SETFL could fail too, so get it caught by the subsequent * error check. */ sockflags = fcntl(fd, F_SETFL, sockflags); } if (sockflags == -1) { logerror("fcntl(O_NONBLOCK), 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 i, m, n; char *p, *q; char **result = NULL; p = list; /* strip off trailing delimiters */ while (*p && p[strlen(p)-1] == LIST_DELIMITER) p[strlen(p)-1] = '\0'; /* cut off leading delimiters */ while (p[0] == LIST_DELIMITER) p++; /* count delimiters to calculate the number of elements */ for (n = i = 0; p[i]; i++) if (p[i] == LIST_DELIMITER) n++; if ((result = (char **)malloc(sizeof(char *) * (n + 2))) == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); exit(1); } /* * We now can assume that the first and last * characters are different from any delimiters, * so we don't have to care about this. */ m = 0; while ((q = strchr(p, LIST_DELIMITER)) && m < n) { result[m] = (char *) malloc((q - p + 1) * sizeof(char)); if (result[m] == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); exit(1); } memcpy(result[m], p, q - p); result[m][q - p] = '\0'; p = q; p++; m++; } if ((result[m] = strdup(p)) == NULL) { printf ("Sorry, can't get enough memory, exiting.\n"); exit(1); } result[++m] = NULL;#if 0 m = 0; while (result[m]) dprintf ("#%d: %s\n", m, result[m++]);#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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -