summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>1998-12-28 15:09:43 +0000
committerdes <des@FreeBSD.org>1998-12-28 15:09:43 +0000
commitb44d350f5dbecc328917a46469163854cf764dd0 (patch)
treee13cb5332b4791dcfe79f99fe1875c054398d009
parentf1120f85a5bec6a70b621d42c53e4a599af30197 (diff)
downloadFreeBSD-src-b44d350f5dbecc328917a46469163854cf764dd0.zip
FreeBSD-src-b44d350f5dbecc328917a46469163854cf764dd0.tar.gz
Back out rev. 1.42 and 1.43. Apply Graham Wheeler's signal handling patch.
Reviewed by: jkh & eivind Submitted by: Graham Wheeler <gram@cdsec.com> PR: bin/8183
-rw-r--r--usr.sbin/inetd/inetd.c188
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);
}
OpenPOWER on IntegriCloud