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