xref: /original-bsd/sbin/startslip/startslip.c (revision 6a39c8ab)
1 
2 /*-
3  * Copyright (c) 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 char copyright[] =
11 "@(#) Copyright (c) 1990, 1991 The Regents of the University of California.\n\
12  All rights reserved.\n";
13 #endif /* not lint */
14 
15 #ifndef lint
16 static char sccsid[] = "@(#)startslip.c	5.6 (Berkeley) 03/16/92";
17 #endif /* not lint */
18 
19 #include <sys/param.h>
20 #if BSD >= 199006
21 #define POSIX
22 #endif
23 #ifdef POSIX
24 #include <sys/termios.h>
25 #include <sys/ioctl.h>
26 #else
27 #include <sgtty.h>
28 #endif
29 #include <sys/socket.h>
30 #include <sys/syslog.h>
31 #include <netinet/in.h>
32 #include <net/if.h>
33 #include <net/if_slvar.h>
34 #include <netdb.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <signal.h>
39 
40 #define DEFAULT_BAUD    B9600
41 int     speed = DEFAULT_BAUD;
42 int	hup;
43 int	logged_in;
44 int	wait_time = 60;		/* then back off */
45 #define	MAXTRIES	6	/* w/60 sec and doubling, takes an hour */
46 #define	PIDFILE		"/var/run/startslip.pid"
47 
48 #ifdef DEBUG
49 int	debug = 1;
50 #undef LOG_ERR
51 #undef LOG_INFO
52 #define syslog fprintf
53 #define LOG_ERR stderr
54 #define LOG_INFO stderr
55 #else
56 int	debug = 0;
57 #endif
58 #define	printd	if (debug) printf
59 
60 main(argc, argv)
61 	int argc;
62 	char **argv;
63 {
64 	extern char *optarg;
65 	extern int optind;
66 	int ch, disc;
67 	int fd = -1;
68 	void sighup();
69 	FILE *wfd = NULL, *pfd;
70 	char *dialerstring = 0, buf[BUFSIZ];
71 	int first = 1, tries = 0;
72 	int pausefirst = 0;
73 	int pid;
74 #ifdef POSIX
75 	struct termios t;
76 #else
77 	struct sgttyb sgtty;
78 #endif
79 
80 	while ((ch = getopt(argc, argv, "db:s:p:")) != EOF)
81 		switch (ch) {
82 		case 'd':
83 			debug = 1;
84 			break;
85 #ifdef POSIX
86 		case 'b':
87 			speed = atoi(optarg);
88 			break;
89 #endif
90 		case 'p':
91 			pausefirst = atoi(optarg);
92 			break;
93 		case 's':
94 			dialerstring = optarg;
95 			break;
96 		case '?':
97 		default:
98 			usage();
99 		}
100 	argc -= optind;
101 	argv += optind;
102 
103 	if (argc != 3)
104 		usage();
105 
106 	openlog("startslip", LOG_PID, LOG_DAEMON);
107 
108 #if BSD <= 43
109 	if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) {
110 		ioctl(fd, TIOCNOTTY, 0);
111 		close(fd);
112 		fd = -1;
113 	}
114 #endif
115 
116 	if (debug)
117 		setbuf(stdout, NULL);
118 
119 	if (pfd = fopen(PIDFILE, "r")) {
120 		pid = 0;
121 		fscanf(pfd, "%d", &pid);
122 		if (pid > 0)
123 			kill(pid, SIGUSR1);
124 		fclose(pfd);
125 	}
126 restart:
127 	logged_in = 0;
128 	if (++tries > MAXTRIES) {
129 		syslog(LOG_ERR, "exiting after %d tries\n", tries);
130 		/* ???
131 		if (first)
132 		*/
133 			exit(1);
134 	}
135 
136 	/*
137 	 * We may get a HUP below, when the parent (session leader/
138 	 * controlling process) exits; ignore HUP until into new session.
139 	 */
140 	signal(SIGHUP, SIG_IGN);
141 	hup = 0;
142 	if (fork() > 0) {
143 		if (pausefirst)
144 			sleep(pausefirst);
145 		if (first)
146 			printd("parent exit\n");
147 		exit(0);
148 	}
149 	pausefirst = 0;
150 #ifdef POSIX
151 	if (setsid() == -1)
152 		perror("setsid");
153 #endif
154 	pid = getpid();
155 	printd("restart: pid %d: ", pid);
156 	if (pfd = fopen(PIDFILE, "w")) {
157 		fprintf(pfd, "%d\n", pid);
158 		fclose(pfd);
159 	}
160 	if (wfd) {
161 		printd("fclose, ");
162 		fclose(wfd);
163 		wfd == NULL;
164 	}
165 	if (fd >= 0) {
166 		printd("close, ");
167 		close(fd);
168 		sleep(5);
169 	}
170 	printd("open");
171 	if ((fd = open(argv[0], O_RDWR)) < 0) {
172 		perror(argv[0]);
173 		syslog(LOG_ERR, "open %s: %m\n", argv[0]);
174 		if (first)
175 			exit(1);
176 		else {
177 			sleep(wait_time * tries);
178 			goto restart;
179 		}
180 	}
181 	printd(" %d", fd);
182 #ifdef TIOCSCTTY
183 	if (ioctl(fd, TIOCSCTTY, 0) < 0)
184 		perror("ioctl (TIOCSCTTY)");
185 #endif
186 	signal(SIGHUP, sighup);
187 	if (debug) {
188 		if (ioctl(fd, TIOCGETD, &disc) < 0)
189 			perror("ioctl(TIOCSETD)");
190 		printf(" (disc was %d)", disc);
191 	}
192 	disc = TTYDISC;
193 	if (ioctl(fd, TIOCSETD, &disc) < 0) {
194 	        perror("ioctl(TIOCSETD)");
195 		syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n",
196 		    argv[0]);
197 	}
198 	printd(", ioctl");
199 #ifdef POSIX
200 	if (tcgetattr(fd, &t) < 0) {
201 		perror("tcgetattr");
202 		syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]);
203 	        exit(2);
204 	}
205 	cfmakeraw(&t);
206 	t.c_iflag &= ~IMAXBEL;
207 	t.c_cflag |= CRTSCTS;
208 	cfsetspeed(&t, speed);
209 	if (tcsetattr(fd, TCSAFLUSH, &t) < 0) {
210 		perror("tcsetattr");
211 		syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]);
212 	        if (first)
213 			exit(2);
214 		else {
215 			sleep(wait_time * tries);
216 			goto restart;
217 		}
218 	}
219 #else
220 	if (ioctl(fd, TIOCGETP, &sgtty) < 0) {
221 	        perror("ioctl (TIOCGETP)");
222 		syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n",
223 		    argv[0]);
224 	        exit(2);
225 	}
226 	sgtty.sg_flags = RAW | ANYP;
227 	sgtty.sg_erase = sgtty.sg_kill = 0377;
228 	sgtty.sg_ispeed = sgtty.sg_ospeed = speed;
229 	if (ioctl(fd, TIOCSETP, &sgtty) < 0) {
230 	        perror("ioctl (TIOCSETP)");
231 		syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n",
232 		    argv[0]);
233 	        if (first)
234 			exit(2);
235 		else {
236 			sleep(wait_time * tries);
237 			goto restart;
238 		}
239 	}
240 #endif
241 	sleep(2);		/* wait for flakey line to settle */
242 	if (hup)
243 		goto restart;
244 
245 	wfd = fdopen(fd, "w+");
246 	if (wfd == NULL) {
247 		syslog(LOG_ERR, "can't fdopen slip line\n");
248 		exit(10);
249 	}
250 	setbuf(wfd, (char *)0);
251 	if (dialerstring) {
252 		printd(", send dialstring");
253 		fprintf(wfd, "%s\r", dialerstring);
254 	} else
255 		putc('\r', wfd);
256 	printd("\n");
257 
258 	/*
259 	 * Log in
260 	 */
261 	printd("look for login: ");
262 	for (;;) {
263 		if (getline(buf, BUFSIZ, fd) == 0 || hup) {
264 			sleep(wait_time * tries);
265 			goto restart;
266 		}
267 	        if (bcmp(&buf[1], "ogin:", 5) == 0) {
268 	                fprintf(wfd, "%s\r", argv[1]);
269 			printd("Sent login: %s\n", argv[1]);
270 	                continue;
271 	        }
272 	        if (bcmp(&buf[1], "assword:", 8) == 0) {
273 	                fprintf(wfd, "%s\r", argv[2]);
274 			printd("Sent password: %s\n", argv[2]);
275 	                break;
276 	        }
277 	}
278 
279 	/*
280 	 * Attach
281 	 */
282 	printd("setd");
283 	disc = SLIPDISC;
284 	if (ioctl(fd, TIOCSETD, &disc) < 0) {
285 	        perror("ioctl(TIOCSETD)");
286 		syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n",
287 		    argv[0]);
288 	        exit(1);
289 	}
290 	if (first && debug == 0) {
291 		close(0);
292 		close(1);
293 		close(2);
294 		(void) open("/dev/null", O_RDWR);
295 		(void) dup2(0, 1);
296 		(void) dup2(0, 2);
297 	}
298 	(void) system("ifconfig sl0 up");
299 	printd(", ready\n");
300 	if (!first)
301 		syslog(LOG_INFO, "reconnected (%d tries).\n", tries);
302 	first = 0;
303 	tries = 0;
304 	logged_in = 1;
305 	while (hup == 0) {
306 		sigpause(0L);
307 		printd("sigpause return\n");
308 	}
309 	goto restart;
310 }
311 
312 void
313 sighup()
314 {
315 
316 	printd("hup\n");
317 	if (hup == 0 && logged_in)
318 		syslog(LOG_INFO, "hangup signal\n");
319 	hup = 1;
320 }
321 
322 getline(buf, size, fd)
323 	char *buf;
324 	int size, fd;
325 {
326 	register int i;
327 	int ret;
328 
329 	size--;
330 	for (i = 0; i < size; i++) {
331 		if (hup)
332 			return (0);
333 	        if ((ret = read(fd, &buf[i], 1)) == 1) {
334 	                buf[i] &= 0177;
335 	                if (buf[i] == '\r' || buf[i] == '\0')
336 	                        buf[i] = '\n';
337 	                if (buf[i] != '\n' && buf[i] != ':')
338 	                        continue;
339 	                buf[i + 1] = '\0';
340 			printd("Got %d: \"%s\"\n", i + 1, buf);
341 	                return (i+1);
342 	        }
343 		if (ret <= 0) {
344 			if (ret < 0)
345 				perror("getline: read");
346 			else
347 				fprintf(stderr, "read returned 0\n");
348 			buf[i] = '\0';
349 			printd("returning 0 after %d: \"%s\"\n", i, buf);
350 			return (0);
351 		}
352 	}
353 	return (0);
354 }
355 
356 usage()
357 {
358 	fprintf(stderr, "usage: startslip [-d] [-s string] dev user passwd\n");
359 	exit(1);
360 }
361