]> git.ozlabs.org Git - ppp.git/blob - pppd/main.c
add reopen_log(), call it after using PAM stuff
[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.70 1999/03/31 05:39:42 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
619             info("Serial connection established.");
620
621             /* set line speed, flow control, etc.;
622                clear CLOCAL if modem option */
623             if (real_ttyfd != -1)
624                 set_up_tty(real_ttyfd, 0);
625         }
626
627         /* reopen tty if necessary to wait for carrier */
628         if (connector == NULL && modem && devnam[0] != 0) {
629             for (;;) {
630                 if ((i = open(devnam, O_RDWR)) >= 0)
631                     break;
632                 if (errno != EINTR)
633                     error("Failed to reopen %s: %m", devnam);
634                 if (!persist || errno != EINTR || hungup || kill_link)
635                     goto fail;
636             }
637             close(i);
638         }
639
640         slprintf(numbuf, sizeof(numbuf), "%d", baud_rate);
641         script_setenv("SPEED", numbuf);
642
643         /* run welcome script, if any */
644         if (welcomer && welcomer[0]) {
645             if (device_script(welcomer, ttyfd, ttyfd, 0) < 0)
646                 warn("Welcome script failed");
647         }
648
649         /* set up the serial device as a ppp interface */
650         fd_ppp = establish_ppp(ttyfd);
651         if (fd_ppp < 0)
652             goto fail;
653
654         if (!demand) {
655             
656             info("Using interface ppp%d", ifunit);
657             slprintf(ifname, sizeof(ifname), "ppp%d", ifunit);
658             script_setenv("IFNAME", ifname);
659
660             create_pidfile();   /* write pid to file */
661         }
662
663         /*
664          * Start opening the connection and wait for
665          * incoming events (reply, timeout, etc.).
666          */
667         notice("Connect: %s <--> %s", ifname, ppp_devnam);
668         gettimeofday(&start_time, NULL);
669         lcp_lowerup(0);
670
671         /*
672          * If we are initiating this connection, wait for a short
673          * time for something from the peer.  This can avoid bouncing
674          * our packets off his tty before he has it set up.
675          */
676         if (connector != NULL || ptycommand != NULL) {
677             struct timeval t;
678             t.tv_sec = 1;
679             t.tv_usec = 0;
680             wait_input(&t);
681         }
682
683         lcp_open(0);            /* Start protocol */
684         open_ccp_flag = 0;
685         add_fd(fd_ppp);
686         for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
687             if (sigsetjmp(sigjmp, 1) == 0) {
688                 sigprocmask(SIG_BLOCK, &mask, NULL);
689                 if (kill_link || open_ccp_flag) {
690                     sigprocmask(SIG_UNBLOCK, &mask, NULL);
691                 } else {
692                     waiting = 1;
693                     sigprocmask(SIG_UNBLOCK, &mask, NULL);
694                     wait_input(timeleft(&timo));
695                 }
696             }
697             waiting = 0;
698             calltimeout();
699             get_input();
700             if (kill_link) {
701                 lcp_close(0, "User request");
702                 kill_link = 0;
703             }
704             if (open_ccp_flag) {
705                 if (phase == PHASE_NETWORK) {
706                     ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
707                     (*ccp_protent.open)(0);
708                 }
709                 open_ccp_flag = 0;
710             }
711             if (got_sigchld)
712                 reap_kids(0);   /* Don't leave dead kids lying around */
713         }
714
715         /*
716          * Print connect time and statistics.
717          */
718         if (gettimeofday(&now, NULL) >= 0) {
719             int t = now.tv_sec - start_time.tv_sec;
720             t = (t + 5) / 6;    /* now in 1/10ths of minutes */
721             info("Connect time %d.%d minutes.", t/10, t%10);
722         }
723         if (link_stats_valid) {
724             info("Sent %d bytes, received %d bytes.",
725                  link_stats.bytes_out, link_stats.bytes_in);
726         }
727
728         /*
729          * If we may want to bring the link up again, transfer
730          * the ppp unit back to the loopback.  Set the
731          * real serial device back to its normal mode of operation.
732          */
733         remove_fd(fd_ppp);
734         clean_check();
735         if (demand)
736             restore_loop();
737         disestablish_ppp(ttyfd);
738         fd_ppp = -1;
739
740         /*
741          * Run disconnector script, if requested.
742          * XXX we may not be able to do this if the line has hung up!
743          */
744         if (disconnector && !hungup) {
745             if (real_ttyfd >= 0)
746                 set_up_tty(real_ttyfd, 1);
747             if (device_script(disconnector, ttyfd, ttyfd, 0) < 0) {
748                 warn("disconnect script failed");
749             } else {
750                 info("Serial link disconnected.");
751             }
752         }
753         if (!hungup)
754             lcp_lowerdown(0);
755
756     fail:
757         if (pty_master >= 0)
758             close(pty_master);
759         if (pty_slave >= 0)
760             close(pty_slave);
761         if (real_ttyfd >= 0)
762             close_tty();
763         if (locked) {
764             unlock();
765             locked = 0;
766         }
767
768         if (!demand) {
769             if (pidfilename[0] != 0
770                 && unlink(pidfilename) < 0 && errno != ENOENT) 
771                 warn("unable to delete pid file: %m");
772             pidfilename[0] = 0;
773         }
774
775         if (!persist)
776             break;
777
778         kill_link = 0;
779         if (demand)
780             demand_discard();
781         if (holdoff > 0 && need_holdoff) {
782             phase = PHASE_HOLDOFF;
783             TIMEOUT(holdoff_end, NULL, holdoff);
784             do {
785                 if (sigsetjmp(sigjmp, 1) == 0) {
786                     sigprocmask(SIG_BLOCK, &mask, NULL);
787                     if (kill_link) {
788                         sigprocmask(SIG_UNBLOCK, &mask, NULL);
789                     } else {
790                         waiting = 1;
791                         sigprocmask(SIG_UNBLOCK, &mask, NULL);
792                         wait_input(timeleft(&timo));
793                     }
794                 }
795                 waiting = 0;
796                 calltimeout();
797                 if (kill_link) {
798                     kill_link = 0;
799                     phase = PHASE_DORMANT; /* allow signal to end holdoff */
800                 }
801                 if (got_sigchld)
802                     reap_kids(0);
803             } while (phase == PHASE_HOLDOFF);
804             if (!persist)
805                 break;
806         }
807     }
808
809     /* Wait for scripts to finish */
810     while (n_children > 0)
811         reap_kids(1);
812
813     die(0);
814     return 0;
815 }
816
817 /*
818  * detach - detach us from the controlling terminal.
819  */
820 void
821 detach()
822 {
823     if (detached)
824         return;
825     if (daemon(0, 0) < 0) {
826         perror("Couldn't detach from controlling terminal");
827         die(1);
828     }
829     detached = 1;
830     log_to_fd = -1;
831     pid = getpid();
832     /* update pid file if it has been written already */
833     if (pidfilename[0])
834         create_pidfile();
835 }
836
837 /*
838  * reopen_log - (re)open our connection to syslog.
839  */
840 void
841 reopen_log()
842 {
843 #ifdef ULTRIX
844     openlog("pppd", LOG_PID);
845 #else
846     openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
847     setlogmask(LOG_UPTO(LOG_INFO));
848 #endif
849 }
850
851 /*
852  * Create a file containing our process ID.
853  */
854 static void
855 create_pidfile()
856 {
857     FILE *pidfile;
858     char numbuf[16];
859
860     slprintf(pidfilename, sizeof(pidfilename), "%s%s.pid",
861              _PATH_VARRUN, ifname);
862     if ((pidfile = fopen(pidfilename, "w")) != NULL) {
863         fprintf(pidfile, "%d\n", pid);
864         (void) fclose(pidfile);
865     } else {
866         error("Failed to create pid file %s: %m", pidfilename);
867         pidfilename[0] = 0;
868     }
869     slprintf(numbuf, sizeof(numbuf), "%d", pid);
870     script_setenv("PPPD_PID", numbuf);
871 }
872
873 /*
874  * holdoff_end - called via a timeout when the holdoff period ends.
875  */
876 static void
877 holdoff_end(arg)
878     void *arg;
879 {
880     phase = PHASE_DORMANT;
881 }
882
883 /*
884  * get_input - called when incoming data is available.
885  */
886 static void
887 get_input()
888 {
889     int len, i;
890     u_char *p;
891     u_short protocol;
892     struct protent *protp;
893
894     p = inpacket_buf;   /* point to beginning of packet buffer */
895
896     len = read_packet(inpacket_buf);
897     if (len < 0)
898         return;
899
900     if (len == 0) {
901         notice("Modem hangup");
902         hungup = 1;
903         lcp_lowerdown(0);       /* serial link is no longer available */
904         link_terminated(0);
905         return;
906     }
907
908     if (debug /*&& (debugflags & DBG_INPACKET)*/)
909         dbglog("rcvd %P", p, len);
910
911     if (len < PPP_HDRLEN) {
912         MAINDEBUG(("io(): Received short packet."));
913         return;
914     }
915
916     p += 2;                             /* Skip address and control */
917     GETSHORT(protocol, p);
918     len -= PPP_HDRLEN;
919
920     /*
921      * Toss all non-LCP packets unless LCP is OPEN.
922      */
923     if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
924         MAINDEBUG(("get_input: Received non-LCP packet when LCP not open."));
925         return;
926     }
927
928     /*
929      * Until we get past the authentication phase, toss all packets
930      * except LCP, LQR and authentication packets.
931      */
932     if (phase <= PHASE_AUTHENTICATE
933         && !(protocol == PPP_LCP || protocol == PPP_LQR
934              || protocol == PPP_PAP || protocol == PPP_CHAP)) {
935         MAINDEBUG(("get_input: discarding proto 0x%x in phase %d",
936                    protocol, phase));
937         return;
938     }
939
940     /*
941      * Upcall the proper protocol input routine.
942      */
943     for (i = 0; (protp = protocols[i]) != NULL; ++i) {
944         if (protp->protocol == protocol && protp->enabled_flag) {
945             (*protp->input)(0, p, len);
946             return;
947         }
948         if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
949             && protp->datainput != NULL) {
950             (*protp->datainput)(0, p, len);
951             return;
952         }
953     }
954
955     if (debug)
956         warn("Unsupported protocol (0x%x) received", protocol);
957     lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
958 }
959
960
961 /*
962  * die - clean up state and exit with the specified status.
963  */
964 void
965 die(status)
966     int status;
967 {
968     cleanup();
969     syslog(LOG_INFO, "Exit.");
970     exit(status);
971 }
972
973 /*
974  * cleanup - restore anything which needs to be restored before we exit
975  */
976 /* ARGSUSED */
977 static void
978 cleanup()
979 {
980     sys_cleanup();
981
982     if (fd_ppp >= 0)
983         disestablish_ppp(ttyfd);
984     if (real_ttyfd >= 0)
985         close_tty();
986
987     if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) 
988         warn("unable to delete pid file: %m");
989     pidfilename[0] = 0;
990
991     if (locked)
992         unlock();
993 }
994
995 /*
996  * close_tty - restore the terminal device and close it.
997  */
998 static void
999 close_tty()
1000 {
1001     /* drop dtr to hang up */
1002     if (!default_device && modem) {
1003         setdtr(real_ttyfd, 0);
1004         /*
1005          * This sleep is in case the serial port has CLOCAL set by default,
1006          * and consequently will reassert DTR when we close the device.
1007          */
1008         sleep(1);
1009     }
1010
1011     restore_tty(real_ttyfd);
1012
1013     if (tty_mode != (mode_t) -1) {
1014         if (fchmod(real_ttyfd, tty_mode) != 0) {
1015             /* XXX if devnam is a symlink, this will change the link */
1016             chmod(devnam, tty_mode);
1017         }
1018     }
1019
1020     close(real_ttyfd);
1021     real_ttyfd = -1;
1022 }
1023
1024
1025 struct  callout {
1026     struct timeval      c_time;         /* time at which to call routine */
1027     void                *c_arg;         /* argument to routine */
1028     void                (*c_func) __P((void *)); /* routine */
1029     struct              callout *c_next;
1030 };
1031
1032 static struct callout *callout = NULL;  /* Callout list */
1033 static struct timeval timenow;          /* Current time */
1034
1035 /*
1036  * timeout - Schedule a timeout.
1037  *
1038  * Note that this timeout takes the number of seconds, NOT hz (as in
1039  * the kernel).
1040  */
1041 void
1042 timeout(func, arg, time)
1043     void (*func) __P((void *));
1044     void *arg;
1045     int time;
1046 {
1047     struct callout *newp, *p, **pp;
1048   
1049     MAINDEBUG(("Timeout %p:%p in %d seconds.", func, arg, time));
1050   
1051     /*
1052      * Allocate timeout.
1053      */
1054     if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL)
1055         fatal("Out of memory in timeout()!");
1056     newp->c_arg = arg;
1057     newp->c_func = func;
1058     gettimeofday(&timenow, NULL);
1059     newp->c_time.tv_sec = timenow.tv_sec + time;
1060     newp->c_time.tv_usec = timenow.tv_usec;
1061   
1062     /*
1063      * Find correct place and link it in.
1064      */
1065     for (pp = &callout; (p = *pp); pp = &p->c_next)
1066         if (newp->c_time.tv_sec < p->c_time.tv_sec
1067             || (newp->c_time.tv_sec == p->c_time.tv_sec
1068                 && newp->c_time.tv_usec < p->c_time.tv_usec))
1069             break;
1070     newp->c_next = p;
1071     *pp = newp;
1072 }
1073
1074
1075 /*
1076  * untimeout - Unschedule a timeout.
1077  */
1078 void
1079 untimeout(func, arg)
1080     void (*func) __P((void *));
1081     void *arg;
1082 {
1083     struct callout **copp, *freep;
1084   
1085     MAINDEBUG(("Untimeout %p:%p.", func, arg));
1086   
1087     /*
1088      * Find first matching timeout and remove it from the list.
1089      */
1090     for (copp = &callout; (freep = *copp); copp = &freep->c_next)
1091         if (freep->c_func == func && freep->c_arg == arg) {
1092             *copp = freep->c_next;
1093             (void) free((char *) freep);
1094             break;
1095         }
1096 }
1097
1098
1099 /*
1100  * calltimeout - Call any timeout routines which are now due.
1101  */
1102 static void
1103 calltimeout()
1104 {
1105     struct callout *p;
1106
1107     while (callout != NULL) {
1108         p = callout;
1109
1110         if (gettimeofday(&timenow, NULL) < 0)
1111             fatal("Failed to get time of day: %m");
1112         if (!(p->c_time.tv_sec < timenow.tv_sec
1113               || (p->c_time.tv_sec == timenow.tv_sec
1114                   && p->c_time.tv_usec <= timenow.tv_usec)))
1115             break;              /* no, it's not time yet */
1116
1117         callout = p->c_next;
1118         (*p->c_func)(p->c_arg);
1119
1120         free((char *) p);
1121     }
1122 }
1123
1124
1125 /*
1126  * timeleft - return the length of time until the next timeout is due.
1127  */
1128 static struct timeval *
1129 timeleft(tvp)
1130     struct timeval *tvp;
1131 {
1132     if (callout == NULL)
1133         return NULL;
1134
1135     gettimeofday(&timenow, NULL);
1136     tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
1137     tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
1138     if (tvp->tv_usec < 0) {
1139         tvp->tv_usec += 1000000;
1140         tvp->tv_sec -= 1;
1141     }
1142     if (tvp->tv_sec < 0)
1143         tvp->tv_sec = tvp->tv_usec = 0;
1144
1145     return tvp;
1146 }
1147
1148
1149 /*
1150  * kill_my_pg - send a signal to our process group, and ignore it ourselves.
1151  */
1152 static void
1153 kill_my_pg(sig)
1154     int sig;
1155 {
1156     struct sigaction act, oldact;
1157
1158     act.sa_handler = SIG_IGN;
1159     act.sa_flags = 0;
1160     kill(0, sig);
1161     sigaction(sig, &act, &oldact);
1162     sigaction(sig, &oldact, NULL);
1163 }
1164
1165
1166 /*
1167  * hup - Catch SIGHUP signal.
1168  *
1169  * Indicates that the physical layer has been disconnected.
1170  * We don't rely on this indication; if the user has sent this
1171  * signal, we just take the link down.
1172  */
1173 static void
1174 hup(sig)
1175     int sig;
1176 {
1177     info("Hangup (SIGHUP)");
1178     kill_link = 1;
1179     if (conn_running)
1180         /* Send the signal to the [dis]connector process(es) also */
1181         kill_my_pg(sig);
1182     if (charshunt_pid)
1183         kill(charshunt_pid, sig);
1184     if (waiting)
1185         siglongjmp(sigjmp, 1);
1186 }
1187
1188
1189 /*
1190  * term - Catch SIGTERM signal and SIGINT signal (^C/del).
1191  *
1192  * Indicates that we should initiate a graceful disconnect and exit.
1193  */
1194 /*ARGSUSED*/
1195 static void
1196 term(sig)
1197     int sig;
1198 {
1199     info("Terminating on signal %d.", sig);
1200     persist = 0;                /* don't try to restart */
1201     kill_link = 1;
1202     if (conn_running)
1203         /* Send the signal to the [dis]connector process(es) also */
1204         kill_my_pg(sig);
1205     if (charshunt_pid)
1206         kill(charshunt_pid, sig);
1207     if (waiting)
1208         siglongjmp(sigjmp, 1);
1209 }
1210
1211
1212 /*
1213  * chld - Catch SIGCHLD signal.
1214  * Sets a flag so we will call reap_kids in the mainline.
1215  */
1216 static void
1217 chld(sig)
1218     int sig;
1219 {
1220     got_sigchld = 1;
1221     if (waiting)
1222         siglongjmp(sigjmp, 1);
1223 }
1224
1225
1226 /*
1227  * toggle_debug - Catch SIGUSR1 signal.
1228  *
1229  * Toggle debug flag.
1230  */
1231 /*ARGSUSED*/
1232 static void
1233 toggle_debug(sig)
1234     int sig;
1235 {
1236     debug = !debug;
1237     if (debug) {
1238         setlogmask(LOG_UPTO(LOG_DEBUG));
1239     } else {
1240         setlogmask(LOG_UPTO(LOG_WARNING));
1241     }
1242 }
1243
1244
1245 /*
1246  * open_ccp - Catch SIGUSR2 signal.
1247  *
1248  * Try to (re)negotiate compression.
1249  */
1250 /*ARGSUSED*/
1251 static void
1252 open_ccp(sig)
1253     int sig;
1254 {
1255     open_ccp_flag = 1;
1256     if (waiting)
1257         siglongjmp(sigjmp, 1);
1258 }
1259
1260
1261 /*
1262  * bad_signal - We've caught a fatal signal.  Clean up state and exit.
1263  */
1264 static void
1265 bad_signal(sig)
1266     int sig;
1267 {
1268     static int crashed = 0;
1269
1270     if (crashed)
1271         _exit(127);
1272     crashed = 1;
1273     error("Fatal signal %d", sig);
1274     if (conn_running)
1275         kill_my_pg(SIGTERM);
1276     if (charshunt_pid)
1277         kill(charshunt_pid, SIGTERM);
1278     die(1);
1279 }
1280
1281
1282 /*
1283  * device_script - run a program to talk to the serial device
1284  * (e.g. to run the connector or disconnector script).
1285  */
1286 static int
1287 device_script(program, in, out, dont_wait)
1288     char *program;
1289     int in, out;
1290     int dont_wait;
1291 {
1292     int pid;
1293     int status = 0;
1294     int errfd;
1295
1296     ++conn_running;
1297     pid = fork();
1298
1299     if (pid < 0) {
1300         --conn_running;
1301         error("Failed to create child process: %m");
1302         return -1;
1303     }
1304
1305     if (pid == 0) {
1306         sys_close();
1307         closelog();
1308         if (in == 2) {
1309             /* aargh!!! */
1310             int newin = dup(in);
1311             if (in == out)
1312                 out = newin;
1313             in = newin;
1314         } else if (out == 2) {
1315             out = dup(out);
1316         }
1317         if (log_to_fd >= 0) {
1318             if (log_to_fd != 2)
1319                 dup2(log_to_fd, 2);
1320         } else {
1321             close(2);
1322             errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
1323             if (errfd >= 0 && errfd != 2) {
1324                 dup2(errfd, 2);
1325                 close(errfd);
1326             }
1327         }
1328         if (in != 0) {
1329             if (out == 0)
1330                 out = dup(out);
1331             dup2(in, 0);
1332             if (in > 2)
1333                 close(in);
1334         }
1335         if (out != 1) {
1336             dup2(out, 1);
1337             if (out > 2)
1338                 close(out);
1339         }
1340         if (real_ttyfd > 2)
1341             close(real_ttyfd);
1342         if (pty_master > 2)
1343             close(pty_master);
1344         if (pty_slave > 2)
1345             close(pty_slave);
1346         setuid(uid);
1347         if (getuid() != uid) {
1348             error("setuid failed");
1349             exit(1);
1350         }
1351         setgid(getgid());
1352         execl("/bin/sh", "sh", "-c", program, (char *)0);
1353         error("could not exec /bin/sh: %m");
1354         exit(99);
1355         /* NOTREACHED */
1356     }
1357
1358     if (dont_wait) {
1359         record_child(pid, program, NULL, NULL);
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 }