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