152905Skarels
245365Smckusick /*-
3*61552Sbostic * Copyright (c) 1990, 1991, 1993
4*61552Sbostic * The Regents of the University of California. All rights reserved.
545365Smckusick *
645365Smckusick * %sccs.include.redist.c%
745365Smckusick */
845365Smckusick
945365Smckusick #ifndef lint
10*61552Sbostic static char copyright[] =
11*61552Sbostic "@(#) Copyright (c) 1990, 1991, 1993\n\
12*61552Sbostic The Regents of the University of California. All rights reserved.\n";
1345365Smckusick #endif /* not lint */
1445365Smckusick
1545365Smckusick #ifndef lint
16*61552Sbostic static char sccsid[] = "@(#)startslip.c 8.1 (Berkeley) 06/05/93";
1745365Smckusick #endif /* not lint */
1845365Smckusick
1945365Smckusick #include <sys/param.h>
2052905Skarels #if BSD >= 199006
2152905Skarels #define POSIX
2252905Skarels #endif
2352905Skarels #ifdef POSIX
2452905Skarels #include <sys/termios.h>
2552905Skarels #include <sys/ioctl.h>
2652905Skarels #else
2745367Smckusick #include <sgtty.h>
2852905Skarels #endif
2945365Smckusick #include <sys/socket.h>
3045365Smckusick #include <sys/syslog.h>
3145365Smckusick #include <netinet/in.h>
3245365Smckusick #include <net/if.h>
3345365Smckusick #include <net/if_slvar.h>
3445365Smckusick #include <netdb.h>
3545365Smckusick #include <errno.h>
3645365Smckusick #include <fcntl.h>
3745365Smckusick #include <stdio.h>
3845367Smckusick #include <signal.h>
3945365Smckusick
4045365Smckusick #define DEFAULT_BAUD B9600
4145365Smckusick int speed = DEFAULT_BAUD;
4259681Shibler #define FC_NONE 0 /* flow control: none */
4359681Shibler #define FC_SW 1 /* flow control: software (XON/XOFF) */
4459681Shibler #define FC_HW 2 /* flow control: hardware (RTS/CTS) */
4559681Shibler int flowcontrol = FC_NONE;
4659681Shibler char *annex;
4745367Smckusick int hup;
4852906Smckusick int logged_in;
4952906Smckusick int wait_time = 60; /* then back off */
5052906Smckusick #define MAXTRIES 6 /* w/60 sec and doubling, takes an hour */
5152906Smckusick #define PIDFILE "/var/run/startslip.pid"
5252906Smckusick
5345365Smckusick #ifdef DEBUG
5445365Smckusick int debug = 1;
5545365Smckusick #undef LOG_ERR
5645365Smckusick #undef LOG_INFO
5745365Smckusick #define syslog fprintf
5845365Smckusick #define LOG_ERR stderr
5945365Smckusick #define LOG_INFO stderr
6045365Smckusick #else
6145365Smckusick int debug = 0;
6245365Smckusick #endif
6345365Smckusick #define printd if (debug) printf
6445365Smckusick
main(argc,argv)6545365Smckusick main(argc, argv)
6645365Smckusick int argc;
6745365Smckusick char **argv;
6845365Smckusick {
6945365Smckusick extern char *optarg;
7045365Smckusick extern int optind;
7158555Selan char *cp, **ap;
7245367Smckusick int ch, disc;
7352906Smckusick int fd = -1;
7452906Smckusick void sighup();
7552906Smckusick FILE *wfd = NULL, *pfd;
7645365Smckusick char *dialerstring = 0, buf[BUFSIZ];
7752906Smckusick int first = 1, tries = 0;
7852906Smckusick int pausefirst = 0;
7952906Smckusick int pid;
8052905Skarels #ifdef POSIX
8152905Skarels struct termios t;
8252905Skarels #else
8345365Smckusick struct sgttyb sgtty;
8452905Skarels #endif
8545365Smckusick
8659681Shibler while ((ch = getopt(argc, argv, "db:s:p:A:F:")) != EOF)
8752905Skarels switch (ch) {
8845365Smckusick case 'd':
8945365Smckusick debug = 1;
9045365Smckusick break;
9152905Skarels #ifdef POSIX
9252905Skarels case 'b':
9352905Skarels speed = atoi(optarg);
9452905Skarels break;
9552905Skarels #endif
9652906Smckusick case 'p':
9752906Smckusick pausefirst = atoi(optarg);
9852906Smckusick break;
9945365Smckusick case 's':
10045365Smckusick dialerstring = optarg;
10145365Smckusick break;
10259681Shibler case 'A':
10359681Shibler annex = optarg;
10459681Shibler break;
10559681Shibler case 'F':
10659681Shibler #ifdef POSIX
10759681Shibler if (strcmp(optarg, "none") == 0)
10859681Shibler flowcontrol = FC_NONE;
10959681Shibler else if (strcmp(optarg, "sw") == 0)
11059681Shibler flowcontrol = FC_SW;
11159681Shibler else if (strcmp(optarg, "hw") == 0)
11259681Shibler flowcontrol = FC_HW;
11359681Shibler else {
11459681Shibler (void)fprintf(stderr,
11559681Shibler "flow control: none, sw, hw\n");
11659681Shibler exit(1);
11759681Shibler }
11859681Shibler break;
11959681Shibler #else
12059681Shibler (void)fprintf(stderr, "flow control not supported\n");
12159681Shibler exit(1);
12259681Shibler #endif
12345365Smckusick case '?':
12445365Smckusick default:
12545365Smckusick usage();
12645365Smckusick }
12745365Smckusick argc -= optind;
12845365Smckusick argv += optind;
12945365Smckusick
13045365Smckusick if (argc != 3)
13145365Smckusick usage();
13245365Smckusick
13345365Smckusick openlog("startslip", LOG_PID, LOG_DAEMON);
13445365Smckusick
13545365Smckusick #if BSD <= 43
13645367Smckusick if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) {
13745365Smckusick ioctl(fd, TIOCNOTTY, 0);
13845365Smckusick close(fd);
13952905Skarels fd = -1;
14045365Smckusick }
14145365Smckusick #endif
14245365Smckusick
14352905Skarels if (debug)
14452905Skarels setbuf(stdout, NULL);
14552906Smckusick
14652906Smckusick if (pfd = fopen(PIDFILE, "r")) {
14752906Smckusick pid = 0;
14852906Smckusick fscanf(pfd, "%d", &pid);
14952906Smckusick if (pid > 0)
15052906Smckusick kill(pid, SIGUSR1);
15152906Smckusick fclose(pfd);
15252906Smckusick }
15345365Smckusick restart:
15452906Smckusick logged_in = 0;
15552906Smckusick if (++tries > MAXTRIES) {
15652906Smckusick syslog(LOG_ERR, "exiting after %d tries\n", tries);
15752906Smckusick /* ???
15852906Smckusick if (first)
15952906Smckusick */
16052906Smckusick exit(1);
16152906Smckusick }
16252906Smckusick
16352905Skarels /*
16452905Skarels * We may get a HUP below, when the parent (session leader/
16552905Skarels * controlling process) exits; ignore HUP until into new session.
16652905Skarels */
16752905Skarels signal(SIGHUP, SIG_IGN);
16845367Smckusick hup = 0;
16952906Smckusick if (fork() > 0) {
17052906Smckusick if (pausefirst)
17152906Smckusick sleep(pausefirst);
17252906Smckusick if (first)
17352906Smckusick printd("parent exit\n");
17452905Skarels exit(0);
17552906Smckusick }
17652906Smckusick pausefirst = 0;
17752905Skarels #ifdef POSIX
17852905Skarels if (setsid() == -1)
17952905Skarels perror("setsid");
18052905Skarels #endif
18152906Smckusick pid = getpid();
18252906Smckusick printd("restart: pid %d: ", pid);
18352906Smckusick if (pfd = fopen(PIDFILE, "w")) {
18452906Smckusick fprintf(pfd, "%d\n", pid);
18552906Smckusick fclose(pfd);
18652906Smckusick }
18752905Skarels if (wfd) {
18852906Smckusick printd("fclose, ");
18952905Skarels fclose(wfd);
19052905Skarels wfd == NULL;
19152905Skarels }
19252905Skarels if (fd >= 0) {
19352906Smckusick printd("close, ");
19445365Smckusick close(fd);
19552905Skarels sleep(5);
19652905Skarels }
19752906Smckusick printd("open");
19845365Smckusick if ((fd = open(argv[0], O_RDWR)) < 0) {
19945365Smckusick perror(argv[0]);
20052906Smckusick syslog(LOG_ERR, "open %s: %m\n", argv[0]);
20145365Smckusick if (first)
20245365Smckusick exit(1);
20345365Smckusick else {
20452906Smckusick sleep(wait_time * tries);
20545365Smckusick goto restart;
20645365Smckusick }
20745365Smckusick }
20852905Skarels printd(" %d", fd);
20945517Smckusick #ifdef TIOCSCTTY
21045517Smckusick if (ioctl(fd, TIOCSCTTY, 0) < 0)
21145517Smckusick perror("ioctl (TIOCSCTTY)");
21245517Smckusick #endif
21352905Skarels signal(SIGHUP, sighup);
21445367Smckusick if (debug) {
21545367Smckusick if (ioctl(fd, TIOCGETD, &disc) < 0)
21645367Smckusick perror("ioctl(TIOCSETD)");
21752905Skarels printf(" (disc was %d)", disc);
21845367Smckusick }
21945367Smckusick disc = TTYDISC;
22045367Smckusick if (ioctl(fd, TIOCSETD, &disc) < 0) {
22145367Smckusick perror("ioctl(TIOCSETD)");
22252906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n",
22345367Smckusick argv[0]);
22445367Smckusick }
22552905Skarels printd(", ioctl");
22652905Skarels #ifdef POSIX
22752905Skarels if (tcgetattr(fd, &t) < 0) {
22852905Skarels perror("tcgetattr");
22952906Smckusick syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]);
23052905Skarels exit(2);
23145365Smckusick }
23252905Skarels cfmakeraw(&t);
23352906Smckusick t.c_iflag &= ~IMAXBEL;
23459681Shibler switch (flowcontrol) {
23559681Shibler case FC_HW:
23659681Shibler t.c_cflag |= (CRTS_IFLOW|CCTS_OFLOW);
23759681Shibler break;
23859681Shibler case FC_SW:
23959681Shibler t.c_iflag |= (IXON|IXOFF);
24059681Shibler break;
24159681Shibler case FC_NONE:
24259681Shibler t.c_cflag &= ~(CRTS_IFLOW|CCTS_OFLOW);
24359681Shibler t.c_iflag &= ~(IXON|IXOFF);
24459681Shibler break;
24559681Shibler }
24652905Skarels cfsetspeed(&t, speed);
24752906Smckusick if (tcsetattr(fd, TCSAFLUSH, &t) < 0) {
24852905Skarels perror("tcsetattr");
24952906Smckusick syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]);
25052905Skarels if (first)
25152905Skarels exit(2);
25252905Skarels else {
25352906Smckusick sleep(wait_time * tries);
25452905Skarels goto restart;
25552905Skarels }
25652905Skarels }
25752905Skarels #else
25845365Smckusick if (ioctl(fd, TIOCGETP, &sgtty) < 0) {
25945365Smckusick perror("ioctl (TIOCGETP)");
26052906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n",
26152905Skarels argv[0]);
26245365Smckusick exit(2);
26345365Smckusick }
26445365Smckusick sgtty.sg_flags = RAW | ANYP;
26545365Smckusick sgtty.sg_erase = sgtty.sg_kill = 0377;
26645365Smckusick sgtty.sg_ispeed = sgtty.sg_ospeed = speed;
26745365Smckusick if (ioctl(fd, TIOCSETP, &sgtty) < 0) {
26845365Smckusick perror("ioctl (TIOCSETP)");
26952906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n",
27045365Smckusick argv[0]);
27152905Skarels if (first)
27252905Skarels exit(2);
27352905Skarels else {
27452906Smckusick sleep(wait_time * tries);
27552905Skarels goto restart;
27652905Skarels }
27745365Smckusick }
27852905Skarels #endif
27952906Smckusick sleep(2); /* wait for flakey line to settle */
28052906Smckusick if (hup)
28152906Smckusick goto restart;
28252906Smckusick
28352906Smckusick wfd = fdopen(fd, "w+");
28452906Smckusick if (wfd == NULL) {
28552906Smckusick syslog(LOG_ERR, "can't fdopen slip line\n");
28652906Smckusick exit(10);
28752906Smckusick }
28852906Smckusick setbuf(wfd, (char *)0);
28952905Skarels if (dialerstring) {
29052905Skarels printd(", send dialstring");
29152906Smckusick fprintf(wfd, "%s\r", dialerstring);
29252906Smckusick } else
29352906Smckusick putc('\r', wfd);
29452905Skarels printd("\n");
29552905Skarels
29645365Smckusick /*
29745365Smckusick * Log in
29845365Smckusick */
29952905Skarels printd("look for login: ");
30052906Smckusick for (;;) {
30152906Smckusick if (getline(buf, BUFSIZ, fd) == 0 || hup) {
30252906Smckusick sleep(wait_time * tries);
30352905Skarels goto restart;
30452906Smckusick }
30559681Shibler if (annex) {
30659681Shibler if (bcmp(buf, annex, strlen(annex)) == 0) {
30759681Shibler fprintf(wfd, "slip\r");
30859681Shibler printd("Sent \"slip\"\n");
30959681Shibler continue;
31059681Shibler }
31159681Shibler if (bcmp(&buf[1], "sername:", 8) == 0) {
31259681Shibler fprintf(wfd, "%s\r", argv[1]);
31359681Shibler printd("Sent login: %s\n", argv[1]);
31459681Shibler continue;
31559681Shibler }
31659681Shibler if (bcmp(&buf[1], "assword:", 8) == 0) {
31759684Shibler fprintf(wfd, "%s\r", argv[2]);
31859684Shibler printd("Sent password: %s\n", argv[2]);
31959681Shibler break;
32059681Shibler }
32159681Shibler } else {
32259681Shibler if (bcmp(&buf[1], "ogin:", 5) == 0) {
32359681Shibler fprintf(wfd, "%s\r", argv[1]);
32459681Shibler printd("Sent login: %s\n", argv[1]);
32559681Shibler continue;
32659681Shibler }
32759681Shibler if (bcmp(&buf[1], "assword:", 8) == 0) {
32859681Shibler fprintf(wfd, "%s\r", argv[2]);
32959681Shibler printd("Sent password: %s\n", argv[2]);
33059681Shibler break;
33159681Shibler }
33259681Shibler }
33345365Smckusick }
33458555Selan
33558555Selan /*
33658555Selan * Security hack. Do not want private information such as the
33758555Selan * password and possible phone number to be left around.
33858555Selan * So we clobber the arguments.
33958555Selan */
34058555Selan for (ap = argv - optind + 1; ap < argv + 3; ap++)
34158555Selan for (cp = *ap; *cp != 0; cp++)
34258555Selan *cp = '\0';
34352906Smckusick
34445365Smckusick /*
34545365Smckusick * Attach
34645365Smckusick */
34752906Smckusick printd("setd");
34845367Smckusick disc = SLIPDISC;
34945367Smckusick if (ioctl(fd, TIOCSETD, &disc) < 0) {
35045365Smckusick perror("ioctl(TIOCSETD)");
35152906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n",
35245365Smckusick argv[0]);
35345365Smckusick exit(1);
35445365Smckusick }
35552905Skarels if (first && debug == 0) {
35645517Smckusick close(0);
35745517Smckusick close(1);
35845517Smckusick close(2);
35945517Smckusick (void) open("/dev/null", O_RDWR);
36045517Smckusick (void) dup2(0, 1);
36145517Smckusick (void) dup2(0, 2);
36245365Smckusick }
36345365Smckusick (void) system("ifconfig sl0 up");
36452905Skarels printd(", ready\n");
36552906Smckusick if (!first)
36652906Smckusick syslog(LOG_INFO, "reconnected (%d tries).\n", tries);
36752905Skarels first = 0;
36852906Smckusick tries = 0;
36952906Smckusick logged_in = 1;
37045517Smckusick while (hup == 0) {
37145367Smckusick sigpause(0L);
37252905Skarels printd("sigpause return\n");
37345517Smckusick }
37445365Smckusick goto restart;
37545365Smckusick }
37645365Smckusick
37752906Smckusick void
sighup()37845365Smckusick sighup()
37945365Smckusick {
38045365Smckusick
38145367Smckusick printd("hup\n");
38252906Smckusick if (hup == 0 && logged_in)
38352906Smckusick syslog(LOG_INFO, "hangup signal\n");
38445367Smckusick hup = 1;
38545365Smckusick }
38645365Smckusick
getline(buf,size,fd)38745365Smckusick getline(buf, size, fd)
38845365Smckusick char *buf;
38945365Smckusick int size, fd;
39045365Smckusick {
39145365Smckusick register int i;
39245517Smckusick int ret;
39345365Smckusick
39445365Smckusick size--;
39545365Smckusick for (i = 0; i < size; i++) {
39645367Smckusick if (hup)
39745367Smckusick return (0);
39845517Smckusick if ((ret = read(fd, &buf[i], 1)) == 1) {
39945365Smckusick buf[i] &= 0177;
40052967Smckusick if (buf[i] == '\r' || buf[i] == '\0')
40145365Smckusick buf[i] = '\n';
40245365Smckusick if (buf[i] != '\n' && buf[i] != ':')
40345365Smckusick continue;
40445365Smckusick buf[i + 1] = '\0';
40552967Smckusick printd("Got %d: \"%s\"\n", i + 1, buf);
40645365Smckusick return (i+1);
40745365Smckusick }
40852906Smckusick if (ret <= 0) {
40952906Smckusick if (ret < 0)
41052906Smckusick perror("getline: read");
41152906Smckusick else
41252906Smckusick fprintf(stderr, "read returned 0\n");
41345517Smckusick buf[i] = '\0';
41445517Smckusick printd("returning 0 after %d: \"%s\"\n", i, buf);
41545517Smckusick return (0);
41645517Smckusick }
41745365Smckusick }
41845367Smckusick return (0);
41945365Smckusick }
42045365Smckusick
usage()42145365Smckusick usage()
42245365Smckusick {
42358289Sbostic (void)fprintf(stderr,
42459681Shibler "usage: startslip [-d] [-b speed] [-s string] [-A annexname] [-F flowcontrol] dev user passwd\n");
42545365Smckusick exit(1);
42645365Smckusick }
427