Xinu7/src/cmd/download/OLD/odt.c
#include <stdio.h>
#include <sgtty.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "getdev.h"
#include "/usr/Xinu/include/baud.h"
/************************************************************************/
/* */
/* program: */
/* odt -- talk to an LSI 11 from a VAX UNIX terminal */
/* */
/* synopsis: */
/* odt [-lx] */
/* */
/* description: */
/* lsi attaches a user's terminal to a tty line that connects */
/* to an LSI 11 so that keystrokes typed at the terminal are */
/* sent to the LSI 11, and characters that the LSI 11 emits */
/* are sent to the terminal display (without any processing). */
/* The standard input, standard output, and standard error */
/* files remain attached to the terminal. File descriptor */
/* lsifd is attached to the LSI 11 tty line. */
/* Input from the keyboard is processed as follows: lines */
/* beginning with ! are passed to a subshell. A backslash / */
/* causes lsi to change the keyboard mode to RAW for the next */
/* character, making it possible to send special characters */
/* like interrupt or kill characters. Echo is turned off when */
/* lsi begins. Thus, any echoing of keystrokes is coming from */
/* the LSI 11. */
/* */
/* Normally, odt looks for any available LSI 11. The argument */
/* -lx restricts the search to the LSI 11 with "number" x. */
/* */
/* Author/status: */
/* Doug Comer, based on a program by Bob Brown */
/* CS Dept., Purdue University */
/* */
/************************************************************************/
#define STDOUT 1
#define STDIN 0
#ifndef TRUE
#define TRUE 1
#define FALSE 0
typedef int Bool;
#endif
int devfd = -1; /* line tty file descriptor */
int quit(); /* procedure called to quit */
int quit2(); /* safe interim quit procedure */
struct sgttyb Lttymode; /* line tty mode upon entry */
struct sgttyb lttymode; /* line tty mode for gtty/stty */
struct sgttyb kttymode; /* keyboard mode upon entry */
struct sgttyb cttymode; /* changed keyboard mode */
int baudrate; /* rate line tty should be at */
int timeout; /* time keyboard can be idle */
int unlock; /* TRUE => unlock device on exit*/
int pid; /* process id of this process */
char class[MAXNAMELEN]; /* group of machines to use */
int machnum; /* number of requested machine */
char dev[MAXNAMELEN], devname[MAXNAMELEN];
char lockfile[MAXNAMELEN]; /* name of lock file */
/*
*========================
* M a i n E n t r y
*========================
*/
main(argc, argv)
int argc;
char *argv[];
{
int useclass; /* use specified class */
int tandem;
int i;
if (ioctl(STDIN, TIOCGETP, &kttymode) < 0 ) {
perror("Cannot set terminal modes");
exit(1);
}
signal(SIGINT, quit2); /* safe handler for parent and child
to execute until fork has completed
and both have reset the handler */
strcpy(class, "LSI");
useclass = FALSE;
machnum = ANYDEV;
baudrate = B9600;
timeout = TIMEOUT;
tandem = TRUE;
unlock = FALSE;
for ( ; argc > 1; --argc) {
if (**++argv != '-') {
fprintf(stderr, "Argument %s unexpected.\n", *argv);
exit(1);
}
switch (*++argv[0]) {
case 'c':
strcpy(class, ++argv[0]);
useclass = TRUE;
break;
case 'l':
if (sscanf(++argv[0], "%d", &machnum) != 1) {
fprintf(stderr, "Illegal device number: %s\n",
argv[0]);
exit(1);
}
break;
case 't':
strcpy(class, ++argv[0]);
machnum = TTYNAME;
break;
case 'B':
if (*++argv[0] == '\0') {
baudrate = NOBAUD;
break;
}
for (i = 0; i < NBAUD; ++i)
if (strcmp(baudlist[i].name, argv[0]) == 0)
break;
if (i < NBAUD)
baudrate = baudlist[i].rate;
else {
fprintf(stderr, "Unknown baud rate: %s\n",
argv[0]);
exit(1);
}
break;
case 'T':
if (*++argv[0] == '\0')
timeout = 0;
else if (sscanf(argv[0], "%d", &timeout) != 1 ||
timeout < 0) {
fprintf(stderr,"Illegal timeout period: %s\n",
argv[0]);
exit(1);
}
break;
case 'f':
tandem = FALSE;
break;
case 'u':
unlock = TRUE;
break;
default:
fprintf(stderr, "Usage: odt [-cclass] [-lnumber] [-tdevice] [-Bbaudrate] [-Ttimeout] [-fu]\n");
exit(1);
}
}
if ( (machnum = getdev(useclass,class,machnum,&devfd,lockfile)) < 0)
exit(1);
if (machnum == 0) {
printf("Using %s\n", class);
strcpy(devname, class);
}
else {
printf("Using %s #%d\n", class, machnum);
sprintf(devname, DEVNAME, DEVDIR, class);
}
sprintf(dev, devname, machnum);
if (ioctl(devfd, TIOCGETP, &Lttymode) < 0) {
perror(dev);
exit(1);
} else {
lttymode = Lttymode;
lttymode.sg_flags |= RAW;
lttymode.sg_flags &= ~ECHO;
if (tandem)
lttymode.sg_flags |= TANDEM;
if (baudrate != NOBAUD) {
Lttymode.sg_ospeed = Lttymode.sg_ispeed = baudrate;
lttymode.sg_ospeed = lttymode.sg_ispeed = baudrate;
}
if (ioctl(devfd, TIOCSETP, <tymode) < 0) {
perror(dev);
exit(1);
}
}
/*
* set up local terminal in cbreak mode
*/
cttymode = kttymode;
cttymode.sg_flags |= CBREAK;
cttymode.sg_flags &= ~ECHO;
cttymode.sg_flags &= ~CRMOD;
if (ioctl(STDIN, TIOCSETP, &cttymode) < 0) {
perror("Cannot set terminal modes");
exit(1);
}
/*
* start up the keyboard monitor and line monitor tasks
*/
if ((pid=fork()))
keymon();
else
linemon();
exit(0);
}
int idle = 0;
/*
*------------------------------------------------------------------
*
* keymon() - terminal keyboard monitor process
*
*------------------------------------------------------------------
*/
keymon()
{
int col, i;
int esc;
char c, buf[BUFSIZ];
int sigsusp(), sigcont(), sigalrm();
/*
* catch interrupt, suspend and continue signals
*/
signal(SIGINT, quit);
signal(SIGTSTP, sigsusp);
signal(SIGCONT, sigcont);
signal(SIGALRM, sigalrm);
alarm(60);
/*
* loop forever over the following: process each keystroke
* on the keyboard.
*/
col = 0;
esc = 0;
while( (i=read(STDIN,&c,1)) != 0) {
if (i == 1) {
idle = 0;
if ( col==0 && c == '!' ) {
while ( c != '\n' && c != '\r' ) {
read(STDIN, &c, 1);
buf[col++] = c;
}
buf[--col] = '\0';
ex(buf);
col = 0;
} else if ( c=='\\' && esc==0 ) {
cttymode.sg_flags |= RAW;
stty(STDIN,&cttymode);
esc = 1;
} else {
if ( esc && (c&0177)=='\0' ) {
ioctl(devfd, TIOCSBRK, NULL);
sleep(2);
ioctl(devfd, TIOCCBRK, NULL);
} else {
write(devfd, &c, 1);
if ( (c&0177)=='\n' || (c&0177)=='\r' )
col = 0;
else
col++;
}
if ( esc ) {
cttymode.sg_flags &= ~RAW;
stty(STDIN, &cttymode);
}
esc = 0;
}
}
}
esc = 0;
ioctl(STDIN, TIOCSETP, &kttymode);
ioctl(devfd, TIOCSETP, &Lttymode);
quit();
}
/*
*---------------------------------------------------------------------
*
* ex -- execute input following a ! and return to normal processing
*
*---------------------------------------------------------------------
*/
ex(bp)
char *bp;
{
int (*oldint)(), (*oldquit)(), (*oldsusp)(), (*oldcont)();
oldint = signal(SIGINT, SIG_DFL);
oldquit = signal(SIGQUIT, SIG_DFL);
oldsusp = signal(SIGTSTP, SIG_DFL);
oldcont = signal(SIGCONT, SIG_DFL);
ioctl(STDIN, TIOCSETP, &kttymode);
system(bp);
signal(SIGINT, oldint);
signal(SIGQUIT, oldquit);
signal(SIGTSTP, oldsusp);
signal(SIGCONT, oldcont);
printf("!\n");
ioctl(STDIN, TIOCSETP, &cttymode);
}
system(s)
char *s;
{
int status, pid, w;
register int (*istat)(), (*qstat)();
if ((pid = vfork()) == 0) {
execl("/bin/sh", "sh", "-c", s, 0);
_exit(127);
}
istat = signal(SIGINT, SIG_IGN);
qstat = signal(SIGQUIT, SIG_IGN);
while ((w = wait(&status)) != pid && w != -1)
;
if (w == -1)
status = -1;
signal(SIGINT, istat);
signal(SIGQUIT, qstat);
return(status);
}
quit()
{
kill(pid,9);
ioctl(STDIN, TIOCSETP, &kttymode);
ioctl(devfd, TIOCSETP, &Lttymode);
printf("\n");
if (unlock) {
if (freedev(class, machnum) > 0)
printf("%s #%d released.\n", class, machnum);
else
printf("Unable to release %s #%d.\n", class, machnum);
}
else if (idle <= timeout)
touch(lockfile);
exit(0);
}
quit2() /* safe interim quit procedure */
{
ioctl(STDIN, TIOCSETP, &kttymode);
if (devfd >= 0)
ioctl(devfd, TIOCSETP, &Lttymode);
printf("\n");
if (!unlock)
touch(lockfile);
else if (freedev(class, machnum) > 0)
printf("%s #%d released.\n", class, machnum);
else
printf("Unable to release %s #%d.\n", class, machnum);
exit(0);
}
sigsusp()
{
ioctl(STDIN, TIOCSETP, &kttymode);
fflush(stdout);
signal(SIGTSTP, SIG_DFL);
kill(getpid(), SIGTSTP);
}
sigcont()
{
signal(SIGCONT, sigcont);
signal(SIGTSTP, sigsusp);
ioctl(STDIN, TIOCSETP, &cttymode);
}
/*
* sigalrm -- terminate if keyboard idle too long
*/
sigalrm()
{
if (timeout > 0 && ++idle > timeout) {
fprintf(stderr,"\nKeyboard idle %d minute%s. %s released.\n",
timeout, (timeout == 1)? "" : "s", dev);
quit();
}
signal(SIGALRM, sigalrm);
touch(lockfile);
alarm(60);
}
/*
*------------------------------------------------------------------
*
* linemon -- monitor LSI line and print characters that arrive
*
*------------------------------------------------------------------
*/
linemon()
{
char buf[512];
int cch;
/*
* ignore interrupt signal -- keyboard process kills us
*/
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTSTP,SIG_DFL);
signal(SIGCONT, SIG_DFL);
for (;;) {
if ((cch=read(devfd, buf, sizeof(buf))) > 0)
write(STDOUT, buf, cch);
}
}