1
2 /*-
3 * Copyright (c) 1990, 1991, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * %sccs.include.redist.c%
7 */
8
9 #ifndef lint
10 static char copyright[] =
11 "@(#) Copyright (c) 1990, 1991, 1993\n\
12 The Regents of the University of California. All rights reserved.\n";
13 #endif /* not lint */
14
15 #ifndef lint
16 static char sccsid[] = "@(#)startslip.c 8.1 (Berkeley) 06/05/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 #define FC_NONE 0 /* flow control: none */
43 #define FC_SW 1 /* flow control: software (XON/XOFF) */
44 #define FC_HW 2 /* flow control: hardware (RTS/CTS) */
45 int flowcontrol = FC_NONE;
46 char *annex;
47 int hup;
48 int logged_in;
49 int wait_time = 60; /* then back off */
50 #define MAXTRIES 6 /* w/60 sec and doubling, takes an hour */
51 #define PIDFILE "/var/run/startslip.pid"
52
53 #ifdef DEBUG
54 int debug = 1;
55 #undef LOG_ERR
56 #undef LOG_INFO
57 #define syslog fprintf
58 #define LOG_ERR stderr
59 #define LOG_INFO stderr
60 #else
61 int debug = 0;
62 #endif
63 #define printd if (debug) printf
64
main(argc,argv)65 main(argc, argv)
66 int argc;
67 char **argv;
68 {
69 extern char *optarg;
70 extern int optind;
71 char *cp, **ap;
72 int ch, disc;
73 int fd = -1;
74 void sighup();
75 FILE *wfd = NULL, *pfd;
76 char *dialerstring = 0, buf[BUFSIZ];
77 int first = 1, tries = 0;
78 int pausefirst = 0;
79 int pid;
80 #ifdef POSIX
81 struct termios t;
82 #else
83 struct sgttyb sgtty;
84 #endif
85
86 while ((ch = getopt(argc, argv, "db:s:p:A:F:")) != EOF)
87 switch (ch) {
88 case 'd':
89 debug = 1;
90 break;
91 #ifdef POSIX
92 case 'b':
93 speed = atoi(optarg);
94 break;
95 #endif
96 case 'p':
97 pausefirst = atoi(optarg);
98 break;
99 case 's':
100 dialerstring = optarg;
101 break;
102 case 'A':
103 annex = optarg;
104 break;
105 case 'F':
106 #ifdef POSIX
107 if (strcmp(optarg, "none") == 0)
108 flowcontrol = FC_NONE;
109 else if (strcmp(optarg, "sw") == 0)
110 flowcontrol = FC_SW;
111 else if (strcmp(optarg, "hw") == 0)
112 flowcontrol = FC_HW;
113 else {
114 (void)fprintf(stderr,
115 "flow control: none, sw, hw\n");
116 exit(1);
117 }
118 break;
119 #else
120 (void)fprintf(stderr, "flow control not supported\n");
121 exit(1);
122 #endif
123 case '?':
124 default:
125 usage();
126 }
127 argc -= optind;
128 argv += optind;
129
130 if (argc != 3)
131 usage();
132
133 openlog("startslip", LOG_PID, LOG_DAEMON);
134
135 #if BSD <= 43
136 if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) {
137 ioctl(fd, TIOCNOTTY, 0);
138 close(fd);
139 fd = -1;
140 }
141 #endif
142
143 if (debug)
144 setbuf(stdout, NULL);
145
146 if (pfd = fopen(PIDFILE, "r")) {
147 pid = 0;
148 fscanf(pfd, "%d", &pid);
149 if (pid > 0)
150 kill(pid, SIGUSR1);
151 fclose(pfd);
152 }
153 restart:
154 logged_in = 0;
155 if (++tries > MAXTRIES) {
156 syslog(LOG_ERR, "exiting after %d tries\n", tries);
157 /* ???
158 if (first)
159 */
160 exit(1);
161 }
162
163 /*
164 * We may get a HUP below, when the parent (session leader/
165 * controlling process) exits; ignore HUP until into new session.
166 */
167 signal(SIGHUP, SIG_IGN);
168 hup = 0;
169 if (fork() > 0) {
170 if (pausefirst)
171 sleep(pausefirst);
172 if (first)
173 printd("parent exit\n");
174 exit(0);
175 }
176 pausefirst = 0;
177 #ifdef POSIX
178 if (setsid() == -1)
179 perror("setsid");
180 #endif
181 pid = getpid();
182 printd("restart: pid %d: ", pid);
183 if (pfd = fopen(PIDFILE, "w")) {
184 fprintf(pfd, "%d\n", pid);
185 fclose(pfd);
186 }
187 if (wfd) {
188 printd("fclose, ");
189 fclose(wfd);
190 wfd == NULL;
191 }
192 if (fd >= 0) {
193 printd("close, ");
194 close(fd);
195 sleep(5);
196 }
197 printd("open");
198 if ((fd = open(argv[0], O_RDWR)) < 0) {
199 perror(argv[0]);
200 syslog(LOG_ERR, "open %s: %m\n", argv[0]);
201 if (first)
202 exit(1);
203 else {
204 sleep(wait_time * tries);
205 goto restart;
206 }
207 }
208 printd(" %d", fd);
209 #ifdef TIOCSCTTY
210 if (ioctl(fd, TIOCSCTTY, 0) < 0)
211 perror("ioctl (TIOCSCTTY)");
212 #endif
213 signal(SIGHUP, sighup);
214 if (debug) {
215 if (ioctl(fd, TIOCGETD, &disc) < 0)
216 perror("ioctl(TIOCSETD)");
217 printf(" (disc was %d)", disc);
218 }
219 disc = TTYDISC;
220 if (ioctl(fd, TIOCSETD, &disc) < 0) {
221 perror("ioctl(TIOCSETD)");
222 syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n",
223 argv[0]);
224 }
225 printd(", ioctl");
226 #ifdef POSIX
227 if (tcgetattr(fd, &t) < 0) {
228 perror("tcgetattr");
229 syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]);
230 exit(2);
231 }
232 cfmakeraw(&t);
233 t.c_iflag &= ~IMAXBEL;
234 switch (flowcontrol) {
235 case FC_HW:
236 t.c_cflag |= (CRTS_IFLOW|CCTS_OFLOW);
237 break;
238 case FC_SW:
239 t.c_iflag |= (IXON|IXOFF);
240 break;
241 case FC_NONE:
242 t.c_cflag &= ~(CRTS_IFLOW|CCTS_OFLOW);
243 t.c_iflag &= ~(IXON|IXOFF);
244 break;
245 }
246 cfsetspeed(&t, speed);
247 if (tcsetattr(fd, TCSAFLUSH, &t) < 0) {
248 perror("tcsetattr");
249 syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]);
250 if (first)
251 exit(2);
252 else {
253 sleep(wait_time * tries);
254 goto restart;
255 }
256 }
257 #else
258 if (ioctl(fd, TIOCGETP, &sgtty) < 0) {
259 perror("ioctl (TIOCGETP)");
260 syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n",
261 argv[0]);
262 exit(2);
263 }
264 sgtty.sg_flags = RAW | ANYP;
265 sgtty.sg_erase = sgtty.sg_kill = 0377;
266 sgtty.sg_ispeed = sgtty.sg_ospeed = speed;
267 if (ioctl(fd, TIOCSETP, &sgtty) < 0) {
268 perror("ioctl (TIOCSETP)");
269 syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n",
270 argv[0]);
271 if (first)
272 exit(2);
273 else {
274 sleep(wait_time * tries);
275 goto restart;
276 }
277 }
278 #endif
279 sleep(2); /* wait for flakey line to settle */
280 if (hup)
281 goto restart;
282
283 wfd = fdopen(fd, "w+");
284 if (wfd == NULL) {
285 syslog(LOG_ERR, "can't fdopen slip line\n");
286 exit(10);
287 }
288 setbuf(wfd, (char *)0);
289 if (dialerstring) {
290 printd(", send dialstring");
291 fprintf(wfd, "%s\r", dialerstring);
292 } else
293 putc('\r', wfd);
294 printd("\n");
295
296 /*
297 * Log in
298 */
299 printd("look for login: ");
300 for (;;) {
301 if (getline(buf, BUFSIZ, fd) == 0 || hup) {
302 sleep(wait_time * tries);
303 goto restart;
304 }
305 if (annex) {
306 if (bcmp(buf, annex, strlen(annex)) == 0) {
307 fprintf(wfd, "slip\r");
308 printd("Sent \"slip\"\n");
309 continue;
310 }
311 if (bcmp(&buf[1], "sername:", 8) == 0) {
312 fprintf(wfd, "%s\r", argv[1]);
313 printd("Sent login: %s\n", argv[1]);
314 continue;
315 }
316 if (bcmp(&buf[1], "assword:", 8) == 0) {
317 fprintf(wfd, "%s\r", argv[2]);
318 printd("Sent password: %s\n", argv[2]);
319 break;
320 }
321 } else {
322 if (bcmp(&buf[1], "ogin:", 5) == 0) {
323 fprintf(wfd, "%s\r", argv[1]);
324 printd("Sent login: %s\n", argv[1]);
325 continue;
326 }
327 if (bcmp(&buf[1], "assword:", 8) == 0) {
328 fprintf(wfd, "%s\r", argv[2]);
329 printd("Sent password: %s\n", argv[2]);
330 break;
331 }
332 }
333 }
334
335 /*
336 * Security hack. Do not want private information such as the
337 * password and possible phone number to be left around.
338 * So we clobber the arguments.
339 */
340 for (ap = argv - optind + 1; ap < argv + 3; ap++)
341 for (cp = *ap; *cp != 0; cp++)
342 *cp = '\0';
343
344 /*
345 * Attach
346 */
347 printd("setd");
348 disc = SLIPDISC;
349 if (ioctl(fd, TIOCSETD, &disc) < 0) {
350 perror("ioctl(TIOCSETD)");
351 syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n",
352 argv[0]);
353 exit(1);
354 }
355 if (first && debug == 0) {
356 close(0);
357 close(1);
358 close(2);
359 (void) open("/dev/null", O_RDWR);
360 (void) dup2(0, 1);
361 (void) dup2(0, 2);
362 }
363 (void) system("ifconfig sl0 up");
364 printd(", ready\n");
365 if (!first)
366 syslog(LOG_INFO, "reconnected (%d tries).\n", tries);
367 first = 0;
368 tries = 0;
369 logged_in = 1;
370 while (hup == 0) {
371 sigpause(0L);
372 printd("sigpause return\n");
373 }
374 goto restart;
375 }
376
377 void
sighup()378 sighup()
379 {
380
381 printd("hup\n");
382 if (hup == 0 && logged_in)
383 syslog(LOG_INFO, "hangup signal\n");
384 hup = 1;
385 }
386
getline(buf,size,fd)387 getline(buf, size, fd)
388 char *buf;
389 int size, fd;
390 {
391 register int i;
392 int ret;
393
394 size--;
395 for (i = 0; i < size; i++) {
396 if (hup)
397 return (0);
398 if ((ret = read(fd, &buf[i], 1)) == 1) {
399 buf[i] &= 0177;
400 if (buf[i] == '\r' || buf[i] == '\0')
401 buf[i] = '\n';
402 if (buf[i] != '\n' && buf[i] != ':')
403 continue;
404 buf[i + 1] = '\0';
405 printd("Got %d: \"%s\"\n", i + 1, buf);
406 return (i+1);
407 }
408 if (ret <= 0) {
409 if (ret < 0)
410 perror("getline: read");
411 else
412 fprintf(stderr, "read returned 0\n");
413 buf[i] = '\0';
414 printd("returning 0 after %d: \"%s\"\n", i, buf);
415 return (0);
416 }
417 }
418 return (0);
419 }
420
usage()421 usage()
422 {
423 (void)fprintf(stderr,
424 "usage: startslip [-d] [-b speed] [-s string] [-A annexname] [-F flowcontrol] dev user passwd\n");
425 exit(1);
426 }
427