X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Fmain.c;h=014d614773d1330931f07cd19a3573f5949b11f4;hb=da6956a56ea8550f33287fc86a960df8ce1b9af0;hp=fe34cff76bf1da04cfab96850d17082c69dfd8de;hpb=f2af1c05596be799c0c0ec1e451b8b0ae5ddabc6;p=ppp.git diff --git a/pppd/main.c b/pppd/main.c index fe34cff..014d614 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -66,7 +66,7 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define RCSID "$Id: main.c,v 1.152 2005/08/25 23:59:34 paulus Exp $" +#define RCSID "$Id: main.c,v 1.156 2008/06/23 11:47:18 paulus Exp $" #include #include @@ -220,6 +220,7 @@ struct subprocess { char *prog; void (*done) __P((void *)); void *arg; + int killable; struct subprocess *next; }; @@ -242,6 +243,7 @@ static void toggle_debug __P((int)); static void open_ccp __P((int)); static void bad_signal __P((int)); static void holdoff_end __P((void *)); +static void forget_child __P((int pid, int status)); static int reap_kids __P((void)); static void childwait_end __P((void *)); @@ -962,7 +964,7 @@ struct protocol_list { { 0x8051, "KNX Bridging Control Protocol" }, { 0x8053, "Encryption Control Protocol" }, { 0x8055, "Individual Link Encryption Control Protocol" }, - { 0x8057, "IPv6 Control Protovol" }, + { 0x8057, "IPv6 Control Protocol" }, { 0x8059, "PPP Muxing Control Protocol" }, { 0x805b, "Vendor-Specific Network Control Protocol (VSNCP)" }, { 0x806f, "Stampede Bridging Control Protocol" }, @@ -1382,7 +1384,21 @@ kill_my_pg(sig) int sig; { struct sigaction act, oldact; + struct subprocess *chp; + if (!detached) { + /* + * There might be other things in our process group that we + * didn't start that would get hit if we did a kill(0), so + * just send the signal individually to our children. + */ + for (chp = children; chp != NULL; chp = chp->next) + if (chp->killable) + kill(chp->pid, sig); + return; + } + + /* We've done a setsid(), so we can just use a kill(0) */ sigemptyset(&act.sa_mask); /* unnecessary in fact */ act.sa_handler = SIG_IGN; act.sa_flags = 0; @@ -1566,6 +1582,8 @@ safe_fork(int infd, int outfd, int errfd) if (errfd == 0 || errfd == 1) errfd = dup(errfd); + closelog(); + /* dup the in, out, err fds to 0, 1, 2 */ if (infd != 0) dup2(infd, 0); @@ -1574,7 +1592,6 @@ safe_fork(int infd, int outfd, int errfd) if (errfd != 2) dup2(errfd, 2); - closelog(); if (log_to_fd > 2) close(log_to_fd); if (the_channel->close) @@ -1631,15 +1648,15 @@ device_script(program, in, out, dont_wait) } if (pid != 0) { - if (dont_wait) { - record_child(pid, program, NULL, NULL); - status = 0; - } else { + record_child(pid, program, NULL, NULL, 1); + status = 0; + if (!dont_wait) { while (waitpid(pid, &status, 0) < 0) { if (errno == EINTR) continue; fatal("error waiting for (dis)connection process: %m"); } + forget_child(pid, status); --conn_running; } return (status == 0 ? 0 : -1); @@ -1661,7 +1678,7 @@ device_script(program, in, out, dont_wait) /* - * run-program - execute a program with given arguments, + * run_program - execute a program with given arguments, * but don't wait for it unless wait is non-zero. * If the program can't be executed, logs an error unless * must_exist is 0 and the program file doesn't exist. @@ -1704,14 +1721,14 @@ run_program(prog, args, must_exist, done, arg, wait) if (pid != 0) { if (debug) dbglog("Script %s started (pid %d)", prog, pid); - record_child(pid, prog, done, arg); + record_child(pid, prog, done, arg, 0); if (wait) { while (waitpid(pid, &status, 0) < 0) { if (errno == EINTR) continue; fatal("error waiting for script %s: %m", prog); } - reap_kids(); + forget_child(pid, status); } return pid; } @@ -1747,11 +1764,12 @@ run_program(prog, args, must_exist, done, arg, wait) * to use. */ void -record_child(pid, prog, done, arg) +record_child(pid, prog, done, arg, killable) int pid; char *prog; void (*done) __P((void *)); void *arg; + int killable; { struct subprocess *chp; @@ -1766,6 +1784,7 @@ record_child(pid, prog, done, arg) chp->done = done; chp->arg = arg; chp->next = children; + chp->killable = killable; children = chp; } } @@ -1788,6 +1807,35 @@ childwait_end(arg) childwait_done = 1; } +/* + * forget_child - clean up after a dead child + */ +static void +forget_child(pid, status) + int pid, status; +{ + struct subprocess *chp, **prevp; + + for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) { + if (chp->pid == pid) { + --n_children; + *prevp = chp->next; + break; + } + } + if (WIFSIGNALED(status)) { + warn("Child process %s (pid %d) terminated with signal %d", + (chp? chp->prog: "??"), pid, WTERMSIG(status)); + } else if (debug) + dbglog("Script %s finished (pid %d), status = 0x%x", + (chp? chp->prog: "??"), pid, + WIFEXITED(status) ? WEXITSTATUS(status) : status); + if (chp && chp->done) + (*chp->done)(chp->arg); + if (chp) + free(chp); +} + /* * reap_kids - get status from any dead child processes, * and log a message for abnormal terminations. @@ -1796,29 +1844,11 @@ static int reap_kids() { int pid, status; - struct subprocess *chp, **prevp; if (n_children == 0) return 0; while ((pid = waitpid(-1, &status, WNOHANG)) != -1 && pid != 0) { - for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next) { - if (chp->pid == pid) { - --n_children; - *prevp = chp->next; - break; - } - } - if (WIFSIGNALED(status)) { - warn("Child process %s (pid %d) terminated with signal %d", - (chp? chp->prog: "??"), pid, WTERMSIG(status)); - } else if (debug) - dbglog("Script %s finished (pid %d), status = 0x%x", - (chp? chp->prog: "??"), pid, - WIFEXITED(status) ? WEXITSTATUS(status) : status); - if (chp && chp->done) - (*chp->done)(chp->arg); - if (chp) - free(chp); + forget_child(pid, status); } if (pid == -1) { if (errno == ECHILD) @@ -2061,7 +2091,7 @@ update_db_entry() dbuf.dptr = vbuf; dbuf.dsize = vlen; if (tdb_store(pppdb, key, dbuf, TDB_REPLACE)) - error("tdb_store failed: %s", tdb_error(pppdb)); + error("tdb_store failed: %s", tdb_errorstr(pppdb)); if (vbuf) free(vbuf); @@ -2082,7 +2112,7 @@ add_db_key(str) dbuf.dptr = db_key; dbuf.dsize = strlen(db_key); if (tdb_store(pppdb, key, dbuf, TDB_REPLACE)) - error("tdb_store key failed: %s", tdb_error(pppdb)); + error("tdb_store key failed: %s", tdb_errorstr(pppdb)); } /*