227 lines
4.8 KiB
C
227 lines
4.8 KiB
C
/* 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);
|
|
}
|