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