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

Defined functions

catchem defined in line 213; used 1 times
catchint defined in line 169; used 4 times
catchz defined in line 179; used 3 times
isinput defined in line 476; used 2 times
mapch defined in line 494; never used
ttystrt defined in line 48; used 3 times
uncatchem defined in line 224; used 1 times
widthch defined in line 519; used 8 times

Defined variables

echoctl defined in line 42; used 8 times
modeset defined in line 43; used 4 times
oldlocalbits defined in line 36; used 3 times
oldmode defined in line 35; used 2 times
ospeed defined in line 44; used 2 times
otty defined in line 29; used 2 times
rcsid defined in line 5; never used
tty defined in line 37; used 19 times
ttyerase defined in line 40; used 4 times
ttykill defined in line 41; used 4 times
Last modified: 1996-03-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3684
Valid CSS Valid XHTML 1.0 Strict