make the parent process wait for children and terminate after

receiving a signal, also terminate on SIGINT


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@8777 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Johan Danielsson
2000-07-22 15:41:07 +00:00
parent cc932ff022
commit d5bd139156

View File

@@ -32,6 +32,9 @@
*/ */
#include "kadmin_locl.h" #include "kadmin_locl.h"
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
RCSID("$Id$"); RCSID("$Id$");
@@ -91,22 +94,73 @@ static pid_t pgrp;
sig_atomic_t term_flag, doing_useful_work; sig_atomic_t term_flag, doing_useful_work;
static RETSIGTYPE static RETSIGTYPE
wait_term(int sig) sigchld(int sig)
{ {
if(doing_useful_work) int status;
term_flag = 1; waitpid(-1, &status, 0);
else
exit(0);
SIGRETURN(0); SIGRETURN(0);
} }
static RETSIGTYPE static RETSIGTYPE
terminate(int sig) terminate(int sig)
{ {
killpg(pgrp, sig); if(getpid() == pgrp) {
/* parent */
term_flag = 1;
signal(sig, SIG_IGN);
killpg(pgrp, sig);
} else {
/* child */
if(doing_useful_work)
term_flag = 1;
else
exit(0);
}
SIGRETURN(0); SIGRETURN(0);
} }
static int
spawn_child(krb5_context context, int *socks, int num_socks, int this_sock)
{
int e, i;
struct sockaddr sa;
size_t sa_len;
int s;
pid_t pid;
krb5_address addr;
char buf[128];
size_t buf_len;
s = accept(socks[this_sock], &sa, &sa_len);
if(s < 0) {
krb5_warn(context, errno, "accept");
return 1;
}
e = krb5_sockaddr2address(&sa, &addr);
if(e)
krb5_warn(context, e, "krb5_sockaddr2address");
else {
e = krb5_print_address (&addr, buf, sizeof(buf),
&buf_len);
if(e)
krb5_warn(context, e, "krb5_sockaddr2address");
else
krb5_warnx(context, "connection from %s", buf);
krb5_free_address(context, &addr);
}
pid = fork();
if(pid == 0) {
for(i = 0; i < num_socks; i++)
close(socks[i]);
dup2(s, STDIN_FILENO);
dup2(s, STDOUT_FILENO);
if(s != STDIN_FILENO && s != STDOUT_FILENO)
close(s);
return 0;
}
return 1;
}
static int static int
wait_for_connection(krb5_context context, wait_for_connection(krb5_context context,
int *socks, int num_socks) int *socks, int num_socks)
@@ -122,63 +176,40 @@ wait_for_connection(krb5_context context,
max_fd = max(max_fd, socks[i]); max_fd = max(max_fd, socks[i]);
} }
signal(SIGTERM, terminate);
if(setpgid(0, getpid()) < 0)
err(1, "setpgid");
pgrp = getpid(); pgrp = getpid();
while (1) { if(setpgid(0, pgrp) < 0)
err(1, "setpgid");
signal(SIGTERM, terminate);
signal(SIGINT, terminate);
signal(SIGCHLD, sigchld);
while (term_flag == 0) {
read_set = orig_read_set; read_set = orig_read_set;
e = select(max_fd + 1, &read_set, NULL, NULL, NULL); e = select(max_fd + 1, &read_set, NULL, NULL, NULL);
if(e < 0) if(e < 0) {
krb5_warn(context, errno, "select"); if(errno != EINTR)
else if(e == 0) krb5_warn(context, errno, "select");
} else if(e == 0)
krb5_warnx(context, "select returned 0"); krb5_warnx(context, "select returned 0");
else { else {
for(i = 0; i < num_socks; i++) { for(i = 0; i < num_socks; i++) {
if(FD_ISSET(socks[i], &read_set)) { if(FD_ISSET(socks[i], &read_set))
struct sockaddr sa; if(spawn_child(context, socks, num_socks, i) == 0)
size_t sa_len;
int s;
pid_t pid;
krb5_address addr;
char buf[128];
size_t buf_len;
s = accept(socks[i], &sa, &sa_len);
if(s < 0) {
krb5_warn(context, errno, "accept");
continue;
}
e = krb5_sockaddr2address(&sa, &addr);
if(e)
krb5_warn(context, e, "krb5_sockaddr2address");
else {
e = krb5_print_address (&addr, buf, sizeof(buf),
&buf_len);
if(e)
krb5_warn(context, e, "krb5_sockaddr2address");
else
krb5_warnx(context, "connection from %s", buf);
krb5_free_address(context, &addr);
}
pid = fork();
if(pid == 0) {
signal(SIGTERM, wait_term);
for(i = 0; i < num_socks; i++)
close(socks[i]);
dup2(s, STDIN_FILENO);
dup2(s, STDOUT_FILENO);
if(s != STDIN_FILENO && s != STDOUT_FILENO)
close(s);
return 0; return 0;
}
}
} }
} }
} }
signal(SIGCHLD, SIG_IGN);
while(1) {
int status;
pid_t pid;
pid = waitpid(-1, &status, 0);
if(pid == -1 && errno == ECHILD)
break;
}
exit(0);
} }