xref: /original-bsd/sbin/startslip/startslip.c (revision 4670e840)
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.8 (Berkeley) 03/08/93";
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 	char *cp, **ap;
67 	int ch, disc;
68 	int fd = -1;
69 	void sighup();
70 	FILE *wfd = NULL, *pfd;
71 	char *dialerstring = 0, buf[BUFSIZ];
72 	int first = 1, tries = 0;
73 	int pausefirst = 0;
74 	int pid;
75 #ifdef POSIX
76 	struct termios t;
77 #else
78 	struct sgttyb sgtty;
79 #endif
80 
81 	while ((ch = getopt(argc, argv, "db:s:p:")) != EOF)
82 		switch (ch) {
83 		case 'd':
84 			debug = 1;
85 			break;
86 #ifdef POSIX
87 		case 'b':
88 			speed = atoi(optarg);
89 			break;
90 #endif
91 		case 'p':
92 			pausefirst = atoi(optarg);
93 			break;
94 		case 's':
95 			dialerstring = optarg;
96 			break;
97 		case '?':
98 		default:
99 			usage();
100 		}
101 	argc -= optind;
102 	argv += optind;
103 
104 	if (argc != 3)
105 		usage();
106 
107 	openlog("startslip", LOG_PID, LOG_DAEMON);
108 
109 #if BSD <= 43
110 	if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) {
111 		ioctl(fd, TIOCNOTTY, 0);
112 		close(fd);
113 		fd = -1;
114 	}
115 #endif
116 
117 	if (debug)
118 		setbuf(stdout, NULL);
119 
120 	if (pfd = fopen(PIDFILE, "r")) {
121 		pid = 0;
122 		fscanf(pfd, "%d", &pid);
123 		if (pid > 0)
124 			kill(pid, SIGUSR1);
125 		fclose(pfd);
126 	}
127 restart:
128 	logged_in = 0;
129 	if (++tries > MAXTRIES) {
130 		syslog(LOG_ERR, "exiting after %d tries\n", tries);
131 		/* ???
132 		if (first)
133 		*/
134 			exit(1);
135 	}
136 
137 	/*
138 	 * We may get a HUP below, when the parent (session leader/
139 	 * controlling process) exits; ignore HUP until into new session.
140 	 */
141 	signal(SIGHUP, SIG_IGN);
142 	hup = 0;
143 	if (fork() > 0) {
144 		if (pausefirst)
145 			sleep(pausefirst);
146 		if (first)
147 			printd("parent exit\n");
148 		exit(0);
149 	}
150 	pausefirst = 0;
151 #ifdef POSIX
152 	if (setsid() == -1)
153 		perror("setsid");
154 #endif
155 	pid = getpid();
156 	printd("restart: pid %d: ", pid);
157 	if (pfd = fopen(PIDFILE, "w")) {
158 		fprintf(pfd, "%d\n", pid);
159 		fclose(pfd);
160 	}
161 	if (wfd) {
162 		printd("fclose, ");
163 		fclose(wfd);
164 		wfd == NULL;
165 	}
166 	if (fd >= 0) {
167 		printd("close, ");
168 		close(fd);
169 		sleep(5);
170 	}
171 	printd("open");
172 	if ((fd = open(argv[0], O_RDWR)) < 0) {
173 		perror(argv[0]);
174 		syslog(LOG_ERR, "open %s: %m\n", argv[0]);
175 		if (first)
176 			exit(1);
177 		else {
178 			sleep(wait_time * tries);
179 			goto restart;
180 		}
181 	}
182 	printd(" %d", fd);
183 #ifdef TIOCSCTTY
184 	if (ioctl(fd, TIOCSCTTY, 0) < 0)
185 		perror("ioctl (TIOCSCTTY)");
186 #endif
187 	signal(SIGHUP, sighup);
188 	if (debug) {
189 		if (ioctl(fd, TIOCGETD, &disc) < 0)
190 			perror("ioctl(TIOCSETD)");
191 		printf(" (disc was %d)", disc);
192 	}
193 	disc = TTYDISC;
194 	if (ioctl(fd, TIOCSETD, &disc) < 0) {
195 	        perror("ioctl(TIOCSETD)");
196 		syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n",
197 		    argv[0]);
198 	}
199 	printd(", ioctl");
200 #ifdef POSIX
201 	if (tcgetattr(fd, &t) < 0) {
202 		perror("tcgetattr");
203 		syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]);
204 	        exit(2);
205 	}
206 	cfmakeraw(&t);
207 	t.c_iflag &= ~IMAXBEL;
208 	t.c_cflag |= CRTSCTS;
209 	cfsetspeed(&t, speed);
210 	if (tcsetattr(fd, TCSAFLUSH, &t) < 0) {
211 		perror("tcsetattr");
212 		syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]);
213 	        if (first)
214 			exit(2);
215 		else {
216 			sleep(wait_time * tries);
217 			goto restart;
218 		}
219 	}
220 #else
221 	if (ioctl(fd, TIOCGETP, &sgtty) < 0) {
222 	        perror("ioctl (TIOCGETP)");
223 		syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n",
224 		    argv[0]);
225 	        exit(2);
226 	}
227 	sgtty.sg_flags = RAW | ANYP;
228 	sgtty.sg_erase = sgtty.sg_kill = 0377;
229 	sgtty.sg_ispeed = sgtty.sg_ospeed = speed;
230 	if (ioctl(fd, TIOCSETP, &sgtty) < 0) {
231 	        perror("ioctl (TIOCSETP)");
232 		syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n",
233 		    argv[0]);
234 	        if (first)
235 			exit(2);
236 		else {
237 			sleep(wait_time * tries);
238 			goto restart;
239 		}
240 	}
241 #endif
242 	sleep(2);		/* wait for flakey line to settle */
243 	if (hup)
244 		goto restart;
245 
246 	wfd = fdopen(fd, "w+");
247 	if (wfd == NULL) {
248 		syslog(LOG_ERR, "can't fdopen slip line\n");
249 		exit(10);
250 	}
251 	setbuf(wfd, (char *)0);
252 	if (dialerstring) {
253 		printd(", send dialstring");
254 		fprintf(wfd, "%s\r", dialerstring);
255 	} else
256 		putc('\r', wfd);
257 	printd("\n");
258 
259 	/*
260 	 * Log in
261 	 */
262 	printd("look for login: ");
263 	for (;;) {
264 		if (getline(buf, BUFSIZ, fd) == 0 || hup) {
265 			sleep(wait_time * tries);
266 			goto restart;
267 		}
268 	        if (bcmp(&buf[1], "ogin:", 5) == 0) {
269 	                fprintf(wfd, "%s\r", argv[1]);
270 			printd("Sent login: %s\n", argv[1]);
271 	                continue;
272 	        }
273 	        if (bcmp(&buf[1], "assword:", 8) == 0) {
274 	                fprintf(wfd, "%s\r", argv[2]);
275 			printd("Sent password: %s\n", argv[2]);
276 	                break;
277 	        }
278 	}
279 
280 	/*
281 	 * Security hack.  Do not want private information such as the
282 	 * password and possible phone number to be left around.
283 	 * So we clobber the arguments.
284 	 */
285 	for (ap = argv - optind + 1; ap < argv + 3; ap++)
286 		for (cp = *ap; *cp != 0; cp++)
287 			*cp = '\0';
288 
289 	/*
290 	 * Attach
291 	 */
292 	printd("setd");
293 	disc = SLIPDISC;
294 	if (ioctl(fd, TIOCSETD, &disc) < 0) {
295 	        perror("ioctl(TIOCSETD)");
296 		syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n",
297 		    argv[0]);
298 	        exit(1);
299 	}
300 	if (first && debug == 0) {
301 		close(0);
302 		close(1);
303 		close(2);
304 		(void) open("/dev/null", O_RDWR);
305 		(void) dup2(0, 1);
306 		(void) dup2(0, 2);
307 	}
308 	(void) system("ifconfig sl0 up");
309 	printd(", ready\n");
310 	if (!first)
311 		syslog(LOG_INFO, "reconnected (%d tries).\n", tries);
312 	first = 0;
313 	tries = 0;
314 	logged_in = 1;
315 	while (hup == 0) {
316 		sigpause(0L);
317 		printd("sigpause return\n");
318 	}
319 	goto restart;
320 }
321 
322 void
323 sighup()
324 {
325 
326 	printd("hup\n");
327 	if (hup == 0 && logged_in)
328 		syslog(LOG_INFO, "hangup signal\n");
329 	hup = 1;
330 }
331 
332 getline(buf, size, fd)
333 	char *buf;
334 	int size, fd;
335 {
336 	register int i;
337 	int ret;
338 
339 	size--;
340 	for (i = 0; i < size; i++) {
341 		if (hup)
342 			return (0);
343 	        if ((ret = read(fd, &buf[i], 1)) == 1) {
344 	                buf[i] &= 0177;
345 	                if (buf[i] == '\r' || buf[i] == '\0')
346 	                        buf[i] = '\n';
347 	                if (buf[i] != '\n' && buf[i] != ':')
348 	                        continue;
349 	                buf[i + 1] = '\0';
350 			printd("Got %d: \"%s\"\n", i + 1, buf);
351 	                return (i+1);
352 	        }
353 		if (ret <= 0) {
354 			if (ret < 0)
355 				perror("getline: read");
356 			else
357 				fprintf(stderr, "read returned 0\n");
358 			buf[i] = '\0';
359 			printd("returning 0 after %d: \"%s\"\n", i, buf);
360 			return (0);
361 		}
362 	}
363 	return (0);
364 }
365 
366 usage()
367 {
368 	(void)fprintf(stderr,
369 	    "usage: startslip [-d] [-b speed] [-s string] dev user passwd\n");
370 	exit(1);
371 }
372