mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-14 14:55:41 +00:00
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
This commit is contained in:
parent
21a9954850
commit
e20e25db62
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=42122
@ -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);
|
||||
@ -673,6 +698,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,8 +739,14 @@ 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;
|
||||
@ -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,12 +957,18 @@ 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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user