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