]> git.ozlabs.org Git - ppp.git/blobdiff - pppd/main.c
priv option stuff; signal [dis]connector if we get a signal
[ppp.git] / pppd / main.c
index 6047918ec17fca1d8153e7e0b6cb766179124d72..170db95cfb4c610c109fa27da268fe63fdeca564 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #ifndef lint
-static char rcsid[] = "$Id: main.c,v 1.33 1996/05/28 00:49:10 paulus Exp $";
+static char rcsid[] = "$Id: main.c,v 1.35 1996/08/28 06:41:16 paulus Exp $";
 #endif
 
 #include <stdio.h>
@@ -60,14 +60,6 @@ extern char *strerror();
 #include "ipxcp.h"
 #endif /* IPX_CHANGE */
 
-/*
- * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless
- * /etc/ppp/options exists.
- */
-#ifndef        REQ_SYSOPTIONS
-#define REQ_SYSOPTIONS 1
-#endif
-
 /* interface vars */
 char ifname[IFNAMSIZ];         /* Interface name */
 int ifunit;                    /* Interface unit number */
@@ -78,22 +70,25 @@ static char pidfilename[MAXPATHLEN];        /* name of pid file */
 static char default_devnam[MAXPATHLEN];        /* name of default device */
 static pid_t pid;              /* Our pid */
 static uid_t uid;              /* Our real user-id */
+static int conn_running;       /* we have a [dis]connector running */
 
 int ttyfd = -1;                        /* Serial port file descriptor */
 mode_t tty_mode = -1;          /* Original access permissions to tty */
+int baud_rate;                 /* Actual bits/second for serial device */
+int hungup;                    /* terminal has been hung up */
+int privileged;                        /* we're running as real uid root */
+int need_holdoff;              /* need holdoff period before restarting */
 
 int phase;                     /* where the link is at */
 int kill_link;
 int open_ccp_flag;
+int redirect_stderr;           /* Connector's stderr should go to file */
 
 u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
 u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
 
-int hungup;                    /* terminal has been hung up */
 static int n_children;         /* # child processes still running */
 
-int baud_rate;                 /* Actual bits/second for serial device */
-
 static int locked;             /* lock() has succeeded */
 
 char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
@@ -182,25 +177,28 @@ main(argc, argv)
     hostname[MAXNAMELEN-1] = 0;
 
     uid = getuid();
+    privileged = uid == 0;
 
     /*
      * Initialize to the standard option set, then parse, in order,
-     * the system options file, the user's options file, and the command
-     * line arguments.
+     * the system options file, the user's options file,
+     * the tty's options file, and the command line arguments.
      */
     for (i = 0; (protp = protocols[i]) != NULL; ++i)
         (*protp->init)(0);
   
     progname = *argv;
 
-    if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) ||
-       !options_for_tty() ||
-       !options_from_user() ||
-       !parse_args(argc-1, argv+1))
+    if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
+       || !options_from_user())
+       exit(1);
+    scan_args(argc-1, argv+1); /* look for tty name on command line */
+    if (!options_for_tty()
+       || !parse_args(argc-1, argv+1))
        exit(1);
 
     if (!ppp_available()) {
-       fprintf(stderr, no_ppp_msg);
+       option_error(no_ppp_msg);
        exit(1);
     }
 
@@ -213,8 +211,7 @@ main(argc, argv)
        if (protp->check_options != NULL)
            (*protp->check_options)();
     if (demand && connector == 0) {
-       fprintf(stderr, "%s: connect script required for demand-dialling\n",
-               progname);
+       option_error("connect script required for demand-dialling\n");
        exit(1);
     }
 
@@ -224,6 +221,7 @@ main(argc, argv)
      */
     if (!default_device && strcmp(devnam, default_devnam) == 0)
        default_device = 1;
+    redirect_stderr = !nodetach || default_device;
 
     /*
      * Initialize system-dependent stuff and magic number package.
@@ -358,6 +356,8 @@ main(argc, argv)
 
     for (;;) {
 
+       need_holdoff = 1;
+
        if (demand) {
            /*
             * Don't do anything until we see some activity.
@@ -497,13 +497,12 @@ main(argc, argv)
            get_input();
            if (kill_link) {
                lcp_close(0, "User request");
-               phase = PHASE_TERMINATE;
                kill_link = 0;
            }
            if (open_ccp_flag) {
                if (phase == PHASE_NETWORK) {
                    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
-                   ccp_open(0);
+                   (*ccp_protent.open)(0);
                }
                open_ccp_flag = 0;
            }
@@ -516,9 +515,14 @@ main(argc, argv)
         * real serial device back to its normal mode of operation.
         */
        clean_check();
+#ifdef _linux_
+       disestablish_ppp(ttyfd);
+#endif
        if (demand)
            restore_loop();
+#ifndef _linux_
        disestablish_ppp(ttyfd);
+#endif
 
        /*
         * Run disconnector script, if requested.
@@ -541,7 +545,8 @@ main(argc, argv)
        }
 
        if (!demand) {
-           if (unlink(pidfilename) < 0 && errno != ENOENT) 
+           if (pidfilename[0] != 0
+               && unlink(pidfilename) < 0 && errno != ENOENT) 
                syslog(LOG_WARNING, "unable to delete pid file: %m");
            pidfilename[0] = 0;
        }
@@ -551,7 +556,7 @@ main(argc, argv)
 
        if (demand)
            demand_discard();
-       if (holdoff > 0) {
+       if (holdoff > 0 && need_holdoff) {
            phase = PHASE_HOLDOFF;
            TIMEOUT(holdoff_end, NULL, holdoff);
            do {
@@ -677,8 +682,6 @@ connect_time_expired(arg)
     caddr_t arg;
 {
     syslog(LOG_INFO, "Connect time expired");
-
-    phase = PHASE_TERMINATE;
     lcp_close(0, "Connect time expired");      /* Close connection */
 }
 
@@ -857,7 +860,24 @@ timeleft(tvp)
 
     return tvp;
 }
-    
+
+
+/*
+ * kill_my_pg - send a signal to our process group, and ignore it ourselves.
+ */
+static void
+kill_my_pg(sig)
+    int sig;
+{
+    struct sigaction act, oldact;
+
+    act.sa_handler = SIG_IGN;
+    act.sa_flags = 0;
+    sigaction(sig, &act, &oldact);
+    kill(-getpgrp(), sig);
+    sigaction(sig, &oldact, NULL);
+}
+
 
 /*
  * hup - Catch SIGHUP signal.
@@ -872,6 +892,9 @@ hup(sig)
 {
     syslog(LOG_INFO, "Hangup (SIGHUP)");
     kill_link = 1;
+    if (conn_running)
+       /* Send the signal to the [dis]connector process(es) also */
+       kill_my_pg(sig);
 }
 
 
@@ -888,6 +911,9 @@ term(sig)
     syslog(LOG_INFO, "Terminating on signal %d.", sig);
     persist = 0;               /* don't try to restart */
     kill_link = 1;
+    if (conn_running)
+       /* Send the signal to the [dis]connector process(es) also */
+       kill_my_pg(sig);
 }
 
 
@@ -944,6 +970,8 @@ bad_signal(sig)
     int sig;
 {
     syslog(LOG_ERR, "Fatal signal %d", sig);
+    if (conn_running)
+       kill_my_pg(SIGTERM);
     die(1);
 }
 
@@ -961,9 +989,11 @@ device_script(program, in, out)
     int status;
     int errfd;
 
+    conn_running = 1;
     pid = fork();
 
     if (pid < 0) {
+       conn_running = 0;
        syslog(LOG_ERR, "Failed to create child process: %m");
        die(1);
     }
@@ -971,11 +1001,32 @@ device_script(program, in, out)
     if (pid == 0) {
        sys_close();
        closelog();
-       dup2(in, 0);
-       dup2(out, 1);
-       errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644);
-       if (errfd >= 0)
-           dup2(errfd, 2);
+       if (in == out) {
+           if (in != 0) {
+               dup2(in, 0);
+               close(in);
+           }
+           dup2(0, 1);
+       } else {
+           if (out == 0)
+               out = dup(out);
+           if (in != 0) {
+               dup2(in, 0);
+               close(in);
+           }
+           if (out != 1) {
+               dup2(out, 1);
+               close(out);
+           }
+       }
+       if (redirect_stderr) {
+           close(2);
+           errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644);
+           if (errfd >= 0 && errfd != 2) {
+               dup2(errfd, 2);
+               close(errfd);
+           }
+       }
        setuid(getuid());
        setgid(getgid());
        execl("/bin/sh", "sh", "-c", program, (char *)0);
@@ -990,6 +1041,7 @@ device_script(program, in, out)
        syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
        die(1);
     }
+    conn_running = 0;
 
     return (status == 0 ? 0 : -1);
 }
@@ -1152,12 +1204,7 @@ format_packet(p, len, printer, arg)
 }
 
 static void
-#if __STDC__
-pr_log(void *arg, char *fmt, ...)
-#else
-pr_log(va_alist)
-    va_dcl
-#endif
+pr_log __V((void *arg, char *fmt, ...))
 {
     int n;
     va_list pvar;
@@ -1201,10 +1248,25 @@ print_string(p, len, printer, arg)
     printer(arg, "\"");
     for (; len > 0; --len) {
        c = *p++;
-       if (' ' <= c && c <= '~')
+       if (' ' <= c && c <= '~') {
+           if (c == '\\' || c == '"')
+               printer(arg, "\\");
            printer(arg, "%c", c);
-       else
-           printer(arg, "\\%.3o", c);
+       } else {
+           switch (c) {
+           case '\n':
+               printer(arg, "\\n");
+               break;
+           case '\r':
+               printer(arg, "\\r");
+               break;
+           case '\t':
+               printer(arg, "\\t");
+               break;
+           default:
+               printer(arg, "\\%.3o", c);
+           }
+       }
     }
     printer(arg, "\"");
 }
@@ -1252,16 +1314,20 @@ fmtmsg __V((char *buf, int buflen, char *fmt, ...))
 /*
  * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
  */
+#define OUTCHAR(c)     (buflen > 0? (--buflen, *buf++ = (c)): 0)
+
 int
 vfmtmsg(char *buf, int buflen, char *fmt, va_list args)
 {
     int c, i, n;
-    int width, prec;
-    int base, len, neg;
+    int width, prec, fillch;
+    int base, len, neg, quoted;
     unsigned long val;
     char *str, *f, *buf0;
+    unsigned char *p;
     va_list a;
     char num[32];
+    time_t t;
     static char hexchars[16] = "0123456789abcdef";
 
     buf0 = buf;
@@ -1282,17 +1348,32 @@ vfmtmsg(char *buf, int buflen, char *fmt, va_list args)
            break;
        c = *++fmt;
        width = prec = 0;
-       while (isdigit(c)) {
-           width = width * 10 + c - '0';
+       fillch = ' ';
+       if (c == '0') {
+           fillch = '0';
            c = *++fmt;
        }
-       if (c == '.') {
+       if (c == '*') {
+           width = va_arg(args, int);
            c = *++fmt;
+       } else {
            while (isdigit(c)) {
-               prec = prec * 10 + c - '0';
+               width = width * 10 + c - '0';
                c = *++fmt;
            }
        }
+       if (c == '.') {
+           c = *++fmt;
+           if (c == '*') {
+               prec = va_arg(args, int);
+               c = *++fmt;
+           } else {
+               while (isdigit(c)) {
+                   prec = prec * 10 + c - '0';
+                   c = *++fmt;
+               }
+           }
+       }
        str = 0;
        base = 0;
        neg = 0;
@@ -1341,6 +1422,58 @@ vfmtmsg(char *buf, int buflen, char *fmt, va_list args)
            buf += n;
            buflen -= n;
            continue;
+       case 't':
+           time(&t);
+           str = ctime(&t);
+           str += 4;           /* chop off the day name */
+           str[15] = 0;        /* chop off year and newline */
+           break;
+       case 'v':               /* "visible" string */
+       case 'q':               /* quoted string */
+           quoted = c == 'q';
+           p = va_arg(args, unsigned char *);
+           if (fillch == '0' && prec > 0) {
+               n = prec;
+           } else {
+               n = strlen((char *)p);
+               if (prec > 0 && prec < n)
+                   n = prec;
+           }
+           while (n > 0 && buflen > 0) {
+               c = *p++;
+               --n;
+               if (!quoted && c >= 0x80) {
+                   OUTCHAR('M');
+                   OUTCHAR('-');
+                   c -= 0x80;
+               }
+               if (quoted && (c == '"' || c == '\\'))
+                   OUTCHAR('\\');
+               if (c < 0x20 || 0x7f <= c && c < 0xa0) {
+                   if (quoted) {
+                       OUTCHAR('\\');
+                       switch (c) {
+                       case '\t':      OUTCHAR('t');   break;
+                       case '\n':      OUTCHAR('n');   break;
+                       case '\b':      OUTCHAR('b');   break;
+                       case '\f':      OUTCHAR('f');   break;
+                       default:
+                           OUTCHAR('x');
+                           OUTCHAR(hexchars[c >> 4]);
+                           OUTCHAR(hexchars[c & 0xf]);
+                       }
+                   } else {
+                       if (c == '\t')
+                           OUTCHAR(c);
+                       else {
+                           OUTCHAR('^');
+                           OUTCHAR(c ^ 0x40);
+                       }
+                   }
+               } else
+                   OUTCHAR(c);
+           }
+           continue;
        default:
            *buf++ = '%';
            if (c != '%')
@@ -1378,7 +1511,7 @@ vfmtmsg(char *buf, int buflen, char *fmt, va_list args)
            if ((n = width - len) > 0) {
                buflen -= n;
                for (; n > 0; --n)
-                   *buf++ = ' ';
+                   *buf++ = fillch;
            }
        }
        if (len > buflen)