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*52967Smckusick static char sccsid[] = "@(#)startslip.c 5.6 (Berkeley) 03/16/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; 4352906Smckusick int logged_in; 4452906Smckusick int wait_time = 60; /* then back off */ 4552906Smckusick #define MAXTRIES 6 /* w/60 sec and doubling, takes an hour */ 4652906Smckusick #define PIDFILE "/var/run/startslip.pid" 4752906Smckusick 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; 6752906Smckusick int fd = -1; 6852906Smckusick void sighup(); 6952906Smckusick FILE *wfd = NULL, *pfd; 7045365Smckusick char *dialerstring = 0, buf[BUFSIZ]; 7152906Smckusick int first = 1, tries = 0; 7252906Smckusick int pausefirst = 0; 7352906Smckusick int pid; 7452905Skarels #ifdef POSIX 7552905Skarels struct termios t; 7652905Skarels #else 7745365Smckusick struct sgttyb sgtty; 7852905Skarels #endif 7945365Smckusick 8052906Smckusick 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 9052906Smckusick case 'p': 9152906Smckusick pausefirst = atoi(optarg); 9252906Smckusick 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); 11852906Smckusick 11952906Smckusick if (pfd = fopen(PIDFILE, "r")) { 12052906Smckusick pid = 0; 12152906Smckusick fscanf(pfd, "%d", &pid); 12252906Smckusick if (pid > 0) 12352906Smckusick kill(pid, SIGUSR1); 12452906Smckusick fclose(pfd); 12552906Smckusick } 12645365Smckusick restart: 12752906Smckusick logged_in = 0; 12852906Smckusick if (++tries > MAXTRIES) { 12952906Smckusick syslog(LOG_ERR, "exiting after %d tries\n", tries); 13052906Smckusick /* ??? 13152906Smckusick if (first) 13252906Smckusick */ 13352906Smckusick exit(1); 13452906Smckusick } 13552906Smckusick 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; 14252906Smckusick if (fork() > 0) { 14352906Smckusick if (pausefirst) 14452906Smckusick sleep(pausefirst); 14552906Smckusick if (first) 14652906Smckusick printd("parent exit\n"); 14752905Skarels exit(0); 14852906Smckusick } 14952906Smckusick pausefirst = 0; 15052905Skarels #ifdef POSIX 15152905Skarels if (setsid() == -1) 15252905Skarels perror("setsid"); 15352905Skarels #endif 15452906Smckusick pid = getpid(); 15552906Smckusick printd("restart: pid %d: ", pid); 15652906Smckusick if (pfd = fopen(PIDFILE, "w")) { 15752906Smckusick fprintf(pfd, "%d\n", pid); 15852906Smckusick fclose(pfd); 15952906Smckusick } 16052905Skarels if (wfd) { 16152906Smckusick printd("fclose, "); 16252905Skarels fclose(wfd); 16352905Skarels wfd == NULL; 16452905Skarels } 16552905Skarels if (fd >= 0) { 16652906Smckusick printd("close, "); 16745365Smckusick close(fd); 16852905Skarels sleep(5); 16952905Skarels } 17052906Smckusick printd("open"); 17145365Smckusick if ((fd = open(argv[0], O_RDWR)) < 0) { 17245365Smckusick perror(argv[0]); 17352906Smckusick syslog(LOG_ERR, "open %s: %m\n", argv[0]); 17445365Smckusick if (first) 17545365Smckusick exit(1); 17645365Smckusick else { 17752906Smckusick 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)"); 19552906Smckusick 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"); 20252906Smckusick syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]); 20352905Skarels exit(2); 20445365Smckusick } 20552905Skarels cfmakeraw(&t); 20652906Smckusick t.c_iflag &= ~IMAXBEL; 20752905Skarels t.c_cflag |= CRTSCTS; 20852905Skarels cfsetspeed(&t, speed); 20952906Smckusick if (tcsetattr(fd, TCSAFLUSH, &t) < 0) { 21052905Skarels perror("tcsetattr"); 21152906Smckusick syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]); 21252905Skarels if (first) 21352905Skarels exit(2); 21452905Skarels else { 21552906Smckusick sleep(wait_time * tries); 21652905Skarels goto restart; 21752905Skarels } 21852905Skarels } 21952905Skarels #else 22045365Smckusick if (ioctl(fd, TIOCGETP, &sgtty) < 0) { 22145365Smckusick perror("ioctl (TIOCGETP)"); 22252906Smckusick 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)"); 23152906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n", 23245365Smckusick argv[0]); 23352905Skarels if (first) 23452905Skarels exit(2); 23552905Skarels else { 23652906Smckusick sleep(wait_time * tries); 23752905Skarels goto restart; 23852905Skarels } 23945365Smckusick } 24052905Skarels #endif 24152906Smckusick sleep(2); /* wait for flakey line to settle */ 24252906Smckusick if (hup) 24352906Smckusick goto restart; 24452906Smckusick 24552906Smckusick wfd = fdopen(fd, "w+"); 24652906Smckusick if (wfd == NULL) { 24752906Smckusick syslog(LOG_ERR, "can't fdopen slip line\n"); 24852906Smckusick exit(10); 24952906Smckusick } 25052906Smckusick setbuf(wfd, (char *)0); 25152905Skarels if (dialerstring) { 25252905Skarels printd(", send dialstring"); 25352906Smckusick fprintf(wfd, "%s\r", dialerstring); 25452906Smckusick } else 25552906Smckusick putc('\r', wfd); 25652905Skarels printd("\n"); 25752905Skarels 25845365Smckusick /* 25945365Smckusick * Log in 26045365Smckusick */ 26152905Skarels printd("look for login: "); 26252906Smckusick for (;;) { 26352906Smckusick if (getline(buf, BUFSIZ, fd) == 0 || hup) { 26452906Smckusick sleep(wait_time * tries); 26552905Skarels goto restart; 26652906Smckusick } 26745365Smckusick if (bcmp(&buf[1], "ogin:", 5) == 0) { 26845365Smckusick fprintf(wfd, "%s\r", argv[1]); 269*52967Smckusick printd("Sent login: %s\n", argv[1]); 27045365Smckusick continue; 27145365Smckusick } 27245365Smckusick if (bcmp(&buf[1], "assword:", 8) == 0) { 27345365Smckusick fprintf(wfd, "%s\r", argv[2]); 274*52967Smckusick printd("Sent password: %s\n", argv[2]); 27545365Smckusick break; 27645365Smckusick } 27745365Smckusick } 27852906Smckusick 27945365Smckusick /* 28045365Smckusick * Attach 28145365Smckusick */ 28252906Smckusick printd("setd"); 28345367Smckusick disc = SLIPDISC; 28445367Smckusick if (ioctl(fd, TIOCSETD, &disc) < 0) { 28545365Smckusick perror("ioctl(TIOCSETD)"); 28652906Smckusick syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n", 28745365Smckusick argv[0]); 28845365Smckusick exit(1); 28945365Smckusick } 29052905Skarels if (first && debug == 0) { 29145517Smckusick close(0); 29245517Smckusick close(1); 29345517Smckusick close(2); 29445517Smckusick (void) open("/dev/null", O_RDWR); 29545517Smckusick (void) dup2(0, 1); 29645517Smckusick (void) dup2(0, 2); 29745365Smckusick } 29845365Smckusick (void) system("ifconfig sl0 up"); 29952905Skarels printd(", ready\n"); 30052906Smckusick if (!first) 30152906Smckusick syslog(LOG_INFO, "reconnected (%d tries).\n", tries); 30252905Skarels first = 0; 30352906Smckusick tries = 0; 30452906Smckusick logged_in = 1; 30545517Smckusick while (hup == 0) { 30645367Smckusick sigpause(0L); 30752905Skarels printd("sigpause return\n"); 30845517Smckusick } 30945365Smckusick goto restart; 31045365Smckusick } 31145365Smckusick 31252906Smckusick void 31345365Smckusick sighup() 31445365Smckusick { 31545365Smckusick 31645367Smckusick printd("hup\n"); 31752906Smckusick if (hup == 0 && logged_in) 31852906Smckusick syslog(LOG_INFO, "hangup signal\n"); 31945367Smckusick hup = 1; 32045365Smckusick } 32145365Smckusick 32245365Smckusick getline(buf, size, fd) 32345365Smckusick char *buf; 32445365Smckusick int size, fd; 32545365Smckusick { 32645365Smckusick register int i; 32745517Smckusick int ret; 32845365Smckusick 32945365Smckusick size--; 33045365Smckusick for (i = 0; i < size; i++) { 33145367Smckusick if (hup) 33245367Smckusick return (0); 33345517Smckusick if ((ret = read(fd, &buf[i], 1)) == 1) { 33445365Smckusick buf[i] &= 0177; 335*52967Smckusick if (buf[i] == '\r' || buf[i] == '\0') 33645365Smckusick buf[i] = '\n'; 33745365Smckusick if (buf[i] != '\n' && buf[i] != ':') 33845365Smckusick continue; 33945365Smckusick buf[i + 1] = '\0'; 340*52967Smckusick printd("Got %d: \"%s\"\n", i + 1, buf); 34145365Smckusick return (i+1); 34245365Smckusick } 34352906Smckusick if (ret <= 0) { 34452906Smckusick if (ret < 0) 34552906Smckusick perror("getline: read"); 34652906Smckusick else 34752906Smckusick fprintf(stderr, "read returned 0\n"); 34845517Smckusick buf[i] = '\0'; 34945517Smckusick printd("returning 0 after %d: \"%s\"\n", i, buf); 35045517Smckusick return (0); 35145517Smckusick } 35245365Smckusick } 35345367Smckusick return (0); 35445365Smckusick } 35545365Smckusick 35645365Smckusick usage() 35745365Smckusick { 35852906Smckusick fprintf(stderr, "usage: startslip [-d] [-s string] dev user passwd\n"); 35945365Smckusick exit(1); 36045365Smckusick } 361