static char *sccsid = "@(#)miscio.c 1.3 2/3/83"; /* * miscio stuff: * * ttystrt/ttystop switch back and forth to character-at-a-time mode * catchem makes our program ignore kills and coredumps. * getnum is a char at a time input routine * gchar sucks in 1 character and masks off parity. */ #include "parms.h" #include "structs.h" #ifdef UNIX4.0 #include #else #include #endif /* #include */ #include #include static int modeset = 0; /* == 1 if ttyflags messed with */ static char t_erase, t_kill; short ospeed; /* for tputs padding */ int replot; #ifdef UNIX4.0 static struct termio tty, otty; #else static int oldmode; /* prev mode bits */ static struct sgttyb tty; #endif ttystrt() { static int initialized = 0; if (!initialized) { #ifdef UNIX4.0 x (ioctl(0, TCGETA, &tty) < 0, "ttystrt: gtty"); otty = tty; t_erase = tty.c_cc[VERASE]; t_kill = tty.c_cc[VKILL]; ospeed = tty.c_cflag & CBAUD; #else UNIX4.0 #ifdef V6 x (gtty(0, &tty) < 0, "ttystrt: gtty"); #else V6 x (ioctl(0, TIOCGETP, &tty) < 0, "ttystrt: gtty"); #endif V6 oldmode = tty.sg_flags; t_erase = tty.sg_erase; t_kill = tty.sg_kill; ospeed = tty.sg_ospeed; #endif UNIX4.0 initialized = 1; } if (!modeset) { #ifdef UNIX4.0 tty.c_lflag &= ~(ECHO|ICANON); tty.c_cc[VEOF] = 1; tty.c_cc[VEOL] = 1; x (ioctl(0, TCSETA, &tty) < 0, "ttystrt: stty"); #else UNIX4.0 tty.sg_flags |= CBREAK; tty.sg_flags &= ~ECHO; #ifdef V6 x (stty(0, &tty) < 0, "ttystrt: stty"); #else V6 x (ioctl(0, TIOCSETN, &tty) < 0, "ttystrt: stty"); #endif V6 #endif UNIX4.0 replot = 1; modeset = 1; } } ttystop() { if (modeset) { #ifndef UNIX4.0 tty.sg_flags = oldmode; #ifdef V6 if (stty(0, &tty) < 0) #else V6 if (ioctl(0, TIOCSETN, &tty) < 0) #endif V6 #else UNIX4.0 if (ioctl(0, TCSETA, &otty) < 0) #endif UNIX4.0 printf("ttystop: stty"); /* can't use x() cause it calls us */ modeset = 0; } } /* * return 1 if there is input from the terminal, * 0 otherwise. systems without the appropriate * call should always return 0. */ isinput() { #ifndef UNIX4.0 long retval; if (ioctl(0,FIONREAD,&retval) == 0) return(retval != 0); #endif return(0); } int ignsigs; struct notesenv curenv; static int (*osigint)(); static int (*osigquit)(); /* hold signal status */ #ifdef SIGTSTP static int (*osigtstp)(); /* control-z job stop */ #endif /* * the new fancy signal catcher. * for interrupts and quits. */ catchint(signo) { signal(signo, catchint); if (ignsigs) return; if (replot == 0) warn("Interrupt"); longjmp(jenv, 1); } #ifdef SIGTSTP /* * the new fancy signal handler * for ^Z/SIGTSTP */ catchz() { int wasset; signal(SIGTSTP, catchz); if (ignsigs) return; if ((wasset = modeset) != 0) { /* want assignment */ ttystop(); /* fix it up for user */ at(0, 1); fflush(stdout); } signal(SIGTSTP, SIG_DFL); /* make sure it nabs us */ kill(0, SIGTSTP); /* halt myself */ signal(SIGTSTP, catchz); /* ready to catch again */ if (wasset) ttystrt(); /* fix his tty */ longjmp(jenv); } #endif catchem() { osigint = signal(SIGINT, catchint); /* interrupts */ osigquit = signal(SIGQUIT, catchint); /* quits */ #ifdef SIGTSTP osigtstp = signal(SIGTSTP, catchz); /* control Z */ #endif } uncatchem() { signal(SIGINT, osigint); signal(SIGQUIT, osigquit); #ifdef SIGTSTP signal(SIGTSTP, osigtstp); #endif } /* * get the next character from the terminal, * stripping the parity bit */ gchar() { char c; int ret; extern int errno; fflush (stdout); /* get rid of what's there */ while ((ret = read (0, &c, 1)) <= 0) /* try again only if interrupted */ x (ret == 0 || errno != EINTR, "gchar: read error"); return(c & 0177); } /* * get a number from the user. * c is the first digit (already typed). */ getnum(c) int c; { int num, numin; int x, y; num = c - '0'; curpos(&x, &y); numin = 1; putch(c); for (; ;) { c = gchar(); if (c == '\n' || c == '\r') return(num); /* done */ if (c == t_erase) { if (numin > 0) { num /= 10; numin--; putstr("\b \b"); } continue; } if (c == t_kill) { num = 0; numin = 0; at(x, y); clear_eol(); continue; } if ('0' <= c && c <= '9') { /* valid character */ putch(c); numin++; num = 10 * num + (c - '0'); } else putch('\07'); } /*NOT REACHED*/ } /* * gline( p, i) - suck a maximum of i characters from the tty. * do erase and kill processing. * The line is terminated by the user typing a or . This * character is converted to null and left on the end of the * string returned. The count of characters (including the null * terminator) is returned. * The array passed in is assumed to have i+1 elements * (enough for the characters plus the terminator) * * Original Coding: Ray Essick December 1981 */ gline(p, max) char *p; { register int numin; register char *q; register int c; int x, y; q = p; numin = 0; curpos(&x, &y); for (;;) { c = gchar(); if (c == t_erase) { if (numin > 0) { numin--; q--; putstr("\b \b"); if (*q < 040 || *q == 0177) putstr("\b \b"); } continue; } if (c == t_kill) { at(x, y); clear_eol(); q = p; numin = 0; continue; } switch (c) { case '\n': case '\r': if (numin >= max) { p[max] = '\0'; return(max + 1); } *q = '\0'; numin++; return(numin); case 'V'&037: /* ^V */ case '\\': /* escape character */ putstr("^\b"); /* back space to it */ c = gchar(); /* grab escaped character */ /* FALL INTO ... */ default: if (numin < max) { *q++ = c; numin++; mapch(c); } else putch('\007'); /* show him I ignored char */ break; } } /*NOT REACHED*/ } /* * returns y or n to the asked question */ askyn() { int c; int x, y; curpos(&x, &y); for (; ;) { c = gchar(); if (c == 'y' || c == 'n') { putch(c); putstr(" (working)"); fflush(stdout); return(c); } putchar('\007'); putstr(" (y/n)"); at(x, y); } /*NOT REACHED*/ } wfchar() { printf("--Hit any key to continue--"); gchar(); } /*VARARGS1*/ warn(s, a1, a2, a3) char *s; { char buf[BUFSIZ]; at(0, 1); sprintf(buf, s, a1, a2, a3); standout(1); putstr(buf); standout(0); clear_eol(); } /*VARARGS1*/ prompt(s, a1, a2, a3) char *s; { char buf[BUFSIZ]; at(0, 1); sprintf(buf, s, a1, a2, a3); putstr(buf); clear_eol(); } cmdprompt() { #ifdef BERKELEY int set = LFLUSHO; /* fflush(stdout); /* sigh... want a synchronous write here */ ioctl(0, TIOCLBIC, &set); #endif BERKELEY at(-1, 1); #ifdef PROMPT putstr(PROMPT); #endif PROMPT } putstr(s) char *s; { while (*s) putch(*s++); } /* * a putchar with all the fancy control * character mapping */ mapch(c) { if (c < 040 || c == 0177) { putch('^'); if (c < 040) c |= 0100; else c = '?'; } putch(c); }