diff options
Diffstat (limited to 'usr.sbin/inetd/inetd.c')
-rw-r--r-- | usr.sbin/inetd/inetd.c | 188 |
1 files changed, 115 insertions, 73 deletions
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c index 154b15c..db2be2a 100644 --- a/usr.sbin/inetd/inetd.c +++ b/usr.sbin/inetd/inetd.c @@ -42,7 +42,7 @@ static const char copyright[] = static char sccsid[] = "@(#)from: inetd.c 8.4 (Berkeley) 4/13/94"; #endif static const char rcsid[] = - "$Id: inetd.c,v 1.42 1998/12/11 17:06:16 dillon Exp $"; + "$Id: inetd.c,v 1.41 1998/11/04 19:39:46 phk Exp $"; #endif /* not lint */ /* @@ -172,6 +172,7 @@ int maxcpm = MAXCHILD; struct servent *sp; struct rpcent *rpc; struct in_addr bind_address; +int signalpipe[2]; struct servtab { char *se_service; /* name of service */ @@ -217,7 +218,9 @@ struct servtab { void chargen_dg __P((int, struct servtab *)); void chargen_stream __P((int, struct servtab *)); void close_sep __P((struct servtab *)); -void config __P((int)); +void flag_signal __P((char)); +void flag_config __P((int)); +void config __P((void)); void daytime_dg __P((int, struct servtab *)); void daytime_stream __P((int, struct servtab *)); void discard_dg __P((int, struct servtab *)); @@ -235,10 +238,12 @@ char *newstr __P((char *)); char *nextline __P((FILE *)); void print_service __P((char *, struct servtab *)); void addchild __P((struct servtab *, int)); -void reapchild __P((int)); +void flag_reapchild __P((int)); +void reapchild __P((void)); void enable __P((struct servtab *)); void disable __P((struct servtab *)); -void retry __P((int)); +void flag_retry __P((int)); +void retry __P((void)); int setconfig __P((void)); void setup __P((struct servtab *)); char *sskip __P((char **)); @@ -411,12 +416,12 @@ main(argc, argv, envp) sigaddset(&sa.sa_mask, SIGALRM); sigaddset(&sa.sa_mask, SIGCHLD); sigaddset(&sa.sa_mask, SIGHUP); - sa.sa_handler = retry; + sa.sa_handler = flag_retry; sigaction(SIGALRM, &sa, (struct sigaction *)0); - config(SIGHUP); - sa.sa_handler = config; + config(); + sa.sa_handler = flag_config; sigaction(SIGHUP, &sa, (struct sigaction *)0); - sa.sa_handler = reapchild; + sa.sa_handler = flag_reapchild; sigaction(SIGCHLD, &sa, (struct sigaction *)0); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, &sapipe); @@ -431,47 +436,68 @@ main(argc, argv, envp) (void)setenv("inetd_dummy", dummy, 1); } - (void) sigblock(SIGBLOCK); + if (pipe(signalpipe) != 0) + { + syslog(LOG_ERR, "pipe: %%m"); + exit(EX_OSERR); + } + FD_SET(signalpipe[0], &allsock); + if (signalpipe[0]>maxsock) maxsock = signalpipe[0]; for (;;) { int n, ctrl; fd_set readable; - struct timeval tv = { 5, 0 }; - - - /* - * Handle signal masking and select. Signals are unmasked and - * we pause if we have no active descriptors. If we do have - * active descriptors, leave signals unmasked through the select() - * call. The select() call is inclusive of a timeout in order - * to handle the race condition where a signal occurs just prior - * to the select() call and potentially changes the allsock - * fd_set, to prevent select() from potentially blocking forever. - * - * Signals are masked at all other times. - */ if (nsock == 0) { + (void) sigblock(SIGBLOCK); while (nsock == 0) sigpause(0L); + (void) sigsetmask(0L); } - - (void) sigsetmask(0L); - - readable = allsock; - errno = 0; - n = select(maxsock + 1, &readable, NULL, NULL, &tv); - - (void) sigblock(SIGBLOCK); - - if (n <= 0) { - if (n < 0 && errno && errno != EINTR) { + if ((n = select(maxsock + 1, &readable, (fd_set *)0, + (fd_set *)0, (struct timeval *)0)) <= 0) { + if (n < 0 && errno != EINTR) { syslog(LOG_WARNING, "select: %m"); sleep(1); } continue; } + /* handle any queued signal flags */ + if (FD_ISSET(signalpipe[0], &readable)) + { + int n; + if (ioctl(signalpipe[0], FIONREAD, &n) == 0) + { + while (--n >= 0) + { + char c; + if (read(signalpipe[0], &c, 1) == 1) + { + if (debug) warnx("Handling signal flag %c", c); + switch(c) + { + case 'A': /* sigalrm */ + retry(); break; + case 'C': /* sigchld */ + reapchild(); break; + case 'H': /* sighup */ + config(); break; + } + } + else + { + syslog(LOG_ERR, "read: %m"); + exit(EX_OSERR); + } + } + } + else + { + syslog(LOG_ERR, "ioctl: %m"); + exit(EX_OSERR); + } + } for (sep = servtab; n && sep; sep = sep->se_next) if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { n--; @@ -512,7 +538,7 @@ main(argc, argv, envp) } } else ctrl = sep->se_fd; - /* (void) sigblock(SIGBLOCK); */ + (void) sigblock(SIGBLOCK); pid = 0; dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); if (dofork) { @@ -531,7 +557,7 @@ main(argc, argv, envp) "%s/%s server failing (looping), service terminated", sep->se_service, sep->se_proto); close_sep(sep); - /* sigsetmask(0L); */ + sigsetmask(0L); if (!timingout) { timingout = 1; alarm(RETRYTIME); @@ -546,13 +572,13 @@ main(argc, argv, envp) if (sep->se_accept && sep->se_socktype == SOCK_STREAM) close(ctrl); - /* sigsetmask(0L); */ + sigsetmask(0L); sleep(1); continue; } if (pid) addchild(sep, pid); - /* sigsetmask(0L); */ + sigsetmask(0L); if (pid == 0) { if (dofork) { if (debug) @@ -658,7 +684,6 @@ main(argc, argv, envp) #endif sigaction(SIGPIPE, &sapipe, (struct sigaction *)0); - sigsetmask(0L); execv(sep->se_server, sep->se_argv); if (sep->se_socktype != SOCK_STREAM) recv(0, buf, sizeof (buf), 0); @@ -674,6 +699,20 @@ main(argc, argv, envp) } /* + * Add a signal flag to the signal flag queue for later handling + */ + +void flag_signal(c) + char c; +{ + if (write(signalpipe[1], &c, 1) != 1) + { + syslog(LOG_ERR, "write: %m"); + exit(EX_OSERR); + } +} + +/* * Record a new child pid for this service. If we've reached the * limit on children, then stop accepting incoming requests. */ @@ -700,9 +739,15 @@ addchild(struct servtab *sep, pid_t pid) */ void -reapchild(signo) +flag_reapchild(signo) int signo; { + flag_signal('C'); +} + +void +reapchild() +{ int k, status; pid_t pid; struct servtab *sep; @@ -732,11 +777,16 @@ reapchild(signo) } void -config(signo) +flag_config(signo) int signo; { + flag_signal('H'); +} + +void config() +{ struct servtab *sep, *new, **sepp; - /* long omask; */ + long omask; if (!setconfig()) { syslog(LOG_ERR, "%s: %m", CONFIG); @@ -774,7 +824,7 @@ config(signo) int i; #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; } - /* omask = sigblock(SIGBLOCK); */ + omask = sigblock(SIGBLOCK); /* copy over outstanding child pids */ if (sep->se_maxchild && new->se_maxchild) { new->se_numchild = sep->se_numchild; @@ -807,7 +857,7 @@ config(signo) SWAP(sep->se_server, new->se_server); for (i = 0; i < MAXARGV; i++) SWAP(sep->se_argv[i], new->se_argv[i]); - /* sigsetmask(omask); */ + sigsetmask(omask); freeconfig(new); if (debug) print_service("REDO", sep); @@ -862,7 +912,7 @@ config(signo) /* * Purge anything not looked at above. */ - /* omask = sigblock(SIGBLOCK); */ + omask = sigblock(SIGBLOCK); sepp = &servtab; while ((sep = *sepp)) { if (sep->se_checked) { @@ -879,7 +929,7 @@ config(signo) freeconfig(sep); free((char *)sep); } - /* (void) sigsetmask(omask); */ + (void) sigsetmask(omask); } void @@ -888,9 +938,9 @@ unregisterrpc(sep) { int i; struct servtab *sepp; - /* long omask; */ + long omask; - /* omask = sigblock(SIGBLOCK); */ + omask = sigblock(SIGBLOCK); for (sepp = servtab; sepp; sepp = sepp->se_next) { if (sepp == sep) continue; @@ -907,13 +957,19 @@ unregisterrpc(sep) if (sep->se_fd != -1) (void) close(sep->se_fd); sep->se_fd = -1; - /* (void) sigsetmask(omask); */ + (void) sigsetmask(omask); } void -retry(signo) +flag_retry(signo) int signo; { + flag_signal('A'); +} + +void +retry() +{ struct servtab *sep; timingout = 0; @@ -1020,7 +1076,7 @@ enter(cp) struct servtab *cp; { struct servtab *sep; - /* long omask; */ + long omask; sep = (struct servtab *)malloc(sizeof (*sep)); if (sep == (struct servtab *)0) { @@ -1029,10 +1085,10 @@ enter(cp) } *sep = *cp; sep->se_fd = -1; - /* omask = sigblock(SIGBLOCK); */ + omask = sigblock(SIGBLOCK); sep->se_next = servtab; servtab = sep; - /* sigsetmask(omask); */ + sigsetmask(omask); return (sep); } @@ -1806,9 +1862,6 @@ print_service(action, sep) /* * Based on TCPMUX.C by Mark K. Lottor November 1988 * sri-nic::ps:<mkl>tcpmux.c - * - * signals are masked on call, we have to unmask SIGALRM for the - * duration of the read. */ @@ -1819,38 +1872,27 @@ getline(fd, buf, len) int len; { int count = 0, n; - int not_done = 1; struct sigaction sa; - long omask; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sa.sa_handler = SIG_DFL; sigaction(SIGALRM, &sa, (struct sigaction *)0); - - omask = sigsetmask(SIGBLOCK & ~sigmask(SIGALRM)); - do { alarm(10); n = read(fd, buf, len-count); alarm(0); if (n == 0) - break; - if (n < 0) { - count = -1; - break; - } + return (count); + if (n < 0) + return (-1); while (--n >= 0) { - if (*buf == '\r' || *buf == '\n' || *buf == '\0') { - not_done = 0; - break; - } + if (*buf == '\r' || *buf == '\n' || *buf == '\0') + return (count); count++; buf++; } - } while (not_done && count < len); - - sigsetmask(omask); + } while (count < len); return (count); } |