254 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			254 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/* modem - Put modem into DIALIN or DIALOUT mode.	Author: F. van Kempen */
 | 
						|
 | 
						|
/* Exit:	0	OK, suspended/restarted GETTY
 | 
						|
 *		1	UNIX error
 | 
						|
 *		2	Process busy
 | 
						|
 * Version:	1.3 	12/30/89
 | 
						|
 *
 | 
						|
 * Author:	F. van Kempen, MicroWalt Corporation
 | 
						|
 *
 | 
						|
 * All fancy stuff removed, see getty.c.	Kees J. Bot.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <sys/wait.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <string.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <utmp.h>
 | 
						|
#include <errno.h>
 | 
						|
 | 
						|
#include <minix/paths.h>
 | 
						|
 | 
						|
char PATH_UTMP[] = _PATH_UTMP;			/* current logins */
 | 
						|
 | 
						|
_PROTOTYPE(void usage , (void));
 | 
						|
_PROTOTYPE(int main , (int argc , char *argv []));
 | 
						|
_PROTOTYPE(void sendcodes , (char *tty, char *codes));
 | 
						|
 | 
						|
 | 
						|
void usage()
 | 
						|
{
 | 
						|
  fprintf(stderr,
 | 
						|
"Usage: modem [-sio] [-I in-codes] [-O out-codes] line [command args ...]\n");
 | 
						|
  exit(1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
main(argc, argv)
 | 
						|
int argc;
 | 
						|
char *argv[];
 | 
						|
{
 | 
						|
  struct utmp entry;
 | 
						|
  char devtty[1024], *tty;
 | 
						|
  char **command;
 | 
						|
  int ex_code = 0;
 | 
						|
  int fd, i, slot, getty;
 | 
						|
  struct stat st;
 | 
						|
  enum { TOGGLE, DIALIN, DIALOUT } mode= TOGGLE;
 | 
						|
  int silent = 0;
 | 
						|
  _PROTOTYPE(void (*hsig), (int));
 | 
						|
  _PROTOTYPE(void (*isig), (int));
 | 
						|
  _PROTOTYPE(void (*qsig), (int));
 | 
						|
  _PROTOTYPE(void (*tsig), (int));
 | 
						|
  pid_t pid;
 | 
						|
  int r, status;
 | 
						|
  uid_t uid = getuid();
 | 
						|
  gid_t gid = getgid();
 | 
						|
  char *in_codes, *out_codes;
 | 
						|
 | 
						|
  i = 1;
 | 
						|
  while (i < argc && argv[i][0] == '-') {
 | 
						|
	char *opt = argv[i++] + 1;
 | 
						|
 | 
						|
	if (opt[0] == '-' && opt[1] == 0) break;
 | 
						|
 | 
						|
	while (*opt != 0) {
 | 
						|
		switch (*opt++) {
 | 
						|
		    case 's':	/* silent mode */
 | 
						|
			silent = 1;
 | 
						|
			break;
 | 
						|
		    case 'i':	/* DIAL-IN mode: suspend GETTY */
 | 
						|
			mode = DIALIN;
 | 
						|
			break;
 | 
						|
		    case 'o':	/* DIAL-OUT mode: restart GETTY */
 | 
						|
			mode = DIALOUT;
 | 
						|
			break;
 | 
						|
		    case 'I':	/* code to switch modem to dial-in */
 | 
						|
			if (*opt == 0) {
 | 
						|
				if (i == argc) usage();
 | 
						|
				opt = argv[i++];
 | 
						|
			}
 | 
						|
			in_codes = opt;
 | 
						|
			opt = "";
 | 
						|
			break;
 | 
						|
		    case 'O':	/* code to switch modem to dial-out */
 | 
						|
			if (*opt == 0) {
 | 
						|
				if (i == argc) usage();
 | 
						|
				opt = argv[i++];
 | 
						|
			}
 | 
						|
			out_codes = opt;
 | 
						|
			opt = "";
 | 
						|
			break;
 | 
						|
		    default:
 | 
						|
			usage();
 | 
						|
		}
 | 
						|
	}
 | 
						|
  }
 | 
						|
 | 
						|
  if (i == argc) usage();
 | 
						|
  tty = argv[i++];		/* Modem line */
 | 
						|
 | 
						|
  if (mode != TOGGLE && i != argc) usage();
 | 
						|
  command = argv + i;		/* Command to execute (if any). */
 | 
						|
 | 
						|
  if (strchr(tty, '/') == NULL) {
 | 
						|
	strcpy(devtty, "/dev/");
 | 
						|
	strncat(devtty, tty, 1024 - 6);
 | 
						|
	tty = devtty;
 | 
						|
  }
 | 
						|
 | 
						|
  if (stat(tty, &st) < 0) {
 | 
						|
	fprintf(stderr, "modem: %s: %s\n", tty, strerror(errno));
 | 
						|
	exit(1);
 | 
						|
  }
 | 
						|
 | 
						|
  if (!S_ISCHR(st.st_mode)) {
 | 
						|
	fprintf(stderr, "%s is not a tty\n", tty);
 | 
						|
	exit(1);
 | 
						|
  }
 | 
						|
 | 
						|
  /* Find the utmp slot number for the line. */
 | 
						|
  if ((fd= open(tty, O_RDONLY)) < 0 || (slot= fttyslot(fd)) == 0) {
 | 
						|
	fprintf(stderr, "modem: %s: %s\n", tty, strerror(errno));
 | 
						|
	exit(1);
 | 
						|
  }
 | 
						|
  close(fd);
 | 
						|
 | 
						|
  /* Read the UTMP file to find out the PID and STATUS of the GETTY. */
 | 
						|
  entry.ut_type= 0;
 | 
						|
  if ((fd = open(PATH_UTMP, O_RDONLY)) < 0
 | 
						|
	|| lseek(fd, (off_t) slot * sizeof(entry), SEEK_SET) < 0
 | 
						|
	|| read(fd, &entry, sizeof(entry)) < 0
 | 
						|
  ) {
 | 
						|
	fprintf(stderr, "modem: cannot read UTMP !\n");
 | 
						|
	exit(1);
 | 
						|
  }
 | 
						|
  close(fd);
 | 
						|
 | 
						|
  hsig= signal(SIGHUP, SIG_IGN);
 | 
						|
  isig= signal(SIGINT, SIG_IGN);
 | 
						|
  qsig= signal(SIGQUIT, SIG_IGN);
 | 
						|
  tsig= signal(SIGTERM, SIG_IGN);
 | 
						|
 | 
						|
  /* Process the terminal entry if we got one. */
 | 
						|
  switch (entry.ut_type) {
 | 
						|
  case LOGIN_PROCESS:		/* getty waiting for a call */
 | 
						|
	getty = 1;
 | 
						|
	break;
 | 
						|
  case USER_PROCESS:		/* login or user-shell */
 | 
						|
	if (!silent) fprintf(stderr, "modem: line is busy.\n");
 | 
						|
	exit(2);
 | 
						|
	break;
 | 
						|
  default:
 | 
						|
	getty = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  for (i = (mode == TOGGLE) ? 0 : 1; i < 2; i++) {
 | 
						|
	/* Now perform the desired action (DIALIN or DIALOUT). */
 | 
						|
	switch (mode) {
 | 
						|
	case DIALOUT:
 | 
						|
	case TOGGLE:
 | 
						|
		if (getty) kill(entry.ut_pid, SIGUSR1);  /* suspend getty */
 | 
						|
		chown(tty, uid, st.st_gid);	/* give line to user */
 | 
						|
		chmod(tty, 0600);
 | 
						|
		if (out_codes != NULL) sendcodes(tty, out_codes);
 | 
						|
		if (!silent) printf("modem on %s set for dialout.\n", tty);
 | 
						|
		break;
 | 
						|
	case DIALIN:
 | 
						|
		if (in_codes != NULL) sendcodes(tty, in_codes);
 | 
						|
		chown(tty, 0, st.st_gid);		/* revoke access */
 | 
						|
		chmod(tty, 0600);
 | 
						|
		if (getty) kill(entry.ut_pid, SIGUSR2);	/* restart getty */
 | 
						|
		if (!silent) printf("modem on %s set for dialin.\n", tty);
 | 
						|
	}
 | 
						|
	if (mode == TOGGLE) {
 | 
						|
		/* Start the command to run */
 | 
						|
		pid_t pid;
 | 
						|
		int status;
 | 
						|
 | 
						|
		switch ((pid = fork())) {
 | 
						|
		case -1:
 | 
						|
			fprintf(stderr, "modem: fork(): %s\n", strerror(errno));
 | 
						|
			ex_code= 1;
 | 
						|
			break;
 | 
						|
		case 0:
 | 
						|
			setgid(gid);
 | 
						|
			setuid(uid);
 | 
						|
			(void) signal(SIGHUP, hsig);
 | 
						|
			(void) signal(SIGINT, isig);
 | 
						|
			(void) signal(SIGQUIT, qsig);
 | 
						|
			(void) signal(SIGTERM, tsig);
 | 
						|
			execvp(command[0], command);
 | 
						|
			fprintf(stderr, "modem: %s: %s\n",
 | 
						|
					command[0], strerror(errno));
 | 
						|
			_exit(127);
 | 
						|
		default:
 | 
						|
			while ((r= wait(&status)) != pid) {
 | 
						|
				if (r == -1 && errno != EINTR) break;
 | 
						|
			}
 | 
						|
			if (r == -1 || status != 0) ex_code = 1;
 | 
						|
		}
 | 
						|
		mode = DIALIN;
 | 
						|
	}
 | 
						|
  }
 | 
						|
  exit(ex_code);
 | 
						|
}
 | 
						|
 | 
						|
void sendcodes(tty, codes)
 | 
						|
char *tty, *codes;
 | 
						|
{
 | 
						|
	int fd;
 | 
						|
	int c;
 | 
						|
	char buf[1024], *bp = buf;
 | 
						|
 | 
						|
	if ((fd = open(tty, O_RDWR|O_NONBLOCK)) < 0) {
 | 
						|
		fprintf(stderr, "modem: can't send codes to %s: %s\n",
 | 
						|
			tty, strerror(errno));
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	while ((c = *codes++) != 0) {
 | 
						|
fprintf(stderr, "%d\n", __LINE__);
 | 
						|
		if (c == '\\') {
 | 
						|
			if ((c = *codes++) == 0) break;
 | 
						|
			if (c == 'r') c= '\r';
 | 
						|
			if (c == 'n') c= '\n';
 | 
						|
		}
 | 
						|
		*bp++ = c;
 | 
						|
		if (bp == buf + sizeof(buf) || c == '\r' || c == '\n') {
 | 
						|
fprintf(stderr, "%d\n", __LINE__);
 | 
						|
			write(fd, buf, bp - buf);
 | 
						|
fprintf(stderr, "%d\n", __LINE__);
 | 
						|
			do {sleep(1);
 | 
						|
fprintf(stderr, "%d\n", __LINE__);
 | 
						|
			fprintf(stderr, "%d\n", read(fd, buf, sizeof(buf)));
 | 
						|
			}while (read(fd, buf, sizeof(buf)) > 0);
 | 
						|
fprintf(stderr, "%d\n", __LINE__);
 | 
						|
			bp = buf;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if (bp > buf) {
 | 
						|
fprintf(stderr, "%d\n", __LINE__);
 | 
						|
		write(fd, buf, bp - buf);
 | 
						|
fprintf(stderr, "%d\n", __LINE__);
 | 
						|
		do sleep(1); while (read(fd, buf, sizeof(buf)) > 0);
 | 
						|
fprintf(stderr, "%d\n", __LINE__);
 | 
						|
	}
 | 
						|
	close(fd);
 | 
						|
}
 |