xref: /csrg-svn/sbin/startslip/startslip.c (revision 52906)
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