]> git.ozlabs.org Git - ppp.git/blob - pppd/main.c
d743b9691a2d14cda7c96c41eb9fcbbf21456d6c
[ppp.git] / pppd / main.c
1 /*
2  * main.c - Point-to-Point Protocol main module
3  *
4  * Copyright (c) 1989 Carnegie Mellon University.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by Carnegie Mellon University.  The name of the
13  * University may not be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19
20 #ifndef lint
21 static char rcsid[] = "$Id: main.c,v 1.71 1999/03/31 12:30:01 paulus Exp $";
22 #endif
23
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <signal.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <syslog.h>
33 #include <netdb.h>
34 #include <utmp.h>
35 #include <pwd.h>
36 #include <setjmp.h>
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <sys/time.h>
41 #include <sys/resource.h>
42 #include <sys/stat.h>
43 #include <sys/socket.h>
44 #include <netinet/in.h>
45
46 #include "pppd.h"
47 #include "magic.h"
48 #include "fsm.h"
49 #include "lcp.h"
50 #include "ipcp.h"
51 #include "upap.h"
52 #include "chap.h"
53 #include "ccp.h"
54 #include "pathnames.h"
55 #include "patchlevel.h"
56
57 #ifdef CBCP_SUPPORT
58 #include "cbcp.h"
59 #endif
60
61 #if defined(SUNOS4)
62 extern char *strerror();
63 #endif
64
65 #ifdef IPX_CHANGE
66 #include "ipxcp.h"
67 #endif /* IPX_CHANGE */
68 #ifdef AT_CHANGE
69 #include "atcp.h"
70 #endif
71
72 /* interface vars */
73 char ifname[32];                /* Interface name */
74 int ifunit;                     /* Interface unit number */
75
76 char *progname;                 /* Name of this program */
77 char hostname[MAXNAMELEN];      /* Our hostname */
78 static char pidfilename[MAXPATHLEN];    /* name of pid file */
79 static char ppp_devnam[MAXPATHLEN]; /* name of PPP tty (maybe ttypx) */
80 static pid_t pid;               /* Our pid */
81 static uid_t uid;               /* Our real user-id */
82 static int conn_running;        /* we have a [dis]connector running */
83
84 int ttyfd;                      /* Serial port file descriptor */
85 mode_t tty_mode = -1;           /* Original access permissions to tty */
86 int baud_rate;                  /* Actual bits/second for serial device */
87 int hungup;                     /* terminal has been hung up */
88 int privileged;                 /* we're running as real uid root */
89 int need_holdoff;               /* need holdoff period before restarting */
90 int detached;                   /* have detached from terminal */
91 int log_to_fd;                  /* send log messages to this fd too */
92
93 static int fd_ppp = -1;         /* fd for talking PPP */
94 static int fd_loop;             /* fd for getting demand-dial packets */
95 static int pty_master;          /* fd for master side of pty */
96 static int pty_slave;           /* fd for slave side of pty */
97 static int real_ttyfd;          /* fd for actual serial port (not pty) */
98
99 int phase;                      /* where the link is at */
100 int kill_link;
101 int open_ccp_flag;
102
103 static int waiting;
104 static sigjmp_buf sigjmp;
105
106 char **script_env;              /* Env. variable values for scripts */
107 int s_env_nalloc;               /* # words avail at script_env */
108
109 u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
110 u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
111
112 static int n_children;          /* # child processes still running */
113 static int got_sigchld;         /* set if we have received a SIGCHLD */
114
115 static int locked;              /* lock() has succeeded */
116
117 char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
118
119 GIDSET_TYPE groups[NGROUPS_MAX];/* groups the user is in */
120 int ngroups;                    /* How many groups valid in groups */
121
122 static struct timeval start_time;       /* Time when link was started. */
123
124 struct pppd_stats link_stats;
125 int link_stats_valid;
126
127 static int charshunt_pid;       /* Process ID for charshunt */
128
129 /* Prototypes for procedures local to this file. */
130
131 static void create_pidfile __P((void));
132 static void cleanup __P((void));
133 static void close_tty __P((void));
134 static void get_input __P((void));
135 static void calltimeout __P((void));
136 static struct timeval *timeleft __P((struct timeval *));
137 static void kill_my_pg __P((int));
138 static void hup __P((int));
139 static void term __P((int));
140 static void chld __P((int));
141 static void toggle_debug __P((int));
142 static void open_ccp __P((int));
143 static void bad_signal __P((int));
144 static void holdoff_end __P((void *));
145 static int device_script __P((char *, int, int, int));
146 static void reap_kids __P((int waitfor));
147 static void pr_log __P((void *, char *, ...));
148 static void logit __P((int, char *, va_list));
149 static void vslp_printer __P((void *, char *, ...));
150 static void format_packet __P((u_char *, int, void (*) (void *, char *, ...),
151                                void *));
152 static void record_child __P((int, char *, void (*) (void *), void *));
153 static int start_charshunt __P((int, int));
154 static void charshunt_done __P((void *));
155 static void charshunt __P((int, int, char *));
156 static int record_write(FILE *, int code, u_char *buf, int nb,
157                         struct timeval *);
158
159 extern  char    *ttyname __P((int));
160 extern  char    *getlogin __P((void));
161 int main __P((int, char *[]));
162
163 #ifdef ultrix
164 #undef  O_NONBLOCK
165 #define O_NONBLOCK      O_NDELAY
166 #endif
167
168 #ifdef ULTRIX
169 #define setlogmask(x)
170 #endif
171
172 /*
173  * PPP Data Link Layer "protocol" table.
174  * One entry per supported protocol.
175  * The last entry must be NULL.
176  */
177 struct protent *protocols[] = {
178     &lcp_protent,
179     &pap_protent,
180     &chap_protent,
181 #ifdef CBCP_SUPPORT
182     &cbcp_protent,
183 #endif
184     &ipcp_protent,
185     &ccp_protent,
186 #ifdef IPX_CHANGE
187     &ipxcp_protent,
188 #endif
189 #ifdef AT_CHANGE
190     &atcp_protent,
191 #endif
192     NULL
193 };
194
195 int
196 main(argc, argv)
197     int argc;
198     char *argv[];
199 {
200     int i, fdflags;
201     struct sigaction sa;
202     char *p;
203     struct passwd *pw;
204     struct timeval timo;
205     sigset_t mask;
206     struct protent *protp;
207     struct stat statbuf;
208     char numbuf[16];
209     struct timeval now;
210
211     phase = PHASE_INITIALIZE;
212     log_to_fd = -1;
213
214     script_env = NULL;
215
216     /* Initialize syslog facilities */
217     reopen_log();
218
219     if (gethostname(hostname, MAXNAMELEN) < 0 ) {
220         option_error("Couldn't get hostname: %m");
221         exit(1);
222     }
223     hostname[MAXNAMELEN-1] = 0;
224
225     uid = getuid();
226     privileged = uid == 0;
227     slprintf(numbuf, sizeof(numbuf), "%d", uid);
228     script_setenv("ORIG_UID", numbuf);
229
230     ngroups = getgroups(NGROUPS_MAX, groups);
231
232     /*
233      * Initialize to the standard option set, then parse, in order,
234      * the system options file, the user's options file,
235      * the tty's options file, and the command line arguments.
236      */
237     for (i = 0; (protp = protocols[i]) != NULL; ++i)
238         (*protp->init)(0);
239
240     progname = *argv;
241
242     if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
243         || !options_from_user())
244         exit(1);
245     using_pty = notty || ptycommand != NULL;
246     scan_args(argc-1, argv+1);  /* look for tty name on command line */
247
248     /*
249      * Work out the device name, if it hasn't already been specified.
250      */
251     if (!using_pty) {
252         p = isatty(0)? ttyname(0): NULL;
253         if (p != NULL) {
254             if (default_device)
255                 strlcpy(devnam, p, sizeof(devnam));
256             else if (strcmp(devnam, p) == 0)
257                 default_device = 1;
258         }
259     }
260
261     /*
262      * Parse the tty options file and the command line.
263      */
264     if (!options_for_tty()
265         || !parse_args(argc-1, argv+1))
266         exit(1);
267
268     /*
269      * Check that we are running as root.
270      */
271     if (geteuid() != 0) {
272         option_error("must be root to run %s, since it is not setuid-root",
273                      argv[0]);
274         exit(1);
275     }
276
277     if (!ppp_available()) {
278         option_error(no_ppp_msg);
279         exit(1);
280     }
281
282     /*
283      * Check that the options given are valid and consistent.
284      */
285     if (!sys_check_options())
286         exit(1);
287     auth_check_options();
288     for (i = 0; (protp = protocols[i]) != NULL; ++i)
289         if (protp->check_options != NULL)
290             (*protp->check_options)();
291     if (demand && connector == 0) {
292         option_error("connect script is required for demand-dialling\n");
293         exit(1);
294     }
295
296     if (using_pty) {
297         if (!default_device) {
298             option_error("%s option precludes specifying device name",
299                          notty? "notty": "pty");
300             exit(1);
301         }
302         if (ptycommand != NULL && notty) {
303             option_error("pty option is incompatible with notty option");
304             exit(1);
305         }
306         default_device = notty;
307         lockflag = 0;
308         modem = 0;
309     } else {
310         if (devnam[0] == 0) {
311             option_error("no device specified and stdin is not a tty");
312             exit(1);
313         }
314     }
315     if (default_device)
316         nodetach = 1;
317     else
318         log_to_fd = 1;          /* default to stdout */
319
320     script_setenv("DEVICE", devnam);
321
322     /*
323      * Initialize system-dependent stuff and magic number package.
324      */
325     sys_init();
326     magic_init();
327     if (debug)
328         setlogmask(LOG_UPTO(LOG_DEBUG));
329
330     /*
331      * Detach ourselves from the terminal, if required,
332      * and identify who is running us.
333      */
334     if (!nodetach && !updetach)
335         detach();
336     pid = getpid();
337     p = getlogin();
338     if (p == NULL) {
339         pw = getpwuid(uid);
340         if (pw != NULL && pw->pw_name != NULL)
341             p = pw->pw_name;
342         else
343             p = "(unknown)";
344     }
345     syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d",
346            VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid);
347   
348     /*
349      * Compute mask of all interesting signals and install signal handlers
350      * for each.  Only one signal handler may be active at a time.  Therefore,
351      * all other signals should be masked when any handler is executing.
352      */
353     sigemptyset(&mask);
354     sigaddset(&mask, SIGHUP);
355     sigaddset(&mask, SIGINT);
356     sigaddset(&mask, SIGTERM);
357     sigaddset(&mask, SIGCHLD);
358     sigaddset(&mask, SIGUSR2);
359
360 #define SIGNAL(s, handler)      do { \
361         sa.sa_handler = handler; \
362         if (sigaction(s, &sa, NULL) < 0) \
363             fatal("Couldn't establish signal handler (%d): %m", s); \
364     } while (0)
365
366     sa.sa_mask = mask;
367     sa.sa_flags = 0;
368     SIGNAL(SIGHUP, hup);                /* Hangup */
369     SIGNAL(SIGINT, term);               /* Interrupt */
370     SIGNAL(SIGTERM, term);              /* Terminate */
371     SIGNAL(SIGCHLD, chld);
372
373     SIGNAL(SIGUSR1, toggle_debug);      /* Toggle debug flag */
374     SIGNAL(SIGUSR2, open_ccp);          /* Reopen CCP */
375
376     /*
377      * Install a handler for other signals which would otherwise
378      * cause pppd to exit without cleaning up.
379      */
380     SIGNAL(SIGABRT, bad_signal);
381     SIGNAL(SIGALRM, bad_signal);
382     SIGNAL(SIGFPE, bad_signal);
383     SIGNAL(SIGILL, bad_signal);
384     SIGNAL(SIGPIPE, bad_signal);
385     SIGNAL(SIGQUIT, bad_signal);
386     SIGNAL(SIGSEGV, bad_signal);
387 #ifdef SIGBUS
388     SIGNAL(SIGBUS, bad_signal);
389 #endif
390 #ifdef SIGEMT
391     SIGNAL(SIGEMT, bad_signal);
392 #endif
393 #ifdef SIGPOLL
394     SIGNAL(SIGPOLL, bad_signal);
395 #endif
396 #ifdef SIGPROF
397     SIGNAL(SIGPROF, bad_signal);
398 #endif
399 #ifdef SIGSYS
400     SIGNAL(SIGSYS, bad_signal);
401 #endif
402 #ifdef SIGTRAP
403     SIGNAL(SIGTRAP, bad_signal);
404 #endif
405 #ifdef SIGVTALRM
406     SIGNAL(SIGVTALRM, bad_signal);
407 #endif
408 #ifdef SIGXCPU
409     SIGNAL(SIGXCPU, bad_signal);
410 #endif
411 #ifdef SIGXFSZ
412     SIGNAL(SIGXFSZ, bad_signal);
413 #endif
414
415     /*
416      * Apparently we can get a SIGPIPE when we call syslog, if
417      * syslogd has died and been restarted.  Ignoring it seems
418      * be sufficient.
419      */
420     signal(SIGPIPE, SIG_IGN);
421
422     waiting = 0;
423
424     /*
425      * If we're doing dial-on-demand, set up the interface now.
426      */
427     if (demand) {
428         /*
429          * Open the loopback channel and set it up to be the ppp interface.
430          */
431         fd_loop = open_ppp_loopback();
432
433         syslog(LOG_INFO, "Using interface ppp%d", ifunit);
434         slprintf(ifname, sizeof(ifname), "ppp%d", ifunit);
435         script_setenv("IFNAME", ifname);
436
437         create_pidfile();       /* write pid to file */
438
439         /*
440          * Configure the interface and mark it up, etc.
441          */
442         demand_conf();
443     }
444
445     for (;;) {
446
447         need_holdoff = 1;
448         ttyfd = -1;
449         real_ttyfd = -1;
450
451         if (demand) {
452             /*
453              * Don't do anything until we see some activity.
454              */
455             kill_link = 0;
456             phase = PHASE_DORMANT;
457             demand_unblock();
458             add_fd(fd_loop);
459             for (;;) {
460                 if (sigsetjmp(sigjmp, 1) == 0) {
461                     sigprocmask(SIG_BLOCK, &mask, NULL);
462                     if (kill_link) {
463                         sigprocmask(SIG_UNBLOCK, &mask, NULL);
464                     } else {
465                         waiting = 1;
466                         sigprocmask(SIG_UNBLOCK, &mask, NULL);
467                         wait_input(timeleft(&timo));
468                     }
469                 }
470                 waiting = 0;
471                 calltimeout();
472                 if (kill_link) {
473                     if (!persist)
474                         break;
475                     kill_link = 0;
476                 }
477                 if (get_loop_output())
478                     break;
479                 if (got_sigchld)
480                     reap_kids(0);
481             }
482             remove_fd(fd_loop);
483             if (kill_link && !persist)
484                 break;
485
486             /*
487              * Now we want to bring up the link.
488              */
489             demand_block();
490             info("Starting link");
491         }
492
493         /*
494          * Get a pty master/slave pair if the pty, notty, or record
495          * options were specified.
496          */
497         strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
498         pty_master = -1;
499         pty_slave = -1;
500         if (ptycommand != NULL || notty || record_file != NULL) {
501             if (!get_pty(&pty_master, &pty_slave, ppp_devnam, uid)) {
502                 error("Couldn't allocate pseudo-tty");
503                 goto fail;
504             }
505             set_up_tty(pty_slave, 1);
506         }
507
508         /*
509          * Lock the device if we've been asked to.
510          */
511         if (lockflag && !default_device) {
512             if (lock(devnam) < 0)
513                 goto fail;
514             locked = 1;
515         }
516
517         /*
518          * Open the serial device and set it up to be the ppp interface.
519          * First we open it in non-blocking mode so we can set the
520          * various termios flags appropriately.  If we aren't dialling
521          * out and we want to use the modem lines, we reopen it later
522          * in order to wait for the carrier detect signal from the modem.
523          */
524         hungup = 0;
525         kill_link = 0;
526         if (devnam[0] != 0) {
527             for (;;) {
528                 /* If the user specified the device name, become the
529                    user before opening it. */
530                 if (!devnam_info.priv && !default_device)
531                     seteuid(uid);
532                 ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
533                 if (!devnam_info.priv && !default_device)
534                     seteuid(0);
535                 if (ttyfd >= 0)
536                     break;
537                 if (errno != EINTR)
538                     error("Failed to open %s: %m", devnam);
539                 if (!persist || errno != EINTR)
540                     goto fail;
541             }
542             if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
543                 || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
544                 warn("Couldn't reset non-blocking mode on device: %m");
545
546             /*
547              * Do the equivalent of `mesg n' to stop broadcast messages.
548              */
549             if (fstat(ttyfd, &statbuf) < 0
550                 || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
551                 warn("Couldn't restrict write permissions to %s: %m", devnam);
552             } else
553                 tty_mode = statbuf.st_mode;
554
555             /*
556              * Set line speed, flow control, etc.
557              * If we have a non-null connection script,
558              * on most systems we set CLOCAL for now so that we can talk
559              * to the modem before carrier comes up.  But this has the
560              * side effect that we might miss it if CD drops before we
561              * get to clear CLOCAL below.  On systems where we can talk
562              * successfully to the modem with CLOCAL clear and CD down,
563              * we could clear CLOCAL at this point.
564              */
565             set_up_tty(ttyfd, (connector != NULL && connector[0] != 0));
566             real_ttyfd = ttyfd;
567         }
568
569         /*
570          * If the notty and/or record option was specified,
571          * start up the character shunt now.
572          */
573         if (ptycommand != NULL) {
574             if (record_file != NULL) {
575                 int ipipe[2], opipe[2], ok;
576
577                 if (pipe(ipipe) < 0 || pipe(opipe) < 0)
578                     fatal("Couldn't create pipes for record option: %m");
579                 ok = device_script(ptycommand, opipe[0], ipipe[1], 1) == 0
580                     && start_charshunt(ipipe[0], opipe[1]);
581                 close(ipipe[0]);
582                 close(ipipe[1]);
583                 close(opipe[0]);
584                 close(opipe[1]);
585                 if (!ok)
586                     goto fail;
587             } else {
588                 if (device_script(ptycommand, pty_master, pty_master, 1) < 0)
589                     goto fail;
590                 ttyfd = pty_slave;
591                 close(pty_master);
592                 pty_master = -1;
593             }
594         } else if (notty) {
595             if (!start_charshunt(0, 1))
596                 goto fail;
597         } else if (record_file != NULL) {
598             if (!start_charshunt(ttyfd, ttyfd))
599                 goto fail;
600         }
601
602         /* run connection script */
603         if (connector && connector[0]) {
604             MAINDEBUG(("Connecting with <%s>", connector));
605
606             if (real_ttyfd != -1) {
607                 if (!default_device && modem) {
608                     setdtr(real_ttyfd, 0);      /* in case modem is off hook */
609                     sleep(1);
610                     setdtr(real_ttyfd, 1);
611                 }
612             }
613
614             if (device_script(connector, ttyfd, ttyfd, 0) < 0) {
615                 error("Connect script failed");
616                 goto fail;
617             }
618             if (kill_link)
619                 goto disconnect;
620
621             info("Serial connection established.");
622
623             /* set line speed, flow control, etc.;
624                clear CLOCAL if modem option */
625             if (real_ttyfd != -1)
626                 set_up_tty(real_ttyfd, 0);
627         }
628
629         /* reopen tty if necessary to wait for carrier */
630         if (connector == NULL && modem && devnam[0] != 0) {
631             for (;;) {
632                 if ((i = open(devnam, O_RDWR)) >= 0)
633                     break;
634                 if (errno != EINTR)
635                     error("Failed to reopen %s: %m", devnam);
636                 if (!persist || errno != EINTR || hungup || kill_link)
637                     goto fail;
638             }
639             close(i);
640         }
641
642         slprintf(numbuf, sizeof(numbuf), "%d", baud_rate);
643         script_setenv("SPEED", numbuf);
644
645         /* run welcome script, if any */
646         if (welcomer && welcomer[0]) {
647             if (device_script(welcomer, ttyfd, ttyfd, 0) < 0)
648                 warn("Welcome script failed");
649         }
650
651         /* set up the serial device as a ppp interface */
652         fd_ppp = establish_ppp(ttyfd);
653         if (fd_ppp < 0)
654             goto disconnect;
655
656         if (!demand) {
657             
658             info("Using interface ppp%d", ifunit);
659             slprintf(ifname, sizeof(ifname), "ppp%d", ifunit);
660             script_setenv("IFNAME", ifname);
661
662             create_pidfile();   /* write pid to file */
663         }
664
665         /*
666          * Start opening the connection and wait for
667          * incoming events (reply, timeout, etc.).
668          */
669         notice("Connect: %s <--> %s", ifname, ppp_devnam);
670         gettimeofday(&start_time, NULL);
671         lcp_lowerup(0);
672
673         /*
674          * If we are initiating this connection, wait for a short
675          * time for something from the peer.  This can avoid bouncing
676          * our packets off his tty before he has it set up.
677          */
678         if (connector != NULL || ptycommand != NULL) {
679             struct timeval t;
680             t.tv_sec = 1;
681             t.tv_usec = 0;
682             wait_input(&t);
683         }
684
685         lcp_open(0);            /* Start protocol */
686         open_ccp_flag = 0;
687         add_fd(fd_ppp);
688         for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
689             if (sigsetjmp(sigjmp, 1) == 0) {
690                 sigprocmask(SIG_BLOCK, &mask, NULL);
691                 if (kill_link || open_ccp_flag) {
692                     sigprocmask(SIG_UNBLOCK, &mask, NULL);
693                 } else {
694                     waiting = 1;
695                     sigprocmask(SIG_UNBLOCK, &mask, NULL);
696                     wait_input(timeleft(&timo));
697                 }
698             }
699             waiting = 0;
700             calltimeout();
701             get_input();
702             if (kill_link) {
703                 lcp_close(0, "User request");
704                 kill_link = 0;
705             }
706             if (open_ccp_flag) {
707                 if (phase == PHASE_NETWORK) {
708                     ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
709                     (*ccp_protent.open)(0);
710                 }
711                 open_ccp_flag = 0;
712             }
713             if (got_sigchld)
714                 reap_kids(0);   /* Don't leave dead kids lying around */
715         }
716
717         /*
718          * Print connect time and statistics.
719          */
720         if (gettimeofday(&now, NULL) >= 0) {
721             int t = now.tv_sec - start_time.tv_sec;
722             t = (t + 5) / 6;    /* now in 1/10ths of minutes */
723             info("Connect time %d.%d minutes.", t/10, t%10);
724         }
725         if (link_stats_valid) {
726             info("Sent %d bytes, received %d bytes.",
727                  link_stats.bytes_out, link_stats.bytes_in);
728         }
729
730         /*
731          * If we may want to bring the link up again, transfer
732          * the ppp unit back to the loopback.  Set the
733          * real serial device back to its normal mode of operation.
734          */
735         remove_fd(fd_ppp);
736         clean_check();
737         if (demand)
738             restore_loop();
739         disestablish_ppp(ttyfd);
740         fd_ppp = -1;
741         if (!hungup)
742             lcp_lowerdown(0);
743
744         /*
745          * Run disconnector script, if requested.
746          * XXX we may not be able to do this if the line has hung up!
747          */
748     disconnect:
749         if (disconnector && !hungup) {
750             if (real_ttyfd >= 0)
751                 set_up_tty(real_ttyfd, 1);
752             if (device_script(disconnector, ttyfd, ttyfd, 0) < 0) {
753                 warn("disconnect script failed");
754             } else {
755                 info("Serial link disconnected.");
756             }
757         }
758
759     fail:
760         if (pty_master >= 0)
761             close(pty_master);
762         if (pty_slave >= 0)
763             close(pty_slave);
764         if (real_ttyfd >= 0)
765             close_tty();
766         if (locked) {
767             unlock();
768             locked = 0;
769         }
770
771         if (!demand) {
772             if (pidfilename[0] != 0
773                 && unlink(pidfilename) < 0 && errno != ENOENT) 
774                 warn("unable to delete pid file: %m");
775             pidfilename[0] = 0;
776         }
777
778         if (!persist)
779             break;
780
781         kill_link = 0;
782         if (demand)
783             demand_discard();
784         if (holdoff > 0 && need_holdoff) {
785             phase = PHASE_HOLDOFF;
786             TIMEOUT(holdoff_end, NULL, holdoff);
787             do {
788                 if (sigsetjmp(sigjmp, 1) == 0) {
789                     sigprocmask(SIG_BLOCK, &mask, NULL);
790                     if (kill_link) {
791                         sigprocmask(SIG_UNBLOCK, &mask, NULL);
792                     } else {
793                         waiting = 1;
794                         sigprocmask(SIG_UNBLOCK, &mask, NULL);
795                         wait_input(timeleft(&timo));
796                     }
797                 }
798                 waiting = 0;
799                 calltimeout();
800                 if (kill_link) {
801                     kill_link = 0;
802                     phase = PHASE_DORMANT; /* allow signal to end holdoff */
803                 }
804                 if (got_sigchld)
805                     reap_kids(0);
806             } while (phase == PHASE_HOLDOFF);
807             if (!persist)
808                 break;
809         }
810     }
811
812     /* Wait for scripts to finish */
813     while (n_children > 0)
814         reap_kids(1);
815
816     die(0);
817     return 0;
818 }
819
820 /*
821  * detach - detach us from the controlling terminal.
822  */
823 void
824 detach()
825 {
826     if (detached)
827         return;
828     if (daemon(0, 0) < 0) {
829         perror("Couldn't detach from controlling terminal");
830         die(1);
831     }
832     detached = 1;
833     log_to_fd = -1;
834     pid = getpid();
835     /* update pid file if it has been written already */
836     if (pidfilename[0])
837         create_pidfile();
838 }
839
840 /*
841  * reopen_log - (re)open our connection to syslog.
842  */
843 void
844 reopen_log()
845 {
846 #ifdef ULTRIX
847     openlog("pppd", LOG_PID);
848 #else
849     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
850     setlogmask(LOG_UPTO(LOG_INFO));
851 #endif
852 }
853
854 /*
855  * Create a file containing our process ID.
856  */
857 static void
858 create_pidfile()
859 {
860     FILE *pidfile;
861     char numbuf[16];
862
863     slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid",
864              _PATH_VARRUN, ifname);
865     if ((pidfile = fopen(pidfilename, "w")) != NULL) {
866         fprintf(pidfile, "%d\n", pid);
867         (void) fclose(pidfile);
868     } else {
869         error("Failed to create pid file %s: %m", pidfilename);
870         pidfilename[0] = 0;
871     }
872     slprintf(numbuf, sizeof(numbuf), "%d", pid);
873     script_setenv("PPPD_PID", numbuf);
874 }
875
876 /*
877  * holdoff_end - called via a timeout when the holdoff period ends.
878  */
879 static void
880 holdoff_end(arg)
881     void *arg;
882 {
883     phase = PHASE_DORMANT;
884 }
885
886 /*
887  * get_input - called when incoming data is available.
888  */
889 static void
890 get_input()
891 {
892     int len, i;
893     u_char *p;
894     u_short protocol;
895     struct protent *protp;
896
897     p = inpacket_buf;   /* point to beginning of packet buffer */
898
899     len = read_packet(inpacket_buf);
900     if (len < 0)
901         return;
902
903     if (len == 0) {
904         notice("Modem hangup");
905         hungup = 1;
906         lcp_lowerdown(0);       /* serial link is no longer available */
907         link_terminated(0);
908         return;
909     }
910
911     if (debug /*&& (debugflags & DBG_INPACKET)*/)
912         dbglog("rcvd %P", p, len);
913
914     if (len < PPP_HDRLEN) {
915         MAINDEBUG(("io(): Received short packet."));
916         return;
917     }
918
919     p += 2;                             /* Skip address and control */
920     GETSHORT(protocol, p);
921     len -= PPP_HDRLEN;
922
923     /*
924      * Toss all non-LCP packets unless LCP is OPEN.
925      */
926     if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
927         MAINDEBUG(("get_input: Received non-LCP packet when LCP not open."));
928         return;
929     }
930
931     /*
932      * Until we get past the authentication phase, toss all packets
933      * except LCP, LQR and authentication packets.
934      */
935     if (phase <= PHASE_AUTHENTICATE
936         && !(protocol == PPP_LCP || protocol == PPP_LQR
937              || protocol == PPP_PAP || protocol == PPP_CHAP)) {
938         MAINDEBUG(("get_input: discarding proto 0x%x in phase %d",
939                    protocol, phase));
940         return;
941     }
942
943     /*
944      * Upcall the proper protocol input routine.
945      */
946     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
947         if (protp->protocol == protocol && protp->enabled_flag) {
948             (*protp->input)(0, p, len);
949             return;
950         }
951         if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
952             && protp->datainput != NULL) {
953             (*protp->datainput)(0, p, len);
954             return;
955         }
956     }
957
958     if (debug)
959         warn("Unsupported protocol (0x%x) received", protocol);
960     lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
961 }
962
963
964 /*
965  * die - clean up state and exit with the specified status.
966  */
967 void
968 die(status)
969     int status;
970 {
971     cleanup();
972     syslog(LOG_INFO, "Exit.");
973     exit(status);
974 }
975
976 /*
977  * cleanup - restore anything which needs to be restored before we exit
978  */
979 /* ARGSUSED */
980 static void
981 cleanup()
982 {
983     sys_cleanup();
984
985     if (fd_ppp >= 0)
986         disestablish_ppp(ttyfd);
987     if (real_ttyfd >= 0)
988         close_tty();
989
990     if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) 
991         warn("unable to delete pid file: %m");
992     pidfilename[0] = 0;
993
994     if (locked)
995         unlock();
996 }
997
998 /*
999  * close_tty - restore the terminal device and close it.
1000  */
1001 static void
1002 close_tty()
1003 {
1004     /* drop dtr to hang up */
1005     if (!default_device && modem) {
1006         setdtr(real_ttyfd, 0);
1007         /*
1008          * This sleep is in case the serial port has CLOCAL set by default,
1009          * and consequently will reassert DTR when we close the device.
1010          */
1011         sleep(1);
1012     }
1013
1014     restore_tty(real_ttyfd);
1015
1016     if (tty_mode != (mode_t) -1) {
1017         if (fchmod(real_ttyfd, tty_mode) != 0) {
1018             /* XXX if devnam is a symlink, this will change the link */
1019             chmod(devnam, tty_mode);
1020         }
1021     }
1022
1023     close(real_ttyfd);
1024     real_ttyfd = -1;
1025 }
1026
1027
1028 struct  callout {
1029     struct timeval      c_time;         /* time at which to call routine */
1030     void                *c_arg;         /* argument to routine */
1031     void                (*c_func) __P((void *)); /* routine */
1032     struct              callout *c_next;
1033 };
1034
1035 static struct callout *callout = NULL;  /* Callout list */
1036 static struct timeval timenow;          /* Current time */
1037
1038 /*
1039  * timeout - Schedule a timeout.
1040  *
1041  * Note that this timeout takes the number of seconds, NOT hz (as in
1042  * the kernel).
1043  */
1044 void
1045 timeout(func, arg, time)
1046     void (*func) __P((void *));
1047     void *arg;
1048     int time;
1049 {
1050     struct callout *newp, *p, **pp;
1051   
1052     MAINDEBUG(("Timeout %p:%p in %d seconds.", func, arg, time));
1053   
1054     /*
1055      * Allocate timeout.
1056      */
1057     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL)
1058         fatal("Out of memory in timeout()!");
1059     newp->c_arg = arg;
1060     newp->c_func = func;
1061     gettimeofday(&timenow, NULL);
1062     newp->c_time.tv_sec = timenow.tv_sec + time;
1063     newp->c_time.tv_usec = timenow.tv_usec;
1064   
1065     /*
1066      * Find correct place and link it in.
1067      */
1068     for (pp = &callout; (p = *pp); pp = &p->c_next)
1069         if (newp->c_time.tv_sec < p->c_time.tv_sec
1070             || (newp->c_time.tv_sec == p->c_time.tv_sec
1071                 && newp->c_time.tv_usec < p->c_time.tv_usec))
1072             break;
1073     newp->c_next = p;
1074     *pp = newp;
1075 }
1076
1077
1078 /*
1079  * untimeout - Unschedule a timeout.
1080  */
1081 void
1082 untimeout(func, arg)
1083     void (*func) __P((void *));
1084     void *arg;
1085 {
1086     struct callout **copp, *freep;
1087   
1088     MAINDEBUG(("Untimeout %p:%p.", func, arg));
1089   
1090     /*
1091      * Find first matching timeout and remove it from the list.
1092      */
1093     for (copp = &callout; (freep = *copp); copp = &freep->c_next)
1094         if (freep->c_func == func && freep->c_arg == arg) {
1095             *copp = freep->c_next;
1096             (void) free((char *) freep);
1097             break;
1098         }
1099 }
1100
1101
1102 /*
1103  * calltimeout - Call any timeout routines which are now due.
1104  */
1105 static void
1106 calltimeout()
1107 {
1108     struct callout *p;
1109
1110     while (callout != NULL) {
1111         p = callout;
1112
1113         if (gettimeofday(&timenow, NULL) < 0)
1114             fatal("Failed to get time of day: %m");
1115         if (!(p->c_time.tv_sec < timenow.tv_sec
1116               || (p->c_time.tv_sec == timenow.tv_sec
1117                   && p->c_time.tv_usec <= timenow.tv_usec)))
1118             break;              /* no, it's not time yet */
1119
1120         callout = p->c_next;
1121         (*p->c_func)(p->c_arg);
1122
1123         free((char *) p);
1124     }
1125 }
1126
1127
1128 /*
1129  * timeleft - return the length of time until the next timeout is due.
1130  */
1131 static struct timeval *
1132 timeleft(tvp)
1133     struct timeval *tvp;
1134 {
1135     if (callout == NULL)
1136         return NULL;
1137
1138     gettimeofday(&timenow, NULL);
1139     tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
1140     tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
1141     if (tvp->tv_usec < 0) {
1142         tvp->tv_usec += 1000000;
1143         tvp->tv_sec -= 1;
1144     }
1145     if (tvp->tv_sec < 0)
1146         tvp->tv_sec = tvp->tv_usec = 0;
1147
1148     return tvp;
1149 }
1150
1151
1152 /*
1153  * kill_my_pg - send a signal to our process group, and ignore it ourselves.
1154  */
1155 static void
1156 kill_my_pg(sig)
1157     int sig;
1158 {
1159     struct sigaction act, oldact;
1160
1161     act.sa_handler = SIG_IGN;
1162     act.sa_flags = 0;
1163     kill(0, sig);
1164     sigaction(sig, &act, &oldact);
1165     sigaction(sig, &oldact, NULL);
1166 }
1167
1168
1169 /*
1170  * hup - Catch SIGHUP signal.
1171  *
1172  * Indicates that the physical layer has been disconnected.
1173  * We don't rely on this indication; if the user has sent this
1174  * signal, we just take the link down.
1175  */
1176 static void
1177 hup(sig)
1178     int sig;
1179 {
1180     info("Hangup (SIGHUP)");
1181     kill_link = 1;
1182     if (conn_running)
1183         /* Send the signal to the [dis]connector process(es) also */
1184         kill_my_pg(sig);
1185     if (charshunt_pid)
1186         kill(charshunt_pid, sig);
1187     if (waiting)
1188         siglongjmp(sigjmp, 1);
1189 }
1190
1191
1192 /*
1193  * term - Catch SIGTERM signal and SIGINT signal (^C/del).
1194  *
1195  * Indicates that we should initiate a graceful disconnect and exit.
1196  */
1197 /*ARGSUSED*/
1198 static void
1199 term(sig)
1200     int sig;
1201 {
1202     info("Terminating on signal %d.", sig);
1203     persist = 0;                /* don't try to restart */
1204     kill_link = 1;
1205     if (conn_running)
1206         /* Send the signal to the [dis]connector process(es) also */
1207         kill_my_pg(sig);
1208     if (charshunt_pid)
1209         kill(charshunt_pid, sig);
1210     if (waiting)
1211         siglongjmp(sigjmp, 1);
1212 }
1213
1214
1215 /*
1216  * chld - Catch SIGCHLD signal.
1217  * Sets a flag so we will call reap_kids in the mainline.
1218  */
1219 static void
1220 chld(sig)
1221     int sig;
1222 {
1223     got_sigchld = 1;
1224     if (waiting)
1225         siglongjmp(sigjmp, 1);
1226 }
1227
1228
1229 /*
1230  * toggle_debug - Catch SIGUSR1 signal.
1231  *
1232  * Toggle debug flag.
1233  */
1234 /*ARGSUSED*/
1235 static void
1236 toggle_debug(sig)
1237     int sig;
1238 {
1239     debug = !debug;
1240     if (debug) {
1241         setlogmask(LOG_UPTO(LOG_DEBUG));
1242     } else {
1243         setlogmask(LOG_UPTO(LOG_WARNING));
1244     }
1245 }
1246
1247
1248 /*
1249  * open_ccp - Catch SIGUSR2 signal.
1250  *
1251  * Try to (re)negotiate compression.
1252  */
1253 /*ARGSUSED*/
1254 static void
1255 open_ccp(sig)
1256     int sig;
1257 {
1258     open_ccp_flag = 1;
1259     if (waiting)
1260         siglongjmp(sigjmp, 1);
1261 }
1262
1263
1264 /*
1265  * bad_signal - We've caught a fatal signal.  Clean up state and exit.
1266  */
1267 static void
1268 bad_signal(sig)
1269     int sig;
1270 {
1271     static int crashed = 0;
1272
1273     if (crashed)
1274         _exit(127);
1275     crashed = 1;
1276     error("Fatal signal %d", sig);
1277     if (conn_running)
1278         kill_my_pg(SIGTERM);
1279     if (charshunt_pid)
1280         kill(charshunt_pid, SIGTERM);
1281     die(1);
1282 }
1283
1284
1285 /*
1286  * device_script - run a program to talk to the serial device
1287  * (e.g. to run the connector or disconnector script).
1288  */
1289 static int
1290 device_script(program, in, out, dont_wait)
1291     char *program;
1292     int in, out;
1293     int dont_wait;
1294 {
1295     int pid;
1296     int status = -1;
1297     int errfd;
1298
1299     ++conn_running;
1300     pid = fork();
1301
1302     if (pid < 0) {
1303         --conn_running;
1304         error("Failed to create child process: %m");
1305         return -1;
1306     }
1307
1308     if (pid == 0) {
1309         sys_close();
1310         closelog();
1311         if (in == 2) {
1312             /* aargh!!! */
1313             int newin = dup(in);
1314             if (in == out)
1315                 out = newin;
1316             in = newin;
1317         } else if (out == 2) {
1318             out = dup(out);
1319         }
1320         if (log_to_fd >= 0) {
1321             if (log_to_fd != 2)
1322                 dup2(log_to_fd, 2);
1323         } else {
1324             close(2);
1325             errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
1326             if (errfd >= 0 && errfd != 2) {
1327                 dup2(errfd, 2);
1328                 close(errfd);
1329             }
1330         }
1331         if (in != 0) {
1332             if (out == 0)
1333                 out = dup(out);
1334             dup2(in, 0);
1335         }
1336         if (out != 1) {
1337             dup2(out, 1);
1338         }
1339         if (real_ttyfd > 2)
1340             close(real_ttyfd);
1341         if (pty_master > 2)
1342             close(pty_master);
1343         if (pty_slave > 2)
1344             close(pty_slave);
1345         setuid(uid);
1346         if (getuid() != uid) {
1347             error("setuid failed");
1348             exit(1);
1349         }
1350         setgid(getgid());
1351         execl("/bin/sh", "sh", "-c", program, (char *)0);
1352         error("could not exec /bin/sh: %m");
1353         exit(99);
1354         /* NOTREACHED */
1355     }
1356
1357     if (dont_wait) {
1358         record_child(pid, program, NULL, NULL);
1359         status = 0;
1360     } else {
1361         while (waitpid(pid, &status, 0) < 0) {
1362             if (errno == EINTR)
1363                 continue;
1364             fatal("error waiting for (dis)connection process: %m");
1365         }
1366         --conn_running;
1367     }
1368
1369     return (status == 0 ? 0 : -1);
1370 }
1371
1372
1373 /*
1374  * We maintain a list of child process pids and
1375  * functions to call when they exit.
1376  */
1377 struct subprocess {
1378     pid_t       pid;
1379     char        *prog;
1380     void        (*done) __P((void *));
1381     void        *arg;
1382     struct subprocess *next;
1383 };
1384
1385 struct subprocess *children;
1386
1387 /*
1388  * run-program - execute a program with given arguments,
1389  * but don't wait for it.
1390  * If the program can't be executed, logs an error unless
1391  * must_exist is 0 and the program file doesn't exist.
1392  * Returns -1 if it couldn't fork, 0 if the file doesn't exist
1393  * or isn't an executable plain file, or the process ID of the child.
1394  * If done != NULL, (*done)(arg) will be called later (within
1395  * reap_kids) iff the return value is > 0.
1396  */
1397 pid_t
1398 run_program(prog, args, must_exist, done, arg)
1399     char *prog;
1400     char **args;
1401     int must_exist;
1402     void (*done) __P((void *));
1403     void *arg;
1404 {
1405     int pid;
1406     struct stat sbuf;
1407
1408     /*
1409      * First check if the file exists and is executable.
1410      * We don't use access() because that would use the
1411      * real user-id, which might not be root, and the script
1412      * might be accessible only to root.
1413      */
1414     errno = EINVAL;
1415     if (stat(prog, &sbuf) < 0 || !S_ISREG(sbuf.st_mode)
1416         || (sbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0) {
1417         if (must_exist || errno != ENOENT)
1418             warn("Can't execute %s: %m", prog);
1419         return 0;
1420     }
1421
1422     pid = fork();
1423     if (pid == -1) {
1424         error("Failed to create child process for %s: %m", prog);
1425         return -1;
1426     }
1427     if (pid == 0) {
1428         int new_fd;
1429
1430         /* Leave the current location */
1431         (void) setsid();        /* No controlling tty. */
1432         (void) umask (S_IRWXG|S_IRWXO);
1433         (void) chdir ("/");     /* no current directory. */
1434         setuid(0);              /* set real UID = root */
1435         setgid(getegid());
1436
1437         /* Ensure that nothing of our device environment is inherited. */
1438         sys_close();
1439         closelog();
1440         close (0);
1441         close (1);
1442         close (2);
1443         close (ttyfd);  /* tty interface to the ppp device */
1444         if (real_ttyfd >= 0)
1445             close(real_ttyfd);
1446
1447         /* Don't pass handles to the PPP device, even by accident. */
1448         new_fd = open (_PATH_DEVNULL, O_RDWR);
1449         if (new_fd >= 0) {
1450             if (new_fd != 0) {
1451                 dup2  (new_fd, 0); /* stdin <- /dev/null */
1452                 close (new_fd);
1453             }
1454             dup2 (0, 1); /* stdout -> /dev/null */
1455             dup2 (0, 2); /* stderr -> /dev/null */
1456         }
1457
1458 #ifdef BSD
1459         /* Force the priority back to zero if pppd is running higher. */
1460         if (setpriority (PRIO_PROCESS, 0, 0) < 0)
1461             warn("can't reset priority to 0: %m"); 
1462 #endif
1463
1464         /* SysV recommends a second fork at this point. */
1465
1466         /* run the program */
1467         execve(prog, args, script_env);
1468         if (must_exist || errno != ENOENT) {
1469             /* have to reopen the log, there's nowhere else
1470                for the message to go. */
1471             reopen_log();
1472             syslog(LOG_ERR, "Can't execute %s: %m", prog);
1473             closelog();
1474         }
1475         _exit(-1);
1476     }
1477
1478     if (debug)
1479         dbglog("Script %s started; pid = %d", prog, pid);
1480     record_child(pid, prog, done, arg);
1481
1482     return pid;
1483 }
1484
1485
1486 /*
1487  * record_child - add a child process to the list for reap_kids
1488  * to use.
1489  */
1490 static void
1491 record_child(pid, prog, done, arg)
1492     int pid;
1493     char *prog;
1494     void (*done) __P((void *));
1495     void *arg;
1496 {
1497     struct subprocess *chp;
1498
1499     ++n_children;
1500
1501     chp = (struct subprocess *) malloc(sizeof(struct subprocess));
1502     if (chp == NULL) {
1503         warn("losing track of %s process", prog);
1504     } else {
1505         chp->pid = pid;
1506         chp->prog = prog;
1507         chp->done = done;
1508         chp->arg = arg;
1509         chp->next = children;
1510         children = chp;
1511     }
1512 }
1513
1514
1515 /*
1516  * reap_kids - get status from any dead child processes,
1517  * and log a message for abnormal terminations.
1518  */
1519 static void
1520 reap_kids(waitfor)
1521     int waitfor;
1522 {
1523     int pid, status;
1524     struct subprocess *chp, **prevp;
1525
1526     got_sigchld = 0;
1527     if (n_children == 0)
1528         return;
1529     while ((pid = waitpid(-1, &status, (waitfor? 0: WNOHANG))) != -1
1530            && pid != 0) {
1531         --n_children;
1532         for (prevp = &children; (chp = *prevp) != NULL; prevp = &chp->next)
1533             if (chp->pid == pid)
1534                 break;
1535         if (WIFSIGNALED(status)) {
1536             warn("Child process %s (pid %d) terminated with signal %d",
1537                  (chp? chp->prog: "??"), pid, WTERMSIG(status));
1538         } else if (debug)
1539             dbglog("process %d (%s) finished, status = 0x%x",
1540                    pid, (chp? chp->prog: "??"), status);
1541         if (chp && chp->done)
1542             (*chp->done)(chp->arg);
1543     }
1544     if (pid == -1 && errno != ECHILD && errno != EINTR)
1545         error("Error waiting for child process: %m");
1546 }
1547
1548
1549 /*
1550  * log_packet - format a packet and log it.
1551  */
1552
1553 char line[256];                 /* line to be logged accumulated here */
1554 char *linep;
1555
1556 void
1557 log_packet(p, len, prefix, level)
1558     u_char *p;
1559     int len;
1560     char *prefix;
1561     int level;
1562 {
1563     strlcpy(line, prefix, sizeof(line));
1564     linep = line + strlen(line);
1565     format_packet(p, len, pr_log, NULL);
1566     if (linep != line)
1567         syslog(level, "%s", line);
1568 }
1569
1570 /*
1571  * format_packet - make a readable representation of a packet,
1572  * calling `printer(arg, format, ...)' to output it.
1573  */
1574 static void
1575 format_packet(p, len, printer, arg)
1576     u_char *p;
1577     int len;
1578     void (*printer) __P((void *, char *, ...));
1579     void *arg;
1580 {
1581     int i, n;
1582     u_short proto;
1583     struct protent *protp;
1584
1585     if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
1586         p += 2;
1587         GETSHORT(proto, p);
1588         len -= PPP_HDRLEN;
1589         for (i = 0; (protp = protocols[i]) != NULL; ++i)
1590             if (proto == protp->protocol)
1591                 break;
1592         if (protp != NULL) {
1593             printer(arg, "[%s", protp->name);
1594             n = (*protp->printpkt)(p, len, printer, arg);
1595             printer(arg, "]");
1596             p += n;
1597             len -= n;
1598         } else {
1599             for (i = 0; (protp = protocols[i]) != NULL; ++i)
1600                 if (proto == (protp->protocol & ~0x8000))
1601                     break;
1602             if (protp != 0 && protp->data_name != 0) {
1603                 printer(arg, "[%s data]", protp->data_name);
1604                 if (len > 8)
1605                     printer(arg, "%.8B ...", p);
1606                 else
1607                     printer(arg, "%.*B", len, p);
1608                 len = 0;
1609             } else
1610                 printer(arg, "[proto=0x%x]", proto);
1611         }
1612     }
1613
1614     if (len > 32)
1615         printer(arg, "%.32B ...", p);
1616     else
1617         printer(arg, "%.*B", len, p);
1618 }
1619
1620 static void
1621 pr_log __V((void *arg, char *fmt, ...))
1622 {
1623     int n;
1624     va_list pvar;
1625     char buf[256];
1626
1627 #if __STDC__
1628     va_start(pvar, fmt);
1629 #else
1630     void *arg;
1631     char *fmt;
1632     va_start(pvar);
1633     arg = va_arg(pvar, void *);
1634     fmt = va_arg(pvar, char *);
1635 #endif
1636
1637     n = vslprintf(buf, sizeof(buf), fmt, pvar);
1638     va_end(pvar);
1639
1640     if (linep + n + 1 > line + sizeof(line)) {
1641         syslog(LOG_DEBUG, "%s", line);
1642         linep = line;
1643     }
1644     strlcpy(linep, buf, line + sizeof(line) - linep);
1645     linep += n;
1646 }
1647
1648 /*
1649  * vslp_printer - used in processing a %P format
1650  */
1651 struct buffer_info {
1652     char *ptr;
1653     int len;
1654 };
1655
1656 static void
1657 vslp_printer __V((void *arg, char *fmt, ...))
1658 {
1659     int n;
1660     va_list pvar;
1661     struct buffer_info *bi;
1662
1663 #if __STDC__
1664     va_start(pvar, fmt);
1665 #else
1666     void *arg;
1667     char *fmt;
1668     va_start(pvar);
1669     arg = va_arg(pvar, void *);
1670     fmt = va_arg(pvar, char *);
1671 #endif
1672
1673     bi = (struct buffer_info *) arg;
1674     n = vslprintf(bi->ptr, bi->len, fmt, pvar);
1675     va_end(pvar);
1676
1677     bi->ptr += n;
1678     bi->len -= n;
1679 }
1680
1681 /*
1682  * print_string - print a readable representation of a string using
1683  * printer.
1684  */
1685 void
1686 print_string(p, len, printer, arg)
1687     char *p;
1688     int len;
1689     void (*printer) __P((void *, char *, ...));
1690     void *arg;
1691 {
1692     int c;
1693
1694     printer(arg, "\"");
1695     for (; len > 0; --len) {
1696         c = *p++;
1697         if (' ' <= c && c <= '~') {
1698             if (c == '\\' || c == '"')
1699                 printer(arg, "\\");
1700             printer(arg, "%c", c);
1701         } else {
1702             switch (c) {
1703             case '\n':
1704                 printer(arg, "\\n");
1705                 break;
1706             case '\r':
1707                 printer(arg, "\\r");
1708                 break;
1709             case '\t':
1710                 printer(arg, "\\t");
1711                 break;
1712             default:
1713                 printer(arg, "\\%.3o", c);
1714             }
1715         }
1716     }
1717     printer(arg, "\"");
1718 }
1719
1720 /*
1721  * novm - log an error message saying we ran out of memory, and die.
1722  */
1723 void
1724 novm(msg)
1725     char *msg;
1726 {
1727     fatal("Virtual memory exhausted allocating %s\n", msg);
1728 }
1729
1730 /*
1731  * slprintf - format a message into a buffer.  Like sprintf except we
1732  * also specify the length of the output buffer, and we handle
1733  * %r (recursive format), %m (error message), %v (visible string),
1734  * %q (quoted string), %t (current time) and %I (IP address) formats.
1735  * Doesn't do floating-point formats.
1736  * Returns the number of chars put into buf.
1737  */
1738 int
1739 slprintf __V((char *buf, int buflen, char *fmt, ...))
1740 {
1741     va_list args;
1742     int n;
1743
1744 #if __STDC__
1745     va_start(args, fmt);
1746 #else
1747     char *buf;
1748     int buflen;
1749     char *fmt;
1750     va_start(args);
1751     buf = va_arg(args, char *);
1752     buflen = va_arg(args, int);
1753     fmt = va_arg(args, char *);
1754 #endif
1755     n = vslprintf(buf, buflen, fmt, args);
1756     va_end(args);
1757     return n;
1758 }
1759
1760 /*
1761  * vslprintf - like slprintf, takes a va_list instead of a list of args.
1762  */
1763 #define OUTCHAR(c)      (buflen > 0? (--buflen, *buf++ = (c)): 0)
1764
1765 int
1766 vslprintf(buf, buflen, fmt, args)
1767     char *buf;
1768     int buflen;
1769     char *fmt;
1770     va_list args;
1771 {
1772     int c, i, n;
1773     int width, prec, fillch;
1774     int base, len, neg, quoted;
1775     unsigned long val = 0;
1776     char *str, *f, *buf0;
1777     unsigned char *p;
1778     char num[32];
1779     time_t t;
1780     u_int32_t ip;
1781     static char hexchars[] = "0123456789abcdef";
1782     struct buffer_info bufinfo;
1783
1784     buf0 = buf;
1785     --buflen;
1786     while (buflen > 0) {
1787         for (f = fmt; *f != '%' && *f != 0; ++f)
1788             ;
1789         if (f > fmt) {
1790             len = f - fmt;
1791             if (len > buflen)
1792                 len = buflen;
1793             memcpy(buf, fmt, len);
1794             buf += len;
1795             buflen -= len;
1796             fmt = f;
1797         }
1798         if (*fmt == 0)
1799             break;
1800         c = *++fmt;
1801         width = prec = 0;
1802         fillch = ' ';
1803         if (c == '0') {
1804             fillch = '0';
1805             c = *++fmt;
1806         }
1807         if (c == '*') {
1808             width = va_arg(args, int);
1809             c = *++fmt;
1810         } else {
1811             while (isdigit(c)) {
1812                 width = width * 10 + c - '0';
1813                 c = *++fmt;
1814             }
1815         }
1816         if (c == '.') {
1817             c = *++fmt;
1818             if (c == '*') {
1819                 prec = va_arg(args, int);
1820                 c = *++fmt;
1821             } else {
1822                 while (isdigit(c)) {
1823                     prec = prec * 10 + c - '0';
1824                     c = *++fmt;
1825                 }
1826             }
1827         }
1828         str = 0;
1829         base = 0;
1830         neg = 0;
1831         ++fmt;
1832         switch (c) {
1833         case 'd':
1834             i = va_arg(args, int);
1835             if (i < 0) {
1836                 neg = 1;
1837                 val = -i;
1838             } else
1839                 val = i;
1840             base = 10;
1841             break;
1842         case 'o':
1843             val = va_arg(args, unsigned int);
1844             base = 8;
1845             break;
1846         case 'x':
1847         case 'X':
1848             val = va_arg(args, unsigned int);
1849             base = 16;
1850             break;
1851         case 'p':
1852             val = (unsigned long) va_arg(args, void *);
1853             base = 16;
1854             neg = 2;
1855             break;
1856         case 's':
1857             str = va_arg(args, char *);
1858             break;
1859         case 'c':
1860             num[0] = va_arg(args, int);
1861             num[1] = 0;
1862             str = num;
1863             break;
1864         case 'm':
1865             str = strerror(errno);
1866             break;
1867         case 'I':
1868             ip = va_arg(args, u_int32_t);
1869             ip = ntohl(ip);
1870             slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff,
1871                      (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
1872             str = num;
1873             break;
1874         case 'r':
1875             f = va_arg(args, char *);
1876 #ifndef __powerpc__
1877             n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list));
1878 #else
1879             /* On the powerpc, a va_list is an array of 1 structure */
1880             n = vslprintf(buf, buflen + 1, f, va_arg(args, void *));
1881 #endif
1882             buf += n;
1883             buflen -= n;
1884             continue;
1885         case 't':
1886             time(&t);
1887             str = ctime(&t);
1888             str += 4;           /* chop off the day name */
1889             str[15] = 0;        /* chop off year and newline */
1890             break;
1891         case 'v':               /* "visible" string */
1892         case 'q':               /* quoted string */
1893             quoted = c == 'q';
1894             p = va_arg(args, unsigned char *);
1895             if (fillch == '0' && prec > 0) {
1896                 n = prec;
1897             } else {
1898                 n = strlen((char *)p);
1899                 if (prec > 0 && prec < n)
1900                     n = prec;
1901             }
1902             while (n > 0 && buflen > 0) {
1903                 c = *p++;
1904                 --n;
1905                 if (!quoted && c >= 0x80) {
1906                     OUTCHAR('M');
1907                     OUTCHAR('-');
1908                     c -= 0x80;
1909                 }
1910                 if (quoted && (c == '"' || c == '\\'))
1911                     OUTCHAR('\\');
1912                 if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
1913                     if (quoted) {
1914                         OUTCHAR('\\');
1915                         switch (c) {
1916                         case '\t':      OUTCHAR('t');   break;
1917                         case '\n':      OUTCHAR('n');   break;
1918                         case '\b':      OUTCHAR('b');   break;
1919                         case '\f':      OUTCHAR('f');   break;
1920                         default:
1921                             OUTCHAR('x');
1922                             OUTCHAR(hexchars[c >> 4]);
1923                             OUTCHAR(hexchars[c & 0xf]);
1924                         }
1925                     } else {
1926                         if (c == '\t')
1927                             OUTCHAR(c);
1928                         else {
1929                             OUTCHAR('^');
1930                             OUTCHAR(c ^ 0x40);
1931                         }
1932                     }
1933                 } else
1934                     OUTCHAR(c);
1935             }
1936             continue;
1937         case 'P':               /* print PPP packet */
1938             bufinfo.ptr = buf;
1939             bufinfo.len = buflen + 1;
1940             p = va_arg(args, unsigned char *);
1941             n = va_arg(args, int);
1942             format_packet(p, n, vslp_printer, &bufinfo);
1943             buf = bufinfo.ptr;
1944             buflen = bufinfo.len - 1;
1945             continue;
1946         case 'B':
1947             p = va_arg(args, unsigned char *);
1948             for (n = prec; n > 0; --n) {
1949                 c = *p++;
1950                 if (fillch == ' ')
1951                     OUTCHAR(' ');
1952                 OUTCHAR(hexchars[(c >> 4) & 0xf]);
1953                 OUTCHAR(hexchars[c & 0xf]);
1954             }
1955             continue;
1956         default:
1957             *buf++ = '%';
1958             if (c != '%')
1959                 --fmt;          /* so %z outputs %z etc. */
1960             --buflen;
1961             continue;
1962         }
1963         if (base != 0) {
1964             str = num + sizeof(num);
1965             *--str = 0;
1966             while (str > num + neg) {
1967                 *--str = hexchars[val % base];
1968                 val = val / base;
1969                 if (--prec <= 0 && val == 0)
1970                     break;
1971             }
1972             switch (neg) {
1973             case 1:
1974                 *--str = '-';
1975                 break;
1976             case 2:
1977                 *--str = 'x';
1978                 *--str = '0';
1979                 break;
1980             }
1981             len = num + sizeof(num) - 1 - str;
1982         } else {
1983             len = strlen(str);
1984             if (prec > 0 && len > prec)
1985                 len = prec;
1986         }
1987         if (width > 0) {
1988             if (width > buflen)
1989                 width = buflen;
1990             if ((n = width - len) > 0) {
1991                 buflen -= n;
1992                 for (; n > 0; --n)
1993                     *buf++ = fillch;
1994             }
1995         }
1996         if (len > buflen)
1997             len = buflen;
1998         memcpy(buf, str, len);
1999         buf += len;
2000         buflen -= len;
2001     }
2002     *buf = 0;
2003     return buf - buf0;
2004 }
2005
2006 /*
2007  * script_setenv - set an environment variable value to be used
2008  * for scripts that we run (e.g. ip-up, auth-up, etc.)
2009  */
2010 void
2011 script_setenv(var, value)
2012     char *var, *value;
2013 {
2014     size_t vl = strlen(var) + strlen(value) + 2;
2015     int i;
2016     char *p, *newstring;
2017
2018     newstring = (char *) malloc(vl);
2019     if (newstring == 0)
2020         return;
2021     slprintf(newstring, vl, "%s=%s", var, value);
2022
2023     /* check if this variable is already set */
2024     if (script_env != 0) {
2025         for (i = 0; (p = script_env[i]) != 0; ++i) {
2026             if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
2027                 free(p);
2028                 script_env[i] = newstring;
2029                 return;
2030             }
2031         }
2032     } else {
2033         i = 0;
2034         script_env = (char **) malloc(16 * sizeof(char *));
2035         if (script_env == 0)
2036             return;
2037         s_env_nalloc = 16;
2038     }
2039
2040     /* reallocate script_env with more space if needed */
2041     if (i + 1 >= s_env_nalloc) {
2042         int new_n = i + 17;
2043         char **newenv = (char **) realloc((void *)script_env,
2044                                           new_n * sizeof(char *));
2045         if (newenv == 0)
2046             return;
2047         script_env = newenv;
2048         s_env_nalloc = new_n;
2049     }
2050
2051     script_env[i] = newstring;
2052     script_env[i+1] = 0;
2053 }
2054
2055 /*
2056  * script_unsetenv - remove a variable from the environment
2057  * for scripts.
2058  */
2059 void
2060 script_unsetenv(var)
2061     char *var;
2062 {
2063     int vl = strlen(var);
2064     int i;
2065     char *p;
2066
2067     if (script_env == 0)
2068         return;
2069     for (i = 0; (p = script_env[i]) != 0; ++i) {
2070         if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
2071             free(p);
2072             while ((script_env[i] = script_env[i+1]) != 0)
2073                 ++i;
2074             break;
2075         }
2076     }
2077 }
2078
2079 /*
2080  * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer,
2081  * always leaves destination null-terminated (for len > 0).
2082  */
2083 size_t
2084 strlcpy(dest, src, len)
2085     char *dest;
2086     const char *src;
2087     size_t len;
2088 {
2089     size_t ret = strlen(src);
2090
2091     if (len != 0) {
2092         if (ret < len)
2093             strcpy(dest, src);
2094         else {
2095             strncpy(dest, src, len - 1);
2096             dest[len-1] = 0;
2097         }
2098     }
2099     return ret;
2100 }
2101
2102 /*
2103  * strlcat - like strcat/strncat, doesn't overflow destination buffer,
2104  * always leaves destination null-terminated (for len > 0).
2105  */
2106 size_t
2107 strlcat(dest, src, len)
2108     char *dest;
2109     const char *src;
2110     size_t len;
2111 {
2112     size_t dlen = strlen(dest);
2113
2114     return dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0));
2115 }
2116
2117 /*
2118  * logit - does the hard work for fatal et al.
2119  */
2120 static void
2121 logit(level, fmt, args)
2122     int level;
2123     char *fmt;
2124     va_list args;
2125 {
2126     int n;
2127     char buf[256];
2128
2129     n = vslprintf(buf, sizeof(buf), fmt, args);
2130     syslog(level, "%s", buf);
2131     if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) {
2132         if (buf[n-1] != '\n')
2133             buf[n++] = '\n';
2134         if (write(log_to_fd, buf, n) != n)
2135             log_to_fd = -1;
2136     }
2137 }
2138
2139 /*
2140  * fatal - log an error message and die horribly.
2141  */
2142 void
2143 fatal __V((char *fmt, ...))
2144 {
2145     va_list pvar;
2146
2147 #if __STDC__
2148     va_start(pvar, fmt);
2149 #else
2150     char *fmt;
2151     va_start(pvar);
2152     fmt = va_arg(pvar, char *);
2153 #endif
2154
2155     logit(LOG_ERR, fmt, pvar);
2156     va_end(pvar);
2157
2158     die(1);                     /* as promised */
2159 }
2160
2161 /*
2162  * error - log an error message.
2163  */
2164 void
2165 error __V((char *fmt, ...))
2166 {
2167     va_list pvar;
2168
2169 #if __STDC__
2170     va_start(pvar, fmt);
2171 #else
2172     char *fmt;
2173     va_start(pvar);
2174     fmt = va_arg(pvar, char *);
2175 #endif
2176
2177     logit(LOG_ERR, fmt, pvar);
2178     va_end(pvar);
2179 }
2180
2181 /*
2182  * warn - log a warning message.
2183  */
2184 void
2185 warn __V((char *fmt, ...))
2186 {
2187     va_list pvar;
2188
2189 #if __STDC__
2190     va_start(pvar, fmt);
2191 #else
2192     char *fmt;
2193     va_start(pvar);
2194     fmt = va_arg(pvar, char *);
2195 #endif
2196
2197     logit(LOG_WARNING, fmt, pvar);
2198     va_end(pvar);
2199 }
2200
2201 /*
2202  * notice - log a notice-level message.
2203  */
2204 void
2205 notice __V((char *fmt, ...))
2206 {
2207     va_list pvar;
2208
2209 #if __STDC__
2210     va_start(pvar, fmt);
2211 #else
2212     char *fmt;
2213     va_start(pvar);
2214     fmt = va_arg(pvar, char *);
2215 #endif
2216
2217     logit(LOG_NOTICE, fmt, pvar);
2218     va_end(pvar);
2219 }
2220
2221 /*
2222  * info - log an informational message.
2223  */
2224 void
2225 info __V((char *fmt, ...))
2226 {
2227     va_list pvar;
2228
2229 #if __STDC__
2230     va_start(pvar, fmt);
2231 #else
2232     char *fmt;
2233     va_start(pvar);
2234     fmt = va_arg(pvar, char *);
2235 #endif
2236
2237     logit(LOG_INFO, fmt, pvar);
2238     va_end(pvar);
2239 }
2240
2241 /*
2242  * dbglog - log a debug message.
2243  */
2244 void
2245 dbglog __V((char *fmt, ...))
2246 {
2247     va_list pvar;
2248
2249 #if __STDC__
2250     va_start(pvar, fmt);
2251 #else
2252     char *fmt;
2253     va_start(pvar);
2254     fmt = va_arg(pvar, char *);
2255 #endif
2256
2257     logit(LOG_DEBUG, fmt, pvar);
2258     va_end(pvar);
2259 }
2260
2261 /*
2262  * start_charshunt - create a child process to run the character shunt.
2263  */
2264 static int
2265 start_charshunt(ifd, ofd)
2266     int ifd, ofd;
2267 {
2268     int cpid;
2269
2270     cpid = fork();
2271     if (cpid == -1) {
2272         error("Can't fork process for character shunt: %m");
2273         return 0;
2274     }
2275     if (cpid == 0) {
2276         /* child */
2277         close(pty_slave);
2278         setuid(uid);
2279         if (getuid() != uid)
2280             fatal("setuid failed");
2281         setgid(getgid());
2282         if (!nodetach)
2283             log_to_fd = -1;
2284         charshunt(ifd, ofd, record_file);
2285         exit(0);
2286     }
2287     charshunt_pid = cpid;
2288     close(pty_master);
2289     pty_master = -1;
2290     ttyfd = pty_slave;
2291     record_child(cpid, "pppd (charshunt)", charshunt_done, NULL);
2292     return 1;
2293 }
2294
2295 static void
2296 charshunt_done(arg)
2297     void *arg;
2298 {
2299     charshunt_pid = 0;
2300 }
2301
2302 /*
2303  * charshunt - the character shunt, which passes characters between
2304  * the pty master side and the serial port (or stdin/stdout).
2305  * This runs as the user (not as root).
2306  * (We assume ofd >= ifd which is true the way this gets called. :-).
2307  */
2308 static void
2309 charshunt(ifd, ofd, record_file)
2310     int ifd, ofd;
2311     char *record_file;
2312 {
2313     int n, nfds;
2314     fd_set ready, writey;
2315     u_char *ibufp, *obufp;
2316     int nibuf, nobuf;
2317     int flags;
2318     int pty_readable, stdin_readable;
2319     struct timeval lasttime;
2320     FILE *recordf = NULL;
2321
2322     /*
2323      * Reset signal handlers.
2324      */
2325     signal(SIGHUP, SIG_IGN);            /* Hangup */
2326     signal(SIGINT, SIG_DFL);            /* Interrupt */
2327     signal(SIGTERM, SIG_DFL);           /* Terminate */
2328     signal(SIGCHLD, SIG_DFL);
2329     signal(SIGUSR1, SIG_DFL);
2330     signal(SIGUSR2, SIG_DFL);
2331     signal(SIGABRT, SIG_DFL);
2332     signal(SIGALRM, SIG_DFL);
2333     signal(SIGFPE, SIG_DFL);
2334     signal(SIGILL, SIG_DFL);
2335     signal(SIGPIPE, SIG_DFL);
2336     signal(SIGQUIT, SIG_DFL);
2337     signal(SIGSEGV, SIG_DFL);
2338 #ifdef SIGBUS
2339     signal(SIGBUS, SIG_DFL);
2340 #endif
2341 #ifdef SIGEMT
2342     signal(SIGEMT, SIG_DFL);
2343 #endif
2344 #ifdef SIGPOLL
2345     signal(SIGPOLL, SIG_DFL);
2346 #endif
2347 #ifdef SIGPROF
2348     signal(SIGPROF, SIG_DFL);
2349 #endif
2350 #ifdef SIGSYS
2351     signal(SIGSYS, SIG_DFL);
2352 #endif
2353 #ifdef SIGTRAP
2354     signal(SIGTRAP, SIG_DFL);
2355 #endif
2356 #ifdef SIGVTALRM
2357     signal(SIGVTALRM, SIG_DFL);
2358 #endif
2359 #ifdef SIGXCPU
2360     signal(SIGXCPU, SIG_DFL);
2361 #endif
2362 #ifdef SIGXFSZ
2363     signal(SIGXFSZ, SIG_DFL);
2364 #endif
2365
2366     /*
2367      * Open the record file if required.
2368      */
2369     if (record_file != NULL) {
2370         recordf = fopen(record_file, "a");
2371         if (recordf == NULL)
2372             error("Couldn't create record file %s: %m", record_file);
2373     }
2374
2375     /* set all the fds to non-blocking mode */
2376     flags = fcntl(pty_master, F_GETFL);
2377     if (flags == -1
2378         || fcntl(pty_master, F_SETFL, flags | O_NONBLOCK) == -1)
2379         warn("couldn't set pty master to nonblock: %m");
2380     flags = fcntl(ifd, F_GETFL);
2381     if (flags == -1
2382         || fcntl(ifd, F_SETFL, flags | O_NONBLOCK) == -1)
2383         warn("couldn't set %s to nonblock: %m", (ifd==0? "stdin": "tty"));
2384     if (ofd != ifd) {
2385         flags = fcntl(ofd, F_GETFL);
2386         if (flags == -1
2387             || fcntl(ofd, F_SETFL, flags | O_NONBLOCK) == -1)
2388             warn("couldn't set stdout to nonblock: %m");
2389     }
2390
2391     nibuf = nobuf = 0;
2392     ibufp = obufp = NULL;
2393     pty_readable = stdin_readable = 1;
2394     nfds = (ofd > pty_master? ofd: pty_master) + 1;
2395     if (recordf != NULL) {
2396         gettimeofday(&lasttime, NULL);
2397         putc(7, recordf);       /* put start marker */
2398         putc(lasttime.tv_sec >> 24, recordf);
2399         putc(lasttime.tv_sec >> 16, recordf);
2400         putc(lasttime.tv_sec >> 8, recordf);
2401         putc(lasttime.tv_sec, recordf);
2402         lasttime.tv_usec = 0;
2403     }
2404
2405     while (nibuf != 0 || nobuf != 0 || pty_readable || stdin_readable) {
2406         FD_ZERO(&ready);
2407         FD_ZERO(&writey);
2408         if (nibuf != 0)
2409             FD_SET(pty_master, &writey);
2410         else if (stdin_readable)
2411             FD_SET(ifd, &ready);
2412         if (nobuf != 0)
2413             FD_SET(ofd, &writey);
2414         else if (pty_readable)
2415             FD_SET(pty_master, &ready);
2416         if (select(nfds, &ready, &writey, NULL, NULL) < 0) {
2417             if (errno != EINTR)
2418                 fatal("select");
2419             continue;
2420         }
2421         if (FD_ISSET(ifd, &ready)) {
2422             ibufp = inpacket_buf;
2423             nibuf = read(ifd, ibufp, sizeof(inpacket_buf));
2424             if (nibuf < 0 && errno == EIO)
2425                 nibuf = 0;
2426             if (nibuf < 0) {
2427                 if (!(errno == EINTR || errno == EAGAIN)) {
2428                     error("Error reading standard input: %m");
2429                     break;
2430                 }
2431                 nibuf = 0;
2432             } else if (nibuf == 0) {
2433                 /* end of file from stdin */
2434                 stdin_readable = 0;
2435                 /* do a 0-length write, hopefully this will generate
2436                    an EOF (hangup) on the slave side. */
2437                 write(pty_master, inpacket_buf, 0);
2438                 if (recordf)
2439                     if (!record_write(recordf, 4, NULL, 0, &lasttime))
2440                         recordf = NULL;
2441             } else {
2442                 FD_SET(pty_master, &writey);
2443                 if (recordf)
2444                     if (!record_write(recordf, 2, ibufp, nibuf, &lasttime))
2445                         recordf = NULL;
2446             }
2447         }
2448         if (FD_ISSET(pty_master, &ready)) {
2449             obufp = outpacket_buf;
2450             nobuf = read(pty_master, obufp, sizeof(outpacket_buf));
2451             if (nobuf < 0 && errno == EIO)
2452                 nobuf = 0;
2453             if (nobuf < 0) {
2454                 if (!(errno == EINTR || errno == EAGAIN)) {
2455                     error("Error reading pseudo-tty master: %m");
2456                     break;
2457                 }
2458                 nobuf = 0;
2459             } else if (nobuf == 0) {
2460                 /* end of file from the pty - slave side has closed */
2461                 pty_readable = 0;
2462                 stdin_readable = 0;     /* pty is not writable now */
2463                 nibuf = 0;
2464                 close(ofd);
2465                 if (recordf)
2466                     if (!record_write(recordf, 3, NULL, 0, &lasttime))
2467                         recordf = NULL;
2468             } else {
2469                 FD_SET(ofd, &writey);
2470                 if (recordf)
2471                     if (!record_write(recordf, 1, obufp, nobuf, &lasttime))
2472                         recordf = NULL;
2473             }
2474         }
2475         if (FD_ISSET(ofd, &writey)) {
2476             n = write(ofd, obufp, nobuf);
2477             if (n < 0) {
2478                 if (errno != EIO) {
2479                     error("Error writing standard output: %m");
2480                     break;
2481                 }
2482                 pty_readable = 0;
2483                 nobuf = 0;
2484             } else {
2485                 obufp += n;
2486                 nobuf -= n;
2487             }
2488         }
2489         if (FD_ISSET(pty_master, &writey)) {
2490             n = write(pty_master, ibufp, nibuf);
2491             if (n < 0) {
2492                 if (errno != EIO) {
2493                     error("Error writing pseudo-tty master: %m");
2494                     break;
2495                 }
2496                 stdin_readable = 0;
2497                 nibuf = 0;
2498             } else {
2499                 ibufp += n;
2500                 nibuf -= n;
2501             }
2502         }
2503     }
2504     exit(0);
2505 }
2506
2507 static int
2508 record_write(f, code, buf, nb, tp)
2509     FILE *f;
2510     int code;
2511     u_char *buf;
2512     int nb;
2513     struct timeval *tp;
2514 {
2515     struct timeval now;
2516     int diff;
2517
2518     gettimeofday(&now, NULL);
2519     now.tv_usec /= 100000;      /* actually 1/10 s, not usec now */
2520     diff = (now.tv_sec - tp->tv_sec) * 10 + (now.tv_usec - tp->tv_usec);
2521     if (diff > 0) {
2522         if (diff > 255) {
2523             putc(5, f);
2524             putc(diff >> 24, f);
2525             putc(diff >> 16, f);
2526             putc(diff >> 8, f);
2527             putc(diff, f);
2528         } else {
2529             putc(6, f);
2530             putc(diff, f);
2531         }
2532         *tp = now;
2533     }
2534     putc(code, f);
2535     if (buf != NULL) {
2536         putc(nb >> 8, f);
2537         putc(nb, f);
2538         fwrite(buf, nb, 1, f);
2539     }
2540     fflush(f);
2541     if (ferror(f)) {
2542         error("Error writing record file: %m");
2543         return 0;
2544     }
2545     return 1;
2546 }