Annotation of 43BSD/contrib/B/src/bed/unix.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.