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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user