Commit | Line | Data |
---|---|---|
b652be8f | 1 | |
61ba62c5 KM |
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[] = | |
b652be8f | 11 | "@(#) Copyright (c) 1990, 1991 The Regents of the University of California.\n\ |
61ba62c5 KM |
12 | All rights reserved.\n"; |
13 | #endif /* not lint */ | |
14 | ||
15 | #ifndef lint | |
1fedb40b | 16 | static char sccsid[] = "@(#)startslip.c 5.6 (Berkeley) %G%"; |
61ba62c5 KM |
17 | #endif /* not lint */ |
18 | ||
19 | #include <sys/param.h> | |
b652be8f MK |
20 | #if BSD >= 199006 |
21 | #define POSIX | |
22 | #endif | |
23 | #ifdef POSIX | |
24 | #include <sys/termios.h> | |
25 | #include <sys/ioctl.h> | |
26 | #else | |
9bdb4436 | 27 | #include <sgtty.h> |
b652be8f | 28 | #endif |
61ba62c5 KM |
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> | |
61ba62c5 KM |
34 | #include <netdb.h> |
35 | #include <errno.h> | |
36 | #include <fcntl.h> | |
37 | #include <stdio.h> | |
9bdb4436 | 38 | #include <signal.h> |
61ba62c5 KM |
39 | |
40 | #define DEFAULT_BAUD B9600 | |
41 | int speed = DEFAULT_BAUD; | |
9bdb4436 | 42 | int hup; |
4f73d838 KM |
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 | ||
61ba62c5 KM |
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; | |
9bdb4436 | 66 | int ch, disc; |
4f73d838 KM |
67 | int fd = -1; |
68 | void sighup(); | |
69 | FILE *wfd = NULL, *pfd; | |
61ba62c5 | 70 | char *dialerstring = 0, buf[BUFSIZ]; |
4f73d838 KM |
71 | int first = 1, tries = 0; |
72 | int pausefirst = 0; | |
73 | int pid; | |
b652be8f MK |
74 | #ifdef POSIX |
75 | struct termios t; | |
76 | #else | |
61ba62c5 | 77 | struct sgttyb sgtty; |
b652be8f | 78 | #endif |
61ba62c5 | 79 | |
4f73d838 | 80 | while ((ch = getopt(argc, argv, "db:s:p:")) != EOF) |
b652be8f | 81 | switch (ch) { |
61ba62c5 KM |
82 | case 'd': |
83 | debug = 1; | |
84 | break; | |
b652be8f MK |
85 | #ifdef POSIX |
86 | case 'b': | |
87 | speed = atoi(optarg); | |
88 | break; | |
89 | #endif | |
4f73d838 KM |
90 | case 'p': |
91 | pausefirst = atoi(optarg); | |
92 | break; | |
61ba62c5 KM |
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 | |
9bdb4436 | 109 | if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) { |
61ba62c5 KM |
110 | ioctl(fd, TIOCNOTTY, 0); |
111 | close(fd); | |
b652be8f | 112 | fd = -1; |
61ba62c5 KM |
113 | } |
114 | #endif | |
115 | ||
b652be8f MK |
116 | if (debug) |
117 | setbuf(stdout, NULL); | |
4f73d838 KM |
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 | } | |
61ba62c5 | 126 | restart: |
4f73d838 KM |
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 | ||
b652be8f MK |
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); | |
9bdb4436 | 141 | hup = 0; |
4f73d838 KM |
142 | if (fork() > 0) { |
143 | if (pausefirst) | |
144 | sleep(pausefirst); | |
145 | if (first) | |
146 | printd("parent exit\n"); | |
b652be8f | 147 | exit(0); |
4f73d838 KM |
148 | } |
149 | pausefirst = 0; | |
b652be8f MK |
150 | #ifdef POSIX |
151 | if (setsid() == -1) | |
152 | perror("setsid"); | |
dc20c96e | 153 | #endif |
4f73d838 KM |
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 | } | |
b652be8f | 160 | if (wfd) { |
4f73d838 | 161 | printd("fclose, "); |
b652be8f MK |
162 | fclose(wfd); |
163 | wfd == NULL; | |
164 | } | |
165 | if (fd >= 0) { | |
4f73d838 | 166 | printd("close, "); |
b652be8f MK |
167 | close(fd); |
168 | sleep(5); | |
169 | } | |
4f73d838 | 170 | printd("open"); |
61ba62c5 KM |
171 | if ((fd = open(argv[0], O_RDWR)) < 0) { |
172 | perror(argv[0]); | |
4f73d838 | 173 | syslog(LOG_ERR, "open %s: %m\n", argv[0]); |
61ba62c5 KM |
174 | if (first) |
175 | exit(1); | |
176 | else { | |
4f73d838 | 177 | sleep(wait_time * tries); |
61ba62c5 KM |
178 | goto restart; |
179 | } | |
180 | } | |
b652be8f | 181 | printd(" %d", fd); |
dc20c96e KM |
182 | #ifdef TIOCSCTTY |
183 | if (ioctl(fd, TIOCSCTTY, 0) < 0) | |
184 | perror("ioctl (TIOCSCTTY)"); | |
185 | #endif | |
b652be8f | 186 | signal(SIGHUP, sighup); |
9bdb4436 KM |
187 | if (debug) { |
188 | if (ioctl(fd, TIOCGETD, &disc) < 0) | |
189 | perror("ioctl(TIOCSETD)"); | |
b652be8f | 190 | printf(" (disc was %d)", disc); |
9bdb4436 KM |
191 | } |
192 | disc = TTYDISC; | |
193 | if (ioctl(fd, TIOCSETD, &disc) < 0) { | |
194 | perror("ioctl(TIOCSETD)"); | |
4f73d838 | 195 | syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n", |
9bdb4436 KM |
196 | argv[0]); |
197 | } | |
b652be8f MK |
198 | printd(", ioctl"); |
199 | #ifdef POSIX | |
200 | if (tcgetattr(fd, &t) < 0) { | |
201 | perror("tcgetattr"); | |
4f73d838 | 202 | syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]); |
b652be8f MK |
203 | exit(2); |
204 | } | |
205 | cfmakeraw(&t); | |
4f73d838 | 206 | t.c_iflag &= ~IMAXBEL; |
b652be8f MK |
207 | t.c_cflag |= CRTSCTS; |
208 | cfsetspeed(&t, speed); | |
4f73d838 | 209 | if (tcsetattr(fd, TCSAFLUSH, &t) < 0) { |
b652be8f | 210 | perror("tcsetattr"); |
4f73d838 | 211 | syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]); |
b652be8f MK |
212 | if (first) |
213 | exit(2); | |
214 | else { | |
4f73d838 | 215 | sleep(wait_time * tries); |
b652be8f MK |
216 | goto restart; |
217 | } | |
61ba62c5 | 218 | } |
b652be8f | 219 | #else |
61ba62c5 KM |
220 | if (ioctl(fd, TIOCGETP, &sgtty) < 0) { |
221 | perror("ioctl (TIOCGETP)"); | |
4f73d838 | 222 | syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n", |
b652be8f | 223 | argv[0]); |
61ba62c5 KM |
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)"); | |
4f73d838 | 231 | syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n", |
61ba62c5 | 232 | argv[0]); |
b652be8f MK |
233 | if (first) |
234 | exit(2); | |
235 | else { | |
4f73d838 | 236 | sleep(wait_time * tries); |
b652be8f MK |
237 | goto restart; |
238 | } | |
61ba62c5 | 239 | } |
b652be8f | 240 | #endif |
4f73d838 KM |
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); | |
b652be8f MK |
251 | if (dialerstring) { |
252 | printd(", send dialstring"); | |
4f73d838 KM |
253 | fprintf(wfd, "%s\r", dialerstring); |
254 | } else | |
255 | putc('\r', wfd); | |
b652be8f MK |
256 | printd("\n"); |
257 | ||
61ba62c5 KM |
258 | /* |
259 | * Log in | |
260 | */ | |
b652be8f | 261 | printd("look for login: "); |
4f73d838 KM |
262 | for (;;) { |
263 | if (getline(buf, BUFSIZ, fd) == 0 || hup) { | |
264 | sleep(wait_time * tries); | |
b652be8f | 265 | goto restart; |
4f73d838 | 266 | } |
61ba62c5 KM |
267 | if (bcmp(&buf[1], "ogin:", 5) == 0) { |
268 | fprintf(wfd, "%s\r", argv[1]); | |
1fedb40b | 269 | printd("Sent login: %s\n", argv[1]); |
61ba62c5 KM |
270 | continue; |
271 | } | |
272 | if (bcmp(&buf[1], "assword:", 8) == 0) { | |
273 | fprintf(wfd, "%s\r", argv[2]); | |
1fedb40b | 274 | printd("Sent password: %s\n", argv[2]); |
61ba62c5 KM |
275 | break; |
276 | } | |
277 | } | |
4f73d838 | 278 | |
61ba62c5 KM |
279 | /* |
280 | * Attach | |
281 | */ | |
4f73d838 | 282 | printd("setd"); |
9bdb4436 KM |
283 | disc = SLIPDISC; |
284 | if (ioctl(fd, TIOCSETD, &disc) < 0) { | |
61ba62c5 | 285 | perror("ioctl(TIOCSETD)"); |
4f73d838 | 286 | syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n", |
61ba62c5 KM |
287 | argv[0]); |
288 | exit(1); | |
289 | } | |
b652be8f | 290 | if (first && debug == 0) { |
dc20c96e KM |
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); | |
61ba62c5 KM |
297 | } |
298 | (void) system("ifconfig sl0 up"); | |
b652be8f | 299 | printd(", ready\n"); |
4f73d838 KM |
300 | if (!first) |
301 | syslog(LOG_INFO, "reconnected (%d tries).\n", tries); | |
b652be8f | 302 | first = 0; |
4f73d838 KM |
303 | tries = 0; |
304 | logged_in = 1; | |
dc20c96e | 305 | while (hup == 0) { |
9bdb4436 | 306 | sigpause(0L); |
b652be8f | 307 | printd("sigpause return\n"); |
dc20c96e | 308 | } |
61ba62c5 KM |
309 | goto restart; |
310 | } | |
311 | ||
4f73d838 | 312 | void |
61ba62c5 KM |
313 | sighup() |
314 | { | |
315 | ||
9bdb4436 | 316 | printd("hup\n"); |
4f73d838 KM |
317 | if (hup == 0 && logged_in) |
318 | syslog(LOG_INFO, "hangup signal\n"); | |
9bdb4436 | 319 | hup = 1; |
61ba62c5 KM |
320 | } |
321 | ||
322 | getline(buf, size, fd) | |
323 | char *buf; | |
324 | int size, fd; | |
325 | { | |
326 | register int i; | |
dc20c96e | 327 | int ret; |
61ba62c5 KM |
328 | |
329 | size--; | |
330 | for (i = 0; i < size; i++) { | |
9bdb4436 KM |
331 | if (hup) |
332 | return (0); | |
dc20c96e | 333 | if ((ret = read(fd, &buf[i], 1)) == 1) { |
61ba62c5 | 334 | buf[i] &= 0177; |
1fedb40b | 335 | if (buf[i] == '\r' || buf[i] == '\0') |
61ba62c5 KM |
336 | buf[i] = '\n'; |
337 | if (buf[i] != '\n' && buf[i] != ':') | |
338 | continue; | |
339 | buf[i + 1] = '\0'; | |
1fedb40b | 340 | printd("Got %d: \"%s\"\n", i + 1, buf); |
61ba62c5 KM |
341 | return (i+1); |
342 | } | |
4f73d838 KM |
343 | if (ret <= 0) { |
344 | if (ret < 0) | |
345 | perror("getline: read"); | |
346 | else | |
347 | fprintf(stderr, "read returned 0\n"); | |
dc20c96e | 348 | buf[i] = '\0'; |
dc20c96e KM |
349 | printd("returning 0 after %d: \"%s\"\n", i, buf); |
350 | return (0); | |
351 | } | |
61ba62c5 | 352 | } |
9bdb4436 | 353 | return (0); |
61ba62c5 KM |
354 | } |
355 | ||
356 | usage() | |
357 | { | |
4f73d838 | 358 | fprintf(stderr, "usage: startslip [-d] [-s string] dev user passwd\n"); |
61ba62c5 KM |
359 | exit(1); |
360 | } |