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

Defined functions

catch defined in line 56; used 1 times
endunix defined in line 196; used 3 times
fixttymodes defined in line 278; used 2 times
initunix defined in line 143; used 1 times
moreinput defined in line 391; used 2 times
setcopybuffer defined in line 222; used 1 times
setenv defined in line 434; never used
tstp defined in line 96; used 2 times
unfixttymodes defined in line 341; used 2 times

Defined variables

Visible defined in line 391; never used
copysavefile defined in line 35; used 9 times
oldltchars defined in line 275; used 3 times
oldtchars defined in line 271; used 2 times
oldtty defined in line 268; used 5 times
rcsid defined in line 2; never used

Defined macros

COPYSAVEFILE defined in line 33; used 2 times
Ctl defined in line 38; used 7 times
INTRCHAR defined in line 45; used 2 times
QUITCHAR defined in line 41; used 2 times
REDRAW defined in line 48; used 1 times
Last modified: 1985-08-27
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1827
Valid CSS Valid XHTML 1.0 Strict