|
|
1.1 ! root 1: #include "parms.h" ! 2: #include "structs.h" ! 3: ! 4: #ifdef RCSIDENT ! 5: static char rcsid[] = "$Header: miscio.c,v 1.7.0.1 85/09/28 11:23:51 notes Rel $"; ! 6: #endif RCSIDENT ! 7: ! 8: ! 9: /* miscio stuff: ! 10: * ! 11: * ttystrt/ttystop switch back and forth to character-at-a-time mode ! 12: * ! 13: * catchem makes our program ignore kills and coredumps. ! 14: * ! 15: * getnum is a char at a time input routine ! 16: * ! 17: * gchar sucks in 1 character. masks off parity. Uses raw mode to do this ! 18: * ! 19: */ ! 20: ! 21: ! 22: #include <signal.h> ! 23: #include <errno.h> ! 24: ! 25: ! 26: #ifdef USG /* Bell's Sys III and V */ ! 27: #include <termio.h> ! 28: struct termio tty, ! 29: otty; ! 30: #endif defined(USG) ! 31: ! 32: #if defined(V7) || defined(BSD4x) ! 33: /* Standard Bell V7 and Berkeley too */ ! 34: #include <sgtty.h> ! 35: int oldmode; /* prev mode bits */ ! 36: long oldlocalbits; /* prev local bits */ ! 37: struct sgttyb tty; ! 38: #endif defined(V7) || defined(BSD4x) ! 39: ! 40: #ifdef BSD2x /* Berkeley PDP-11 Unix */ ! 41: #include <sgtty.h> ! 42: int oldmode; /* prev mode bits */ ! 43: int oldlocalbits; /* 2.8 Bsd uses 16 bits */ ! 44: struct sgttyb tty; ! 45: #endif defined(BSD2x) ! 46: ! 47: char ttyerase, /* user's chosen erase character */ ! 48: ttykill; /* and his line kill character */ ! 49: int modeset = 0; /* == 1 if ttyflags messed with */ ! 50: short ospeed; /* for tputs padding */ ! 51: ! 52: ! 53: ! 54: ttystrt () ! 55: { ! 56: #if defined(BSD2x) ! 57: int localbits; /* 2.8 Bsd uses 16 bits */ ! 58: #endif defined(BSD2x) ! 59: ! 60: #if defined(BSD4x) ! 61: long localbits; /* for ctlecho and tildes */ ! 62: #endif defined(BSD4x) ! 63: ! 64: ! 65: /* ! 66: * Grab the current tty state ! 67: */ ! 68: ! 69: #ifdef V7 /* V7 has simple tty controls */ ! 70: if (gtty (0, &tty) < 0) /* failure to grab */ ! 71: { ! 72: fprintf (stderr, "%s: Unable to gtty\n", Invokedas); ! 73: exit (1); ! 74: } ! 75: #endif defined(V7) ! 76: ! 77: #ifdef USG /* BTL SYS III & V */ ! 78: if (ioctl (0, TCGETA, &tty) < 0 || ! 79: ioctl (0, TCGETA, &otty) < 0) /* one failed */ ! 80: { ! 81: fprintf (stderr, "%s: Unable to get tty state\n", Invokedas); ! 82: exit (1); ! 83: } ! 84: #endif defined(USG) ! 85: ! 86: #if defined(BSD4x) || defined(BSD2x) ! 87: /* Berkeley Unices */ ! 88: if (ioctl (0, TIOCGETP, &tty) < 0 || ! 89: ioctl (0, TIOCLGET, &oldlocalbits) < 0) ! 90: { ! 91: fprintf (stderr, "%s: Unable to get tty states\n"); ! 92: exit (1); ! 93: } ! 94: #endif defined(BSD4x) || defined(BSD2x) ! 95: ! 96: /* ! 97: * Modify the state to what we want: cbreak, fix tildes for cursor ! 98: * and disable "control-echo" (berkeley) ! 99: */ ! 100: ! 101: #if defined(USG) ! 102: tty.c_lflag &= NOT ICANON; ! 103: tty.c_cc[VEOF] = 1; ! 104: tty.c_cc[VEOL] = 1; ! 105: ospeed = tty.c_cflag & CBAUD; ! 106: ttyerase = tty.c_cc[VERASE]; /* grab erase char */ ! 107: ttykill = tty.c_cc[VKILL]; /* and kill char */ ! 108: #endif defined(USG) ! 109: ! 110: #if defined(BSD4x) || defined(BSD2x) || defined(V7) ! 111: oldmode = tty.sg_flags; ! 112: tty.sg_flags |= CBREAK; ! 113: ospeed = tty.sg_ospeed; /* speed of terminal */ ! 114: ttyerase = tty.sg_erase; /* grab erase character */ ! 115: ttykill = tty.sg_kill; /* and kill character */ ! 116: #endif defined(BSD4x) || defined(BSD2x) || defined(V7) ! 117: ! 118: ! 119: /* ! 120: * Now actually tell the system that we want it this way ! 121: */ ! 122: ! 123: #if defined(V7) ! 124: if (stty (0, &tty) < 0) /* failed */ ! 125: { ! 126: fprintf (stderr, "%s: Unable to stty\n", Invokedas); ! 127: exit (1); ! 128: } ! 129: #endif defined(V7) ! 130: ! 131: #if defined(USG) ! 132: if (ioctl (0, TCSETA, &tty) < 0) ! 133: { ! 134: fprintf (stderr, "%s: Unable to set tty state\n", Invokedas); ! 135: exit (1); ! 136: } ! 137: #endif defined(USG) ! 138: ! 139: #if defined(BSD4x) || defined(BSD2x) ! 140: localbits = LTILDE | LCTLECH; /* zap tildes (hazeltines) and ctlecho */ ! 141: if (ioctl (0, TIOCSETN, &tty) < 0 || ! 142: ioctl (0, TIOCLBIC, &localbits) < 0) ! 143: { ! 144: fprintf (stderr, "%s: Unable to set tty state\n", Invokedas); ! 145: exit (1); ! 146: } ! 147: #endif defined(BSD4x) || defined(BSD2x) ! 148: ! 149: modeset = 1; ! 150: cmstart (); /* so can cursor address reliably */ ! 151: } ! 152: ! 153: ttystop () ! 154: { ! 155: if (modeset) ! 156: { ! 157: #if defined(V7) || defined(BSD4x) || defined(BSD2x) ! 158: tty.sg_flags = oldmode; ! 159: #endif defined(V7) || defined(BSD4x) || defined(BSD2x) ! 160: ! 161: #if defined(V7) ! 162: if (stty (0, &tty) < 0) /* vanilla Version 7 */ ! 163: printf ("ttystop: stty"); /* cant use x cause he calls us */ ! 164: #endif defined(V7) ! 165: ! 166: #if defined(USG) ! 167: if (ioctl (0, TCSETA, &otty) < 0) /* Unix 4.0 */ ! 168: printf ("ttystop: stty"); /* cant use x cause he calls us */ ! 169: #endif defined(USG) ! 170: ! 171: #if defined(BSD4x) || defined(BSD2x) ! 172: if ((ioctl (0, TIOCSETN, &tty) < 0) || ! 173: (ioctl (0, TIOCLSET, &oldlocalbits) < 0)) ! 174: printf ("ttystop: stty"); /* cant use x cause he calls us */ ! 175: #endif defined(BSD4x) || defined(BSD2x) ! 176: } ! 177: cmstop (); /* get out of cursor addressing mode */ ! 178: modeset = 0; ! 179: } ! 180: ! 181: ! 182: static int (*osigint) (), ! 183: (*osigquit) (); /* hold signal status */ ! 184: #if defined(SIGTSTP) ! 185: static int (*osigtstp) (); /* control-z job stop */ ! 186: #endif defined(SIGTSTP) ! 187: ! 188: catchint () ! 189: { ! 190: intflag = 1; ! 191: signal (SIGINT, catchint); /* fix em up again */ ! 192: #ifndef DEBUG ! 193: signal (SIGQUIT, catchint); ! 194: #endif DEBUG ! 195: } ! 196: ! 197: #if defined(SIGTSTP) ! 198: catchz () /* handle ^Z gracefully */ ! 199: { ! 200: int wasset; /* tty mode flag */ ! 201: ! 202: if (ignoresigs) /* if in critical section */ ! 203: { ! 204: signal (SIGTSTP, catchz); /* re-catch */ ! 205: return; /* and ignore */ ! 206: } ! 207: if ((wasset = modeset) != 0) /* want assignment */ ! 208: { ! 209: at (0, 1); /* go to bottom corner */ ! 210: fflush (stdout); ! 211: ttystop (); /* fix tty modes */ ! 212: } ! 213: ! 214: signal (SIGTSTP, SIG_DFL); /* make sure it nabs us */ ! 215: #if defined(BSD42) ! 216: /* ! 217: * since 4.2 Bsd blocks signals while we are handling them, we ! 218: * have to explicitly tell the kernel that we want the signals ! 219: * to come through. ! 220: * It would probably be more correct to only let some signals ! 221: * through instead of all. ! 222: */ ! 223: (void) sigsetmask (0); /* pass signals */ ! 224: #endif BSD42 ! 225: kill (0, SIGTSTP); /* halt myself */ ! 226: signal (SIGTSTP, catchz); /* ready to catch again */ ! 227: if (wasset) ! 228: ttystrt (); /* fix his tty */ ! 229: } ! 230: #endif defined(SIGTSTP) ! 231: ! 232: catchem () ! 233: { ! 234: osigint = signal (SIGINT, catchint); /* interrupts */ ! 235: #ifndef DEBUG ! 236: osigquit = signal (SIGQUIT, catchint); /* quits */ ! 237: #endif DEBUG ! 238: #if defined(SIGTSTP) ! 239: osigtstp = signal (SIGTSTP, catchz); /* control Z */ ! 240: #endif ! 241: } ! 242: ! 243: uncatchem () /* restore signal status */ ! 244: { ! 245: signal (SIGINT, osigint); ! 246: #ifndef DEBUG ! 247: signal (SIGQUIT, osigquit); ! 248: #endif DEBUG ! 249: #if defined(SIGTSTP) ! 250: signal (SIGTSTP, osigtstp); ! 251: #endif ! 252: } ! 253: ! 254: gchar () ! 255: /* ! 256: * Return next character from tty. ! 257: * this is all done in cbreak mode of course ! 258: */ ! 259: { ! 260: char c; ! 261: register int retcode; ! 262: fflush (stdout); /* get rid of what's there */ ! 263: while ((retcode = read (0, &c, 1)) <= 0) /* try reading */ ! 264: if (retcode == 0 || errno != EINTR) /* if bizarre */ ! 265: { ! 266: fprintf (stderr, "%s: Bad tty read\n", Invokedas); ! 267: exit (1); ! 268: } ! 269: intflag = 0; /* remove any pending */ ! 270: ! 271: return (c & 0177); ! 272: } ! 273: ! 274: /* ! 275: * getnum (c) ! 276: * grab a number from the terminal. "c" is the first digit o ! 277: * the number. ! 278: * ! 279: * Originally coded: Rob Kolstad Fall 1980 ! 280: * Modified: Ray Essick (with help from Malcolm Slaney) ! 281: * July 1982 ! 282: * to handle user defined erase and kill ! 283: * characters. ! 284: */ ! 285: ! 286: getnum (c) /* c is the initial character! */ ! 287: char c; ! 288: { ! 289: int num, ! 290: numin; ! 291: num = c - '0'; ! 292: numin = 1; ! 293: putc (c, stdout); ! 294: while (1) ! 295: { ! 296: c = gchar (); /* get next digit */ ! 297: if (c == ttyerase) /* want to erase? */ ! 298: { ! 299: if (numin > 0) /* if have some */ ! 300: { ! 301: if (c != '\10') /* Assumes physically */ ! 302: printf ("\10\10 \10\10"); /* backspaces on ^H */ ! 303: else ! 304: printf (" \10"); ! 305: numin--; ! 306: num /= 10; /* drop that digit */ ! 307: } ! 308: else ! 309: { /* nothing to zap */ ! 310: if (c != '\10') /* non-backspace char */ ! 311: printf ("\10\10 "); ! 312: else ! 313: putchar (' '); /* backspace */ ! 314: } ! 315: } ! 316: else ! 317: if (c == ttykill) ! 318: { ! 319: num = 0; /* blast it away */ ! 320: numin++; ! 321: while (numin > 0) /* erase the screen */ ! 322: { ! 323: numin--; ! 324: printf ("\10 \10"); ! 325: } ! 326: numin = 0; /* in case */ ! 327: } ! 328: else ! 329: switch (c) ! 330: { ! 331: case '\n': ! 332: case '\r': ! 333: return num; /* done */ ! 334: ! 335: default: ! 336: if (c < '0' || c > '9') ! 337: { ! 338: printf ("\10 \10\07"); ! 339: continue; ! 340: } ! 341: numin++; ! 342: num = 10 * num + (c - '0'); ! 343: break; ! 344: } ! 345: } ! 346: } ! 347: ! 348: /* ! 349: * gline( p, i) - suck a maximum of i characters from the tty. ! 350: * do erase and kill processing. ! 351: * The line is terminated by the user typing a <cr> or <nl>. This ! 352: * character is converted to null and left on the end of the ! 353: * string returned. The count of characters (including the null ! 354: * terminator) is returned. ! 355: * The array passed in is assumed to have i+1 elements ! 356: * (enough for the characters plus the terminator) ! 357: * ! 358: * Original Coding: Ray Essick December 1981 ! 359: * Repaired to use user's erase and kill characters ! 360: * Malcolm Slaney July 1982 ! 361: * ! 362: */ ! 363: ! 364: gline (p, max) ! 365: char *p; ! 366: { ! 367: register int numin; ! 368: register char *q; /* pointer to buffer */ ! 369: register char c; /* hold the input character */ ! 370: ! 371: q = p; /* get base */ ! 372: numin = 0; ! 373: while (1) ! 374: { ! 375: c = gchar (); /* flushes stdout also */ ! 376: if (c == ttyerase) ! 377: { ! 378: if (numin > 0) ! 379: { ! 380: if (c != '\10') /* Assumes TTY physically */ ! 381: printf ("\10\10 \10\10"); /* backspaces on ^H */ ! 382: else ! 383: printf (" \10"); ! 384: numin--; ! 385: q--; /* back up in buffer also */ ! 386: } ! 387: else ! 388: { ! 389: if (c != '\10') ! 390: printf ("\10 \10"); ! 391: else ! 392: printf (" "); ! 393: } ! 394: } ! 395: else ! 396: if (c == ttykill) ! 397: { ! 398: numin++; ! 399: while (numin > 0) /* erase the screen */ ! 400: { ! 401: numin--; ! 402: printf ("\10 \10"); ! 403: } ! 404: q = p; /* reset pointer */ ! 405: numin = 0; /* in case .. */ ! 406: } ! 407: else ! 408: switch (c) ! 409: { ! 410: case '\n': ! 411: case '\r': ! 412: if (numin >= max) /* should only ever be = */ ! 413: { ! 414: p[max] = '\0'; /* put a null at the end */ ! 415: return max + 1; /* which is how many we return */ ! 416: } ! 417: *q = '\0'; ! 418: numin++; ! 419: return numin; ! 420: ! 421: case '\\': /* escape character */ ! 422: printf ("\010"); /* back space to it */ ! 423: c = gchar (); /* grab escaped character */ ! 424: /* and fall through to default */ ! 425: ! 426: default: /* add character to buffer */ ! 427: if (numin < max) ! 428: { ! 429: *q++ = c; ! 430: numin++; ! 431: } ! 432: else ! 433: { ! 434: printf ("\10 \10"); /* show him I ignored char */ ! 435: } ! 436: break; ! 437: } ! 438: } ! 439: } ! 440: ! 441: askyn (p) char *p; /* returns y or n to the question */ ! 442: { ! 443: char c; /* return temp */ ! 444: printf ("%s", p); ! 445: while (1) ! 446: { ! 447: c = gchar (); ! 448: if (c == 'y' || c == 'n') ! 449: break; ! 450: printf ("\07 y or n please\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); ! 451: } ! 452: return c; ! 453: } ! 454: ! 455: /* ! 456: * return 1 if there is input from the terminal, ! 457: * 0 otherwise. systems without the appropriate ! 458: * call should always return 0. ! 459: */ ! 460: isinput () ! 461: { ! 462: #ifdef FIONREAD /* BSD 4.1, 4.1a, 4.2 */ ! 463: long retval; ! 464: if (ioctl (0, FIONREAD, &retval)) ! 465: return 0; /* failed, say no input */ ! 466: return (retval != 0); /* count of characters */ ! 467: #endif FIONREAD ! 468: ! 469: return 0; /* for other systems */ ! 470: } ! 471: ! 472: /* ! 473: * mapch(c) char c; ! 474: * ! 475: * prints control characters as ^x style. ! 476: * others as normal. ! 477: */ ! 478: mapch (c) ! 479: char c; ! 480: { ! 481: if (c < 40) ! 482: { ! 483: putchar ('^'); ! 484: putchar (c | 0100); /* make visible */ ! 485: } ! 486: else ! 487: if (c == 0177) ! 488: { ! 489: putchar ('^'); ! 490: putchar ('?'); ! 491: } ! 492: else ! 493: putchar (c); ! 494: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.