diff options
Diffstat (limited to 'sbin/slattach/slattach.c')
-rw-r--r-- | sbin/slattach/slattach.c | 599 |
1 files changed, 0 insertions, 599 deletions
diff --git a/sbin/slattach/slattach.c b/sbin/slattach/slattach.c deleted file mode 100644 index afdfce8a2e712..0000000000000 --- a/sbin/slattach/slattach.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Rick Adams. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static const char copyright[] = -"@(#) Copyright (c) 1988 Regents of the University of California.\n\ - All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "from: @(#)slattach.c 4.6 (Berkeley) 6/1/90"; -#endif -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/socket.h> - -#include <err.h> -#include <fcntl.h> -#include <libutil.h> -#include <paths.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <termios.h> -#include <unistd.h> - -#include <net/if.h> -#include <net/slip.h> - -#define DEFAULT_BAUD 9600 - -void sighup_handler(); /* SIGHUP handler */ -void sigint_handler(); /* SIGINT handler */ -void sigterm_handler(); /* SIGTERM handler */ -void sigurg_handler(); /* SIGURG handler */ -void exit_handler(int ret); /* run exit_cmd iff specified upon exit. */ -void setup_line(int cflag); /* configure terminal settings */ -void slip_discipline(); /* switch to slip line discipline */ -void configure_network(); /* configure slip interface */ -void acquire_line(); /* get tty device as controlling terminal */ -static void usage(void); - -int fd = -1; -char *dev = (char *)0; /* path name of the tty (e.g. /dev/tty01) */ -char *dvname; /* basename of dev */ -int locked = 0; /* uucp lock active */ -int flow_control = 0; /* non-zero to enable hardware flow control. */ -int modem_control = HUPCL; /* !CLOCAL+HUPCL iff we watch carrier. */ -int comstate; /* TIOCMGET current state of serial driver */ -int redial_on_startup = 0; /* iff non-zero execute redial_cmd on startup */ -speed_t speed = DEFAULT_BAUD; /* baud rate of tty */ -int slflags = 0; /* compression flags */ -int unit = -1; /* slip device unit number */ -int foreground = 0; /* act as daemon if zero, else don't fork. */ -int keepal = 0; /* keepalive timeout */ -int outfill = 0; /* outfill timeout */ -int sl_unit = -1; /* unit number */ -int uucp_lock = 0; /* do uucp locking */ -int exiting = 0; /* already running exit_handler */ - -struct termios tty; /* tty configuration/state */ - -char tty_path[32]; /* path name of the tty (e.g. /dev/tty01) */ -char pidfilename[40]; /* e.g. /var/run/slattach.tty01.pid */ -char *redial_cmd = 0; /* command to exec upon shutdown. */ -char *config_cmd = 0; /* command to exec if slip unit changes. */ -char *exit_cmd = 0; /* command to exec before exiting. */ - -static void -usage() -{ - fprintf(stderr, "%s\n%s\n%s\n", -"usage: slattach [-acfhLlnz] [-e exit-command] [-K keepalive] [-O outfill]", -" [-r redial-command] [-S unit] [-s baudrate] [-u unit-command]", -" ttyname"); - /* do not exit here */ -} - -int -main(int argc, char **argv) -{ - int option; - - while ((option = getopt(argc, argv, "ace:fhlnr:s:u:zLK:O:S:")) != -1) { - switch (option) { - case 'a': - slflags |= IFF_LINK2; - slflags &= ~IFF_LINK0; - break; - case 'c': - slflags |= IFF_LINK0; - slflags &= ~IFF_LINK2; - break; - case 'e': - exit_cmd = strdup (optarg); - break; - case 'f': - foreground = 1; - break; - case 'h': - flow_control |= CRTSCTS; - break; - case 'l': - modem_control = CLOCAL; /* clear HUPCL too */ - break; - case 'n': - slflags |= IFF_LINK1; - break; - case 'r': - redial_cmd = strdup (optarg); - break; - case 's': - speed = atoi(optarg); - break; - case 'u': - config_cmd = strdup (optarg); - break; - case 'z': - redial_on_startup = 1; - break; - case 'L': - uucp_lock = 1; - break; - case 'K': - keepal = atoi(optarg); - break; - case 'O': - outfill = atoi(optarg); - break; - case 'S': - sl_unit = atoi(optarg); - break; - case '?': - default: - usage(); - exit_handler(1); - } - } - - if (optind == argc - 1) - dev = argv[optind]; - - if (optind < (argc - 1)) - warnx("too many args, first='%s'", argv[optind]); - if (optind > (argc - 1)) - warnx("not enough args"); - if (dev == (char *)0) { - usage(); - exit_handler(2); - } - if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) { - strcpy(tty_path, _PATH_DEV); - strcat(tty_path, "/"); - strncat(tty_path, dev, 10); - dev = tty_path; - } - dvname = strrchr(dev, '/'); /* always succeeds */ - dvname++; /* trailing tty pathname component */ - snprintf(pidfilename, sizeof(pidfilename), - "%sslattach.%s.pid", _PATH_VARRUN, dvname); - printf("%s\n",pidfilename); - - if (!foreground) - daemon(0,0); /* fork, setsid, chdir /, and close std*. */ - /* daemon() closed stderr, so log errors from here on. */ - openlog("slattach",LOG_CONS|LOG_PID,LOG_DAEMON); - - acquire_line(); /* get tty device as controlling terminal */ - setup_line(0); /* configure for slip line discipline */ - slip_discipline(); /* switch to slip line discipline */ - - /* upon INT log a timestamp and exit. */ - if (signal(SIGINT,sigint_handler) == SIG_ERR) - syslog(LOG_NOTICE,"cannot install SIGINT handler: %m"); - /* upon TERM log a timestamp and exit. */ - if (signal(SIGTERM,sigterm_handler) == SIG_ERR) - syslog(LOG_NOTICE,"cannot install SIGTERM handler: %m"); - /* upon HUP redial and reconnect. */ - if (signal(SIGHUP,sighup_handler) == SIG_ERR) - syslog(LOG_NOTICE,"cannot install SIGHUP handler: %m"); - - if (redial_on_startup) - sighup_handler(); - else if (!(modem_control & CLOCAL)) { - if (ioctl(fd, TIOCMGET, &comstate) < 0) - syslog(LOG_NOTICE,"cannot get carrier state: %m"); - if (!(comstate & TIOCM_CD)) { /* check for carrier */ - /* force a redial if no carrier */ - kill (getpid(), SIGHUP); - } else - configure_network(); - } else - configure_network(); /* configure the network if needed. */ - - for (;;) { - sigset_t mask; - sigemptyset(&mask); - sigsuspend(&mask); - } -} - -/* Close all FDs, fork, reopen tty port as 0-2, and make it the - controlling terminal for our process group. */ -void acquire_line() -{ - int ttydisc = TTYDISC; - int oflags; - FILE *pidfile; - - /* reset to tty discipline */ - if (fd >= 0 && ioctl(fd, TIOCSETD, &ttydisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); - exit_handler(1); - } - - (void)close(STDIN_FILENO); /* close FDs before forking. */ - (void)close(STDOUT_FILENO); - (void)close(STDERR_FILENO); - if (fd > 2) - (void)close(fd); - - signal(SIGHUP, SIG_IGN); /* ignore HUP signal when parent dies. */ - if (daemon(0,0)) { /* fork, setsid, chdir /, and close std*. */ - syslog(LOG_ERR, "daemon(0,0): %m"); - exit_handler(1); - } - - while (getppid () != 1) - sleep (1); /* Wait for parent to die. */ - - /* create PID file */ - if((pidfile = fopen(pidfilename, "w"))) { - fprintf(pidfile, "%ld\n", (long)getpid()); - fclose(pidfile); - } - - if (signal(SIGHUP,sighup_handler) == SIG_ERR) /* Re-enable HUP signal */ - syslog(LOG_NOTICE,"cannot install SIGHUP handler: %m"); - - if (uucp_lock) { - /* unlock not needed here, always re-lock with new pid */ - int res; - if ((res = uu_lock(dvname)) != UU_LOCK_OK) { - if (res != UU_LOCK_INUSE) - syslog(LOG_ERR, "uu_lock: %s", uu_lockerr(res)); - syslog(LOG_ERR, "can't lock %s", dev); - exit_handler(1); - } - locked = 1; - } - - if ((fd = open(dev, O_RDWR | O_NONBLOCK, 0)) < 0) { - syslog(LOG_ERR, "open(%s) %m", dev); - exit_handler(1); - } - /* Turn off O_NONBLOCK for dumb redialers, if any. */ - if ((oflags = fcntl(fd, F_GETFL)) == -1) { - syslog(LOG_ERR, "fcntl(F_GETFL) failed: %m"); - exit_handler(1); - } - if (fcntl(fd, F_SETFL, oflags & ~O_NONBLOCK) == -1) { - syslog(LOG_ERR, "fcntl(F_SETFL) failed: %m"); - exit_handler(1); - } - (void)dup2(fd, STDIN_FILENO); - (void)dup2(fd, STDOUT_FILENO); - (void)dup2(fd, STDERR_FILENO); - if (fd > 2) - (void)close (fd); - fd = STDIN_FILENO; - - /* acquire the serial line as a controlling terminal. */ - if (ioctl(fd, TIOCSCTTY, 0) < 0) { - syslog(LOG_ERR,"ioctl(TIOCSCTTY): %m"); - exit_handler(1); - } - /* Make us the foreground process group associated with the - slip line which is our controlling terminal. */ - if (tcsetpgrp(fd, getpid()) < 0) - syslog(LOG_NOTICE,"tcsetpgrp failed: %m"); -} - -/* Set the tty flags and set DTR. */ -/* Call as setup_line(CLOCAL) to force clocal assertion. */ -void setup_line(int cflag) -{ - tty.c_lflag = tty.c_iflag = tty.c_oflag = 0; - tty.c_cflag = CREAD | CS8 | flow_control | modem_control | cflag; - cfsetispeed(&tty, speed); - cfsetospeed(&tty, speed); - /* set the line speed and flow control */ - if (tcsetattr(fd, TCSAFLUSH, &tty) < 0) { - syslog(LOG_ERR, "tcsetattr(TCSAFLUSH): %m"); - exit_handler(1); - } - /* set data terminal ready */ - if (ioctl(fd, TIOCSDTR) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSDTR): %m"); - exit_handler(1); - } -} - -/* Put the line in slip discipline. */ -void slip_discipline() -{ - struct ifreq ifr; - int slipdisc = SLIPDISC; - int s, tmp_unit = -1; - - /* Switch to slip line discipline. */ - if (ioctl(fd, TIOCSETD, &slipdisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); - exit_handler(1); - } - - if (sl_unit >= 0 && ioctl(fd, SLIOCSUNIT, &sl_unit) < 0) { - syslog(LOG_ERR, "ioctl(SLIOCSUNIT): %m"); - exit_handler(1); - } - - /* find out what unit number we were assigned */ - if (ioctl(fd, SLIOCGUNIT, (caddr_t)&tmp_unit) < 0) { - syslog(LOG_ERR, "ioctl(SLIOCGUNIT): %m"); - exit_handler(1); - } - - if (tmp_unit < 0) { - syslog(LOG_ERR, "bad unit (%d) from ioctl(SLIOCGUNIT)",tmp_unit); - exit_handler(1); - } - - if (keepal > 0) { - signal(SIGURG, sigurg_handler); - if (ioctl(fd, SLIOCSKEEPAL, &keepal) < 0) { - syslog(LOG_ERR, "ioctl(SLIOCSKEEPAL): %m"); - exit_handler(1); - } - } - if (outfill > 0 && ioctl(fd, SLIOCSOUTFILL, &outfill) < 0) { - syslog(LOG_ERR, "ioctl(SLIOCSOUTFILL): %m"); - exit_handler(1); - } - - /* open a socket as the handle to the interface */ - s = socket(AF_INET, SOCK_DGRAM, 0); - if (s < 0) { - syslog(LOG_ERR, "socket: %m"); - exit_handler(1); - } - sprintf(ifr.ifr_name, "sl%d", tmp_unit); - - /* get the flags for the interface */ - if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { - syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); - exit_handler(1); - } - - /* Assert any compression or no-icmp flags. */ -#define SLMASK (~(IFF_LINK0 | IFF_LINK1 | IFF_LINK2)) - ifr.ifr_flags &= SLMASK; - ifr.ifr_flags |= slflags; - if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { - syslog(LOG_ERR, "ioctl (SIOCSIFFLAGS): %m"); - exit_handler(1); - } - close(s); -} - -/* configure the interface, e.g. by passing the unit number to a script. */ -void configure_network() -{ - int new_unit; - - /* find out what unit number we were assigned */ - if (ioctl(fd, SLIOCGUNIT, (caddr_t)&new_unit) < 0) { - syslog(LOG_ERR, "ioctl(SLIOCGUNIT): %m"); - exit_handler(1); - } - /* iff the unit number changes either invoke config_cmd or punt. */ - if (config_cmd) { - char *s; - s = (char*) malloc(strlen(config_cmd) + 32); - if (s == NULL) { - syslog(LOG_ERR, "malloc failed"); - exit(1); - } - sprintf (s, "%s %d %d", config_cmd, unit, new_unit); - syslog(LOG_NOTICE, "configuring %s (sl%d):", dev, unit); - syslog(LOG_NOTICE, " '%s'", s); - system(s); - free (s); - unit = new_unit; - } else { - /* don't compare unit numbers if this is the first time to attach. */ - if (unit < 0) - unit = new_unit; - if (new_unit != unit) { - syslog(LOG_ERR, - "slip unit changed from sl%d to sl%d, but no -u CMD was specified!", - unit, new_unit); - exit_handler(1); - } - syslog(LOG_NOTICE,"sl%d connected to %s at %d baud",unit,dev,speed); - } -} - -/* sighup_handler() is invoked when carrier drops, eg. before redial. */ -void sighup_handler() -{ - if(exiting) return; - - if (redial_cmd == NULL) { - syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); exiting", dev, unit); - exit_handler(1); - } -again: - /* invoke a shell for redial_cmd or punt. */ - if (*redial_cmd) { /* Non-empty redial command */ - syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); running '%s'", - dev, unit, redial_cmd); - acquire_line(); /* reopen dead line */ - setup_line(CLOCAL); - if (locked) { - if (uucp_lock) - uu_unlock(dvname); /* for redial */ - locked = 0; - } - if (system(redial_cmd)) - goto again; - if (uucp_lock) { - int res; - if ((res = uu_lock(dvname)) != UU_LOCK_OK) { - if (res != UU_LOCK_INUSE) - syslog(LOG_ERR, "uu_lock: %s", uu_lockerr(res)); - syslog(LOG_ERR, "can't relock %s after %s, aborting", - dev, redial_cmd); - exit_handler(1); - } - locked = 1; - } - /* Now check again for carrier (dial command is done): */ - if (!(modem_control & CLOCAL)) { - tty.c_cflag &= ~CLOCAL; - if (tcsetattr(fd, TCSAFLUSH, &tty) < 0) { - syslog(LOG_ERR, "tcsetattr(TCSAFLUSH): %m"); - exit_handler(1); - } - ioctl(fd, TIOCMGET, &comstate); - if (!(comstate & TIOCM_CD)) { /* check for carrier */ - /* force a redial if no carrier */ - goto again; - } - } else - setup_line(0); - } else { /* Empty redial command */ - syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); reestablish connection", - dev, unit); - acquire_line(); /* reopen dead line */ - setup_line(0); /* restore ospeed from hangup (B0) */ - /* If modem control, just wait for carrier before attaching. - If no modem control, just fall through immediately. */ - if (!(modem_control & CLOCAL)) { - int carrier = 0; - - syslog(LOG_NOTICE, "waiting for carrier on %s (sl%d)", - dev, unit); - /* Now wait for carrier before attaching line. */ - /* We must poll since CLOCAL prevents signal. */ - while (! carrier) { - sleep(2); - ioctl(fd, TIOCMGET, &comstate); - if (comstate & TIOCM_CD) - carrier = 1; - } - syslog(LOG_NOTICE, "carrier now present on %s (sl%d)", - dev, unit); - } - } - slip_discipline(); - configure_network(); -} -/* Signal handler for SIGINT. We just log and exit. */ -void sigint_handler() -{ - if(exiting) return; - syslog(LOG_NOTICE,"SIGINT on %s (sl%d); exiting",dev,unit); - exit_handler(0); -} -/* Signal handler for SIGURG. */ -void sigurg_handler() -{ - int ttydisc = TTYDISC; - - signal(SIGURG, SIG_IGN); - if(exiting) return; - syslog(LOG_NOTICE,"SIGURG on %s (sl%d); hangup",dev,unit); - if (ioctl(fd, TIOCSETD, &ttydisc) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); - exit_handler(1); - } - cfsetospeed(&tty, B0); - if (tcsetattr(fd, TCSANOW, &tty) < 0) { - syslog(LOG_ERR, "tcsetattr(TCSANOW): %m"); - exit_handler(1); - } - /* Need to go to sighup handler in any case */ - if (modem_control & CLOCAL) - kill (getpid(), SIGHUP); - -} -/* Signal handler for SIGTERM. We just log and exit. */ -void sigterm_handler() -{ - if(exiting) return; - syslog(LOG_NOTICE,"SIGTERM on %s (sl%d); exiting",dev,unit); - exit_handler(0); -} -/* Run config_cmd if specified before exiting. */ -void exit_handler(int ret) -{ - if(exiting) return; - exiting = 1; - /* - * First close the slip line in case exit_cmd wants it (like to hang - * up a modem or something). - */ - if (fd != -1) - close(fd); - if (uucp_lock && locked) - uu_unlock(dvname); - - /* Remove the PID file */ - (void)unlink(pidfilename); - - if (config_cmd) { - char *s; - s = (char*) malloc(strlen(config_cmd) + 32); - if (s == NULL) { - syslog(LOG_ERR, "malloc failed"); - exit(1); - } - sprintf (s, "%s %d -1", config_cmd, unit); - syslog(LOG_NOTICE, "deconfiguring %s (sl%d):", dev, unit); - syslog(LOG_NOTICE, " '%s'", s); - system(s); - free (s); - } - /* invoke a shell for exit_cmd. */ - if (exit_cmd) { - syslog(LOG_NOTICE,"exiting after running %s", exit_cmd); - system(exit_cmd); - } - exit(ret); -} - -/* local variables: */ -/* c-indent-level: 8 */ -/* c-argdecl-indent: 0 */ -/* c-label-offset: -8 */ -/* c-continued-statement-offset: 8 */ -/* c-brace-offset: 0 */ -/* comment-column: 32 */ -/* end: */ |