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.10 (Berkeley) 05/03/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 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 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 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 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