Пример #1
2
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 */
}
Пример #2
0
int
ID0uu_lock(const char *basettyname)
{
  int ret;

  ID0set0();
  ret = uu_lock(basettyname);
  log_Printf(LogID0, "%d = uu_lock(\"%s\")\n", ret, basettyname);
  ID0setuser();
  return ret;
}
Пример #3
0
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);
}
Пример #4
0
long
hunt(char *name)
{
	char *cp;
	sig_t f;

	f = signal(SIGALRM, dead);
	while ((cp = getremote(name))) {
		deadfl = 0;
		uucplock = strrchr(cp, '/');
		if (uucplock == NULL)
			uucplock = cp;
		else
			uucplock++;

		if (uu_lock(uucplock) < 0)
			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 |
			    (boolean(value(DC)) ? O_NONBLOCK : 0)));
		}
		alarm(0);
		if (FD < 0) {
			perror(cp);
			deadfl = 1;
		}
		if (!deadfl) {
			struct termios cntrl;

			tcgetattr(FD, &cntrl);
			if (!boolean(value(DC)))
				cntrl.c_cflag |= HUPCL;
			tcsetattr(FD, TCSAFLUSH, &cntrl);
			ioctl(FD, TIOCEXCL, 0);
			signal(SIGALRM, SIG_DFL);
			return ((long)cp);
		}
		(void)uu_unlock(uucplock);
	}
	signal(SIGALRM, f);
	return (deadfl ? -1 : (long)cp);
}
Пример #5
0
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);
}
Пример #6
0
/* 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();
}
Пример #7
0
/* 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");
}