From 408e8824289fa317933d199b0926aff7dc4adcb1 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 23 Mar 1999 01:23:46 +0000 Subject: [PATCH] Allow record option with pty option. Open record file in charshunt. Be more careful about closing things. Ignore SIGHUP in charshunt. --- pppd/main.c | 231 ++++++++++++++++++++++++++++------------------- pppd/sys-linux.c | 8 +- 2 files changed, 144 insertions(+), 95 deletions(-) diff --git a/pppd/main.c b/pppd/main.c index 4a4e14b..c69d6c2 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.64 1999/03/22 05:55:31 paulus Exp $"; +static char rcsid[] = "$Id: main.c,v 1.65 1999/03/23 01:23:46 paulus Exp $"; #endif #include @@ -90,7 +90,7 @@ int need_holdoff; /* need holdoff period before restarting */ int detached; /* have detached from terminal */ int log_to_fd; /* send log messages to this fd too */ -static int fd_ppp; /* fd for talking PPP */ +static int fd_ppp = -1; /* fd for talking PPP */ static int fd_loop; /* fd for getting demand-dial packets */ static int pty_master; /* fd for master side of pty */ static int pty_slave; /* fd for slave side of pty */ @@ -124,7 +124,6 @@ struct pppd_stats link_stats; int link_stats_valid; static int charshunt_pid; /* Process ID for charshunt */ -static FILE *recordf; /* File for recording chars sent/rcvd */ /* Prototypes for procedures local to this file. */ @@ -142,7 +141,7 @@ static void toggle_debug __P((int)); static void open_ccp __P((int)); static void bad_signal __P((int)); static void holdoff_end __P((void *)); -static int device_script __P((char *, int, int)); +static int device_script __P((char *, int, int, int)); static void reap_kids __P((int waitfor)); static void pr_log __P((void *, char *, ...)); static void logit __P((int, char *, va_list)); @@ -150,7 +149,9 @@ static void vslp_printer __P((void *, char *, ...)); static void format_packet __P((u_char *, int, void (*) (void *, char *, ...), void *)); static void record_child __P((int, char *, void (*) (void *), void *)); -static void charshunt __P((int)); +static int start_charshunt __P((int, int)); +static void charshunt_done __P((void *)); +static void charshunt __P((int, int, char *)); static int record_write(FILE *, int code, u_char *buf, int nb, struct timeval *); @@ -284,9 +285,8 @@ main(argc, argv) notty? "notty": "pty"); exit(1); } - if (ptycommand != NULL && (notty || record_file != NULL)) { - option_error("pty option is incompatible with %s option", - notty? "notty": "record"); + if (ptycommand != NULL && notty) { + option_error("pty option is incompatible with notty option"); exit(1); } default_device = notty; @@ -319,19 +319,6 @@ main(argc, argv) slprintf(numbuf, sizeof(numbuf), "%d", baud_rate); script_setenv("SPEED", numbuf); - /* - * Open the record file (as the user) if required. - */ - if (record_file != NULL) { - if (uid != 0) - seteuid(uid); - recordf = fopen(record_file, "a"); - if (uid != 0) - seteuid(0); - if (recordf == NULL) - option_error("Couldn't create record file %s: %m", record_file); - } - /* * Initialize system-dependent stuff and magic number package. */ @@ -515,13 +502,6 @@ main(argc, argv) goto fail; } set_up_tty(pty_slave, 1); - if (ptycommand != NULL) { - if (device_script(ptycommand, pty_master, 1) < 0) - goto fail; - ttyfd = pty_slave; - close(pty_master); - pty_master = -1; - } } /* @@ -589,30 +569,33 @@ main(argc, argv) * If the notty and/or record option was specified, * start up the character shunt now. */ - if (notty || record_file != NULL) { - int cpid; - - cpid = fork(); - if (cpid == -1) { - error("Can't fork process for character shunt: %m"); - goto fail; - } - if (cpid == 0) { - close(pty_slave); - setuid(uid); - if (getuid() != uid) - fatal("setuid failed"); - setgid(getgid()); - charshunt(ttyfd); - exit(0); + if (ptycommand != NULL) { + if (record_file != NULL) { + int ipipe[2], opipe[2], ok; + + if (pipe(ipipe) < 0 || pipe(opipe) < 0) + fatal("Couldn't create pipes for record option: %m"); + ok = device_script(ptycommand, opipe[0], ipipe[1], 1) == 0 + && start_charshunt(ipipe[0], opipe[1]); + close(ipipe[0]); + close(ipipe[1]); + close(opipe[0]); + close(opipe[1]); + if (!ok) + goto fail; + } else { + if (device_script(ptycommand, pty_master, pty_master, 1) < 0) + goto fail; + ttyfd = pty_slave; + close(pty_master); + pty_master = -1; } - charshunt_pid = cpid; - close(pty_master); - pty_master = -1; - if (ttyfd >= 0) - close(ttyfd); - ttyfd = pty_slave; - record_child(cpid, "pppd (charshunt)", NULL, NULL); + } else if (notty) { + if (!start_charshunt(0, 1)) + goto fail; + } else if (record_file != NULL) { + if (!start_charshunt(ttyfd, ttyfd)) + goto fail; } /* run connection script */ @@ -627,7 +610,7 @@ main(argc, argv) } } - if (device_script(connector, ttyfd, 0) < 0) { + if (device_script(connector, ttyfd, ttyfd, 0) < 0) { error("Connect script failed"); goto fail; } @@ -655,7 +638,7 @@ main(argc, argv) /* run welcome script, if any */ if (welcomer && welcomer[0]) { - if (device_script(welcomer, ttyfd, 0) < 0) + if (device_script(welcomer, ttyfd, ttyfd, 0) < 0) warn("Welcome script failed"); } @@ -747,14 +730,16 @@ main(argc, argv) if (demand) restore_loop(); disestablish_ppp(ttyfd); + fd_ppp = -1; /* * Run disconnector script, if requested. * XXX we may not be able to do this if the line has hung up! */ if (disconnector && !hungup) { - set_up_tty(ttyfd, 1); - if (device_script(disconnector, ttyfd, 0) < 0) { + if (real_ttyfd >= 0) + set_up_tty(real_ttyfd, 1); + if (device_script(disconnector, ttyfd, ttyfd, 0) < 0) { warn("disconnect script failed"); } else { info("Serial link disconnected."); @@ -766,9 +751,9 @@ main(argc, argv) fail: if (pty_master >= 0) close(pty_master); - if (pty_slave >= 0 && pty_slave != ttyfd) + if (pty_slave >= 0) close(pty_slave); - if (ttyfd >= 0) + if (real_ttyfd >= 0) close_tty(); if (locked) { unlock(); @@ -974,7 +959,9 @@ cleanup() { sys_cleanup(); - if (ttyfd >= 0) + if (fd_ppp >= 0) + disestablish_ppp(ttyfd); + if (real_ttyfd >= 0) close_tty(); if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) @@ -991,11 +978,9 @@ cleanup() static void close_tty() { - disestablish_ppp(ttyfd); - /* drop dtr to hang up */ if (!default_device && modem) { - setdtr(ttyfd, 0); + setdtr(real_ttyfd, 0); /* * This sleep is in case the serial port has CLOCAL set by default, * and consequently will reassert DTR when we close the device. @@ -1003,17 +988,17 @@ close_tty() sleep(1); } - restore_tty(ttyfd); + restore_tty(real_ttyfd); if (tty_mode != (mode_t) -1) { - if (fchmod(ttyfd, tty_mode) != 0) { + if (fchmod(real_ttyfd, tty_mode) != 0) { /* XXX if devnam is a symlink, this will change the link */ chmod(devnam, tty_mode); } } - close(ttyfd); - ttyfd = -1; + close(real_ttyfd); + real_ttyfd = -1; } @@ -1274,13 +1259,13 @@ bad_signal(sig) /* - * device_script - run a program to connect or disconnect the - * serial device. + * device_script - run a program to talk to the serial device + * (e.g. to run the connector or disconnector script). */ static int -device_script(program, inout, dont_wait) +device_script(program, in, out, dont_wait) char *program; - int inout; + int in, out; int dont_wait; { int pid; @@ -1299,11 +1284,14 @@ device_script(program, inout, dont_wait) if (pid == 0) { sys_close(); closelog(); - if (inout == 2) { + if (in == 2) { /* aargh!!! */ - int newio = dup(inout); - close(inout); - inout = newio; + int newin = dup(in); + if (in == out) + out = newin; + in = newin; + } else if (out == 2) { + out = dup(out); } if (log_to_fd >= 0) { if (log_to_fd != 2) @@ -1316,18 +1304,28 @@ device_script(program, inout, dont_wait) close(errfd); } } - if (inout != 0) { - dup2(inout, 0); - close(inout); + if (in != 0) { + if (out == 0) + out = dup(out); + dup2(in, 0); + if (in != out) + close(in); + } + if (out != 1) { + dup2(out, 1); + close(out); } - dup2(0, 1); + if (real_ttyfd > 2) + close(real_ttyfd); + if (pty_master > 2) + close(pty_master); + if (pty_slave > 2) + close(pty_slave); setuid(uid); if (getuid() != uid) { error("setuid failed"); exit(1); } - if (ttyfd > 2 && ttyfd != inout) - close(ttyfd); setgid(getgid()); execl("/bin/sh", "sh", "-c", program, (char *)0); error("could not exec /bin/sh: %m"); @@ -1421,6 +1419,8 @@ run_program(prog, args, must_exist, done, arg) close (1); close (2); close (ttyfd); /* tty interface to the ppp device */ + if (real_ttyfd >= 0) + close(real_ttyfd); /* Don't pass handles to the PPP device, even by accident. */ new_fd = open (_PATH_DEVNULL, O_RDWR); @@ -2240,28 +2240,71 @@ dbglog __V((char *fmt, ...)) va_end(pvar); } +/* + * start_charshunt - create a child process to run the character shunt. + */ +static int +start_charshunt(ifd, ofd) + int ifd, ofd; +{ + int cpid; + + cpid = fork(); + if (cpid == -1) { + error("Can't fork process for character shunt: %m"); + return 0; + } + if (cpid == 0) { + /* child */ + close(pty_slave); + setuid(uid); + if (getuid() != uid) + fatal("setuid failed"); + setgid(getgid()); + if (!nodetach) + log_to_fd = -1; + charshunt(ifd, ofd, record_file); + exit(0); + } + charshunt_pid = cpid; + close(pty_master); + pty_master = -1; + ttyfd = pty_slave; + record_child(cpid, "pppd (charshunt)", charshunt_done, NULL); + return 1; +} + +static void +charshunt_done(arg) + void *arg; +{ + charshunt_pid = 0; +} + /* * charshunt - the character shunt, which passes characters between * the pty master side and the serial port (or stdin/stdout). * This runs as the user (not as root). + * (We assume ofd >= ifd which is true the way this gets called. :-). */ static void -charshunt(ttyfd) - int ttyfd; +charshunt(ifd, ofd, record_file) + int ifd, ofd; + char *record_file; { - int ifd, ofd, nfds; - int n; + int n, nfds; fd_set ready, writey; u_char *ibufp, *obufp; int nibuf, nobuf; int flags; int pty_readable, stdin_readable; struct timeval lasttime; + FILE *recordf = NULL; /* * Reset signal handlers. */ - signal(SIGHUP, SIG_DFL); /* Hangup */ + signal(SIGHUP, SIG_IGN); /* Hangup */ signal(SIGINT, SIG_DFL); /* Interrupt */ signal(SIGTERM, SIG_DFL); /* Terminate */ signal(SIGCHLD, SIG_DFL); @@ -2302,14 +2345,14 @@ charshunt(ttyfd) signal(SIGXFSZ, SIG_DFL); #endif - /* work out which fds we're using. */ - if (notty) { - ifd = 0; - ofd = 1; - } else { - ifd = ofd = ttyfd; + /* + * Open the record file if required. + */ + if (record_file != NULL) { + recordf = fopen(record_file, "a"); + if (recordf == NULL) + error("Couldn't create record file %s: %m", record_file); } - nfds = (ofd > pty_master? ifd: pty_master) + 1; /* set all the fds to non-blocking mode */ flags = fcntl(pty_master, F_GETFL); @@ -2319,8 +2362,8 @@ charshunt(ttyfd) flags = fcntl(ifd, F_GETFL); if (flags == -1 || fcntl(ifd, F_SETFL, flags | O_NONBLOCK) == -1) - warn("couldn't set %s to nonblock: %m", (notty? "stdin": "tty")); - if (notty) { + warn("couldn't set %s to nonblock: %m", (ifd==0? "stdin": "tty")); + if (ofd != ifd) { flags = fcntl(ofd, F_GETFL); if (flags == -1 || fcntl(ofd, F_SETFL, flags | O_NONBLOCK) == -1) @@ -2331,6 +2374,8 @@ charshunt(ttyfd) ibufp = obufp = NULL; pty_readable = stdin_readable = 1; gettimeofday(&lasttime, NULL); + nfds = (ofd > pty_master? ofd: pty_master) + 1; + while (nibuf != 0 || nobuf != 0 || pty_readable || stdin_readable) { FD_ZERO(&ready); FD_ZERO(&writey); diff --git a/pppd/sys-linux.c b/pppd/sys-linux.c index ba25a93..1139369 100644 --- a/pppd/sys-linux.c +++ b/pppd/sys-linux.c @@ -281,8 +281,12 @@ void sys_cleanup(void) void sys_close(void) { - close(sock_fd); - sock_fd = -1; + if (sock_fd >= 0) + close(sock_fd); + if (slave_fd >= 0) + close(slave_fd); + if (master_fd >= 0) + close(master_fd); closelog(); } -- 2.39.2