|
|
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.