|
|
1.1 root 1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2: static char rcsid[] = "$Header: unix.c,v 2.6 85/08/22 16:09:38 timo Exp $";
3:
4: /*
5: * B editor -- UNIX interface, i.e. signal and tty fiddling.
6: */
7:
8: /* #define BADTABSTOPS /* Obsolete -- "b" doesn't set the tabs any more */
9: /* Defined if (soft) tabs may have been placed at strange positions. */
10: /* Actually this has only effect if curses(3) is used.
11: However this source file doesn't #include "curses.h" so we can't
12: check for that, and will assume curses(3) is always used.
13: For very slow baudrates when curses(3) is used, it may prove useful
14: to undefine BADTABSTOPS. The "b" shell script must then be modified
15: to keep the tabs at the UNIX 8 space apart default. */
16:
17: #include "b.h" /* Only for definitions like bool, string, Hidden etc. */
18: #include "unix.h" /* What kind of UNIX is this? */
19:
20: #ifdef SIGNAL
21: #include <signal.h>
22: #endif SIGNAL
23:
24: #ifdef SGTTY_H
25: #include <sgtty.h>
26: #endif SGTTY_H
27:
28: extern bool slowterminal; /* Set for speeds <= 600 baud */
29: extern bool hushbaby; /* Set if no bells are to be heard */
30: extern bool dflag; /* Debugging mode */
31:
32:
33: #define COPYSAVEFILE ".Bed_buf"
34:
35: Visible char copysavefile[200] = COPYSAVEFILE;
36:
37:
38: #define Ctl(x) ('x'&037)
39:
40: #ifndef QUITCHAR
41: #define QUITCHAR Ctl(\\)
42: #endif QUITCHAR
43:
44: #ifndef INTRCHAR
45: #define INTRCHAR Ctl(])
46: #endif INTRCHAR
47:
48: #define REDRAW Ctl(L) /* From "keys.h" */
49:
50:
51: #ifdef SIGNAL
52: /*
53: * Call exit code when signal arrives, then resend the signal.
54: */
55:
56: catch(sig)
57: int sig;
58: {
59: signal(sig, SIG_DFL);
60: #ifndef NDEBUG
61: fprintf(stderr, "*** Caught signal %d \n\r", sig);
62: if (sig == SIGQUIT) { /* QUIT only resets terminal modes */
63: endterm();
64: endunix();
65: }
66: else
67: #endif NDEBUG
68: endall();
69: #ifdef BTOP
70: termchild(); /* Kill possible child, but don't wait for it */
71: #endif BTOP
72: kill(getpid(), sig);
73: }
74: #endif SIGNAL
75:
76:
77: #ifdef SIGTSTP /* I.e., only on BSD systems with job control. */
78: /*
79: * Reset tty modes etc. when STOP signal arrives (control-Z).
80: * This is like interrupt but the program may continue later
81: * so we must not do all exit code).
82: *
83: * In order that the code works for 4.1 and 4.2 BSD Unix (V7 and sys III/V
84: * don't have the SIGTSTP signal at all, so there wo don't bother), we use
85: * neither the awkward "-ljobs" mechanism nor the nicer but (yet!) even
86: * less portable sigmask/sigblock system calls. Rather, to kill ourselves
87: * again after the screen and tty modes have been restored, we use another
88: * signal, i.e., SIGSTOP (which is uncatchable).
89: *
90: * Note! Since curses' initscr() also executes signal(SIGTSTP, tstp),
91: * and initscr() is called after initunix(), the name of this routine
92: * must be tstp, overriding a routine of the same name in the curses
93: * library which does not do what we want.
94: */
95:
96: tstp(sig)
97: int sig;
98: {
99: int (*prevttousig)() = signal(SIGTTOU, SIG_IGN);
100: /* Ignore SIGTTOU so stty calls won't stop us again! */
101: char cread = REDRAW;
102:
103: #ifndef NDEBUG
104: if (dflag)
105: fprintf(stderr, "*** Caught stop signal %d \n\r", sig);
106: #endif NDEBUG
107: signal(sig, SIG_DFL);
108: endterm();
109: unfixttymodes();
110: signal(SIGTTOU, prevttousig);
111: kill(getpid(), SIGSTOP); /* Hard stop */
112:
113: /*
114: * A stop signal made us go to sleep in Tumbolia.
115: * When we awake, we continue at this point.
116: * The world may well have changed a little bit,
117: * so do the tty initializations anew.
118: */
119:
120: fixttymodes();
121: initterm();
122:
123: #ifdef TIOCSTI
124: /* Simulate receipt of REDRAW initially so we come up
125: with a nice display. */
126: ioctl(0, TIOCSTI, &cread);
127: #endif TIOCSTI
128: signal(SIGTSTP, tstp);
129: }
130: #endif SIGTSTP
131:
132:
133: /*
134: * Prepare for interrupts (UNIX `signals') to be caught so
135: * we can reset the tty modes and perform miscellaneous other
136: * exit routines.
137: * Note -- if a signal arrives before the call to fixttymodes,
138: * the unfixttymodes may render the terminal useless. The fix is
139: * easy, but I'm too lazy now (just read the statuses BEFORE,
140: * but change them only AFTER signal setting).
141: */
142:
143: initunix()
144: {
145: #ifdef SIGNAL
146: register int i;
147: #endif SIGNAL
148:
149: #ifndef NDEBUG
150: if (dflag)
151: fprintf(stderr, "*** initunix();\n\r");
152: #endif NDEBUG
153:
154: #ifdef SIGNAL
155: for (i = 1; i <= NSIG; ++i) {
156: #ifndef NDEBUG
157: if (i == SIGQUIT)
158: continue;
159: #endif NDEBUG
160: #ifdef SIGCONT
161: if (i == SIGCONT)
162: continue;
163: #endif SIGCONT
164: #ifdef SIGCHLD
165: if (i == SIGCHLD)
166: continue;
167: #endif SIGCHLD
168: if (signal(i, SIG_IGN) != SIG_IGN) {
169: signal(i, catch);
170: #ifndef NDEBUG
171: if (dflag)
172: fprintf(stderr, "Catching signal %d\n", i);
173: #endif NDEBUG
174: }
175: }
176: /* Stop/continue must be handled differently, see stop() above. */
177: #ifdef SIGTSTP
178: if (signal(SIGTSTP, SIG_IGN) != SIG_IGN)
179: signal(SIGTSTP, tstp);
180: #endif SIGTSTP
181:
182: #endif SIGNAL
183:
184: #ifdef SGTTY_H
185: fixttymodes();
186: #endif SGTTY_H
187: setcopybuffer();
188: }
189:
190:
191: /*
192: * The last termination routine to be called.
193: * It also resets all signals to their default status.
194: */
195:
196: endunix()
197: {
198: #ifdef SIGNAL
199: int i;
200: #endif SIGNAL
201:
202: fflush(stdout);
203: #ifndef NDEBUG
204: if (dflag)
205: fprintf(stderr, "*** endunix();\n\r");
206: #endif NDEBUG
207: #ifdef SGTTY_H
208: unfixttymodes();
209: #endif SGTTY_H
210:
211: #ifdef SIGNAL
212: for (i = 1; i <= NSIG; ++i)
213: signal(i, SIG_DFL);
214: #endif SIGNAL
215: }
216:
217:
218: /*
219: * Determine the name of the file where the copy buffer is saved.
220: */
221:
222: Hidden Procedure
223: setcopybuffer()
224: {
225: string home = getenv("HOME");
226:
227: if (home)
228: sprintf(copysavefile, "%.150s/%.40s", home, COPYSAVEFILE);
229: /* Else, retain default initialization! */
230: }
231:
232:
233: /*
234: * Return a string like the one that perror(arg) would print
235: * (see UNIX manual page perror(3) for details).
236: * Like all C library routines returning strings, the string points
237: * to static storage that is overwritten on each call.
238: * If arg is fairly long, it may get truncated.
239: */
240:
241: string
242: unixerror(arg)
243: string arg;
244: {
245: static char msg[200];
246: #ifdef PERROR
247: extern int sys_nerr, errno;
248: extern string sys_errlist[];
249:
250: if (errno > 0 && errno < sys_nerr)
251: sprintf(msg, "%.80s: %.80s", arg, sys_errlist[errno]);
252: else
253: sprintf(msg, "%.80s: UNIX error %d", arg, errno);
254: #else !PERROR
255: sprintf(msg, "%.68s: I/O error", arg);
256: #endif !PERROR
257: msg[80] = '\0';
258: return msg;
259: }
260:
261:
262: #ifdef SGTTY_H
263: /*
264: * Hacks to fix certain peculiarities due to the hostile environment
265: * in which the editor lives.
266: */
267:
268: Hidden struct sgttyb oldtty;
269:
270: #ifdef TIOCSETC
271: Hidden struct tchars oldtchars;
272: #endif
273:
274: #ifdef TIOCSLTC
275: Hidden struct ltchars oldltchars;
276: #endif
277:
278: Hidden Procedure
279: fixttymodes()
280: {
281: gtty(2, &oldtty);
282: if (oldtty.sg_ospeed <= B600)
283: slowterminal = Yes;
284: #ifdef BADTABSTOPS
285: /*
286: * Turn on XTABS mode, to be able to live when terminal tabs are
287: * set at 4 rather than 8 columns (the B interpreter used to set
288: * this).
289: */
290: if (!(oldtty.sg_flags & XTABS)) {
291: struct sgttyb newtty;
292: gtty(2, &newtty);
293: newtty.sg_flags |= XTABS;
294: ioctl(0, TIOCSETN, &newtty);
295: }
296: #endif BADTABSTOPS
297:
298: #ifdef TIOCSETC /* I.e., not at pre-version 7 UNIX systems */
299: /*
300: * Set the quit character to ^\ and the interrupt at DEL.
301: * The start/stop characters are kept only if they are ^S/^Q.
302: */
303: {
304: struct tchars newtchars;
305: ioctl(0, TIOCGETC, &oldtchars);
306: ioctl(0, TIOCGETC, &newtchars);
307: if ((newtchars.t_intrc & 0377) != 0377
308: && newtchars.t_intrc != 0177/*DEL*/)
309: newtchars.t_intrc = INTRCHAR;
310: if ((newtchars.t_quitc & 0377) != 0377)
311: newtchars.t_quitc = QUITCHAR;
312: if (newtchars.t_startc != Ctl(Q))
313: newtchars.t_startc = -1;
314: if (newtchars.t_stopc != Ctl(S))
315: newtchars.t_stopc = -1;
316: ioctl(0, TIOCSETC, &newtchars);
317: }
318: #endif TIOCSETC
319:
320: #ifdef TIOCSLTC /* I.e., at 4.xBSD systems */
321: /*
322: * Turn off all local control characters except keep stop (^Z) and delayed
323: * stop (^Y) when these are the originals.
324: */
325: {
326: static struct ltchars newltchars = {-1, -1, -1, -1, -1, -1};
327:
328: ioctl(0, TIOCGLTC, &oldltchars);
329: if (oldltchars.t_suspc == Ctl(Z))
330: newltchars.t_dsuspc = Ctl(Z);
331: ioctl(0, TIOCSLTC, &newltchars);
332: }
333: #endif
334: }
335:
336:
337: /*
338: * Undo the effects of fixttymodes(), see comments there.
339: */
340:
341: Hidden Procedure
342: unfixttymodes()
343: {
344: if (!oldtty.sg_ospeed)
345: return; /* Not yet initialized! */
346: #ifdef BADTABSTOPS
347: ioctl(0, TIOCSETN, &oldtty);
348: #endif
349: #ifdef TIOCSETC
350: ioctl(0, TIOCSETC, &oldtchars);
351: #endif
352: #ifdef TIOCSLTC
353: ioctl(0, TIOCSLTC, &oldltchars);
354: #endif
355: }
356: #endif SGTTY_H
357:
358:
359: /*
360: * Return Yes if more input immediately available
361: */
362:
363: #ifdef IBMPC
364:
365: Visible bool
366: moreinput()
367: {
368: return kbhit();
369: }
370:
371: #else !IBMPC
372:
373: /*
374: * ***** UNIX DEPENDENCE *****
375: * Assumes the standard UNIX definition of FILE: assumes there is
376: * buffered input if stdin->_cnt > 0, so uses the `_cnt' field.
377: *
378: * ***** 4.2 BSD DEPENDENCE *****
379: * If the symbol SIGNAL is defined, uses the select() system call to determine
380: * whether more input is available; see select(2) in 4.2 BSD manual.
381: *
382: * ***** 4.1 BSD DEPENDENCE *****
383: * If the symbol FIONREAD is defined, uses the correponding ioctl call to
384: * determine whether more input is available; see tty(4) in 4.1 BSD manual.
385: */
386:
387: #ifdef SELECT
388: #include <sys/time.h>
389: #endif SELECT
390:
391: Visible bool
392: moreinput()
393: {
394: if (stdin->_cnt > 0)
395: return Yes;
396: #ifdef SELECT
397: {
398: int readfds;
399: int nfds;
400: static struct timeval timeout = {0, 0};
401:
402: readfds = 1<<fileno(stdin);
403: nfds = 1+fileno(stdin);
404: nfds = select(nfds, &readfds, (int*)0, (int*)0, &timeout);
405: if (nfds > 0) {
406: if (dflag)
407: fputc('\07', stderr);
408: return Yes;
409: }
410: }
411: #else SELECT
412: #ifdef FIONREAD
413: {
414: long n = 0;
415:
416: if (ioctl(0, FIONREAD, &n) != -1 && n > 0)
417: return Yes;
418: }
419: #endif FIONREAD
420: #endif SELECT
421: return No;
422: }
423: #endif !IBMPC
424:
425:
426: #ifdef SETENV
427: /*
428: * Routine to add or change an environment variable.
429: * (No longer used.)
430: */
431:
432: extern string *environ;
433:
434: setenv(entry)
435: string entry;
436: {
437: string equals = index(entry, '=');
438: int len;
439: string *ep;
440: static string *myenviron;
441:
442: if (!equals)
443: syserr("setenv: no = sign");
444: len = equals - entry;
445: for (ep = environ; *ep && !Strnequ(*ep, entry, len+1); ++ep)
446: ;
447: if (*ep) {
448: *ep = entry;
449: return;
450: }
451: len = ep - environ + 2;
452: if (myenviron) {
453: myenviron = (string*)
454: realloc((string)myenviron, (unsigned)(len * sizeof(string)));
455: if (!myenviron)
456: syserr("setenv: realloc");
457: }
458: else {
459: myenviron = (string*) malloc((unsigned)(len * sizeof(string)));
460: if (!myenviron)
461: syserr("setenv: malloc");
462: for (ep = environ; *ep; ++ep)
463: myenviron[ep-environ] = *ep;
464: }
465: myenviron[len-1] = (string)NULL;
466: myenviron[len-2] = entry;
467: environ = myenviron;
468: }
469: #endif SETENV
470:
471:
472: #ifdef PWB
473: /*
474: * Substitute getenv routine - there is no environment on PWB systems,
475: * but as a substitute (not te be encouraged!) we allow a file with the
476: * name of the environment variable to contain the desired value;
477: * e.g. the file "TERM" may contain a line saying hp2621 or hp etc.
478: */
479:
480: Visible string
481: getenv(name)
482: string name;
483: {
484: static char buffer[100];
485: FILE *fp;
486: string cp;
487:
488: fp = fopen(name, "r");
489: if (!fp)
490: return NULL;
491: if (!fgets(buffer, sizeof buffer, fp))
492: buffer[0] = '\0';
493: else {
494: cp = index(buffer, '\n');
495: if (cp)
496: *cp = '\0';
497: }
498: fclose(fp);
499: return buffer;
500: }
501: #endif PWB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.