Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/syslogd/syslogd.c
| Show First 20 Lines • Show All 382 Lines • ▼ Show 20 Lines | static const int sigcatch[] = { | ||||
| SIGINT, | SIGINT, | ||||
| SIGQUIT, | SIGQUIT, | ||||
| SIGPIPE, | SIGPIPE, | ||||
| SIGALRM, | SIGALRM, | ||||
| SIGTERM, | SIGTERM, | ||||
| SIGCHLD, | SIGCHLD, | ||||
| }; | }; | ||||
| static int nulldesc; /* /dev/null descriptor */ | |||||
| static bool Debug; /* debug flag */ | static bool Debug; /* debug flag */ | ||||
| static bool Foreground = false; /* Run in foreground, instead of daemonizing */ | static bool Foreground = false; /* Run in foreground, instead of daemonizing */ | ||||
| static bool resolve = true; /* resolve hostname */ | static bool resolve = true; /* resolve hostname */ | ||||
| static char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ | static char LocalHostName[MAXHOSTNAMELEN]; /* our hostname */ | ||||
| static const char *LocalDomain; /* our local domain name */ | static const char *LocalDomain; /* our local domain name */ | ||||
| static bool Initialized; /* set when we have initialized ourselves */ | static bool Initialized; /* set when we have initialized ourselves */ | ||||
| static int MarkInterval = 20 * 60; /* interval between marks in seconds */ | static int MarkInterval = 20 * 60; /* interval between marks in seconds */ | ||||
| static int MarkSeq; /* mark sequence number */ | static int MarkSeq; /* mark sequence number */ | ||||
| ▲ Show 20 Lines • Show All 383 Lines • ▼ Show 20 Lines | #endif | ||||
| consfile.f_file = open(_PATH_CONSOLE, O_WRONLY | O_NONBLOCK); | consfile.f_file = open(_PATH_CONSOLE, O_WRONLY | O_NONBLOCK); | ||||
| if (consfile.f_file < 0) { | if (consfile.f_file < 0) { | ||||
| warn("cannot open %s", _PATH_CONSOLE); | warn("cannot open %s", _PATH_CONSOLE); | ||||
| pidfile_remove(pfh); | pidfile_remove(pfh); | ||||
| exit(1); | exit(1); | ||||
| } | } | ||||
| (void)strlcpy(consfile.fu_fname, _PATH_CONSOLE + sizeof(_PATH_DEV) - 1, | (void)strlcpy(consfile.fu_fname, _PATH_CONSOLE + sizeof(_PATH_DEV) - 1, | ||||
| sizeof(consfile.fu_fname)); | sizeof(consfile.fu_fname)); | ||||
| nulldesc = open(_PATH_DEVNULL, O_RDWR); | |||||
| if (nulldesc == -1) { | |||||
| warn("cannot open %s", _PATH_DEVNULL); | |||||
| pidfile_remove(pfh); | |||||
| exit(1); | |||||
| } | |||||
| (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile)); | (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile)); | ||||
| kq = kqueue(); | kq = kqueue(); | ||||
| if (kq == -1) { | if (kq == -1) { | ||||
| warn("failed to initialize kqueue"); | warn("failed to initialize kqueue"); | ||||
| pidfile_remove(pfh); | pidfile_remove(pfh); | ||||
| exit(1); | exit(1); | ||||
| } | } | ||||
| Show All 31 Lines | #endif | ||||
| } | } | ||||
| /* tuck my process id away */ | /* tuck my process id away */ | ||||
| pidfile_write(pfh); | pidfile_write(pfh); | ||||
| dprintf("off & running....\n"); | dprintf("off & running....\n"); | ||||
| init(false); | init(false); | ||||
| for (;;) { | for (;;) { | ||||
| switch (kevent(kq, NULL, 0, &ev, 1, needdofsync ? &ts : tsp)) { | switch (kevent(kq, NULL, 0, &ev, 1, needdofsync ? &ts : tsp)) { | ||||
markj: I think you could reasonably abort the process if /dev/null isn't accessible. Then you don't… | |||||
| case 0: | case 0: | ||||
| dofsync(); | dofsync(); | ||||
| if (tsp != NULL) { | if (tsp != NULL) { | ||||
| tsp = NULL; | tsp = NULL; | ||||
| if (ppid != -1) | if (ppid != -1) | ||||
| kill(ppid, SIGALRM); | kill(ppid, SIGALRM); | ||||
| } | } | ||||
| continue; | continue; | ||||
| ▲ Show 20 Lines • Show All 2,362 Lines • ▼ Show 20 Lines | |||||
| /* | /* | ||||
| * fork off and become a daemon, but wait for the child to come online | * fork off and become a daemon, but wait for the child to come online | ||||
| * before returning to the parent, or we get disk thrashing at boot etc. | * before returning to the parent, or we get disk thrashing at boot etc. | ||||
| * Set a timer so we don't hang forever if it wedges. | * Set a timer so we don't hang forever if it wedges. | ||||
| */ | */ | ||||
| static int | static int | ||||
| waitdaemon(int maxwait) | waitdaemon(int maxwait) | ||||
| { | { | ||||
| int fd; | |||||
| int status; | int status; | ||||
| pid_t pid, childpid; | pid_t pid, childpid; | ||||
| switch (childpid = fork()) { | switch (childpid = fork()) { | ||||
| case -1: | case -1: | ||||
| return (-1); | return (-1); | ||||
| case 0: | case 0: | ||||
| break; | break; | ||||
| Show All 14 Lines | default: | ||||
| } | } | ||||
| exit(0); | exit(0); | ||||
| } | } | ||||
| if (setsid() == -1) | if (setsid() == -1) | ||||
| return (-1); | return (-1); | ||||
| (void)chdir("/"); | (void)chdir("/"); | ||||
| if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { | (void)dup2(nulldesc, STDIN_FILENO); | ||||
| (void)dup2(fd, STDIN_FILENO); | (void)dup2(nulldesc, STDOUT_FILENO); | ||||
| (void)dup2(fd, STDOUT_FILENO); | (void)dup2(nulldesc, STDERR_FILENO); | ||||
| (void)dup2(fd, STDERR_FILENO); | |||||
| if (fd > STDERR_FILENO) | |||||
| (void)close(fd); | |||||
| } | |||||
| return (getppid()); | return (getppid()); | ||||
| } | } | ||||
| /* | /* | ||||
| * We get a SIGALRM from the child when it's running and finished doing it's | * We get a SIGALRM from the child when it's running and finished doing it's | ||||
| * fsync()'s or O_SYNC writes for all the boot messages. | * fsync()'s or O_SYNC writes for all the boot messages. | ||||
| * | * | ||||
| * We also get a signal from the kernel if the timer expires, so check to | * We also get a signal from the kernel if the timer expires, so check to | ||||
| ▲ Show 20 Lines • Show All 306 Lines • ▼ Show 20 Lines | |||||
| /* | /* | ||||
| * Fairly similar to popen(3), but returns an open descriptor, as | * Fairly similar to popen(3), but returns an open descriptor, as | ||||
| * opposed to a FILE *. | * opposed to a FILE *. | ||||
| */ | */ | ||||
| static int | static int | ||||
| p_open(const char *prog, int *rpd) | p_open(const char *prog, int *rpd) | ||||
| { | { | ||||
| sigset_t sigset = { }; | sigset_t sigset = { }; | ||||
| int nulldesc, pfd[2], pd; | int pfd[2], pd; | ||||
| pid_t pid; | pid_t pid; | ||||
| char *argv[4]; /* sh -c cmd NULL */ | char *argv[4]; /* sh -c cmd NULL */ | ||||
| char errmsg[200]; | char errmsg[200]; | ||||
| if (pipe(pfd) == -1) | if (pipe(pfd) == -1) | ||||
| return (-1); | return (-1); | ||||
| if ((nulldesc = open(_PATH_DEVNULL, O_RDWR)) == -1) | |||||
| /* we are royally screwed anyway */ | |||||
| return (-1); | |||||
| switch ((pid = pdfork(&pd, PD_CLOEXEC))) { | switch ((pid = pdfork(&pd, PD_CLOEXEC))) { | ||||
| case -1: | case -1: | ||||
| close(nulldesc); | |||||
| return (-1); | return (-1); | ||||
Not Done Inline ActionsThere is a pre-existing buglet here in that pfd[0] and [1] are not closed if pdfork() fails. markj: There is a pre-existing buglet here in that pfd[0] and [1] are not closed if pdfork() fails. | |||||
| case 0: | case 0: | ||||
| (void)setsid(); /* Avoid catching SIGHUPs. */ | (void)setsid(); /* Avoid catching SIGHUPs. */ | ||||
| argv[0] = strdup("sh"); | argv[0] = strdup("sh"); | ||||
| argv[1] = strdup("-c"); | argv[1] = strdup("-c"); | ||||
| argv[2] = strdup(prog); | argv[2] = strdup(prog); | ||||
| argv[3] = NULL; | argv[3] = NULL; | ||||
| if (argv[0] == NULL || argv[1] == NULL || argv[2] == NULL) { | if (argv[0] == NULL || argv[1] == NULL || argv[2] == NULL) { | ||||
| Show All 13 Lines | case 0: | ||||
| dup2(pfd[0], STDIN_FILENO); | dup2(pfd[0], STDIN_FILENO); | ||||
| dup2(nulldesc, STDOUT_FILENO); | dup2(nulldesc, STDOUT_FILENO); | ||||
| dup2(nulldesc, STDERR_FILENO); | dup2(nulldesc, STDERR_FILENO); | ||||
| closefrom(STDERR_FILENO + 1); | closefrom(STDERR_FILENO + 1); | ||||
| (void)execvp(_PATH_BSHELL, argv); | (void)execvp(_PATH_BSHELL, argv); | ||||
| _exit(255); | _exit(255); | ||||
| } | } | ||||
| close(nulldesc); | |||||
| close(pfd[0]); | close(pfd[0]); | ||||
| /* | /* | ||||
| * Avoid blocking on a hung pipe. With O_NONBLOCK, we are | * Avoid blocking on a hung pipe. With O_NONBLOCK, we are | ||||
| * supposed to get an EWOULDBLOCK on writev(2), which is | * supposed to get an EWOULDBLOCK on writev(2), which is | ||||
| * caught by the logic above anyway, which will in turn close | * caught by the logic above anyway, which will in turn close | ||||
| * the pipe, and fork a new logging subprocess if necessary. | * the pipe, and fork a new logging subprocess if necessary. | ||||
| * The stale subprocess will be killed some time later unless | * The stale subprocess will be killed some time later unless | ||||
| * it terminated itself due to closing its input pipe (so we | * it terminated itself due to closing its input pipe (so we | ||||
| ▲ Show 20 Lines • Show All 166 Lines • Show Last 20 Lines | |||||
I think you could reasonably abort the process if /dev/null isn't accessible. Then you don't need those nulldesc >= 0 checks.