Annotation of 43BSD/contrib/B/src/bed/unix.c, revision 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.