]> git.saurik.com Git - apple/network_cmds.git/blob - startslip.tproj/startslip.c
network_cmds-85.tar.gz
[apple/network_cmds.git] / startslip.tproj / startslip.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1990, 1991, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57
58 #include <sys/param.h>
59 #if BSD >= 199006
60 #define POSIX
61 #endif
62 #ifdef POSIX
63 #include <sys/termios.h>
64 #include <sys/ioctl.h>
65 #else
66 #include <sgtty.h>
67 #endif
68 #include <sys/socket.h>
69 #include <sys/syslog.h>
70 #include <netinet/in_systm.h>
71 #include <netinet/in.h>
72 #include <net/if.h>
73 #include <net/if_slvar.h>
74 #include <netdb.h>
75 #include <errno.h>
76 #include <fcntl.h>
77 #include <stdio.h>
78 #include <signal.h>
79
80 #define DEFAULT_BAUD B9600
81 int speed = DEFAULT_BAUD;
82 #define FC_NONE 0 /* flow control: none */
83 #define FC_SW 1 /* flow control: software (XON/XOFF) */
84 #define FC_HW 2 /* flow control: hardware (RTS/CTS) */
85 int flowcontrol = FC_NONE;
86 char *annex;
87 int hup;
88 int logged_in;
89 int wait_time = 60; /* then back off */
90 #define MAXTRIES 6 /* w/60 sec and doubling, takes an hour */
91 #define PIDFILE "/var/run/startslip.pid"
92
93 #ifdef DEBUG
94 int debug = 1;
95 #undef LOG_ERR
96 #undef LOG_INFO
97 #define syslog fprintf
98 #define LOG_ERR stderr
99 #define LOG_INFO stderr
100 #else
101 int debug = 0;
102 #endif
103 #define printd if (debug) printf
104
105 main(argc, argv)
106 int argc;
107 char **argv;
108 {
109 extern char *optarg;
110 extern int optind;
111 char *cp, **ap;
112 int ch, disc;
113 int fd = -1;
114 void sighup();
115 FILE *wfd = NULL, *pfd;
116 char *dialerstring = 0, buf[BUFSIZ];
117 int first = 1, tries = 0;
118 int pausefirst = 0;
119 int pid;
120 #ifdef POSIX
121 struct termios t;
122 #else
123 struct sgttyb sgtty;
124 #endif
125
126 while ((ch = getopt(argc, argv, "db:s:p:A:F:")) != EOF)
127 switch (ch) {
128 case 'd':
129 debug = 1;
130 break;
131 #ifdef POSIX
132 case 'b':
133 speed = atoi(optarg);
134 break;
135 #endif
136 case 'p':
137 pausefirst = atoi(optarg);
138 break;
139 case 's':
140 dialerstring = optarg;
141 break;
142 case 'A':
143 annex = optarg;
144 break;
145 case 'F':
146 #ifdef POSIX
147 if (strcmp(optarg, "none") == 0)
148 flowcontrol = FC_NONE;
149 else if (strcmp(optarg, "sw") == 0)
150 flowcontrol = FC_SW;
151 else if (strcmp(optarg, "hw") == 0)
152 flowcontrol = FC_HW;
153 else {
154 (void)fprintf(stderr,
155 "flow control: none, sw, hw\n");
156 exit(1);
157 }
158 break;
159 #else
160 (void)fprintf(stderr, "flow control not supported\n");
161 exit(1);
162 #endif
163 case '?':
164 default:
165 usage();
166 }
167 argc -= optind;
168 argv += optind;
169
170 if (argc != 3)
171 usage();
172
173 openlog("startslip", LOG_PID, LOG_DAEMON);
174
175 #if BSD <= 43
176 if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) {
177 ioctl(fd, TIOCNOTTY, 0);
178 close(fd);
179 fd = -1;
180 }
181 #endif
182
183 if (debug)
184 setbuf(stdout, NULL);
185
186 if (pfd = fopen(PIDFILE, "r")) {
187 pid = 0;
188 fscanf(pfd, "%d", &pid);
189 if (pid > 0)
190 kill(pid, SIGUSR1);
191 fclose(pfd);
192 }
193 restart:
194 logged_in = 0;
195 if (++tries > MAXTRIES) {
196 syslog(LOG_ERR, "exiting after %d tries\n", tries);
197 /* ???
198 if (first)
199 */
200 exit(1);
201 }
202
203 /*
204 * We may get a HUP below, when the parent (session leader/
205 * controlling process) exits; ignore HUP until into new session.
206 */
207 signal(SIGHUP, SIG_IGN);
208 hup = 0;
209 if (fork() > 0) {
210 if (pausefirst)
211 sleep(pausefirst);
212 if (first)
213 printd("parent exit\n");
214 exit(0);
215 }
216 pausefirst = 0;
217 #ifdef POSIX
218 if (setsid() == -1)
219 perror("setsid");
220 #endif
221 pid = getpid();
222 printd("restart: pid %d: ", pid);
223 if (pfd = fopen(PIDFILE, "w")) {
224 fprintf(pfd, "%d\n", pid);
225 fclose(pfd);
226 }
227 if (wfd) {
228 printd("fclose, ");
229 fclose(wfd);
230 wfd == NULL;
231 }
232 if (fd >= 0) {
233 printd("close, ");
234 close(fd);
235 sleep(5);
236 }
237 printd("open");
238 if ((fd = open(argv[0], O_RDWR)) < 0) {
239 perror(argv[0]);
240 syslog(LOG_ERR, "open %s: %m\n", argv[0]);
241 if (first)
242 exit(1);
243 else {
244 sleep(wait_time * tries);
245 goto restart;
246 }
247 }
248 printd(" %d", fd);
249 #ifdef TIOCSCTTY
250 if (ioctl(fd, TIOCSCTTY, 0) < 0)
251 perror("ioctl (TIOCSCTTY)");
252 #endif
253 signal(SIGHUP, sighup);
254 if (debug) {
255 if (ioctl(fd, TIOCGETD, &disc) < 0)
256 perror("ioctl(TIOCSETD)");
257 printf(" (disc was %d)", disc);
258 }
259 disc = TTYDISC;
260 if (ioctl(fd, TIOCSETD, &disc) < 0) {
261 perror("ioctl(TIOCSETD)");
262 syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n",
263 argv[0]);
264 }
265 printd(", ioctl");
266 #ifdef POSIX
267 if (tcgetattr(fd, &t) < 0) {
268 perror("tcgetattr");
269 syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]);
270 exit(2);
271 }
272 cfmakeraw(&t);
273 t.c_iflag &= ~IMAXBEL;
274 switch (flowcontrol) {
275 case FC_HW:
276 t.c_cflag |= (CRTS_IFLOW|CCTS_OFLOW);
277 break;
278 case FC_SW:
279 t.c_iflag |= (IXON|IXOFF);
280 break;
281 case FC_NONE:
282 t.c_cflag &= ~(CRTS_IFLOW|CCTS_OFLOW);
283 t.c_iflag &= ~(IXON|IXOFF);
284 break;
285 }
286 cfsetspeed(&t, speed);
287 if (tcsetattr(fd, TCSAFLUSH, &t) < 0) {
288 perror("tcsetattr");
289 syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]);
290 if (first)
291 exit(2);
292 else {
293 sleep(wait_time * tries);
294 goto restart;
295 }
296 }
297 #else
298 if (ioctl(fd, TIOCGETP, &sgtty) < 0) {
299 perror("ioctl (TIOCGETP)");
300 syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n",
301 argv[0]);
302 exit(2);
303 }
304 sgtty.sg_flags = RAW | ANYP;
305 sgtty.sg_erase = sgtty.sg_kill = 0377;
306 sgtty.sg_ispeed = sgtty.sg_ospeed = speed;
307 if (ioctl(fd, TIOCSETP, &sgtty) < 0) {
308 perror("ioctl (TIOCSETP)");
309 syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n",
310 argv[0]);
311 if (first)
312 exit(2);
313 else {
314 sleep(wait_time * tries);
315 goto restart;
316 }
317 }
318 #endif
319 sleep(2); /* wait for flakey line to settle */
320 if (hup)
321 goto restart;
322
323 wfd = fdopen(fd, "w+");
324 if (wfd == NULL) {
325 syslog(LOG_ERR, "can't fdopen slip line\n");
326 exit(10);
327 }
328 setbuf(wfd, (char *)0);
329 if (dialerstring) {
330 printd(", send dialstring");
331 fprintf(wfd, "%s\r", dialerstring);
332 } else
333 putc('\r', wfd);
334 printd("\n");
335
336 /*
337 * Log in
338 */
339 printd("look for login: ");
340 for (;;) {
341 if (getline(buf, BUFSIZ, fd) == 0 || hup) {
342 sleep(wait_time * tries);
343 goto restart;
344 }
345 if (annex) {
346 if (bcmp(buf, annex, strlen(annex)) == 0) {
347 fprintf(wfd, "slip\r");
348 printd("Sent \"slip\"\n");
349 continue;
350 }
351 if (bcmp(&buf[1], "sername:", 8) == 0) {
352 fprintf(wfd, "%s\r", argv[1]);
353 printd("Sent login: %s\n", argv[1]);
354 continue;
355 }
356 if (bcmp(&buf[1], "assword:", 8) == 0) {
357 fprintf(wfd, "%s\r", argv[2]);
358 printd("Sent password: %s\n", argv[2]);
359 break;
360 }
361 } else {
362 if (bcmp(&buf[1], "ogin:", 5) == 0) {
363 fprintf(wfd, "%s\r", argv[1]);
364 printd("Sent login: %s\n", argv[1]);
365 continue;
366 }
367 if (bcmp(&buf[1], "assword:", 8) == 0) {
368 fprintf(wfd, "%s\r", argv[2]);
369 printd("Sent password: %s\n", argv[2]);
370 break;
371 }
372 }
373 }
374
375 /*
376 * Security hack. Do not want private information such as the
377 * password and possible phone number to be left around.
378 * So we clobber the arguments.
379 */
380 for (ap = argv - optind + 1; ap < argv + 3; ap++)
381 for (cp = *ap; *cp != 0; cp++)
382 *cp = '\0';
383
384 /*
385 * Attach
386 */
387 printd("setd");
388 disc = SLIPDISC;
389 if (ioctl(fd, TIOCSETD, &disc) < 0) {
390 perror("ioctl(TIOCSETD)");
391 syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n",
392 argv[0]);
393 exit(1);
394 }
395 if (first && debug == 0) {
396 close(0);
397 close(1);
398 close(2);
399 (void) open("/dev/null", O_RDWR);
400 (void) dup2(0, 1);
401 (void) dup2(0, 2);
402 }
403 (void) system("ifconfig sl0 up");
404 printd(", ready\n");
405 if (!first)
406 syslog(LOG_INFO, "reconnected (%d tries).\n", tries);
407 first = 0;
408 tries = 0;
409 logged_in = 1;
410 while (hup == 0) {
411 sigpause(0L);
412 printd("sigpause return\n");
413 }
414 goto restart;
415 }
416
417 void
418 sighup()
419 {
420
421 printd("hup\n");
422 if (hup == 0 && logged_in)
423 syslog(LOG_INFO, "hangup signal\n");
424 hup = 1;
425 }
426
427 getline(buf, size, fd)
428 char *buf;
429 int size, fd;
430 {
431 register int i;
432 int ret;
433
434 size--;
435 for (i = 0; i < size; i++) {
436 if (hup)
437 return (0);
438 if ((ret = read(fd, &buf[i], 1)) == 1) {
439 buf[i] &= 0177;
440 if (buf[i] == '\r' || buf[i] == '\0')
441 buf[i] = '\n';
442 if (buf[i] != '\n' && buf[i] != ':')
443 continue;
444 buf[i + 1] = '\0';
445 printd("Got %d: \"%s\"\n", i + 1, buf);
446 return (i+1);
447 }
448 if (ret <= 0) {
449 if (ret < 0)
450 perror("getline: read");
451 else
452 fprintf(stderr, "read returned 0\n");
453 buf[i] = '\0';
454 printd("returning 0 after %d: \"%s\"\n", i, buf);
455 return (0);
456 }
457 }
458 return (0);
459 }
460
461 usage()
462 {
463 (void)fprintf(stderr,
464 "usage: startslip [-d] [-b speed] [-s string] [-A annexname] [-F flowcontrol] dev user passwd\n");
465 exit(1);
466 }