Minix1.5/commands/modem.c

Compare this file to the similar file:
Show the results in this format:

/* modem - Put modem into DIALIN or DIALOUT mode.	Author: F. van Kempen */

/* Exit:	1	OK, suspended/restarted GETTY
 *		0	Error, GETTY would not listen
 *		-1	Error in UTMP file
 *		-2	TTY not found
 *		-3	Process not GETTY
 *		-4	Process busy
 *		-5	Unknown process type
 *
 * Version:	1.3 	12/30/89
 *
 * Author:	F. van Kempen, MicroWalt Corporation
 */

#include <sys/types.h>
#include <fcntl.h>
#include <sgtty.h>
#include <signal.h>
#include <string.h>
#include <utmp.h>

static char *Version = "@(#) MODEM 1.3 (12/30/89)";
int debug = 0;			/* generate some debugging output */
int rings = -999;		/* number of rings for dial-in */


extern char *itoa();


/* Tell modem to go into DIAL-IN mode.
 * We do this by resetting it and by setting the
 * S0-register to a positive value.
 */
int dialin(tty)
char *tty;
{
  struct sgttyb old, new;
  char buff[32];
  int fd;

  /* Create file name of modem. */
  strcpy(buff, "/dev/");
  strcat(buff, tty);

  /* open the device */
  fd = open(buff, O_RDWR);
  if (fd < 0) return(0);

  /* Get old terminal status. */
  ioctl(fd, TIOCGETP, &old);

  /* Set temporary parameters. This equals 'stty sane 1200'. */
  ioctl(fd, TIOCGETP, &new);
  new.sg_ispeed = B1200;
  new.sg_ospeed = B1200;
  new.sg_flags = (BITS8 | CRMOD | XTABS);
  ioctl(fd, TIOCSETP, &new);

  /* Say hello to the modem. */
  write(fd, "+++", 3);
  sleep(2);

  /* Reset the modem. */
  write(fd, "AT Z\n", 5);  
  sleep(1);

  /* Create the ANSWER string. */
  strcpy(buff, "AT S0=");
  strcat(buff, itoa(rings));
  strcat(buff, "\n");
  write(fd, buff, strlen(buff));

  /* Restore the old terminal parameters. */
  ioctl(fd, TIOCSETP, &old);

  close(fd);
  return(1);
}


/* Tell modem to go into DIAL-OUT mode.
 * We do this by resetting it and by setting the
 * S0-register to a zero (zero rings!).
 */
int dialout(tty)
char *tty;
{
  struct sgttyb old, new;
  char buff[32];
  int fd;

  /* create file name of modem */
  strcpy(buff, "/dev/");
  strcat(buff, tty);

  /* open the device */
  fd = open(buff, O_RDWR);
  if (fd < 0) return(0);

  /* Get old terminal status. */
  ioctl(fd, TIOCGETP, &old);

  /* Set temporary parameters. This equals 'stty sane 1200'. */
  ioctl(fd, TIOCGETP, &new);
  new.sg_ispeed = B1200;
  new.sg_ospeed = B1200;
  new.sg_flags = (BITS8 | CRMOD | XTABS);
  ioctl(fd, TIOCSETP, &new);

  /* Say hello to the modem. */
  write(fd, "+++", 3);
  sleep(2);

  /* Reset the modem. */
  write(fd, "AT Z\n", 5);  
  sleep(1);

  /* Send the NO-ANSWER string. */
  write(fd, "AT S0=0\n", 8);

  /* Restore the old terminal parameters. */
  ioctl(fd, TIOCSETP, &old);

  close(fd);
  return(1);
}


void usage()
{
   write(2, "Usage: modem [-d] [-g] <-i rings | -o> line\n", 44);
  exit(-1);
}


main(argc, argv)
int argc;
char *argv[];
{
  struct utmp entry;
  char *tty, *s;
  int fd, st;

  st = 0;
  while (st < argc) {
	s = argv[++st];
	if (s && *s == '-') switch (*++s) {
		    case 'd':	/* DEBUG mode */
			debug = 1;
			break;
		    case 'g':	/* GETTY mode */
			rings = -1;
			break;
		    case 'i':	/* DIAL-IN mode: suspend GETTY and
				 * call modem */
			s++;
			if (*s != '\0')
				rings = atoi(s);
			else
				rings = atoi(argv[++st]);
			break;
		    case 'o':	/* DIAL-OUT mode: restart GETTY and
				 * call modem */
			rings = 0;
			break;
		    default:
			usage();
	} else
		break;
  }

  if (rings == -999) usage();	/* badly formed parameters! */

  if (st >= argc) usage();	/* we need the TTY name as well! */
  tty = argv[st];		/* get the terminal name */

  /* Read the UTMP file to find out the PID and STATUS of the GETTY. */
  if ((fd = open(UTMP, O_RDONLY)) < 0) {
	write(2, "modem: cannot open UTMP !\n", 26);
	exit(-1);
  }
  while (read(fd, &entry, sizeof(struct utmp)) == sizeof(struct utmp)) {
	if (!strcmp(entry.ut_line, tty)) {
		close(fd);
		tty = entry.ut_line;
		fd = -1;
		break;
	}
  }
  close(fd);

  /* Process the terminal entry if we got one. */
  if (fd == -1) switch (entry.ut_type) {
	    case INIT_PROCESS:		/* this is not a tty-process! */
		if (debug)
			write(2, "modem: no TTY-servicing process!\n", 33);
		exit(-3);
	    case LOGIN_PROCESS:		/* getty waiting for a call */
		break;
	    case USER_PROCESS:		/* login or user-shell */
		if (debug) write(2, "modem: line is busy.\n", 21);
		exit(-4);
		break;
	    default:
		if (debug) write(2, "modem: unknown UTMP entry\n", 26);
		exit(-5);
  } else
	exit(-2);

  /* Now perform the desired action (DIALIN or DIALOUT). */
  switch (rings) {
      case -1:				/* -1 means "plain GETTY" */
	kill(entry.ut_pid, SIGBUS);	/* send IGNORE signal */
	st = 0;
	break;
      case 0:
	kill(entry.ut_pid, SIGEMT);	/* send SUSPEND signal */
	st = dialout(tty);		/* put MODEM into DIALOUT */
	break;
      default:
	kill(entry.ut_pid, SIGIOT);	/* send RESTART signal */
	st = dialin(tty);		/* put MODEM in DIALIN */
  }
  exit(st);
}