152905Skarels 245365Smckusick /*- 345365Smckusick * Copyright (c) 1990 The Regents of the University of California. 445365Smckusick * All rights reserved. 545365Smckusick * 645365Smckusick * %sccs.include.redist.c% 745365Smckusick */ 845365Smckusick 945365Smckusick #ifndef lint 1045365Smckusick char copyright[] = 1152905Skarels "@(#) Copyright (c) 1990, 1991 The Regents of the University of California.\n\ 1245365Smckusick All rights reserved.\n"; 1345365Smckusick #endif /* not lint */ 1445365Smckusick 1545365Smckusick #ifndef lint 16*52906Smckusick static char sccsid[] = "@(#)startslip.c 5.5 (Berkeley) 03/09/92"; 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; 4245367Smckusick int hup; 43*52906Smckusick int logged_in; 44*52906Smckusick int wait_time = 60; /* then back off */ 45*52906Smckusick #define MAXTRIES 6 /* w/60 sec and doubling, takes an hour */ 46*52906Smckusick #define PIDFILE "/var/run/startslip.pid" 47*52906Smckusick 4845365Smckusick #ifdef DEBUG 4945365Smckusick int debug = 1; 5045365Smckusick #undef LOG_ERR 5145365Smckusick #undef LOG_INFO 5245365Smckusick #define syslog fprintf 5345365Smckusick #define LOG_ERR stderr 5445365Smckusick #define LOG_INFO stderr 5545365Smckusick #else 5645365Smckusick int debug = 0; 5745365Smckusick #endif 5845365Smckusick #define printd if (debug) printf 5945365Smckusick 6045365Smckusick main(argc, argv) 6145365Smckusick int argc; 6245365Smckusick char **argv; 6345365Smckusick { 6445365Smckusick extern char *optarg; 6545365Smckusick extern int optind; 6645367Smckusick int ch, disc; 67*52906Smckusick int fd = -1; 68*52906Smckusick void sighup(); 69*52906Smckusick FILE *wfd = NULL, *pfd; 7045365Smckusick char *dialerstring = 0, buf[BUFSIZ]; 71*52906Smckusick int first = 1, tries = 0; 72*52906Smckusick int pausefirst = 0; 73*52906Smckusick int pid; 7452905Skarels #ifdef POSIX 7552905Skarels struct termios t; 7652905Skarels #else 7745365Smckusick struct sgttyb sgtty; 7852905Skarels #endif 7945365Smckusick 80*52906Smckusick while ((ch = getopt(argc, argv, "db:s:p:")) != EOF) 8152905Skarels switch (ch) { 8245365Smckusick case 'd': 8345365Smckusick debug = 1; 8445365Smckusick break; 8552905Skarels #ifdef POSIX 8652905Skarels case 'b': 8752905Skarels speed = atoi(optarg); 8852905Skarels break; 8952905Skarels #endif 90*52906Smckusick case 'p': 91*52906Smckusick pausefirst = atoi(optarg); 92*52906Smckusick break; 9345365Smckusick case 's': 9445365Smckusick dialerstring = optarg; 9545365Smckusick break; 9645365Smckusick case '?': 9745365Smckusick default: 9845365Smckusick usage(); 9945365Smckusick } 10045365Smckusick argc -= optind; 10145365Smckusick argv += optind; 10245365Smckusick 10345365Smckusick if (argc != 3) 10445365Smckusick usage(); 10545365Smckusick 10645365Smckusick openlog("startslip", LOG_PID, LOG_DAEMON); 10745365Smckusick 10845365Smckusick #if BSD <= 43 10945367Smckusick if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) { 11045365Smckusick ioctl(fd, TIOCNOTTY, 0); 11145365Smckusick close(fd); 11252905Skarels fd = -1; 11345365Smckusick } 11445365Smckusick #endif 11545365Smckusick 11652905Skarels if (debug) 11752905Skarels setbuf(stdout, NULL); 118*52906Smckusick 119*52906Smckusick if (pfd = fopen(PIDFILE, "r")) { 120*52906Smckusick pid = 0; 121*52906Smckusick fscanf(pfd, "%d", &pid); 122*52906Smckusick if (pid > 0) 123*52906Smckusick kill(pid, SIGUSR1); 124*52906Smckusick fclose(pfd); 125*52906Smckusick } 12645365Smckusick restart: 127*52906Smckusick logged_in = 0; 128*52906Smckusick if (++tries > MAXTRIES) { 129*52906Smckusick syslog(LOG_ERR, "exiting after %d tries\n", tries); 130*52906Smckusick /* ??? 131*52906Smckusick if (first) 132*52906Smckusick */ 133*52906Smckusick exit(1); 134*52906Smckusick } 135*52906Smckusick 13652905Skarels /* 13752905Skarels * We may get a HUP below, when the parent (session leader/ 13852905Skarels * controlling process) exits; ignore HUP until into new session. 13952905Skarels */ 14052905Skarels signal(SIGHUP, SIG_IGN); 14145367Smckusick hup = 0; 142*52906Smckusick if (fork() > 0) { 143*52906Smckusick if (pausefirst) 144*52906Smckusick sleep(pausefirst); 145*52906Smckusick if (first) 146*52906Smckusick printd("parent exit\n"); 14752905Skarels exit(0); 148*52906Smckusick } 149*52906Smckusick pausefirst = 0; 15052905Skarels #ifdef POSIX 15152905Skarels if (setsid() == -1) 15252905Skarels perror("setsid"); 15352905Skarels #endif 154*52906Smckusick pid = getpid(); 155*52906Smckusick printd("restart: pid %d: ", pid); 156*52906Smckusick if (pfd = fopen(PIDFILE, "w")) { 157*52906Smckusick fprintf(pfd, "%d\n", pid); 158*52906Smckusick fclose(pfd); 159*52906Smckusick } 16052905Skarels if (wfd) { 161*52906Smckusick printd("fclose, "); 16252905Skarels fclose(wfd); 16352905Skarels wfd == NULL; 16452905Skarels } 16552905Skarels if (fd >= 0) { 166*52906Smckusick printd("close, "); 16745365Smckusick close(fd); 16852905Skarels sleep(5); 16952905Skarels } 170*52906Smckusick printd("open"); 17145365Smckusick if ((fd = open(argv[0], O_RDWR)) < 0) { 17245365Smckusick perror(argv[0]); 173*52906Smckusick syslog(LOG_ERR, "open %s: %m\n", argv[0]); 17445365Smckusick if (first) 17545365Smckusick exit(1); 17645365Smckusick else { 177*52906Smckusick sleep(wait_time * tries); 17845365Smckusick goto restart; 17945365Smckusick } 18045365Smckusick } 18152905Skarels printd(" %d", fd); 18245517Smckusick #ifdef TIOCSCTTY 18345517Smckusick if (ioctl(fd, TIOCSCTTY, 0) < 0) 18445517Smckusick perror("ioctl (TIOCSCTTY)"); 18545517Smckusick #endif 18652905Skarels signal(SIGHUP, sighup); 18745367Smckusick if (debug) { 18845367Smckusick if (ioctl(fd, TIOCGETD, &disc) < 0) 18945367Smckusick perror("ioctl(TIOCSETD)"); 19052905Skarels printf(" (disc was %d)", disc); 19145367Smckusick } 19245367Smckusick disc = TTYDISC; 19345367Smckusick if (ioctl(fd, TIOCSETD, &disc) < 0) { 19445367Smckusick perror("ioctl(TIOCSETD)"); 195*52906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n", 19645367Smckusick argv[0]); 19745367Smckusick } 19852905Skarels printd(", ioctl"); 19952905Skarels #ifdef POSIX 20052905Skarels if (tcgetattr(fd, &t) < 0) { 20152905Skarels perror("tcgetattr"); 202*52906Smckusick syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]); 20352905Skarels exit(2); 20445365Smckusick } 20552905Skarels cfmakeraw(&t); 206*52906Smckusick t.c_iflag &= ~IMAXBEL; 20752905Skarels t.c_cflag |= CRTSCTS; 20852905Skarels cfsetspeed(&t, speed); 209*52906Smckusick if (tcsetattr(fd, TCSAFLUSH, &t) < 0) { 21052905Skarels perror("tcsetattr"); 211*52906Smckusick syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]); 21252905Skarels if (first) 21352905Skarels exit(2); 21452905Skarels else { 215*52906Smckusick sleep(wait_time * tries); 21652905Skarels goto restart; 21752905Skarels } 21852905Skarels } 21952905Skarels #else 22045365Smckusick if (ioctl(fd, TIOCGETP, &sgtty) < 0) { 22145365Smckusick perror("ioctl (TIOCGETP)"); 222*52906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n", 22352905Skarels argv[0]); 22445365Smckusick exit(2); 22545365Smckusick } 22645365Smckusick sgtty.sg_flags = RAW | ANYP; 22745365Smckusick sgtty.sg_erase = sgtty.sg_kill = 0377; 22845365Smckusick sgtty.sg_ispeed = sgtty.sg_ospeed = speed; 22945365Smckusick if (ioctl(fd, TIOCSETP, &sgtty) < 0) { 23045365Smckusick perror("ioctl (TIOCSETP)"); 231*52906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n", 23245365Smckusick argv[0]); 23352905Skarels if (first) 23452905Skarels exit(2); 23552905Skarels else { 236*52906Smckusick sleep(wait_time * tries); 23752905Skarels goto restart; 23852905Skarels } 23945365Smckusick } 24052905Skarels #endif 241*52906Smckusick sleep(2); /* wait for flakey line to settle */ 242*52906Smckusick if (hup) 243*52906Smckusick goto restart; 244*52906Smckusick 245*52906Smckusick wfd = fdopen(fd, "w+"); 246*52906Smckusick if (wfd == NULL) { 247*52906Smckusick syslog(LOG_ERR, "can't fdopen slip line\n"); 248*52906Smckusick exit(10); 249*52906Smckusick } 250*52906Smckusick setbuf(wfd, (char *)0); 25152905Skarels if (dialerstring) { 25252905Skarels printd(", send dialstring"); 253*52906Smckusick fprintf(wfd, "%s\r", dialerstring); 254*52906Smckusick } else 255*52906Smckusick putc('\r', wfd); 25652905Skarels printd("\n"); 25752905Skarels 25845365Smckusick /* 25945365Smckusick * Log in 26045365Smckusick */ 26152905Skarels printd("look for login: "); 262*52906Smckusick for (;;) { 263*52906Smckusick if (getline(buf, BUFSIZ, fd) == 0 || hup) { 264*52906Smckusick sleep(wait_time * tries); 26552905Skarels goto restart; 266*52906Smckusick } 26745365Smckusick if (bcmp(&buf[1], "ogin:", 5) == 0) { 26845365Smckusick fprintf(wfd, "%s\r", argv[1]); 26945365Smckusick continue; 27045365Smckusick } 27145365Smckusick if (bcmp(&buf[1], "assword:", 8) == 0) { 27245365Smckusick fprintf(wfd, "%s\r", argv[2]); 27345365Smckusick break; 27445365Smckusick } 27545365Smckusick } 276*52906Smckusick 27745365Smckusick /* 27845365Smckusick * Attach 27945365Smckusick */ 280*52906Smckusick printd("setd"); 28145367Smckusick disc = SLIPDISC; 28245367Smckusick if (ioctl(fd, TIOCSETD, &disc) < 0) { 28345365Smckusick perror("ioctl(TIOCSETD)"); 284*52906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n", 28545365Smckusick argv[0]); 28645365Smckusick exit(1); 28745365Smckusick } 28852905Skarels if (first && debug == 0) { 28945517Smckusick close(0); 29045517Smckusick close(1); 29145517Smckusick close(2); 29245517Smckusick (void) open("/dev/null", O_RDWR); 29345517Smckusick (void) dup2(0, 1); 29445517Smckusick (void) dup2(0, 2); 29545365Smckusick } 29645365Smckusick (void) system("ifconfig sl0 up"); 29752905Skarels printd(", ready\n"); 298*52906Smckusick if (!first) 299*52906Smckusick syslog(LOG_INFO, "reconnected (%d tries).\n", tries); 30052905Skarels first = 0; 301*52906Smckusick tries = 0; 302*52906Smckusick logged_in = 1; 30345517Smckusick while (hup == 0) { 30445367Smckusick sigpause(0L); 30552905Skarels printd("sigpause return\n"); 30645517Smckusick } 30745365Smckusick goto restart; 30845365Smckusick } 30945365Smckusick 310*52906Smckusick void 31145365Smckusick sighup() 31245365Smckusick { 31345365Smckusick 31445367Smckusick printd("hup\n"); 315*52906Smckusick if (hup == 0 && logged_in) 316*52906Smckusick syslog(LOG_INFO, "hangup signal\n"); 31745367Smckusick hup = 1; 31845365Smckusick } 31945365Smckusick 32045365Smckusick getline(buf, size, fd) 32145365Smckusick char *buf; 32245365Smckusick int size, fd; 32345365Smckusick { 32445365Smckusick register int i; 32545517Smckusick int ret; 32645365Smckusick 32745365Smckusick size--; 32845365Smckusick for (i = 0; i < size; i++) { 32945367Smckusick if (hup) 33045367Smckusick return (0); 33145517Smckusick if ((ret = read(fd, &buf[i], 1)) == 1) { 33245365Smckusick buf[i] &= 0177; 33345365Smckusick if (buf[i] == '\r') 33445365Smckusick buf[i] = '\n'; 33545365Smckusick if (buf[i] != '\n' && buf[i] != ':') 33645365Smckusick continue; 33745365Smckusick buf[i + 1] = '\0'; 33845365Smckusick if (debug) 33945367Smckusick fprintf(stderr, "Got %d: \"%s\"\n", i + 1, buf); 34045365Smckusick return (i+1); 34145365Smckusick } 342*52906Smckusick if (ret <= 0) { 343*52906Smckusick if (ret < 0) 344*52906Smckusick perror("getline: read"); 345*52906Smckusick else 346*52906Smckusick fprintf(stderr, "read returned 0\n"); 34745517Smckusick buf[i] = '\0'; 34845517Smckusick printd("returning 0 after %d: \"%s\"\n", i, buf); 34945517Smckusick return (0); 35045517Smckusick } 35145365Smckusick } 35245367Smckusick return (0); 35345365Smckusick } 35445365Smckusick 35545365Smckusick usage() 35645365Smckusick { 357*52906Smckusick fprintf(stderr, "usage: startslip [-d] [-s string] dev user passwd\n"); 35845365Smckusick exit(1); 35945365Smckusick } 360