xref: /openbsd-src/usr.sbin/pppd/main.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: main.c,v 1.42 2003/04/25 23:24:04 deraadt Exp $	*/
2 
3 /*
4  * main.c - Point-to-Point Protocol main module
5  *
6  * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. The name "Carnegie Mellon University" must not be used to
21  *    endorse or promote products derived from this software without
22  *    prior written permission. For permission or any legal
23  *    details, please contact
24  *      Office of Technology Transfer
25  *      Carnegie Mellon University
26  *      5000 Forbes Avenue
27  *      Pittsburgh, PA  15213-3890
28  *      (412) 268-4387, fax: (412) 268-7395
29  *      tech-transfer@andrew.cmu.edu
30  *
31  * 4. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by Computing Services
34  *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
35  *
36  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
37  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
38  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
39  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
40  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
41  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
42  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
43  */
44 
45 #ifndef lint
46 #if 0
47 static char rcsid[] = "Id: main.c,v 1.49 1998/05/05 05:24:17 paulus Exp $";
48 #else
49 static char rcsid[] = "$OpenBSD: main.c,v 1.42 2003/04/25 23:24:04 deraadt Exp $";
50 #endif
51 #endif
52 
53 #include <stdio.h>
54 #include <ctype.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <unistd.h>
58 #include <signal.h>
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <syslog.h>
62 #include <netdb.h>
63 #include <utmp.h>
64 #include <pwd.h>
65 #include <sys/param.h>
66 #include <sys/types.h>
67 #include <sys/wait.h>
68 #include <sys/time.h>
69 #include <sys/resource.h>
70 #include <sys/stat.h>
71 #include <sys/socket.h>
72 #include <net/if.h>
73 
74 #include "pppd.h"
75 #include "magic.h"
76 #include "fsm.h"
77 #include "lcp.h"
78 #include "ipcp.h"
79 #include "upap.h"
80 #include "chap.h"
81 #include "ccp.h"
82 #include "pathnames.h"
83 #include "patchlevel.h"
84 
85 #ifdef CBCP_SUPPORT
86 #include "cbcp.h"
87 #endif
88 
89 #if defined(SUNOS4)
90 extern char *strerror();
91 #endif
92 
93 #ifdef IPX_CHANGE
94 #include "ipxcp.h"
95 #endif /* IPX_CHANGE */
96 #ifdef AT_CHANGE
97 #include "atcp.h"
98 #endif
99 
100 /* interface vars */
101 char ifname[IFNAMSIZ];		/* Interface name */
102 int ifunit;			/* Interface unit number */
103 
104 char *progname;			/* Name of this program */
105 char hostname[MAXHOSTNAMELEN];	/* Our hostname */
106 static char pidfilename[MAXPATHLEN];	/* name of pid file */
107 static char default_devnam[MAXPATHLEN];	/* name of default device */
108 static pid_t pid;		/* Our pid */
109 static uid_t uid;		/* Our real user-id */
110 static int conn_running;	/* we have a [dis]connector running */
111 static int crashed = 0;
112 
113 int ttyfd = -1;			/* Serial port file descriptor */
114 mode_t tty_mode = -1;		/* Original access permissions to tty */
115 int baud_rate;			/* Actual bits/second for serial device */
116 int hungup;			/* terminal has been hung up */
117 int privileged;			/* we're running as real uid root */
118 int need_holdoff;		/* need holdoff period before restarting */
119 int detached;			/* have detached from terminal */
120 
121 int phase;			/* where the link is at */
122 int kill_link;
123 int open_ccp_flag;
124 
125 char **script_env;		/* Env. variable values for scripts */
126 int s_env_nalloc;		/* # words avail at script_env */
127 
128 u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
129 u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
130 
131 static int n_children;		/* # child processes still running */
132 
133 static int locked;		/* lock() has succeeded */
134 
135 char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
136 
137 /* Prototypes for procedures local to this file. */
138 
139 static void create_pidfile(void);
140 static void cleanup(void);
141 static void close_tty(void);
142 static void get_input(void);
143 static void calltimeout(void);
144 static struct timeval *timeleft(struct timeval *);
145 static void kill_my_pg(int);
146 static void hup(int);
147 static void term(int);
148 static void chld(int);
149 static void toggle_debug(int);
150 static void open_ccp(int);
151 static void bad_signal(int);
152 static void holdoff_end(void *);
153 static int device_script(char *, int, int);
154 static void reap_kids(void);
155 static void pr_log(void *, char *, ...);
156 
157 extern	char	*ttyname(int);
158 extern	char	*getlogin(void);
159 int main(int, char *[]);
160 
161 #ifdef ultrix
162 #undef	O_NONBLOCK
163 #define	O_NONBLOCK	O_NDELAY
164 #endif
165 
166 #ifdef ULTRIX
167 #define setlogmask(x)
168 #endif
169 
170 /*
171  * PPP Data Link Layer "protocol" table.
172  * One entry per supported protocol.
173  * The last entry must be NULL.
174  */
175 struct protent *protocols[] = {
176     &lcp_protent,
177     &pap_protent,
178     &chap_protent,
179 #ifdef CBCP_SUPPORT
180     &cbcp_protent,
181 #endif
182     &ipcp_protent,
183     &ccp_protent,
184 #ifdef IPX_CHANGE
185     &ipxcp_protent,
186 #endif
187 #ifdef AT_CHANGE
188     &atcp_protent,
189 #endif
190     NULL
191 };
192 
193 int
194 main(argc, argv)
195     int argc;
196     char *argv[];
197 {
198     int i, fdflags;
199     struct sigaction sa;
200     char *p;
201     struct passwd *pw;
202     struct timeval timo;
203     sigset_t mask;
204     struct protent *protp;
205     struct stat statbuf;
206     char numbuf[16];
207 
208     phase = PHASE_INITIALIZE;
209     p = ttyname(0);
210     if (p)
211 	strlcpy(devnam, p, MAXPATHLEN);
212     strlcpy(default_devnam, devnam, sizeof default_devnam);
213 
214     script_env = NULL;
215 
216     /* Initialize syslog facilities */
217 #ifdef ULTRIX
218     openlog("pppd", LOG_PID);
219 #else
220     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
221     setlogmask(LOG_UPTO(LOG_INFO));
222 #endif
223 
224     if (gethostname(hostname, sizeof hostname) < 0 ) {
225 	option_error("Couldn't get hostname: %m");
226 	die(1);
227     }
228 
229     uid = getuid();
230     privileged = uid == 0;
231     snprintf(numbuf, sizeof numbuf, "%u", uid);
232     script_setenv("UID", numbuf);
233 
234     /*
235      * Initialize to the standard option set, then parse, in order,
236      * the system options file, the user's options file,
237      * the tty's options file, and the command line arguments.
238      */
239     for (i = 0; (protp = protocols[i]) != NULL; ++i)
240 	(*protp->init)(0);
241 
242     progname = *argv;
243 
244     if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
245 	|| !options_from_user())
246 	exit(1);
247     scan_args(argc-1, argv+1);	/* look for tty name on command line */
248     if (!options_for_tty()
249 	|| !parse_args(argc-1, argv+1))
250 	exit(1);
251 
252     /*
253      * Check that we are running as root.
254      */
255     if (geteuid() != 0) {
256 	option_error("must be root to run %s, since it is not setuid-root",
257 		     argv[0]);
258 	die(1);
259     }
260 
261     if (!ppp_available()) {
262 	option_error(no_ppp_msg);
263 	exit(1);
264     }
265 
266     /*
267      * Check that the options given are valid and consistent.
268      */
269     sys_check_options();
270     auth_check_options();
271     for (i = 0; (protp = protocols[i]) != NULL; ++i)
272 	if (protp->check_options != NULL)
273 	    (*protp->check_options)();
274     if (demand && connector == 0) {
275 	option_error("connect script required for demand-dialling\n");
276 	exit(1);
277     }
278 
279     script_setenv("DEVICE", devnam);
280     snprintf(numbuf, sizeof numbuf, "%d", baud_rate);
281     script_setenv("SPEED", numbuf);
282 
283     /*
284      * If the user has specified the default device name explicitly,
285      * pretend they hadn't.
286      */
287     if (!default_device && strcmp(devnam, default_devnam) == 0)
288 	default_device = 1;
289     if (default_device)
290 	nodetach = 1;
291 
292     /*
293      * Initialize system-dependent stuff and magic number package.
294      */
295     sys_init();
296     magic_init();
297     if (debug)
298 	setlogmask(LOG_UPTO(LOG_DEBUG));
299 
300     /*
301      * Detach ourselves from the terminal, if required,
302      * and identify who is running us.
303      */
304     if (nodetach == 0)
305 	detach();
306     pid = getpid();
307     p = getlogin();
308     if (p == NULL) {
309 	pw = getpwuid(uid);
310 	if (pw != NULL && pw->pw_name != NULL)
311 	    p = pw->pw_name;
312 	else
313 	    p = "(unknown)";
314     }
315     syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %u",
316 	   VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid);
317 
318     /*
319      * Compute mask of all interesting signals and install signal handlers
320      * for each.  Only one signal handler may be active at a time.  Therefore,
321      * all other signals should be masked when any handler is executing.
322      */
323     sigemptyset(&mask);
324     sigaddset(&mask, SIGHUP);
325     sigaddset(&mask, SIGINT);
326     sigaddset(&mask, SIGTERM);
327     sigaddset(&mask, SIGCHLD);
328 
329 #define SIGNAL(s, handler)	{ \
330 	sa.sa_handler = handler; \
331 	if (sigaction(s, &sa, NULL) < 0) { \
332 	    syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \
333 	    die(1); \
334 	} \
335     }
336 
337     sa.sa_mask = mask;
338     sa.sa_flags = 0;
339     SIGNAL(SIGHUP, hup);		/* Hangup */
340     SIGNAL(SIGINT, term);		/* Interrupt */
341     SIGNAL(SIGTERM, term);		/* Terminate */
342     SIGNAL(SIGCHLD, chld);
343 
344     SIGNAL(SIGUSR1, toggle_debug);	/* Toggle debug flag */
345     SIGNAL(SIGUSR2, open_ccp);		/* Reopen CCP */
346 
347     /*
348      * Install a handler for other signals which would otherwise
349      * cause pppd to exit without cleaning up.
350      */
351     SIGNAL(SIGABRT, bad_signal);
352     SIGNAL(SIGALRM, bad_signal);
353     SIGNAL(SIGFPE, bad_signal);
354     SIGNAL(SIGILL, bad_signal);
355     SIGNAL(SIGPIPE, bad_signal);
356     SIGNAL(SIGQUIT, bad_signal);
357 #if SIGSEGV_CHECK
358     SIGNAL(SIGSEGV, bad_signal);
359 #endif
360 #ifdef SIGBUS
361     SIGNAL(SIGBUS, bad_signal);
362 #endif
363 #ifdef SIGEMT
364     SIGNAL(SIGEMT, bad_signal);
365 #endif
366 #ifdef SIGPOLL
367     SIGNAL(SIGPOLL, bad_signal);
368 #endif
369 #ifdef SIGPROF
370     SIGNAL(SIGPROF, bad_signal);
371 #endif
372 #ifdef SIGSYS
373     SIGNAL(SIGSYS, bad_signal);
374 #endif
375 #ifdef SIGTRAP
376     SIGNAL(SIGTRAP, bad_signal);
377 #endif
378 #ifdef SIGVTALRM
379     SIGNAL(SIGVTALRM, bad_signal);
380 #endif
381 #ifdef SIGXCPU
382     SIGNAL(SIGXCPU, bad_signal);
383 #endif
384 #ifdef SIGXFSZ
385     SIGNAL(SIGXFSZ, bad_signal);
386 #endif
387 
388     /*
389      * Apparently we can get a SIGPIPE when we call syslog, if
390      * syslogd has died and been restarted.  Ignoring it seems
391      * be sufficient.
392      */
393     signal(SIGPIPE, SIG_IGN);
394 
395     /*
396      * If we're doing dial-on-demand, set up the interface now.
397      */
398     if (demand) {
399 	/*
400 	 * Open the loopback channel and set it up to be the ppp interface.
401 	 */
402 	open_ppp_loopback();
403 
404 	syslog(LOG_INFO, "Using interface ppp%d", ifunit);
405 	(void) snprintf(ifname, sizeof ifname, "ppp%d", ifunit);
406 	script_setenv("IFNAME", ifname);
407 
408 	create_pidfile();	/* write pid to file */
409 
410 	/*
411 	 * Configure the interface and mark it up, etc.
412 	 */
413 	demand_conf();
414     }
415 
416     for (;;) {
417 
418 	need_holdoff = 1;
419 
420 	if (demand) {
421 	    /*
422 	     * Don't do anything until we see some activity.
423 	     */
424 	    phase = PHASE_DORMANT;
425 	    kill_link = 0;
426 	    demand_unblock();
427 	    for (;;) {
428 		wait_loop_output(timeleft(&timo));
429 		calltimeout();
430 		if (kill_link) {
431 		    if (!persist)
432 			die(0);
433 		    kill_link = 0;
434 		}
435 		if (get_loop_output())
436 		    break;
437 		reap_kids();
438 	    }
439 
440 	    /*
441 	     * Now we want to bring up the link.
442 	     */
443 	    demand_drop();
444 	    syslog(LOG_INFO, "Starting link");
445 	}
446 
447 	/*
448 	 * Lock the device if we've been asked to.
449 	 */
450 	if (lockflag && !default_device) {
451 	    if (lock(devnam) < 0)
452 		goto fail;
453 	    locked = 1;
454 	}
455 
456 	/*
457 	 * Open the serial device and set it up to be the ppp interface.
458 	 * First we open it in non-blocking mode so we can set the
459 	 * various termios flags appropriately.  If we aren't dialling
460 	 * out and we want to use the modem lines, we reopen it later
461 	 * in order to wait for the carrier detect signal from the modem.
462 	 */
463 	while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) {
464 	    if (errno != EINTR)
465 		syslog(LOG_ERR, "Failed to open %s: %m", devnam);
466 	    if (!persist || errno != EINTR)
467 		goto fail;
468 	}
469 	if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
470 	    || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
471 	    syslog(LOG_WARNING,
472 		   "Couldn't reset non-blocking mode on device: %m");
473 
474 	hungup = 0;
475 	kill_link = 0;
476 
477 	/*
478 	 * Do the equivalent of `mesg n' to stop broadcast messages.
479 	 */
480 	if (fstat(ttyfd, &statbuf) < 0
481 	    || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
482 	    syslog(LOG_WARNING,
483 		   "Couldn't restrict write permissions to %s: %m", devnam);
484 	} else
485 	    tty_mode = statbuf.st_mode;
486 
487 	/* run connection script */
488 	if (connector && connector[0]) {
489 	    MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));
490 
491 	    /*
492 	     * Set line speed, flow control, etc.
493 	     * On most systems we set CLOCAL for now so that we can talk
494 	     * to the modem before carrier comes up.  But this has the
495 	     * side effect that we might miss it if CD drops before we
496 	     * get to clear CLOCAL below.  On systems where we can talk
497 	     * successfully to the modem with CLOCAL clear and CD down,
498 	     * we can clear CLOCAL at this point.
499 	     */
500 	    set_up_tty(ttyfd, (modem_chat == 0));
501 
502 	    /* drop dtr to hang up in case modem is off hook */
503 	    if (!default_device && modem) {
504 		setdtr(ttyfd, FALSE);
505 		sleep(1);
506 		setdtr(ttyfd, TRUE);
507 	    }
508 
509 	    if (device_script(connector, ttyfd, ttyfd) < 0) {
510 		syslog(LOG_ERR, "Connect script failed");
511 		setdtr(ttyfd, FALSE);
512 		goto fail;
513 	    }
514 
515 	    syslog(LOG_INFO, "Serial connection established.");
516 	    sleep(1);		/* give it time to set up its terminal */
517 	}
518 
519 	set_up_tty(ttyfd, 0);
520 
521 	/* reopen tty if necessary to wait for carrier */
522 	if (connector == NULL && modem) {
523 	    while ((i = open(devnam, O_RDWR)) < 0) {
524 		if (errno != EINTR)
525 		    syslog(LOG_ERR, "Failed to reopen %s: %m", devnam);
526 		if (!persist || errno != EINTR || hungup || kill_link)
527 		    goto fail;
528 	    }
529 	    close(i);
530 	}
531 
532 	/* run welcome script, if any */
533 	if (welcomer && welcomer[0]) {
534 	    if (device_script(welcomer, ttyfd, ttyfd) < 0)
535 		syslog(LOG_WARNING, "Welcome script failed");
536 	}
537 
538 	/* set up the serial device as a ppp interface */
539 	establish_ppp(ttyfd);
540 
541 	if (!demand) {
542 
543 	    syslog(LOG_INFO, "Using interface ppp%d", ifunit);
544 	    (void) snprintf(ifname, sizeof ifname, "ppp%d", ifunit);
545 	    script_setenv("IFNAME", ifname);
546 
547 	    create_pidfile();	/* write pid to file */
548 	}
549 
550 	/*
551 	 * Start opening the connection and wait for
552 	 * incoming events (reply, timeout, etc.).
553 	 */
554 	syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
555 	lcp_lowerup(0);
556 	lcp_open(0);		/* Start protocol */
557 	for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
558 	    wait_input(timeleft(&timo));
559 	    calltimeout();
560 	    get_input();
561 	    if (kill_link) {
562 		lcp_close(0, "User request");
563 		kill_link = 0;
564 	    }
565 	    if (open_ccp_flag) {
566 		if (phase == PHASE_NETWORK) {
567 		    ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
568 		    (*ccp_protent.open)(0);
569 		}
570 		open_ccp_flag = 0;
571 	    }
572 	    reap_kids();	/* Don't leave dead kids lying around */
573 	}
574 
575 	/*
576 	 * If we may want to bring the link up again, transfer
577 	 * the ppp unit back to the loopback.  Set the
578 	 * real serial device back to its normal mode of operation.
579 	 */
580 	clean_check();
581 	if (demand)
582 	    restore_loop();
583 	disestablish_ppp(ttyfd);
584 
585 	/*
586 	 * Run disconnector script, if requested.
587 	 * XXX we may not be able to do this if the line has hung up!
588 	 */
589 	if (disconnector && !hungup) {
590 	    set_up_tty(ttyfd, 1);
591 	    if (device_script(disconnector, ttyfd, ttyfd) < 0) {
592 		syslog(LOG_WARNING, "disconnect script failed");
593 	    } else {
594 		syslog(LOG_INFO, "Serial link disconnected.");
595 	    }
596 	}
597 
598     fail:
599 	if (ttyfd >= 0)
600 	    close_tty();
601 	if (locked) {
602 	    unlock();
603 	    locked = 0;
604 	}
605 
606 	if (!demand) {
607 	    if (pidfilename[0] != 0
608 		&& unlink(pidfilename) < 0 && errno != ENOENT)
609 		syslog(LOG_WARNING, "unable to delete pid file: %m");
610 	    pidfilename[0] = 0;
611 	}
612 
613 	if (!persist)
614 	    die(1);
615 
616 	if (holdoff > 0 && need_holdoff) {
617 	    phase = PHASE_HOLDOFF;
618 	    TIMEOUT(holdoff_end, NULL, holdoff);
619 	    do {
620 		wait_time(timeleft(&timo));
621 		calltimeout();
622 		if (kill_link) {
623 		    if (!persist)
624 			die(0);
625 		    kill_link = 0;
626 		    phase = PHASE_DORMANT; /* allow signal to end holdoff */
627 		}
628 		reap_kids();
629 	    } while (phase == PHASE_HOLDOFF);
630 	}
631     }
632 
633     die(0);
634     return 0;
635 }
636 
637 /*
638  * detach - detach us from the controlling terminal.
639  */
640 void
641 detach()
642 {
643     if (detached)
644 	return;
645     if (daemon(0, 0) < 0) {
646 	perror("Couldn't detach from controlling terminal");
647 	die(1);
648     }
649     detached = 1;
650     pid = getpid();
651     /* update pid file if it has been written already */
652     if (pidfilename[0])
653 	create_pidfile();
654 }
655 
656 /*
657  * Create a file containing our process ID.
658  */
659 static void
660 create_pidfile()
661 {
662     FILE *pidfile;
663 
664     (void) snprintf(pidfilename, sizeof pidfilename,
665 	"%s%s.pid", _PATH_VARRUN, ifname);
666     if ((pidfile = fopen(pidfilename, "w")) != NULL) {
667 	fprintf(pidfile, "%ld\n", (long)pid);
668 	(void) fclose(pidfile);
669     } else {
670 	syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename);
671 	pidfilename[0] = 0;
672     }
673 }
674 
675 /*
676  * holdoff_end - called via a timeout when the holdoff period ends.
677  */
678 static void
679 holdoff_end(arg)
680     void *arg;
681 {
682     phase = PHASE_DORMANT;
683 }
684 
685 /*
686  * get_input - called when incoming data is available.
687  */
688 static void
689 get_input()
690 {
691     int len, i;
692     u_char *p;
693     u_short protocol;
694     struct protent *protp;
695 
696     p = inpacket_buf;	/* point to beginning of packet buffer */
697 
698     len = read_packet(inpacket_buf);
699     if (len < 0)
700 	return;
701 
702     if (len == 0) {
703 	syslog(LOG_NOTICE, "Modem hangup");
704 	hungup = 1;
705 	lcp_lowerdown(0);	/* serial link is no longer available */
706 	link_terminated(0);
707 	return;
708     }
709 
710     if (debug /*&& (debugflags & DBG_INPACKET)*/)
711 	log_packet(p, len, "rcvd ", LOG_DEBUG);
712 
713     if (len < PPP_HDRLEN) {
714 	MAINDEBUG((LOG_INFO, "io(): Received short packet."));
715 	return;
716     }
717 
718     p += 2;				/* Skip address and control */
719     GETSHORT(protocol, p);
720     len -= PPP_HDRLEN;
721 
722     /*
723      * Toss all non-LCP packets unless LCP is OPEN.
724      */
725     if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
726 	MAINDEBUG((LOG_INFO,
727 		   "get_input: Received non-LCP packet when LCP not open."));
728 	return;
729     }
730 
731     /*
732      * Until we get past the authentication phase, toss all packets
733      * except LCP, LQR and authentication packets.
734      */
735     if (phase <= PHASE_AUTHENTICATE
736 	&& !(protocol == PPP_LCP || protocol == PPP_LQR
737 	|| protocol == PPP_PAP || protocol == PPP_CHAP)) {
738 	MAINDEBUG((LOG_INFO, "get_input: discarding proto 0x%x in phase %d",
739 		   protocol, phase));
740 	return;
741     }
742 
743     /*
744      * Upcall the proper protocol input routine.
745      */
746     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
747 	if (protp->protocol == protocol && protp->enabled_flag) {
748 	    (*protp->input)(0, p, len);
749 	    return;
750 	}
751 	if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
752 	    && protp->datainput != NULL) {
753 	    (*protp->datainput)(0, p, len);
754 	    return;
755 	}
756     }
757 
758     if (debug)
759     	syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol);
760     lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
761 }
762 
763 
764 /*
765  * quit - Clean up state and exit (with an error indication).
766  */
767 void
768 quit()
769 {
770     die(1);
771 }
772 
773 /*
774  * die - like quit, except we can specify an exit status.
775  */
776 void
777 die(status)
778     int status;
779 {
780     struct syslog_data sdata = SYSLOG_DATA_INIT;
781 
782     cleanup();
783     syslog_r(LOG_INFO, &sdata, "Exit.");
784     _exit(status);
785 }
786 
787 /*
788  * cleanup - restore anything which needs to be restored before we exit
789  */
790 /* ARGSUSED */
791 static void
792 cleanup()
793 {
794     sys_cleanup();
795 
796     if (ttyfd >= 0)
797 	close_tty();
798 
799     if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT)
800 	syslog(LOG_WARNING, "unable to delete pid file: %m");
801     pidfilename[0] = 0;
802 
803     if (locked)
804 	unlock();
805 }
806 
807 /*
808  * close_tty - restore the terminal device and close it.
809  */
810 static void
811 close_tty()
812 {
813     disestablish_ppp(ttyfd);
814 
815     /* drop dtr to hang up */
816     if (modem) {
817 	setdtr(ttyfd, FALSE);
818 	/*
819 	 * This sleep is in case the serial port has CLOCAL set by default,
820 	 * and consequently will reassert DTR when we close the device.
821 	 */
822 	sleep(1);
823     }
824 
825     restore_tty(ttyfd);
826 
827     if (tty_mode != (mode_t) -1)
828 	fchmod(ttyfd, tty_mode);
829 
830     close(ttyfd);
831     ttyfd = -1;
832 }
833 
834 
835 struct	callout {
836     struct timeval	c_time;		/* time at which to call routine */
837     void		*c_arg;		/* argument to routine */
838     void		(*c_func)(void *); /* routine */
839     struct		callout *c_next;
840 };
841 
842 static struct callout *callout = NULL;	/* Callout list */
843 static struct timeval timenow;		/* Current time */
844 
845 /*
846  * timeout - Schedule a timeout.
847  *
848  * Note that this timeout takes the number of seconds, NOT hz (as in
849  * the kernel).
850  */
851 void
852 timeout(func, arg, time)
853     void (*func)(void *);
854     void *arg;
855     int time;
856 {
857     struct callout *newp, *p, **pp;
858 
859     MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.",
860 	       (long) func, (long) arg, time));
861 
862     /*
863      * Allocate timeout.
864      */
865     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
866 	syslog(LOG_ERR, "Out of memory in timeout()!");
867 	die(1);
868     }
869     newp->c_arg = arg;
870     newp->c_func = func;
871     gettimeofday(&timenow, NULL);
872     newp->c_time.tv_sec = timenow.tv_sec + time;
873     newp->c_time.tv_usec = timenow.tv_usec;
874 
875     /*
876      * Find correct place and link it in.
877      */
878     for (pp = &callout; (p = *pp); pp = &p->c_next)
879 	if (newp->c_time.tv_sec < p->c_time.tv_sec
880 	    || (newp->c_time.tv_sec == p->c_time.tv_sec
881 		&& newp->c_time.tv_usec < p->c_time.tv_sec))
882 	    break;
883     newp->c_next = p;
884     *pp = newp;
885 }
886 
887 
888 /*
889  * untimeout - Unschedule a timeout.
890  */
891 void
892 untimeout(func, arg)
893     void (*func)(void *);
894     void *arg;
895 {
896     struct callout **copp, *freep;
897 
898     MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg));
899 
900     /*
901      * Find first matching timeout and remove it from the list.
902      */
903     for (copp = &callout; (freep = *copp); copp = &freep->c_next)
904 	if (freep->c_func == func && freep->c_arg == arg) {
905 	    *copp = freep->c_next;
906 	    (void) free((char *) freep);
907 	    break;
908 	}
909 }
910 
911 
912 /*
913  * calltimeout - Call any timeout routines which are now due.
914  */
915 static void
916 calltimeout()
917 {
918     struct callout *p;
919 
920     while (callout != NULL) {
921 	p = callout;
922 
923 	if (gettimeofday(&timenow, NULL) < 0) {
924 	    syslog(LOG_ERR, "Failed to get time of day: %m");
925 	    die(1);
926 	}
927 	if (!(p->c_time.tv_sec < timenow.tv_sec
928 	      || (p->c_time.tv_sec == timenow.tv_sec
929 		  && p->c_time.tv_usec <= timenow.tv_usec)))
930 	    break;		/* no, it's not time yet */
931 
932 	callout = p->c_next;
933 	(*p->c_func)(p->c_arg);
934 
935 	free((char *) p);
936     }
937 }
938 
939 
940 /*
941  * timeleft - return the length of time until the next timeout is due.
942  */
943 static struct timeval *
944 timeleft(tvp)
945     struct timeval *tvp;
946 {
947     if (callout == NULL)
948 	return NULL;
949 
950     gettimeofday(&timenow, NULL);
951     tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
952     tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
953     if (tvp->tv_usec < 0) {
954 	tvp->tv_usec += 1000000;
955 	tvp->tv_sec -= 1;
956     }
957     if (tvp->tv_sec < 0)
958 	tvp->tv_sec = tvp->tv_usec = 0;
959 
960     return tvp;
961 }
962 
963 
964 /*
965  * kill_my_pg - send a signal to our process group, and ignore it ourselves.
966  */
967 static void
968 kill_my_pg(sig)
969     int sig;
970 {
971     struct sigaction act, oldact;
972 
973     act.sa_handler = SIG_IGN;
974     act.sa_flags = 0;
975     kill(0, sig);
976     sigaction(sig, &act, &oldact);
977     sigaction(sig, &oldact, NULL);
978 }
979 
980 
981 /*
982  * hup - Catch SIGHUP signal.
983  *
984  * Indicates that the physical layer has been disconnected.
985  * We don't rely on this indication; if the user has sent this
986  * signal, we just take the link down.
987  */
988 static void
989 hup(sig)
990     int sig;
991 {
992     int save_errno = errno;
993     struct syslog_data sdata = SYSLOG_DATA_INIT;
994 
995     if (crashed)
996 	_exit(127);
997     syslog_r(LOG_INFO, &sdata, "Hangup (SIGHUP)");
998     kill_link = 1;
999     if (conn_running)
1000 	/* Send the signal to the [dis]connector process(es) also */
1001 	kill_my_pg(sig);
1002     errno = save_errno;
1003 }
1004 
1005 
1006 /*
1007  * term - Catch SIGTERM signal and SIGINT signal (^C/del).
1008  *
1009  * Indicates that we should initiate a graceful disconnect and exit.
1010  */
1011 /*ARGSUSED*/
1012 static void
1013 term(sig)
1014     int sig;
1015 {
1016     int save_errno = errno;
1017     struct syslog_data sdata = SYSLOG_DATA_INIT;
1018 
1019     if (crashed)
1020 	_exit(127);
1021     syslog_r(LOG_INFO, &sdata, "Terminating on signal %d.", sig);
1022     persist = 0;		/* don't try to restart */
1023     kill_link = 1;
1024     if (conn_running)
1025 	/* Send the signal to the [dis]connector process(es) also */
1026 	kill_my_pg(sig);
1027     errno = save_errno;
1028 }
1029 
1030 
1031 /*
1032  * chld - Catch SIGCHLD signal.
1033  * Calls reap_kids to get status for any dead kids.
1034  */
1035 static void
1036 chld(sig)
1037     int sig;
1038 {
1039     int save_errno = errno;
1040 
1041     reap_kids();		/* XXX somewhat unsafe */
1042     errno = save_errno;
1043 }
1044 
1045 
1046 /*
1047  * toggle_debug - Catch SIGUSR1 signal.
1048  *
1049  * Toggle debug flag.
1050  */
1051 /*ARGSUSED*/
1052 static void
1053 toggle_debug(sig)
1054     int sig;
1055 {
1056     debug = !debug;
1057     if (debug) {
1058 	setlogmask(LOG_UPTO(LOG_DEBUG));	/* XXX safe, but wrong */
1059     } else {
1060 	setlogmask(LOG_UPTO(LOG_WARNING));	/* XXX safe, but wrong */
1061     }
1062 }
1063 
1064 
1065 /*
1066  * open_ccp - Catch SIGUSR2 signal.
1067  *
1068  * Try to (re)negotiate compression.
1069  */
1070 /*ARGSUSED*/
1071 static void
1072 open_ccp(sig)
1073     int sig;
1074 {
1075     open_ccp_flag = 1;
1076 }
1077 
1078 
1079 /*
1080  * bad_signal - We've caught a fatal signal.  Clean up state and exit.
1081  */
1082 static void
1083 bad_signal(sig)
1084     int sig;
1085 {
1086     struct syslog_data sdata = SYSLOG_DATA_INIT;
1087 
1088     if (crashed)
1089 	_exit(127);
1090     crashed = 1;
1091     syslog_r(LOG_ERR, &sdata, "Fatal signal %d", sig);
1092     if (conn_running)
1093 	kill_my_pg(SIGTERM);
1094     die(1);					/* XXX unsafe! */
1095 }
1096 
1097 
1098 /*
1099  * device_script - run a program to connect or disconnect the
1100  * serial device.
1101  */
1102 static int
1103 device_script(program, in, out)
1104     char *program;
1105     int in, out;
1106 {
1107     pid_t pid;
1108     int status;
1109     int errfd;
1110 
1111     conn_running = 1;
1112     pid = fork();
1113 
1114     if (pid < 0) {
1115 	conn_running = 0;
1116 	syslog(LOG_ERR, "Failed to create child process: %m");
1117 	die(1);
1118     }
1119 
1120     if (pid == 0) {
1121 	sys_close();
1122 	closelog();
1123 	if (in == out) {
1124 	    if (in != 0) {
1125 		dup2(in, 0);
1126 		close(in);
1127 	    }
1128 	    dup2(0, 1);
1129 	} else {
1130 	    if (out == 0)
1131 		out = dup(out);
1132 	    if (in != 0) {
1133 		dup2(in, 0);
1134 		close(in);
1135 	    }
1136 	    if (out != 1) {
1137 		dup2(out, 1);
1138 		close(out);
1139 	    }
1140 	}
1141 	if (nodetach == 0) {
1142 	    close(2);
1143 	    errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
1144 	    if (errfd >= 0 && errfd != 2) {
1145 		dup2(errfd, 2);
1146 		close(errfd);
1147 	    }
1148 	}
1149 	/* revoke privs */
1150 	seteuid(getuid());
1151 	setuid(getuid());
1152 	setegid(getgid());
1153 	setgid(getgid());
1154 	execl("/bin/sh", "sh", "-c", program, (char *)0);
1155 	syslog(LOG_ERR, "could not exec /bin/sh: %m");
1156 	_exit(99);
1157 	/* NOTREACHED */
1158     }
1159 
1160     while (waitpid(pid, &status, 0) < 0) {
1161 	if (errno == EINTR)
1162 	    continue;
1163 	syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
1164 	die(1);
1165     }
1166     conn_running = 0;
1167 
1168     return (status == 0 ? 0 : -1);
1169 }
1170 
1171 
1172 /*
1173  * run-program - execute a program with given arguments,
1174  * but don't wait for it.
1175  * If the program can't be executed, logs an error unless
1176  * must_exist is 0 and the program file doesn't exist.
1177  */
1178 int
1179 run_program(prog, args, must_exist)
1180     char *prog;
1181     char **args;
1182     int must_exist;
1183 {
1184     pid_t pid;
1185 
1186     pid = fork();
1187     if (pid == -1) {
1188 	syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
1189 	return -1;
1190     }
1191     if (pid == 0) {
1192 	int new_fd;
1193 
1194 	/* Leave the current location */
1195 	(void) setsid();    /* No controlling tty. */
1196 	(void) umask (S_IRWXG|S_IRWXO);
1197 	(void) chdir ("/"); /* no current directory. */
1198 	setuid(geteuid());
1199 	setgid(getegid());
1200 
1201 	/* Ensure that nothing of our device environment is inherited. */
1202 	sys_close();
1203 	closelog();
1204 	close (0);
1205 	close (1);
1206 	close (2);
1207 	close (ttyfd);  /* tty interface to the ppp device */
1208 
1209 	/* Don't pass handles to the PPP device, even by accident. */
1210 	new_fd = open (_PATH_DEVNULL, O_RDWR);
1211 	if (new_fd >= 0) {
1212 	    if (new_fd != 0) {
1213 		dup2  (new_fd, 0); /* stdin <- /dev/null */
1214 		close (new_fd);
1215 	    }
1216 	    dup2 (0, 1); /* stdout -> /dev/null */
1217 	    dup2 (0, 2); /* stderr -> /dev/null */
1218 	}
1219 
1220 #ifdef BSD
1221 	/* Force the priority back to zero if pppd is running higher. */
1222 	if (setpriority (PRIO_PROCESS, 0, 0) < 0)
1223 	    syslog (LOG_WARNING, "can't reset priority to 0: %m");
1224 #endif
1225 
1226 	/* SysV recommends a second fork at this point. */
1227 
1228 	/* run the program; give it a null environment */
1229 	execve(prog, args, script_env);
1230 	if (must_exist || errno != ENOENT)
1231 	    syslog(LOG_WARNING, "Can't execute %s: %m", prog);
1232 	_exit(1);
1233     }
1234     MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %ld", prog, (long)pid));
1235     ++n_children;
1236     return 0;
1237 }
1238 
1239 
1240 /*
1241  * reap_kids - get status from any dead child processes,
1242  * and log a message for abnormal terminations.
1243  */
1244 static void
1245 reap_kids()
1246 {
1247     int status;
1248     pid_t pid;
1249 
1250     if (n_children == 0)
1251 	return;
1252     if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
1253 	if (errno != ECHILD)
1254 	    syslog(LOG_ERR, "Error waiting for child process: %m");
1255 	return;
1256     }
1257     if (pid > 0) {
1258 	--n_children;
1259 	if (WIFSIGNALED(status)) {
1260 	    syslog(LOG_WARNING, "Child process %ld terminated with signal %d",
1261 		   (long)pid, WTERMSIG(status));
1262 	}
1263     }
1264 }
1265 
1266 
1267 /*
1268  * log_packet - format a packet and log it.
1269  */
1270 
1271 char line[256];			/* line to be logged accumulated here */
1272 char *linep;
1273 
1274 void
1275 log_packet(p, len, prefix, level)
1276     u_char *p;
1277     int len;
1278     char *prefix;
1279     int level;
1280 {
1281     strlcpy(line, prefix, sizeof line);
1282     linep = line + strlen(line);
1283     format_packet(p, len, pr_log, NULL);
1284     if (linep != line)
1285 	syslog(level, "%s", line);
1286 }
1287 
1288 /*
1289  * format_packet - make a readable representation of a packet,
1290  * calling `printer(arg, format, ...)' to output it.
1291  */
1292 void
1293 format_packet(p, len, printer, arg)
1294     u_char *p;
1295     int len;
1296     void (*printer)(void *, char *, ...);
1297     void *arg;
1298 {
1299     int i, n;
1300     u_short proto;
1301     u_char x;
1302     struct protent *protp;
1303 
1304     if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
1305 	p += 2;
1306 	GETSHORT(proto, p);
1307 	len -= PPP_HDRLEN;
1308 	for (i = 0; (protp = protocols[i]) != NULL; ++i)
1309 	    if (proto == protp->protocol)
1310 		break;
1311 	if (protp != NULL) {
1312 	    printer(arg, "[%s", protp->name);
1313 	    n = (*protp->printpkt)(p, len, printer, arg);
1314 	    printer(arg, "]");
1315 	    p += n;
1316 	    len -= n;
1317 	} else {
1318 	    printer(arg, "[proto=0x%x]", proto);
1319 	}
1320     }
1321 
1322     for (; len > 0; --len) {
1323 	GETCHAR(x, p);
1324 	printer(arg, " %.2x", x);
1325     }
1326 }
1327 
1328 static void
1329 pr_log(void *arg, char *fmt, ...)
1330 {
1331     int n;
1332     va_list pvar;
1333     char buf[256];
1334 
1335     va_start(pvar, fmt);
1336 
1337     n = vfmtmsg(buf, sizeof(buf), fmt, pvar);
1338     va_end(pvar);
1339 
1340     if (linep + n + 1 > line + sizeof(line)) {
1341 	syslog(LOG_DEBUG, "%s", line);
1342 	linep = line;
1343     }
1344     strlcpy(linep, buf, line + sizeof line - linep);
1345     linep += n;
1346 }
1347 
1348 /*
1349  * print_string - print a readable representation of a string using
1350  * printer.
1351  */
1352 void
1353 print_string(p, len, printer, arg)
1354     char *p;
1355     int len;
1356     void (*printer)(void *, char *, ...);
1357     void *arg;
1358 {
1359     int c;
1360 
1361     printer(arg, "\"");
1362     for (; len > 0; --len) {
1363 	c = *p++;
1364 	if (' ' <= c && c <= '~') {
1365 	    if (c == '\\' || c == '"')
1366 		printer(arg, "\\");
1367 	    printer(arg, "%c", c);
1368 	} else {
1369 	    switch (c) {
1370 	    case '\n':
1371 		printer(arg, "\\n");
1372 		break;
1373 	    case '\r':
1374 		printer(arg, "\\r");
1375 		break;
1376 	    case '\t':
1377 		printer(arg, "\\t");
1378 		break;
1379 	    default:
1380 		printer(arg, "\\%.3o", c);
1381 	    }
1382 	}
1383     }
1384     printer(arg, "\"");
1385 }
1386 
1387 /*
1388  * novm - log an error message saying we ran out of memory, and die.
1389  */
1390 void
1391 novm(msg)
1392     char *msg;
1393 {
1394     syslog(LOG_ERR, "Virtual memory exhausted allocating %s", msg);
1395     die(1);
1396 }
1397 
1398 /*
1399  * fmtmsg - format a message into a buffer.  Like snprintf except we
1400  * also specify the length of the output buffer, and we handle
1401  * %r (recursive format), %m (error message) and %I (IP address) formats.
1402  * Doesn't do floating-point formats.
1403  * Returns the number of chars put into buf.
1404  */
1405 int
1406 fmtmsg(char *buf, int buflen, char *fmt, ...)
1407 {
1408     va_list args;
1409     int n;
1410 
1411     va_start(args, fmt);
1412     n = vfmtmsg(buf, buflen, fmt, args);
1413     va_end(args);
1414     return n;
1415 }
1416 
1417 /*
1418  * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
1419  */
1420 #define OUTCHAR(c)	(buflen > 0? (--buflen, *buf++ = (c)): 0)
1421 
1422 int
1423 vfmtmsg(buf, buflen, fmt, args)
1424     char *buf;
1425     int buflen;
1426     char *fmt;
1427     va_list args;
1428 {
1429     int c, i, n;
1430     int width, prec, fillch;
1431     int base, len, neg, quoted;
1432     unsigned long val = 0;
1433     char *str, *f, *buf0;
1434     unsigned char *p;
1435     char num[32];
1436     time_t t;
1437     static char hexchars[] = "0123456789abcdef";
1438 
1439     buf0 = buf;
1440     --buflen;
1441     while (buflen > 0) {
1442 	for (f = fmt; *f != '%' && *f != 0; ++f)
1443 	    ;
1444 	if (f > fmt) {
1445 	    len = f - fmt;
1446 	    if (len > buflen)
1447 		len = buflen;
1448 	    memcpy(buf, fmt, len);
1449 	    buf += len;
1450 	    buflen -= len;
1451 	    fmt = f;
1452 	}
1453 	if (*fmt == 0)
1454 	    break;
1455 	c = *++fmt;
1456 	width = prec = 0;
1457 	fillch = ' ';
1458 	if (c == '0') {
1459 	    fillch = '0';
1460 	    c = *++fmt;
1461 	}
1462 	if (c == '*') {
1463 	    width = va_arg(args, int);
1464 	    c = *++fmt;
1465 	} else {
1466 	    while (isdigit(c)) {
1467 		width = width * 10 + c - '0';
1468 		c = *++fmt;
1469 	    }
1470 	}
1471 	if (c == '.') {
1472 	    c = *++fmt;
1473 	    if (c == '*') {
1474 		prec = va_arg(args, int);
1475 		c = *++fmt;
1476 	    } else {
1477 		while (isdigit(c)) {
1478 		    prec = prec * 10 + c - '0';
1479 		    c = *++fmt;
1480 		}
1481 	    }
1482 	}
1483 	str = 0;
1484 	base = 0;
1485 	neg = 0;
1486 	++fmt;
1487 	switch (c) {
1488 	case 'd':
1489 	    i = va_arg(args, int);
1490 	    if (i < 0) {
1491 		neg = 1;
1492 		val = -i;
1493 	    } else
1494 		val = i;
1495 	    base = 10;
1496 	    break;
1497 	case 'o':
1498 	    val = va_arg(args, unsigned int);
1499 	    base = 8;
1500 	    break;
1501 	case 'x':
1502 	    val = va_arg(args, unsigned int);
1503 	    base = 16;
1504 	    break;
1505 	case 'p':
1506 	    val = (unsigned long) va_arg(args, void *);
1507 	    base = 16;
1508 	    neg = 2;
1509 	    break;
1510 	case 's':
1511 	    str = va_arg(args, char *);
1512 	    break;
1513 	case 'c':
1514 	    num[0] = va_arg(args, int);
1515 	    num[1] = 0;
1516 	    str = num;
1517 	    break;
1518 	case 'm':
1519 	    str = strerror(errno);
1520 	    break;
1521 	case 'I':
1522 	    str = ip_ntoa(va_arg(args, u_int32_t));
1523 	    break;
1524 	case 'r':
1525 	    f = va_arg(args, char *);
1526 #ifndef __powerpc__
1527 	    n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list));
1528 #else
1529 	    /* On the powerpc, a va_list is an array of 1 structure */
1530 	    n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *));
1531 #endif
1532 	    buf += n;
1533 	    buflen -= n;
1534 	    continue;
1535 	case 't':
1536 	    time(&t);
1537 	    str = ctime(&t);
1538 	    str += 4;		/* chop off the day name */
1539 	    str[15] = 0;	/* chop off year and newline */
1540 	    break;
1541 	case 'v':		/* "visible" string */
1542 	case 'q':		/* quoted string */
1543 	    quoted = c == 'q';
1544 	    p = va_arg(args, unsigned char *);
1545 	    if (fillch == '0' && prec > 0) {
1546 		n = prec;
1547 	    } else {
1548 		n = strlen((char *)p);
1549 		if (prec > 0 && prec < n)
1550 		    n = prec;
1551 	    }
1552 	    while (n > 0 && buflen > 0) {
1553 		c = *p++;
1554 		--n;
1555 		if (!quoted && c >= 0x80) {
1556 		    OUTCHAR('M');
1557 		    OUTCHAR('-');
1558 		    c -= 0x80;
1559 		}
1560 		if (quoted && (c == '"' || c == '\\'))
1561 		    OUTCHAR('\\');
1562 		if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
1563 		    if (quoted) {
1564 			OUTCHAR('\\');
1565 			switch (c) {
1566 			case '\t':	OUTCHAR('t');	break;
1567 			case '\n':	OUTCHAR('n');	break;
1568 			case '\b':	OUTCHAR('b');	break;
1569 			case '\f':	OUTCHAR('f');	break;
1570 			default:
1571 			    OUTCHAR('x');
1572 			    OUTCHAR(hexchars[c >> 4]);
1573 			    OUTCHAR(hexchars[c & 0xf]);
1574 			}
1575 		    } else {
1576 			if (c == '\t')
1577 			    OUTCHAR(c);
1578 			else {
1579 			    OUTCHAR('^');
1580 			    OUTCHAR(c ^ 0x40);
1581 			}
1582 		    }
1583 		} else
1584 		    OUTCHAR(c);
1585 	    }
1586 	    continue;
1587 	default:
1588 	    *buf++ = '%';
1589 	    if (c != '%')
1590 		--fmt;		/* so %z outputs %z etc. */
1591 	    --buflen;
1592 	    continue;
1593 	}
1594 	if (base != 0) {
1595 	    str = num + sizeof(num);
1596 	    *--str = 0;
1597 	    while (str > num + neg) {
1598 		*--str = hexchars[val % base];
1599 		val = val / base;
1600 		if (--prec <= 0 && val == 0)
1601 		    break;
1602 	    }
1603 	    switch (neg) {
1604 	    case 1:
1605 		*--str = '-';
1606 		break;
1607 	    case 2:
1608 		*--str = 'x';
1609 		*--str = '0';
1610 		break;
1611 	    }
1612 	    len = num + sizeof(num) - 1 - str;
1613 	} else {
1614 	    len = strlen(str);
1615 	    if (prec > 0 && len > prec)
1616 		len = prec;
1617 	}
1618 	if (width > 0) {
1619 	    if (width > buflen)
1620 		width = buflen;
1621 	    if ((n = width - len) > 0) {
1622 		buflen -= n;
1623 		for (; n > 0; --n)
1624 		    *buf++ = fillch;
1625 	    }
1626 	}
1627 	if (len > buflen)
1628 	    len = buflen;
1629 	memcpy(buf, str, len);
1630 	buf += len;
1631 	buflen -= len;
1632     }
1633     *buf = 0;
1634     return buf - buf0;
1635 }
1636 
1637 /*
1638  * script_setenv - set an environment variable value to be used
1639  * for scripts that we run (e.g. ip-up, auth-up, etc.)
1640  */
1641 void
1642 script_setenv(var, value)
1643     char *var, *value;
1644 {
1645     int vl = strlen(var);
1646     int i;
1647     char *p, *newstring;
1648 
1649     if (asprintf(&newstring, "%s=%s", var, value) == -1)
1650 	novm("script_setenv");
1651 
1652     /* check if this variable is already set */
1653     if (script_env != 0) {
1654 	for (i = 0; (p = script_env[i]) != 0; ++i) {
1655 	    if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
1656 		free(p);
1657 		script_env[i] = newstring;
1658 		return;
1659 	    }
1660 	}
1661     } else {
1662 	i = 0;
1663 	script_env = (char **) malloc(16 * sizeof(char *));
1664 	if (script_env == 0)
1665 	    novm("script_setenv");
1666 	s_env_nalloc = 16;
1667     }
1668 
1669     /* reallocate script_env with more space if needed */
1670     if (i + 1 >= s_env_nalloc) {
1671 	int new_n = i + 17;
1672 	char **newenv = (char **) realloc((void *)script_env,
1673 					  new_n * sizeof(char *));
1674 	if (newenv == 0)
1675 	    novm("script_setenv");
1676 	script_env = newenv;
1677 	s_env_nalloc = new_n;
1678     }
1679 
1680     script_env[i] = newstring;
1681     script_env[i+1] = 0;
1682 }
1683 
1684 /*
1685  * script_unsetenv - remove a variable from the environment
1686  * for scripts.
1687  */
1688 void
1689 script_unsetenv(var)
1690     char *var;
1691 {
1692     int vl = strlen(var);
1693     int i;
1694     char *p;
1695 
1696     if (script_env == 0)
1697 	return;
1698     for (i = 0; (p = script_env[i]) != 0; ++i) {
1699 	if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
1700 	    free(p);
1701 	    while ((script_env[i] = script_env[i+1]) != 0)
1702 		++i;
1703 	    break;
1704 	}
1705     }
1706 }
1707