]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/main.c
Fix compilation of pppd/session.c
[ppp.git] / pppd / main.c
index f136a281291b297e8b81ace181b57397f0764d2a..4e1952b1da6227b83ff3453c4412a5652c095346 100644 (file)
@@ -66,7 +66,7 @@
  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define RCSID  "$Id: main.c,v 1.149 2004/11/14 22:53:42 carlsonj Exp $"
+#define RCSID  "$Id: main.c,v 1.156 2008/06/23 11:47:18 paulus Exp $"
 
 #include <stdio.h>
 #include <ctype.h>
@@ -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 *));
 
@@ -534,6 +536,7 @@ main(argc, argv)
        script_unsetenv("BYTES_RCVD");
 
        lcp_open(0);            /* Start protocol */
+       start_link(0);
        while (phase != PHASE_DEAD) {
            handle_events();
            get_input();
@@ -551,6 +554,8 @@ main(argc, argv)
                }
            }
        }
+       /* restore FSMs to original state */
+       lcp_close(0, "");
 
        if (!persist || asked_to_quit || (maxfail > 0 && unsuccess >= maxfail))
            break;
@@ -1379,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;
@@ -1563,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);
@@ -1571,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)
@@ -1628,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);
@@ -1658,8 +1678,8 @@ device_script(program, in, out, dont_wait)
 
 
 /*
- * run-program - execute a program with given arguments,
- * but don't wait for it.
+ * 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.
  * Returns -1 if it couldn't fork, 0 if the file doesn't exist
@@ -1668,14 +1688,15 @@ device_script(program, in, out, dont_wait)
  * reap_kids) iff the return value is > 0.
  */
 pid_t
-run_program(prog, args, must_exist, done, arg)
+run_program(prog, args, must_exist, done, arg, wait)
     char *prog;
     char **args;
     int must_exist;
     void (*done) __P((void *));
     void *arg;
+    int wait;
 {
-    int pid;
+    int pid, status;
     struct stat sbuf;
 
     /*
@@ -1700,7 +1721,15 @@ run_program(prog, args, must_exist, done, arg)
     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);
+           }
+           forget_child(pid, status);
+       }
        return pid;
     }
 
@@ -1735,11 +1764,12 @@ run_program(prog, args, must_exist, done, arg)
  * 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;
 
@@ -1754,6 +1784,7 @@ record_child(pid, prog, done, arg)
        chp->done = done;
        chp->arg = arg;
        chp->next = children;
+       chp->killable = killable;
        children = chp;
     }
 }
@@ -1776,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.
@@ -1784,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)
@@ -2049,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);
@@ -2070,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));
 }
 
 /*