int main(int argc, char **argv) { char *cp, **ap; int ch, disc; FILE *wfd = NULL; char *dialerstring = 0, buf[BUFSIZ]; int unitnum, keepal = 0, outfill = 0; char unitname[32]; char *password; char *upscript = NULL, *downscript = NULL; int first = 1, tries = 0; time_t fintimeout; long lpid; pid_t pid; struct termios t; int result; while ((ch = getopt(argc, argv, "dhlb:s:t:w:A:U:D:W:K:O:S:L")) != -1) switch (ch) { case 'd': debug = 1; break; case 'b': speed = atoi(optarg); break; case 's': if (diali >= MAXDIALS) errx(1, "max dial strings number (%d) exceeded", MAXDIALS); dials[diali++] = strdup(optarg); break; case 't': script_timeout = atoi(optarg); break; case 'w': wait_time = atoi(optarg); break; case 'W': MAXTRIES = atoi(optarg); break; case 'A': annex = strdup(optarg); break; case 'U': upscript = strdup(optarg); break; case 'D': downscript = strdup(optarg); break; case 'L': uucp_lock = 1; break; case 'l': modem_control = 0; break; case 'h': flowcontrol = FC_HW; break; case 'K': keepal = atoi(optarg); break; case 'O': outfill = atoi(optarg); break; case 'S': sl_unit = atoi(optarg); break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc != 3) usage(); /* * Copy these so they exist after we clobber them. */ devicename = strdup(argv[0]); username = strdup(argv[1]); password = strdup(argv[2]); /* * Security hack. Do not want private information such as the * password and possible phone number to be left around. * So we clobber the arguments. */ for (ap = argv - optind + 1; ap < argv + 3; ap++) for (cp = *ap; *cp != 0; cp++) *cp = '\0'; openlog("startslip", LOG_PID|LOG_PERROR, LOG_DAEMON); if (debug) setbuf(stdout, NULL); signal(SIGTERM, sigterm); if ((dvname = strrchr(devicename, '/')) == NULL) dvname = devicename; else dvname++; result = snprintf(my_pidfile, sizeof(my_pidfile), PIDFILE, _PATH_VARRUN, dvname); if (result < 0 || (unsigned int)result >= sizeof(my_pidfile)) usage(); if ((pfd = fopen(my_pidfile, "r")) != NULL) { if (fscanf(pfd, "%ld\n", &lpid) == 1) { pid = lpid; if (pid == lpid && pid > 0) kill(pid, SIGTERM); } fclose(pfd); pfd = NULL; /* not remove pidfile yet */ sleep(5); /* allow down script to be completed */ } else restart: signal(SIGHUP, SIG_IGN); signal(SIGURG, SIG_IGN); hup = 0; if (wfd) { printd("fclose, "); fclose(wfd); conn_time = time(NULL) - start_time; if (uucp_lock) uu_unlock(dvname); locked = 0; wfd = NULL; fd = -1; sleep(5); } else if (fd >= 0) { printd("close, "); close(fd); conn_time = time(NULL) - start_time; if (uucp_lock) uu_unlock(dvname); locked = 0; fd = -1; sleep(5); } if (logged_in) { syslog(LOG_INFO, "%s: connection time elapsed: %ld secs", username, (long)conn_time); sprintf(buf, "LINE=%d %s %s down", diali ? (dialc - 1) % diali : 0, downscript ? downscript : "/sbin/ifconfig" , unitname); system(buf); logged_in = 0; } if (terminate) down(0); tries++; if (MAXTRIES > 0 && tries > MAXTRIES) { syslog(LOG_ERR, "%s: exiting login after %d tries", username, tries); /* ??? if (first) */ down(3); } if (tries > 1) { syslog(LOG_INFO, "%s: sleeping %d seconds (%d tries)", username, wait_time * (tries - 1), tries); sleep(wait_time * (tries - 1)); if (terminate) goto restart; } if (daemon(1, debug) < 0) { syslog(LOG_ERR, "%s: daemon: %m", username); down(2); } pid = getpid(); printd("restart: pid %ld: ", (long)pid); if ((pfd = fopen(my_pidfile, "w")) != NULL) { fprintf(pfd, "%ld\n", (long)pid); fclose(pfd); } printd("open"); if (uucp_lock) { int res; if ((res = uu_lock(dvname)) != UU_LOCK_OK) { if (res != UU_LOCK_INUSE) syslog(LOG_ERR, "uu_lock: %s", uu_lockerr(res)); syslog(LOG_ERR, "%s: can't lock %s", username, devicename); goto restart; } locked = 1; } if ((fd = open(devicename, O_RDWR | O_NONBLOCK)) < 0) { syslog(LOG_ERR, "%s: open %s: %m", username, devicename); if (first) down(1); else { if (uucp_lock) uu_unlock(dvname); locked = 0; goto restart; } } printd(" %d", fd); signal(SIGHUP, sighup); if (ioctl(fd, TIOCSCTTY, 0) < 0) { syslog(LOG_ERR, "%s: ioctl (TIOCSCTTY): %m", username); down(2); } if (tcsetpgrp(fd, getpid()) < 0) { syslog(LOG_ERR, "%s: tcsetpgrp failed: %m", username); down(2); } printd(", ioctl\n"); if (tcgetattr(fd, &t) < 0) { syslog(LOG_ERR, "%s: tcgetattr(%s): %m", username, devicename); down(2); } cfmakeraw(&t); switch (flowcontrol) { case FC_HW: t.c_cflag |= (CRTS_IFLOW|CCTS_OFLOW); break; case FC_NONE: t.c_cflag &= ~(CRTS_IFLOW|CCTS_OFLOW); break; } if (modem_control) t.c_cflag |= HUPCL; else t.c_cflag &= ~(HUPCL); t.c_cflag |= CLOCAL; /* until modem commands passes */ cfsetispeed(&t, speed); cfsetospeed(&t, speed); if (tcsetattr(fd, TCSAFLUSH, &t) < 0) { syslog(LOG_ERR, "%s: tcsetattr(%s): %m", username, devicename); down(2); } sleep(2); /* wait for flakey line to settle */ if (hup || terminate) goto restart; wfd = fdopen(fd, "w+"); if (wfd == NULL) { syslog(LOG_ERR, "%s: can't fdopen %s: %m", username, devicename); down(2); } setbuf(wfd, NULL); if (diali > 0) dialerstring = dials[dialc++ % diali]; if (dialerstring) { syslog(LOG_INFO, "%s: dialer string: %s\\r", username, dialerstring); fprintf(wfd, "%s\r", dialerstring); } printd("\n"); fintimeout = time(NULL) + script_timeout; if (modem_control) { printd("waiting for carrier\n"); while (time(NULL) < fintimeout && !carrier()) { sleep(1); if (hup || terminate) goto restart; } if (!carrier()) goto restart; t.c_cflag &= ~(CLOCAL); if (tcsetattr(fd, TCSANOW, &t) < 0) { syslog(LOG_ERR, "%s: tcsetattr(%s): %m", username, devicename); down(2); } /* Only now we able to receive HUP on carrier drop! */ } /* * Log in */ printd("look for login: "******"slip\r"); printd("Sent \"slip\"\n"); continue; } if (bcmp(&buf[1], "sername:", 8) == 0) { fprintf(wfd, "%s\r", username); printd("Sent login: %s\n", username); continue; } if (bcmp(&buf[1], "assword:", 8) == 0) { fprintf(wfd, "%s\r", password); printd("Sent password: %s\n", password); break; } } else { if (strstr(&buf[1], "ogin:") != NULL) { fprintf(wfd, "%s\r", username); printd("Sent login: %s\n", username); continue; } if (strstr(&buf[1], "assword:") != NULL) { fprintf(wfd, "%s\r", password); printd("Sent password: %s\n", password); break; } } } sleep(5); /* Wait until login completed */ if (hup || terminate) goto restart; start_time = time(NULL); /* * Attach */ printd("setd"); disc = SLIPDISC; if (ioctl(fd, TIOCSETD, &disc) < 0) { syslog(LOG_ERR, "%s: ioctl (%s, TIOCSETD): %m", username, devicename); down(2); } if (sl_unit >= 0 && ioctl(fd, SLIOCSUNIT, &sl_unit) < 0) { syslog(LOG_ERR, "%s: ioctl(SLIOCSUNIT): %m", username); down(2); } if (ioctl(fd, SLIOCGUNIT, &unitnum) < 0) { syslog(LOG_ERR, "%s: ioctl(SLIOCGUNIT): %m", username); down(2); } sprintf(unitname, "sl%d", unitnum); if (keepal > 0) { signal(SIGURG, sigurg); if (ioctl(fd, SLIOCSKEEPAL, &keepal) < 0) { syslog(LOG_ERR, "%s: ioctl(SLIOCSKEEPAL): %m", username); down(2); } } if (outfill > 0 && ioctl(fd, SLIOCSOUTFILL, &outfill) < 0) { syslog(LOG_ERR, "%s: ioctl(SLIOCSOUTFILL): %m", username); down(2); } sprintf(buf, "LINE=%d %s %s up", diali ? (dialc - 1) % diali : 0, upscript ? upscript : "/sbin/ifconfig" , unitname); system(buf); printd(", ready\n"); if (!first) syslog(LOG_INFO, "%s: reconnected on %s (%d tries)", username, unitname, tries); else syslog(LOG_INFO, "%s: connected on %s", username, unitname); first = 0; tries = 0; logged_in = 1; while (hup == 0 && terminate == 0) { sigpause(0L); printd("sigpause return\n"); } goto restart; return(0); /* not reached */ }
void physical_ChangedPid(struct physical *p, pid_t newpid) { if (physical_LockedDevice(p)) { int res; if ((res = ID0uu_lock_txfr(p->name.base, newpid)) != UU_LOCK_OK) log_Printf(LogPHASE, "uu_lock_txfr: %s\n", uu_lockerr(res)); } }
long hunt(char *name) { char *cp; sig_t f; int res; f = signal(SIGALRM, dead); while ((cp = getremote(name))) { deadfl = 0; if ((uucplock = strrchr(cp, '/')) == NULL) uucplock = cp; else ++uucplock; if ((res = uu_lock(uucplock)) != UU_LOCK_OK) { if (res != UU_LOCK_INUSE) fprintf(stderr, "uu_lock: %s\n", uu_lockerr(res)); continue; } /* * Straight through call units, such as the BIZCOMP, * VADIC and the DF, must indicate they're hardwired in * order to get an open file descriptor placed in FD. * Otherwise, as for a DN-11, the open will have to * be done in the "open" routine. */ if (!HW) break; if (setjmp(deadline) == 0) { alarm(10); FD = open(cp, O_RDWR); } alarm(0); if (FD < 0) { warn("%s", cp); deadfl = 1; } if (!deadfl) { ioctl(FD, TIOCEXCL, 0); { struct termios t; if (tcgetattr(FD, &t) == 0) { t.c_cflag |= HUPCL; (void)tcsetattr(FD, TCSANOW, &t); } } signal(SIGALRM, SIG_DFL); return ((long)cp); } (void)uu_unlock(uucplock); } signal(SIGALRM, f); return (deadfl ? -1 : (long)cp); }
static int physical_Lock(struct physical *p) { int res; if (*p->name.full == '/' && p->type != PHYS_DIRECT && (res = ID0uu_lock(p->name.base)) != UU_LOCK_OK) { if (res == UU_LOCK_INUSE) log_Printf(LogPHASE, "%s: %s is in use\n", p->link.name, p->name.full); else log_Printf(LogPHASE, "%s: %s is in use: uu_lock: %s\n", p->link.name, p->name.full, uu_lockerr(res)); return 0; } return 1; }
int ExclusiveOpenDevice(const char *label, const char *pathname) { int fd, locked = FALSE; const char *ttyname = NULL; time_t startTime; /* Lock device UUCP style, if it resides in /dev */ if (!strncmp(pathname, _PATH_DEV, 5)) { int res; ttyname = pathname + 5; if ((res = uu_lock(ttyname)) != UU_LOCK_OK) { Log(LG_ERR, ("[%s] uu_lock(%s): %s", label, ttyname, uu_lockerr(res))); return (-1); } locked = TRUE; } /* Open it, but give up after so many interruptions */ for (startTime = time(NULL); (fd = open(pathname, O_RDWR, 0)) < 0 && time(NULL) < startTime + MAX_OPEN_DELAY;) if (errno != EINTR) { Perror("[%s] can't open %s", label, pathname); if (locked) uu_unlock(ttyname); return (-1); } /* Did we succeed? */ if (fd < 0) { Log(LG_ERR, ("[%s] can't open %s after %d secs", label, pathname, MAX_OPEN_DELAY)); if (locked) uu_unlock(ttyname); return (-1); } (void)fcntl(fd, F_SETFD, 1); /* Done */ return (fd); }
/* sighup_handler() is invoked when carrier drops, eg. before redial. */ static void sighup_handler(int signo __unused) { if(exiting) return; if (redial_cmd == NULL) { syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); exiting", dev, unit); exit_handler(1); } again: /* invoke a shell for redial_cmd or punt. */ if (*redial_cmd) { /* Non-empty redial command */ syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); running '%s'", dev, unit, redial_cmd); acquire_line(); /* reopen dead line */ setup_line(CLOCAL); if (locked) { if (uucp_lock) uu_unlock(dvname); /* for redial */ locked = 0; } if (system(redial_cmd)) goto again; if (uucp_lock) { int res; if ((res = uu_lock(dvname)) != UU_LOCK_OK) { if (res != UU_LOCK_INUSE) syslog(LOG_ERR, "uu_lock: %s", uu_lockerr(res)); syslog(LOG_ERR, "can't relock %s after %s, aborting", dev, redial_cmd); exit_handler(1); } locked = 1; } /* Now check again for carrier (dial command is done): */ if (!(modem_control & CLOCAL)) { tty.c_cflag &= ~CLOCAL; if (tcsetattr(fd, TCSAFLUSH, &tty) < 0) { syslog(LOG_ERR, "tcsetattr(TCSAFLUSH): %m"); exit_handler(1); } ioctl(fd, TIOCMGET, &comstate); if (!(comstate & TIOCM_CD)) { /* check for carrier */ /* force a redial if no carrier */ goto again; } } else setup_line(0); } else { /* Empty redial command */ syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); reestablish connection", dev, unit); acquire_line(); /* reopen dead line */ setup_line(0); /* restore ospeed from hangup (B0) */ /* If modem control, just wait for carrier before attaching. If no modem control, just fall through immediately. */ if (!(modem_control & CLOCAL)) { int carrier = 0; syslog(LOG_NOTICE, "waiting for carrier on %s (sl%d)", dev, unit); /* Now wait for carrier before attaching line. */ /* We must poll since CLOCAL prevents signal. */ while (! carrier) { sleep(2); ioctl(fd, TIOCMGET, &comstate); if (comstate & TIOCM_CD) carrier = 1; } syslog(LOG_NOTICE, "carrier now present on %s (sl%d)", dev, unit); } } slip_discipline(); configure_network(); }
/* Close all FDs, fork, reopen tty port as 0-2, and make it the controlling terminal for our process group. */ static void acquire_line(void) { int ttydisc = TTYDISC; int oflags; FILE *pid_file; /* reset to tty discipline */ if (fd >= 0 && ioctl(fd, TIOCSETD, &ttydisc) < 0) { syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); exit_handler(1); } close(STDIN_FILENO); /* close FDs before forking. */ close(STDOUT_FILENO); close(STDERR_FILENO); if (fd > 2) close(fd); signal(SIGHUP, SIG_IGN); /* ignore HUP signal when parent dies. */ if (daemon(0,0)) { /* fork, setsid, chdir /, and close std*. */ syslog(LOG_ERR, "daemon(0,0): %m"); exit_handler(1); } while (getppid () != 1) sleep (1); /* Wait for parent to die. */ /* create PID file */ if((pid_file = fopen(pidfilename, "w"))) { fprintf(pid_file, "%ld\n", (long)getpid()); fclose(pid_file); } if (signal(SIGHUP,sighup_handler) == SIG_ERR) /* Re-enable HUP signal */ syslog(LOG_NOTICE,"cannot install SIGHUP handler: %m"); if (uucp_lock) { /* unlock not needed here, always re-lock with new pid */ int res; if ((res = uu_lock(dvname)) != UU_LOCK_OK) { if (res != UU_LOCK_INUSE) syslog(LOG_ERR, "uu_lock: %s", uu_lockerr(res)); syslog(LOG_ERR, "can't lock %s", dev); exit_handler(1); } locked = 1; } if ((fd = open(dev, O_RDWR | O_NONBLOCK, 0)) < 0) { syslog(LOG_ERR, "open(%s) %m", dev); exit_handler(1); } /* Turn off O_NONBLOCK for dumb redialers, if any. */ if ((oflags = fcntl(fd, F_GETFL)) == -1) { syslog(LOG_ERR, "fcntl(F_GETFL) failed: %m"); exit_handler(1); } if (fcntl(fd, F_SETFL, oflags & ~O_NONBLOCK) == -1) { syslog(LOG_ERR, "fcntl(F_SETFL) failed: %m"); exit_handler(1); } dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > 2) close (fd); fd = STDIN_FILENO; /* acquire the serial line as a controlling terminal. */ if (ioctl(fd, TIOCSCTTY, 0) < 0) { syslog(LOG_ERR,"ioctl(TIOCSCTTY): %m"); exit_handler(1); } /* Make us the foreground process group associated with the slip line which is our controlling terminal. */ if (tcsetpgrp(fd, getpid()) < 0) syslog(LOG_NOTICE,"tcsetpgrp failed: %m"); }