char *ckxv = "Unix tty I/O, 4C(040), 30 Sep 86"; /* C K U T I O */ /* C-Kermit interrupt, terminal control & i/o functions for Unix systems */ /* Author: Frank da Cruz (SY.FDC@CU20B), Columbia University Center for Computing Activities, January 1985. Copyright (C) 1985, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ /* Includes for all Unixes (conditional includes come later) */ #include /* Types */ #include /* Directory */ #include /* Character types */ #ifdef NULL #undef NULL #endif NULL #include /* Unix Standard i/o */ #include /* Interrupts */ #include /* Longjumps */ #include "ckcdeb.h" /* Typedefs, formats for debug() */ /* Maximum length for the name of a tty device */ #ifndef DEVNAMLEN #define DEVNAMLEN 25 #endif /* 4.1 BSD support added by Charles E. Brooks, EDN-VAX */ /* Fortune 16:32 For:Pro 1.7 support mostly like 4.1, added by J-P Dumas */ #ifdef BSD4 #define ANYBSD #ifdef MAXNAMLEN #define BSD42 char *ckxsys = " 4.2 BSD"; #else #ifdef FT17 #define BSD41 char *ckxsys = " For:Pro Fortune 1.7"; #else #define BSD41 #ifndef C70 char *ckxsys = " 4.1 BSD"; #endif #endif #endif #endif /* 2.9bsd support contributed by Bradley Smith, UCLA */ #ifdef BSD29 #define ANYBSD char *ckxsys = " 2.9 BSD"; #endif /* Version 7 UNIX support contributed by Gregg Wonderly, Oklahoma State University: gregg@okstate.csnet */ #ifdef V7 #ifndef MINIX char *ckxsys = " Version 7 UNIX (tm)"; #else /* MINIX support by Adrian Godwin, Bedford, England */ char *ckxsys = " MINIX version 1.1"; #endif #endif /* BBN C70 support from Frank Wancho, WANCHO@SIMTEL20 */ #ifdef C70 char *ckxsys = " BBN C/70"; #endif /* Amdahl UTS 2.4 (v7 derivative) for IBM 370 series compatible mainframes */ /* Contributed by Garard Gaye, Jean-Pierre Dumas, DUMAS@SUMEX-AIM. */ #ifdef UTS24 char *ckxsys = " Amdahl UTS 2.4"; #endif /* Pro/Venix Version 1.x support from Columbia U. */ #ifdef PROVX1 char *ckxsys = " Pro-3xx Venix v1"; #endif /* Tower support contributed by John Bray, Auburn, Alabama */ #ifdef TOWER1 char *ckxsys = " NCR Tower 1632, OS 1.02"; #endif /* The following applies to Apollo Domain/ix, not Aegis... */ #ifdef apollo #undef TIOCEXCL #endif apollo /* Sys III/V, Xenix, PC/IX support by Herm Fischer, Encino, CA */ #ifdef UXIII #ifdef XENIX char *ckxsys = " Xenix/286"; #else #ifdef PCIX char *ckxsys = " PC/IX"; #else #ifdef ISIII char *ckxsys = " Interactive Systems Corp System III"; #else char *ckxsys = " AT&T System III/System V"; #endif #endif #endif #endif /* Features... */ /* Do own buffering, using unbuffered read() calls... */ #ifdef UXIII #define MYREAD #endif #ifdef BSD42 #define MYREAD #include #endif #ifdef MINIX #define MYREAD #endif /* Note - KERLD is the Berkeley Unix Berknet line driver, modified to pass through all 8 bits, and to allow an arbitrary break character to be set. Don't define this symbol unless you have made this modification to your 4.2BSD kernel! */ #ifdef BSD4 /* #define KERLD */ /* <-- note, commented out */ #endif /* Variables available to outside world: dftty -- Pointer to default tty name string, like "/dev/tty". dfloc -- 0 if dftty is console, 1 if external line. dfprty -- Default parity dfflow -- Default flow control ckxech -- Flag for who echoes console typein: 1 - The program (system echo is turned off) 0 - The system (or front end, or terminal). functions that want to do their own echoing should check this flag before doing so. flfnam -- Name of lock file, including its path, e.g., "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77" hasLock -- Flag set if this kermit established a uucp lock. inbufc -- number of tty line rawmode unread characters (system III/V unixes) backgrd -- Flag indicating program executing in background ( & on end of shell command). Used to ignore INT and QUIT signals. Functions for assigned communication line (either external or console tty): sysinit() -- System dependent program initialization ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access. ttclos() -- Close & reset the tty, releasing any access lock. ttpkt(speed,flow) -- Put the tty in packet mode and set the speed. ttvt(speed,flow) -- Put the tty in virtual terminal mode. or in DIALING or CONNECTED modem control state. ttinl(dest,max,timo) -- Timed read line from the tty. ttinc(timo) -- Timed read character from tty. myread() -- System 3 raw mode bulk buffer read, gives -- subsequent chars one at a time and simulates -- FIONREAD! myunrd(c) -- Places c back in buffer to be read (one only) ttchk() -- See how many characters in tty input buffer. ttxin(n,buf) -- Read n characters from tty (untimed). ttol(string,length) -- Write a string to the tty. ttoc(c) -- Write a character to the tty. ttflui() -- Flush tty input buffer. ttlock(ttname) -- Lock against uucp collisions (Sys III) ttunlck() -- Unlock " " " look4lk(ttname) -- Check if a lock file exists */ /* Functions for console terminal: congm() -- Get console terminal modes. concb(esc) -- Put the console in single-character wakeup mode with no echo. conbin(esc) -- Put the console in binary (raw) mode. conres() -- Restore the console to mode obtained by congm(). conoc(c) -- Unbuffered output, one character to console. conol(s) -- Unbuffered output, null-terminated string to the console. conola(s) -- Unbuffered output, array of strings to the console. conxo(n,s) -- Unbuffered output, n characters to the console. conchk() -- Check if characters available at console (bsd 4.2). Check if escape char (^\) typed at console (System III/V). coninc(timo) -- Timed get a character from the console. conint() -- Enable terminal interrupts on the console if not background. connoi() -- Disable terminal interrupts on the console if not background. Time functions msleep(m) -- Millisecond sleep ztime(&s) -- Return pointer to date/time string rtimer() -- Reset timer gtimer() -- Get elapsed time since last call to rtimer() */ /* Conditional Includes */ #ifdef FT17 #include /* File information */ #endif #ifndef MINIX #ifndef PROVX1 #include /* File information */ #endif #endif /* where does a V7 version get the tm structure from ? */ #ifdef MINIX #include #endif /* System III, System V */ #ifdef UXIII #include #include #include /* directory reading for locking */ #include /* error numbers for system returns */ #endif /* Not Sys III/V */ #ifndef UXIII #include /* Set/Get tty modes */ #ifndef PROVX1 #ifndef V7 #ifndef BSD41 #include /* Clock info (for break generation) */ #endif #endif #endif #endif #ifdef BSD41 #include /* BSD 4.1 ... ceb */ #endif #ifdef BSD29 #include /* BSD 2.9 (Vic Abell, Purdue) */ #endif #ifdef TOWER1 #include /* Clock info for NCR Tower */ #endif /* Declarations */ long time(); /* All Unixes should have this... */ extern int errno; /* System call error return */ /* Special stuff for V7 input buffer peeking */ #ifdef V7 int kmem[2] = { -1, -1}; char *initrawq(), *qaddr[2]={0,0}; #define CON 0 #define TTY 1 #endif /* dftty is the device name of the default device for file transfer */ /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */ #ifdef PROVX1 char *dftty = "/dev/com1.dout"; /* Only example so far of a system */ int dfloc = 1; /* that goes in local mode by default */ #else char *dftty = CTTNAM; /* Remote by default, use normal */ int dfloc = 0; /* controlling terminal name. */ #endif int dfprty = 0; /* Parity (0 = none) */ int dfflow = 1; /* Xon/Xoff flow control */ int backgrd = 0; /* Assume in foreground (no '&' ) */ int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */ /* Declarations of variables global within this module */ static long tcount; /* Elapsed time counter */ static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */ static jmp_buf sjbuf, jjbuf; /* Longjump buffer */ static int lkf = 0, /* Line lock flag */ conif = 0, /* Console interrupts on/off flag */ cgmf = 0, /* Flag that console modes saved */ xlocal = 0, /* Flag for tty local or remote */ ttyfd = -1; /* TTY file descriptor */ static char escchr; /* Escape or attn character */ /* Special line discipline, 4.2bsd only, and only with kernel mods... */ #ifdef KERLD static int kerld = 1; /* Special Kermit line discipline... */ struct tchars oldc, newc; /* Special characters */ int ld = NETLDISC; /* Really a hack to "Berknet" l.d. */ int oldld; /* Old discipline */ #else static int kerld = 0; /* Not selected, no special l.d. */ #endif #ifdef BSD42 static struct timeval tv; /* For getting time, from sys/time.h */ static struct timezone tz; #endif #ifdef BSD29 static long clock; /* For getting time from sys/time.h */ static struct timeb ftp; /* And from sys/timeb.h */ #endif #ifdef BSD41 static long clock; /* For getting time from sys/time.h */ static struct timeb ftp; /* And from sys/timeb.h */ #endif #ifdef TOWER1 static long clock; /* For getting time from sys/time.h */ static struct timeb ftp; /* And from sys/timeb.h */ #endif #ifdef V7 static long clock; #endif #ifdef UXIII static struct termio /* sgtty info... */ ttold, ttraw, tttvt, /* for communication line */ ccold, ccraw, cccbrk; /* and for console */ #else static struct sgttyb /* sgtty info... */ ttold, ttraw, tttvt, ttbuf, /* for communication line */ ccold, ccraw, cccbrk; /* and for console */ #endif static char flfnam[80]; /* uucp lock file path name */ static int hasLock = 0; /* =1 if this kermit locked uucp */ static int inbufc = 0; /* stuff for efficient SIII raw line */ static int ungotn = -1; /* pushback to unread character */ static int conesc = 0; /* set to 1 if esc char (^\) typed */ static int ttlock(); /* definition of ttlock subprocedure */ static int ttunlck(); /* and unlock subprocedure */ static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */ /* S Y S I N I T -- System-dependent program initialization. */ sysinit() { /* for now, nothing... */ return(0); } /* T T O P E N -- Open a tty for exclusive access. */ /* Returns 0 on success, -1 on failure. */ /* If called with lcl < 0, sets value of lcl as follows: 0: the terminal named by ttname is the job's controlling terminal. 1: the terminal named by ttname is not the job's controlling terminal. But watch out: if a line is already open, or if requested line can't be opened, then lcl remains (and is returned as) -1. */ ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; { #ifdef UXIII char *ctermid(); /* Wish they all had this! */ #endif char *x; extern char* ttyname(); char cname[DEVNAMLEN+4]; if (ttyfd > -1) return(0); /* If already open, ignore this call */ xlocal = *lcl; /* Make this available to other fns */ #ifdef NEWUUCP acucntrl("disable",ttname); /* Open getty on line (4.3BSD) */ #endif #ifdef UXIII /* if modem connection, don't wait for carrier */ ttyfd = open(ttname,O_RDWR | (modem ? O_NDELAY : 0) ); #else ttyfd = open(ttname,2); /* Try to open for read/write */ #endif if (ttyfd < 0) { /* If couldn't open, fail. */ perror(ttname); return(-1); } strncpy(ttnmsv,ttname,DEVNAMLEN); /* Open, keep copy of name locally. */ /* Caller wants us to figure out if line is controlling tty */ debug(F111,"ttopen ok",ttname,*lcl); if (*lcl == -1) { if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */ debug(F110," Same as CTTNAM",ttname,0); xlocal = 0; } else if (isatty(0)) { /* Else, if stdin not redirected */ x = ttyname(0); /* then compare its device name */ strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */ debug(F110," ttyname(0)",x,0); x = ttyname(ttyfd); /* ...with real name of ttname. */ xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; debug(F111," ttyname",x,xlocal); } else { /* Else, if stdin redirected... */ #ifdef UXIII /* Sys III/V provides nice ctermid() function to get name of controlling tty */ ctermid(cname); /* Get name of controlling terminal */ debug(F110," ctermid",cname,0); x = ttyname(ttyfd); /* Compare with name of comm line. */ xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; debug(F111," ttyname",x,xlocal); #else /* Just assume local, so "set speed" and similar commands will work */ /* If not really local, how could it work anyway?... */ xlocal = 1; debug(F101," redirected stdin","",xlocal); #endif } } /* Now check if line is locked -- if so fail, else lock for ourselves */ lkf = 0; /* Check lock */ if (xlocal > 0) { if (ttlock(ttname) < 0) { fprintf(stderr,"Exclusive access to %s denied\n",ttname); close(ttyfd); ttyfd = -1; debug(F110," Access denied by lock",ttname,0); return(-1); /* Not if already locked */ } else lkf = 1; } /* Got the line, now set the desired value for local. */ if (*lcl < 0) *lcl = xlocal; /* Some special stuff for v7... */ #ifdef V7 #ifndef MINIX if (kmem[TTY] < 0) { /* If open, then skip this. */ qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */ if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) { fprintf(stderr, "Can't read /dev/kmem in ttopen.\n"); perror("/dev/kmem"); exit(1); } } #endif #endif V7 /* Request exclusive access on systems that allow it. */ #ifndef XENIX /* Xenix exclusive access prevents open(close(...)) from working... */ #ifdef TIOCEXCL if (ioctl(ttyfd,TIOCEXCL, NULL) < 0) fprintf(stderr,"Warning, problem getting exclusive access\n"); #endif #endif /* Get tty device settings */ #ifndef UXIII gtty(ttyfd,&ttold); /* Get sgtty info */ gtty(ttyfd,&ttraw); /* And a copy of it for packets*/ gtty(ttyfd,&tttvt); /* And one for virtual tty service */ #else ioctl(ttyfd,TCGETA,&ttold); /* Same deal for Sys III, Sys V */ ioctl(ttyfd,TCGETA,&ttraw); ioctl(ttyfd,TCGETA,&tttvt); #endif debug(F101,"ttopen, ttyfd","",ttyfd); debug(F101," lcl","",*lcl); debug(F111," lock file",flfnam,lkf); return(0); } /* T T C L O S -- Close the TTY, releasing any lock. */ ttclos() { if (ttyfd < 0) return(0); /* Wasn't open. */ if (xlocal) { if (tthang()) /* Hang up phone line */ fprintf(stderr,"Warning, problem hanging up the phone\n"); if (ttunlck()) /* Release uucp-style lock */ fprintf(stderr,"Warning, problem releasing lock\n"); } ttres(); /* Reset modes. */ /* Relinquish exclusive access if we might have had it... */ #ifndef XENIX #ifdef TIOCEXCL #ifdef TIOCNXCL if (ioctl(ttyfd, TIOCNXCL, NULL) < 0) fprintf(stderr,"Warning, problem relinquishing exclusive access\n"); #endif #endif #endif close(ttyfd); /* Close it. */ #ifdef NEWUUCP acucntrl("enable",flfnam); /* Close getty on line. */ #endif ttyfd = -1; /* Mark it as closed. */ return(0); } /* T T H A N G -- Hangup phone line */ tthang() { #ifdef UXIII unsigned short ttc_save; #endif if (ttyfd < 0) return(0); /* Not open. */ #ifdef ANYBSD ioctl(ttyfd,TIOCCDTR,0); /* Clear DTR */ msleep(500); /* Let things settle */ ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */ #endif #ifdef UXIII ttc_save = ttraw.c_cflag; ttraw.c_cflag &= ~CBAUD; /* swa: set baud rate to 0 to hangup */ if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */ msleep(100); /* let things settle */ ttraw.c_cflag = ttc_save; #ifndef XENIX /* xenix cannot do close/open when carrier drops */ /* following corrects a PC/IX defficiency */ ttc_save = fcntl(ttyfd,F_GETFL,0); close(ttyfd); /* close/reopen file descriptor */ if ((ttyfd = open(ttnmsv, ttc_save)) < 0) return(-1); #endif if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */ #endif return (0); } /* T T R E S -- Restore terminal to "normal" mode. */ ttres() { /* Restore the tty to normal. */ if (ttyfd < 0) return(-1); /* Not open. */ #ifndef UXIII /* except for sIII, */ sleep(1); /* Wait for pending i/o to finish. */ #endif /* (sIII does wait in ioctls) */ #ifdef KERLD if (kerld) ioctl(ttyfd,TIOCSETD,&oldld); /* Restore old line discipline. */ #endif #ifdef UXIII if (ioctl(ttyfd,TCSETAW,&ttold) < 0) return(-1); /* restore termio stuff */ #else if (stty(ttyfd,&ttold) < 0) return(-1); /* Restore sgtty stuff */ #endif #ifdef KERLD if (kerld) ioctl(ttyfd,TIOCSETC,&oldc); /* Restore old special chars. */ #endif return(0); } #ifdef MINIX #ifndef NOLOCKS #define NOLOCKS #endif #endif #ifdef NOLOCKS /* why bother with all the locking code on little systems that don't care? */ ttlock() { return 0; } ttunlck() { return 0; } #else /* Exclusive uucp file locking control */ /* by H. Fischer, creative non-Bell coding ! copyright rights for lock modules assigned to Columbia University */ static char * xxlast(s,c) char *s; char c; { /* Equivalent to strrchr() */ int i; for (i = strlen(s); i > 0; i--) if ( s[i-1] == c ) return( s + (i - 1) ); return(NULL); } static look4lk(ttname) char *ttname; { extern char *strcat(), *strcpy(); char *device, *devname; char lockfil[50]; /* Max length for lock file name */ #ifdef ISIII char *lockdir = "/etc/locks"; #else #ifdef ATT3BX char *lockdir = "/usr/spool/locks"; #else #ifdef NEWUUCP char *lockdir = "/usr/spool/uucp/LCK"; #else char *lockdir = "/usr/spool/uucp"; #endif #endif #endif device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname); #ifdef ISIII (void) strcpy( lockfil, device ); #else strcat( strcpy( lockfil, "LCK.." ), device ); #endif if (access( lockdir, 04 ) < 0) { /* read access denied on lock dir */ fprintf(stderr,"Warning, read access to lock directory denied\n"); return( 1 ); /* cannot check or set lock file */ } strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil); debug(F110,"look4lk",flfnam,0); if ( ! access( flfnam, 00 ) ) { /* print out lock file entry */ char lckcmd[40] ; strcat( strcpy(lckcmd, "ls -l ") , flfnam); system(lckcmd); if (access(flfnam,02) == 0) printf("(You may type \"! rm %s\" to remove this file)\n",flfnam); return( -1 ); } if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */ fprintf(stderr,"Warning, write access to lock directory denied\n"); return( 1 ); } return( 0 ); /* okay to go ahead and lock */ } /* T T L O C K */ static ttlock(ttyfd) char *ttyfd; { /* lock uucp if possible */ #ifdef ATT3BX FILE *lck_fild; #endif int lck_fil, l4l; int pid_buf = getpid(); /* pid to save in lock file */ hasLock = 0; /* not locked yet */ l4l = look4lk(ttyfd); if (l4l < 0) return (-1); /* already locked */ if (l4l == 1) return (0); /* can't read/write lock directory */ lck_fil = creat(flfnam, 0444); /* create lock file ... */ if (lck_fil < 0) return (-1); /* create of lockfile failed */ /* creat leaves file handle open for writing -- hf */ #ifdef ATT3BX fprintf((lck_fild = fdopen(lck_fil, "w")), "%10d\n", pid_buf); fflush(lck_fild); #else write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */ #endif close (lck_fil); hasLock = 1; /* now is locked */ return(0); } /* T T U N L O C K */ static ttunlck() { /* kill uucp lock if possible */ if (hasLock) return( unlink( flfnam ) ); } #endif /* NOLOCKS */ /* New-style (4.3BSD) UUCP line direction control (Stan Barber, Rice U) */ #ifdef NEWUUCP acucntrl(flag,ttname) char *flag, *ttname; { char x[DEVNAMLEN+32], *device, *devname; if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */ return; /* just return. */ device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname); if (strncmp(device,"LCK..",4) == 0) device += 5; sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device); debug(F000,"called ",x,0); system(x); } #endif /* T T P K T -- Condition the communication line for packets. */ /* or for modem dialing */ #define DIALING 4 /* flags (via flow) for modem handling */ #define CONNECT 5 /* If called with speed > -1, also set the speed. */ /* Returns 0 on success, -1 on failure. */ ttpkt(speed,flow) int speed, flow; { int s; if (ttyfd < 0) return(-1); /* Not open. */ #ifdef KERLD /* Note, KERLD ignores the TANDEM, ECHO, and CRMOD bits */ if (kerld) { ioctl(ttyfd,TIOCGETD,&oldld); /* Get line discipline */ ioctl(ttyfd,TIOCGETC,&oldc); /* Get special chars */ newc = oldc; /* Copy special chars */ newc.t_brkc = '\r'; /* Set CR to be break character */ if(ioctl(ttyfd,TIOCSETC,&newc) < 0) return(-1); } #endif s = ttsspd(speed); /* Check the speed */ #ifndef UXIII if (flow == 1) ttraw.sg_flags |= TANDEM; /* Use XON/XOFF if selected */ if (flow == 0) ttraw.sg_flags &= ~TANDEM; ttraw.sg_flags |= RAW; /* Go into raw mode */ ttraw.sg_flags &= ~(ECHO|CRMOD); /* Use CR for break character */ #ifdef TOWER1 ttraw.sg_flags &= ~ANYP; /* Must tell Tower no parityr */ #endif if (s > -1) ttraw.sg_ispeed = ttraw.sg_ospeed = s; /* Do the speed */ if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */ #ifdef MYREAD #ifdef BSD4 /* Try to make reads nonblocking */ if (kerld == 0) { if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1) return(-1); else return(0); } #endif #endif #endif #ifdef UXIII if (flow == 1) ttraw.c_iflag |= (IXON|IXOFF); if (flow == 0) ttraw.c_iflag &= ~(IXON|IXOFF); if (flow == DIALING) ttraw.c_cflag |= CLOCAL|HUPCL; if (flow == CONNECT) ttraw.c_cflag &= ~CLOCAL; ttraw.c_lflag &= ~(ICANON|ECHO); ttraw.c_lflag |= ISIG; /* do check for interrupt */ ttraw.c_iflag |= (BRKINT|IGNPAR); ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY); ttraw.c_oflag &= ~OPOST; ttraw.c_cflag &= ~(CSIZE|PARENB); ttraw.c_cflag |= (CS8|CREAD); ttraw.c_cc[4] = 1; ttraw.c_cc[5] = 0; if (s > -1) { /* set speed */ ttraw.c_cflag &= ~CBAUD; ttraw.c_cflag |= s; } if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */ if (flow == DIALING) { if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) return(-1); close( open(ttnmsv,2) ); /* magic to force mode change!!! */ } #endif #ifdef KERLD if (kerld) { if (ioctl(ttyfd,TIOCSETD,&ld) < 0) return(-1); /* Set line discpline. */ } #endif ttflui(); /* Flush any pending input */ return(0); } /* T T V T -- Condition communication line for use as virtual terminal */ ttvt(speed,flow) int speed, flow; { int s; if (ttyfd < 0) return(-1); /* Not open. */ s = ttsspd(speed); /* Check the speed */ #ifndef UXIII if (flow == 1) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */ if (flow == 0) tttvt.sg_flags &= ~TANDEM; tttvt.sg_flags |= RAW; /* Raw mode */ #ifdef TOWER1 tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or system III ??? parity */ #else tttvt.sg_flags &= ~ECHO; /* No echo */ #endif if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */ if (stty(ttyfd,&tttvt) < 0) return(-1); #ifdef MYREAD #ifdef BSD4 /* Make reads nonblocking */ if (kerld == 0) { if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1) return(-1); else return(0); } #endif #endif #else if (flow == 1) tttvt.c_iflag |= (IXON|IXOFF); if (flow == 0) tttvt.c_iflag &= ~(IXON|IXOFF); if (flow == DIALING) tttvt.c_cflag |= CLOCAL|HUPCL; if (flow == CONNECT) tttvt.c_cflag &= ~CLOCAL; tttvt.c_lflag &= ~(ISIG|ICANON|ECHO); tttvt.c_iflag |= (IGNBRK|IGNPAR); tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY); tttvt.c_oflag &= ~OPOST; tttvt.c_cflag &= ~(CSIZE|PARENB); tttvt.c_cflag |= (CS8|CREAD); tttvt.c_cc[4] = 1; tttvt.c_cc[5] = 0; if (s > -1) { /* set speed */ tttvt.c_cflag &= ~CBAUD; tttvt.c_cflag |= s; } if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */ if (flow == DIALING) { if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) return(-1); close( open(ttnmsv,2) ); /* magic to force mode change!!! */ } return(0); #endif } /* T T S S P D -- Return the internal baud rate code for 'speed'. */ ttsspd(speed) { int s, spdok; if (speed < 0) return(-1); spdok = 1; /* Assume arg ok */ switch (speed) { case 0: s = B0; break; /* Just the common ones. */ case 110: s = B110; break; /* The others from ttydev.h */ case 150: s = B150; break; /* could also be included if */ case 300: s = B300; break; /* necessary... */ case 600: s = B600; break; case 1200: s = B1200; break; case 1800: s = B1800; break; case 2400: s = B2400; break; case 4800: s = B4800; break; case 9600: s = B9600; break; #ifdef PLEXUS case 19200: s = EXTA; break; #endif default: spdok = 0; fprintf(stderr,"Unsupported line speed - %d\n",speed); fprintf(stderr,"Current speed not changed\n"); break; } if (spdok) return(s); else return(-1); } /* T T F L U I -- Flush tty input buffer */ ttflui() { #ifndef UXIII long n; #endif if (ttyfd < 0) return(-1); /* Not open. */ ungotn = -1; /* Initialize myread() stuff */ inbufc = 0; #ifdef UXIII if (ioctl(ttyfd,TCFLSH,0) < 0) perror("flush failed"); #else #ifdef TIOCFLUSH #ifdef ANYBSD n = FREAD; /* Specify read queue */ if (ioctl(ttyfd,TIOCFLUSH,&n) < 0) perror("flush failed"); #else if (ioctl(ttyfd,TIOCFLUSH,0) < 0) perror("flush failed"); #endif #endif #endif return(0); } /* Interrupt Functions */ /* Timeout handler for communication line input functions */ timerh() { longjmp(sjbuf,1); } /* Set up terminal interrupts on console terminal */ #ifdef UXIII esctrp() { /* trap console escapes (^\) */ conesc = 1; signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ } #endif #ifdef V7 esctrp() { /* trap console escapes (^\) */ conesc = 1; signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ } #endif #ifdef C70 esctrp() { /* trap console escapes (^\) */ conesc = 1; signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ } #endif /* C O N I N T -- Console Interrupt setter */ conint(f) int (*f)(); { /* Set an interrupt trap. */ if (!isatty(0)) return(0); /* only for real ttys */ if (backgrd) return; /* must ignore signals in bkgrd */ /* Except for special cases below, ignore keyboard quit signal. ^\ too easily confused with connect escape, and besides, we don't want to leave lock files around. (Frank Prindle) */ signal(SIGQUIT,SIG_IGN); #ifdef UXIII signal(SIGQUIT,esctrp); /* console escape in pkt modes */ if (conesc) { /* clear out pending escapes */ conesc = 0; } #endif #ifdef V7 signal(SIGQUIT,esctrp); /* console escape in pkt modes */ if (conesc) { /* clear out pending escapes */ conesc = 0; } #endif if (conif) return; /* Nothing to do if already on. */ /* check if invoked in background -- if so signals set to be ignored */ if (signal(SIGINT,SIG_IGN) == SIG_IGN) { backgrd = 1; /* means running in background */ #ifdef UXIII signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */ #endif #ifdef V7 signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */ #endif return; } signal(SIGINT,f); /* Function to trap to on interrupt. */ signal(SIGHUP,f); /* Or hangup, so lock file cleared. */ conif = 1; /* Flag console interrupts on. */ } /* C O N N O I -- Reset console terminal interrupts */ connoi() { /* Console-no-interrupts */ if (!isatty(0)) return(0); /* only for real ttys */ if (backgrd) return; /* Ignore signals in background */ signal(SIGINT,SIG_DFL); signal(SIGHUP,SIG_DFL); signal(SIGQUIT,SIG_DFL); conif = 0; /* Flag interrupt trapping off */ } /* myread() -- For use by systems that can do nonblocking read() calls */ /* Returns: -1 if no characters available, -2 upon error (such as disconnect), otherwise value of character (0 or greater) */ myread() { static int inbuf_item; static CHAR inbuf[257]; CHAR readit; if (ungotn >= 0) { readit = ungotn; } else { if (inbufc > 0) { readit = inbuf[++inbuf_item]; } else { if ((inbufc = read(ttyfd,inbuf,256)) == 0) { /* end of file */ /* means carrier dropped on modem connection */ errno = 9999; /* magic number for no carrier */ return(-2); /* end of file has no errno */ } if (inbufc < 0) { /* Real error */ return(-2); } readit = inbuf[inbuf_item = 0]; } inbufc--; } ungotn = -1; return(((int)readit) & 0377); } myunrd(ch) CHAR ch; { /* push back up to one character */ ungotn = ch; } /* I N I T R A W Q -- Set up to read /DEV/KMEM for character count. */ #ifdef V7 #ifndef MINIX /* Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This eliminates blocking on a read, because we can read /dev/kmem to get the number of characters available for raw input. If your system can't or you won't let it read /dev/kmem (the world that is) then you must figure out a different way to do the counting of characters available, or else replace this by a dummy function that always returns 0. */ /* * Call this routine as: initrawq(tty) * where tty is the file descriptor of a terminal. It will return * (as a char *) the kernel-mode memory address of the rawq character * count, which may then be read. It has the side-effect of flushing * input on the terminal. */ /* * John Mackin, Physiology Dept., University of Sydney (Australia) * ...!decvax!mulga!physiol.su.oz!john * * Permission is hereby granted to do anything with this code, as * long as this comment is retained unmodified and no commercial * advantage is gained. */ #include #include char *initrawq(tty) int tty; { #ifdef UTS24 return(0); #else #ifdef BSD29 return(0); #else long lseek(); static struct nlist nl[] = { {PROCNAME}, {NPROCNAME}, {""} }; static struct proc *pp; char *malloc(), *qaddr, *p, c; int m, pid, me; NPTYPE xproc; /* Its type is defined in makefile. */ int catch(); me = getpid(); if ((m = open("/dev/kmem", 0)) < 0) err("kmem"); nlist(BOOTNAME, nl); if (nl[0].n_type == 0) err("proc array"); if (nl[1].n_type == 0) err("nproc"); lseek(m, (long)(nl[1].n_value), 0); read (m, &xproc, sizeof(xproc)); signal(SIGALRM, catch); if ((pid = fork()) == 0) { while(1) read(tty, &c, 1); } alarm(2); if(setjmp(jjbuf) == 0) { while(1) read(tty, &c, 1); } signal(SIGALRM, SIG_DFL); #ifdef DIRECT pp = (struct proc *) nl[0].n_value; #else if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek"); if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr"); #endif lseek(m, (long)(nl[1].n_value), 0); read(m, &xproc, sizeof(xproc)); if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc"); if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc"); if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc)) err("read proc table"); for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) { if (pp -> p_pid == (short) pid) goto iout; } err("no such proc"); iout: close(m); qaddr = (char *)(pp -> p_wchan); free (p); kill(pid, SIGKILL); wait((int *)0); /* Destroy the ZOMBIEs! */ return (qaddr); #endif #endif } /* More V7-support functions... */ static err(s) char *s; { char buf[200]; sprintf(buf, "fatal error in initrawq: %s", s); perror(buf); doexit(1); } static catch() { longjmp(jjbuf, -1); } #endif MINIX /* G E N B R K -- Simulate a modem break. */ #define BSPEED B150 genbrk(fn) int fn; { struct sgttyb ttbuf; int ret, sospeed; ret = ioctl(fn, TIOCGETP, &ttbuf); sospeed = ttbuf.sg_ospeed; ttbuf.sg_ospeed = BSPEED; ret = ioctl(fn, TIOCSETP, &ttbuf); ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", 8); ttbuf.sg_ospeed = sospeed; ret = ioctl(fn, TIOCSETP, &ttbuf); ret = write(fn, "@", 1); return; } #endif V7 /* T T C H K -- Tell how many characters are waiting in tty input buffer */ ttchk() { int x; long n; #ifdef MYREAD if ((x = inbufc + (ungotn >= 0)) > 0) return x; #endif #ifdef FIONREAD x = ioctl(ttyfd, FIONREAD, &n); /* Berkeley and maybe some others */ debug(F101,"ttchk","",n); return((x < 0) ? 0 : n); #else #ifdef V7 #ifndef MINIX lseek(kmem[TTY], (long) qaddr[TTY], 0); x = read(kmem[TTY], &n, sizeof(int)); return((x == sizeof(int))? n: 0); #endif #else V7 #ifdef PROVX1 x = ioctl(ttyfd, TIOCQCNT, &ttbuf); n = ttbuf.sg_ispeed & 0377; return((x < 0) ? 0 : n); #else return(0); #endif #endif #endif } /* T T X I N -- Get n characters from tty input buffer */ /* Returns number of characters actually gotten, or -1 on failure */ /* Intended for use only when it is known that n characters are actually */ /* Available in the input buffer. */ ttxin(n,buf) int n; char *buf; { int x; CHAR c; #ifdef MYREAD for( x = 0; (x > -1) && (x < n); buf[x++] = myread() ); #else debug(F101,"ttxin: n","",n); x = read(ttyfd,buf,n); debug(F101," x","",x); #endif if (x > 0) buf[x] = '\0'; if (x < 0) x = -1; return(x); } /* T T O L -- Similar to "ttinl", but for writing. */ ttol(s,n) int n; char *s; { int x; if (ttyfd < 0) return(-1); /* Not open. */ x = write(ttyfd,s,n); debug(F111,"ttol",s,n); if (x < 0) debug(F101,"ttol failed","",x); return(x); } /* T T O C -- Output a character to the communication line */ ttoc(c) char c; { if (ttyfd < 0) return(-1); /* Not open. */ return(write(ttyfd,&c,1)); } /* T T I N L -- Read a record (up to break character) from comm line. */ /* If no break character encountered within "max", return "max" characters, with disposition of any remaining characters undefined. Otherwise, return the characters that were read, including the break character, in "dest" and the number of characters read as the value of function, or 0 upon end of file, or -1 if an error occurred. Times out & returns error if not completed within "timo" seconds. */ ttinl(dest,max,timo,eol) int max,timo; char *dest; char eol; { int x, y; CHAR c; if (ttyfd < 0) return(-1); /* Not open. */ if (timo <= 0) { /* Untimed read... */ #ifdef MYREAD for (x = c = 0; (x < max) && (c != eol); x++) { while ((y = myread()) == -1) ; if (y == -2) return(-1); dest[x] = c = y & 0377; } #else x = read(ttyfd,dest,max); /* Try to read. */ #endif return(x); /* Return the count. */ } /* Timed read... */ signal(SIGALRM,timerh); /* Set up timeout action. */ alarm(timo); /* Set the timer. */ if (setjmp(sjbuf)) /* Do this if timer went off. */ x = -1; else if (kerld) { /* Efficient Kermit line discipline */ x = read(ttyfd,dest,max); /* for 4.2bsd only... */ } else { /* Normal case... */ for (x = c = y = 0; (x < max) && (c != eol); x++) { #ifdef MYREAD while ((y = myread()) == -1) /* Use own buffering if we can */ ; if (y == -2) y++; c = y & 0377; #else while ((y = read(ttyfd,&c,1)) == 0) /* Else call system */ ; /* ...for each character. */ #endif if (y < 0) { alarm(0); /* Error, turn off timer, */ signal(SIGALRM,SIG_DFL); /* and associated interrupt. */ return(y); /* Return the error indication. */ } dest[x] = c; } x++; } alarm(0); /* Success, turn off timer, */ signal(SIGALRM,SIG_DFL); /* and associated interrupt. */ return(x); /* Return the count. */ } /* T T I N C -- Read a character from the communication line */ ttinc(timo) int timo; { int n = 0; CHAR ch = 0; if (ttyfd < 0) return(-1); /* Not open. */ if (timo <= 0) { /* Untimed. */ #ifdef MYREAD /* comm line failure returns -1 thru myread, so no &= 0377 */ while ((n = myread()) == -1) ; /* Wait for a character... */ if (n == -2) n++; return( n ); #else while ((n = read(ttyfd,&ch,1)) == 0) ; /* Wait for a character. */ return( (n > 0) ? (ch & 0377) : n ); #endif } signal(SIGALRM,timerh); /* Timed, set up timer. */ alarm(timo); if (setjmp(sjbuf)) { n = -1; } else { #ifdef MYREAD while ((n = myread()) == -1) ; /* If managing own buffer... */ if (n == -2) { n++; } else { ch = n; n = 1; } #else n = read(ttyfd,&ch,1); /* Otherwise call the system. */ #endif } alarm(0); /* Turn off timer, */ signal(SIGALRM,SIG_DFL); /* and interrupt. */ return( (n > 0) ? (ch & 0377) : n ); /* Return char or -1. */ } /* T T S N D B -- Send a BREAK signal */ ttsndb() { int x; long n; char spd; if (ttyfd < 0) return(-1); /* Not open. */ #ifdef PROVX1 gtty(ttyfd,&ttbuf); /* Get current tty flags */ spd = ttbuf.sg_ospeed; /* Save speed */ ttbuf.sg_ospeed = B50; /* Change to 50 baud */ stty(ttyfd,&ttbuf); /* ... */ write(ttyfd,brnuls,3); /* Send 3 nulls */ ttbuf.sg_ospeed = spd; /* Restore speed */ stty(ttyfd,&ttbuf); /* ... */ return(0); #else #ifdef UXIII if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) { /* Send a BREAK */ perror("Can't send BREAK"); return(-1); } return(0); #else #ifdef ANYBSD n = FWRITE; /* Flush output queue. */ ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */ if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */ perror("Can't send BREAK"); return(-1); } x = msleep(275); /* Sleep for so many milliseconds */ if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */ perror("BREAK stuck!!!"); doexit(1); /* Get out, closing the line. */ /* with exit status = 1 */ } return(x); #else #ifdef V7 genbrk(ttyfd); /* Simulate a BREAK */ return(x); #endif #endif #endif #endif } /* M S L E E P -- Millisecond version of sleep(). */ /* Intended only for small intervals. For big ones, just use sleep(). */ msleep(m) int m; { #ifdef PROVX1 if (m <= 0) return(0); sleep(-((m * 60 + 500) / 1000)); return(0); #endif #ifdef ANYBSD int t1, t3, t4; if (m <= 0) return(0); #ifndef BSD42 /* 2.9 and 4.1 BSD do it this way */ if (ftime(&ftp) < 0) return(-1); /* Get current time. */ t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; while (1) { ftime(&ftp); /* new time */ t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1; if (t3 > m) return (t3); } #else /* 4.2 & above can do it with select()... */ if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */ t1 = tv.tv_sec; /* Seconds */ tv.tv_sec = 0; /* Use select() */ tv.tv_usec = m * 1000; return(select( 0, (int *)0, (int *)0, (int *)0, &tv) ); #endif #endif #ifdef UXIII #ifdef XENIX #define CLOCK_TICK 50 /* millisecs per clock tick */ #else #define CLOCK_TICK 17 /* 1/60 sec */ #endif extern long times(); long t1, t2, tarray[4]; int t3; if (m <= 0) return(0); if ((t1 = times(tarray)) < 0) return(-1); while (1) { if ((t2 = times(tarray)) < 0) return(-1); t3 = ((int)(t2 - t1)) * CLOCK_TICK; if (t3 > m) return(t3); } #endif #ifdef TOWER1 int t1, t3; if (m <= 0) return(0); if (ftime(&ftp) < 0) return(-1); /* Get current time. */ t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; while (1) { ftime(&ftp); /* new time */ t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1; if (t3 > m) return (t3); } #endif } /* R T I M E R -- Reset elapsed time counter */ rtimer() { tcount = time( (long *) 0 ); } /* G T I M E R -- Get current value of elapsed time counter in seconds */ gtimer() { int x; x = (int) (time( (long *) 0 ) - tcount); rtimer(); return( (x < 0) ? 0 : x ); } /* Z T I M E -- Return date/time string */ ztime(s) char **s; { #ifdef UXIII extern long time(); /* Sys III/V way to do it */ char *ctime(); long clock_storage; clock_storage = time( (long *) 0 ); *s = ctime( &clock_storage ); #endif #ifdef PROVX1 int utime[2]; /* Venix way */ time(utime); *s = ctime(utime); #endif #ifdef ANYBSD char *asctime(); /* Berkeley way */ struct tm *localtime(); struct tm *tp; #ifdef BSD42 gettimeofday(&tv, &tz); /* BSD 4.2 */ time(&tv.tv_sec); tp = localtime(&tv.tv_sec); #else time(&clock); /* BSD 4.1, 2.9 ... ceb */ tp = localtime(&clock); #endif *s = asctime(tp); #endif #ifdef TOWER1 char *asctime(); /* Tower way */ struct tm *localtime(); struct tm *tp; time(&clock); tp = localtime(&clock); *s = asctime(tp); #endif #ifdef V7 char *asctime(); /* V7 way */ struct tm *localtime(); struct tm *tp; time(&clock); tp = localtime(&clock); *s = asctime(tp); #endif } /* C O N G M -- Get console terminal modes. */ /* Saves current console mode, and establishes variables for switching between current (presumably normal) mode and other modes. */ congm() { if (!isatty(0)) return(0); /* only for real ttys */ #ifndef UXIII gtty(0,&ccold); /* Structure for restoring */ gtty(0,&cccbrk); /* For setting CBREAK mode */ gtty(0,&ccraw); /* For setting RAW mode */ #else ioctl(0,TCGETA,&ccold); ioctl(0,TCGETA,&cccbrk); ioctl(0,TCGETA,&ccraw); #endif cgmf = 1; /* Flag that we got them. */ } /* C O N C B -- Put console in cbreak mode. */ /* Returns 0 if ok, -1 if not */ concb(esc) char esc; { int x; if (!isatty(0)) return(0); /* only for real ttys */ if (cgmf == 0) congm(); /* Get modes if necessary. */ escchr = esc; /* Make this available to other fns */ ckxech = 1; /* Program can echo characters */ #ifndef UXIII cccbrk.sg_flags |= CBREAK; /* Set to character wakeup, */ cccbrk.sg_flags &= ~ECHO; /* no echo. */ x = stty(0,&cccbrk); #else cccbrk.c_lflag &= ~(ICANON|ECHO); cccbrk.c_cc[0] = 003; /* interrupt char is control-c */ cccbrk.c_cc[1] = escchr; /* escape during packet modes */ cccbrk.c_cc[4] = 1; cccbrk.c_cc[5] = 1; x = ioctl(0,TCSETAW,&cccbrk); /* set new modes . */ #endif if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */ #ifdef V7 #ifndef MINIX if (kmem[CON] < 0) { qaddr[CON] = initrawq(0); if((kmem[CON] = open("/dev/kmem", 0)) < 0) { fprintf(stderr, "Can't read /dev/kmem in concb.\n"); perror("/dev/kmem"); exit(1); } } #endif #endif V7 return(x); } /* C O N B I N -- Put console in binary mode */ /* Returns 0 if ok, -1 if not */ conbin(esc) char esc; { if (!isatty(0)) return(0); /* only for real ttys */ if (cgmf == 0) congm(); /* Get modes if necessary. */ escchr = esc; /* Make this available to other fns */ ckxech = 1; /* Program can echo characters */ #ifndef UXIII ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF */ ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */ return(stty(0,&ccraw)); #else ccraw.c_lflag &= ~(ISIG|ICANON|ECHO); ccraw.c_iflag |= (BRKINT|IGNPAR); ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF |INPCK|ISTRIP); ccraw.c_oflag &= ~OPOST; /*** Kermit used to put the console in 8-bit raw mode, but some users have *** pointed out that this should not be done, since some sites actually *** use terminals with parity settings on their Unix systems, and if we *** override the current settings and stop doing parity, then their terminals *** will display blotches for characters whose parity is wrong. Therefore, *** the following two lines are commented out (Larry Afrin, Clemson U): *** *** ccraw.c_cflag &= ~(PARENB|CSIZE); *** ccraw.c_cflag |= (CS8|CREAD); *** *** Sys III/V sites that have trouble with this can restore these lines. ***/ ccraw.c_cc[4] = 1; ccraw.c_cc[5] = 1; return(ioctl(0,TCSETAW,&ccraw) ); /* set new modes . */ #endif } /* C O N R E S -- Restore the console terminal */ conres() { if (cgmf == 0) return(0); /* Don't do anything if modes */ if (!isatty(0)) return(0); /* only for real ttys */ #ifndef UXIII /* except for sIII, */ sleep(1); /* not known! */ #endif /* (sIII does wait in ioctls) */ ckxech = 0; /* System should echo chars */ #ifndef UXIII return(stty(0,&ccold)); /* Restore controlling tty */ #else return(ioctl(0,TCSETAW,&ccold)); #endif } /* C O N O C -- Output a character to the console terminal */ conoc(c) char c; { write(1,&c,1); } /* C O N X O -- Write x characters to the console terminal */ conxo(x,s) char *s; int x; { write(1,s,x); } /* C O N O L -- Write a line to the console terminal */ conol(s) char *s; { int len; len = strlen(s); write(1,s,len); } /* C O N O L A -- Write an array of lines to the console terminal */ conola(s) char *s[]; { int i; for (i=0 ; *s[i] ; i++) conol(s[i]); } /* C O N O L L -- Output a string followed by CRLF */ conoll(s) char *s; { conol(s); write(1,"\r\n",2); } /* C O N C H K -- Return how many characters available at console */ conchk() { int x; long n; #ifdef PROVX1 x = ioctl(0, TIOCQCNT, &ttbuf); n = ttbuf.sg_ispeed & 0377; return((x < 0) ? 0 : n); #else #ifdef V7 #ifndef MINIX lseek(kmem[CON], (long) qaddr[CON], 0); x = read(kmem[CON], &n, sizeof(int)); return((x == sizeof(int))? n: 0); #endif #else #ifdef UXIII if (conesc) { /* Escape typed */ conesc = 0; signal(SIGQUIT,esctrp); /* Restore escape */ return(1); } return(0); #else #ifdef C70 if (conesc) { /* Escape typed */ conesc = 0; signal(SIGQUIT,esctrp); /* Restore escape */ return(1); } return(0); #endif #endif #endif #endif #ifdef FIONREAD x = ioctl(0, FIONREAD, &n); /* BSD and maybe some others */ return((x < 0) ? 0 : n); #endif return(0); /* Others can't do. */ } /* C O N I N C -- Get a character from the console */ coninc(timo) int timo; { int n = 0; char ch; if (timo <= 0 ) { /* untimed */ n = read(0, &ch, 1); /* Read a character. */ ch &= 0377; if (n > 0) return(ch); /* Return the char if read */ else #ifdef UXIII if (n < 0 && errno == EINTR) /* if read was interrupted by QUIT */ return(escchr); /* user entered escape character */ else /* couldnt be ^c, sigint never returns */ #endif return(-1); /* Return the char, or -1. */ } signal(SIGALRM,timerh); /* Timed read, so set up timer */ alarm(timo); if (setjmp(sjbuf)) n = -2; else { n = read(0, &ch, 1); ch &= 0377; } alarm(0); /* Stop timing, we got our character */ signal(SIGALRM,SIG_DFL); if (n > 0) return(ch); else #ifdef UXIII if (n == -1 && errno == EINTR) /* If read interrupted by QUIT, */ return(escchr); /* user entered escape character, */ else /* can't be ^c, sigint never returns */ #endif return(-1); }