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

1.1       root        1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
                      2: static char rcsid[] = "$Header: comm.c,v 2.4 85/08/22 16:00:49 timo Exp $";
                      3: 
                      4: /*
                      5:  * B editor -- Communication with B interpreter.
                      6:  */
                      7: 
                      8: #include "feat.h"
                      9: #ifdef BTOP
                     10: 
                     11: #include <signal.h>
                     12: #include <setjmp.h>
                     13: #include <ctype.h>
                     14: 
                     15: #include "b.h"
                     16: #include "node.h"
                     17: #include "supr.h"
                     18: #include "unix.h"
                     19: #include "cell.h" /* For winheight */
                     20: 
                     21: #define TABS 8
                     22: 
                     23: string unixerror();
                     24: 
                     25: 
                     26: /*
                     27:  * Communication to other modules (demo, getc, ...):
                     28:  */
                     29: 
                     30: Visible bool interrupted; /* Set when interrupt caught but not propagated */
                     31: Visible bool canjump; /* Set when disrupt() can safely longjmp(jumpback) */
                     32: Visible jmp_buf jumpback; /* Set by other module where to jump */
                     33: 
                     34: /*
                     35:  * Pipeline protocol with interpreter:
                     36:  */
                     37: 
                     38: #define ESCAPE '\001' /* Character signalling special function */
                     39: #define RESYNC '\177' /* Character signalling acknowledge of interrupt */
                     40: #define INTRCHILD SIGTRAP /* Signal to send as interrupt */
                     41: 
                     42: #ifndef INTERPRETER
                     43: #define INTERPRETER "/usr/new/lib/B/bint"
                     44: #endif
                     45: 
                     46: /*
                     47:  * Local definitions:
                     48:  */
                     49: 
                     50: #ifndef INTRMSG
                     51: #define INTRMSG "*** Interrupted" /* Acknowledges interrupt */
                     52: #endif INTRMSG
                     53: 
                     54: #define Moreinput(stream) ((stream)->_cnt > 0)
                     55: 
                     56: Hidden int fdown[2]; /* File descriptors for pipe down */
                     57: Hidden int fup[2]; /* Pipe up */
                     58: 
                     59: Hidden int pid; /* Process id of child */
                     60: 
                     61: Hidden FILE *pdown; /* FILE pointer for pipe down to child process */
                     62: Hidden FILE *pup; /* Pipe up */
                     63: 
                     64: Hidden string interpreter; /* Name of interpreter to be used */
                     65: 
                     66: 
                     67: Hidden char pushback[100]; /* Limited pushback facility */
                     68: Hidden int npushback; /* Number of characters pushed back */
                     69: 
                     70: 
                     71: /*
                     72:  * Routine to set canjump, do a getc, and clear canjump.
                     73:  */
                     74: 
                     75: Visible int
                     76: ffgetc(fp)
                     77:        FILE *fp;
                     78: {
                     79:        register int c;
                     80: 
                     81:        canjump = Yes;
                     82:        c = getc(fp);
                     83:        canjump = No;
                     84:        return c;
                     85: }
                     86: 
                     87: 
                     88: /*
                     89:  * Similar for fgets.
                     90:  */
                     91: 
                     92: Visible string
                     93: ffgets(buf, len, fp)
                     94:        string buf;
                     95:        int len;
                     96:        FILE *fp;
                     97: {
                     98:        canjump = Yes;
                     99:        buf = fgets(buf, len, fp);
                    100:        canjump = No;
                    101:        return buf;
                    102: }
                    103: 
                    104: 
                    105: /*
                    106:  * Assign values to `fdown' and `fup'.
                    107:  */
                    108: 
                    109: Hidden Procedure
                    110: getdevices()
                    111: {
                    112:        if (pipe(fdown) < 0 || pipe(fup) < 0)
                    113:                syserr("%s", unixerror("can't pipe"));
                    114: }
                    115: 
                    116: 
                    117: /*
                    118:  * Do the magic required for child-birth.
                    119:  */
                    120: 
                    121: Hidden Procedure
                    122: makechild()
                    123: {
                    124: #ifdef VFORK
                    125:        pid = vfork();
                    126: #else VFORK
                    127:        pid = fork();
                    128: #endif VFORK
                    129:        if (pid == -1)
                    130:                syserr("%s", unixerror("can't fork"));
                    131:        if (pid == 0) /* Child */
                    132:                exec_b(); /* Does not return */
                    133:        /* Parent */
                    134:        close(fdown[0]);
                    135:        close(fup[1]);
                    136: }
                    137: 
                    138: 
                    139: /*
                    140:  * Code executed in the child process.  Never returns.
                    141:  * Just dup the pipe ends to files 0, a and 2 (stdin, stdout and stderr),
                    142:  * then close the original pipes.
                    143:  */
                    144: 
                    145: Hidden Procedure
                    146: exec_b()
                    147: {
                    148:        close(fdown[1]), close(fup[0]);
                    149:        close(0), close(1), close(2);
                    150:        dup(fdown[0]), dup(fup[1]), dup(fup[1]);
                    151:        close(fdown[0]), close(fup[1]);
                    152:        execl(interpreter, interpreter, "-i", (char*)NULL);
                    153:        fprintf(stderr, "*** ");
                    154:        perror(interpreter);
                    155:        _exit(1);
                    156: }
                    157: 
                    158: 
                    159: /*
                    160:  * Interrupt handler.
                    161:  * Usually only the flag `interrupted' is set.
                    162:  *
                    163:  * When `canjump' is on, it is cleared and we do a longjmp
                    164:  * back to where jumpbuf leads us (usually done when a read
                    165:  * system call is interrupted, as 4.2BSD tends to continue
                    166:  * these rather than have them return with errno = EINTR).
                    167:  */
                    168: 
                    169: Hidden Procedure
                    170: disrupt()
                    171: {
                    172:        interrupted = Yes;
                    173:        signal(SIGINT, disrupt);
                    174:        if (canjump) {
                    175:                canjump = No;
                    176:                longjmp(jumpback, 1);
                    177:        }
                    178: }
                    179: 
                    180: 
                    181: /*
                    182:  * Start the B interpreter as a subprocess.
                    183:  * Set up communication pipes in pdown, pup.
                    184:  */
                    185: 
                    186: Visible Procedure
                    187: start_b(ppdown, ppup)
                    188:        FILE **ppdown;
                    189:        FILE **ppup;
                    190: {
                    191:        interpreter = getenv("B_INTERPRETER");
                    192:        if (!interpreter)
                    193:                interpreter = INTERPRETER;
                    194:        getdevices();
                    195:        makechild();
                    196:        pdown = fdopen(fdown[1], "w");
                    197:        pup = fdopen(fup[0], "r");
                    198:        if (!pdown || !pup)
                    199:                syserr("%s", unixerror("can't fdopen"));
                    200:        *ppdown = pdown;
                    201:        *ppup = pup;
                    202:        signal(SIGINT, disrupt);
                    203: }
                    204: 
                    205: 
                    206: /*
                    207:  * Routine to be called after each line of data has been passed
                    208:  * to the B interpreter; it checks whether the immediate next
                    209:  * output is a request for an immediate command, and if so,
                    210:  * eats the request and returns Yes.  Otherwise it pushes back the
                    211:  * request for later processing by sleur(), and returns No.
                    212:  * ***** The prompt parameter is a relict of old times. *****
                    213:  */
                    214: 
                    215: Visible bool
                    216: expect(prompt)
                    217:        string prompt; /* Only first char used; should be ">" */
                    218: {
                    219:        register int c;
                    220: 
                    221:        fflush(pdown);
                    222:        if (setjmp(jumpback))
                    223:                return No;
                    224:        if (npushback)
                    225:                c = pushback[--npushback];
                    226:        else
                    227:                c = ffgetc(pup);
                    228:        if (c != ESCAPE) {
                    229:                if (c != EOF)
                    230:                        pushback[npushback++] = c;
                    231:                return No;
                    232:        }
                    233:        if (npushback)
                    234:                c = pushback[--npushback];
                    235:        else
                    236:                c = ffgetc(pup);
                    237:        if (c == *prompt)
                    238:                return Yes;
                    239:        if (c != EOF)
                    240:                pushback[npushback++] = c;
                    241:        pushback[npushback++] = ESCAPE;
                    242:        return No;
                    243: }
                    244: 
                    245: 
                    246: Visible int
                    247: sleur()
                    248: {
                    249:        register int c;
                    250:        register int x = 0;
                    251:        bool show = Yes; /* No when looking for interrupt sync char */
                    252:        bool idle = Yes; /* Yes when no output done yet this call */
                    253: 
                    254:        fflush(pdown);
                    255: 
                    256:        for (;;) {
                    257:                if (interrupted) {
                    258:                        interrupted = No;
                    259:                        intrchild();
                    260:                        show = No;
                    261:                }
                    262:                if (show && npushback == 0 && !Moreinput(pup))
                    263:                        fflush(stdout);
                    264:                if (setjmp(jumpback))
                    265:                        continue;
                    266:                if (npushback > 0)
                    267:                        c = pushback[--npushback];
                    268:                else
                    269:                        c = ffgetc(pup);
                    270:                if (c == EOF) { /* End-of-file: B interpreter has terminated. */
                    271:                        fflush(stdout);
                    272:                        return EOF;
                    273:                }
                    274:                if (c == RESYNC) {
                    275:                        /* B interpreter acknowledges interrupt. */
                    276:                        if (!show) {
                    277:                                if (x != 0) putchar('\n');
                    278:                                fputs(INTRMSG, stdout);
                    279:                                putchar('\n');
                    280:                                x = 0;
                    281:                                show = Yes;
                    282:                        }
                    283:                        continue;
                    284:                }
                    285:                if (show) {
                    286:                        if (c != ESCAPE) {
                    287:                                putchar(c);
                    288:                                switch (c) {
                    289:                                case '\t':
                    290:                                        x = (x/TABS + 1)*TABS;
                    291:                                        break;
                    292:                                case '\b':
                    293:                                        if (x > 0) --x;
                    294:                                        break;
                    295:                                case '\r':
                    296:                                case '\n':
                    297:                                        x = 0;
                    298:                                        break;
                    299:                                default:
                    300:                                        if (isascii(c) && isprint(c)
                    301:                                                || c == ' ') ++x;
                    302:                                        break;
                    303:                                }
                    304:                        }
                    305:                        else {
                    306:                                /* Control-A: B interpreter needs input. */
                    307:                                if (setjmp(jumpback))
                    308:                                        continue;
                    309:                                if (npushback)
                    310:                                        c = pushback[--npushback];
                    311:                                else {
                    312:                                        c = ffgetc(pup);
                    313:                                        if (c == EOF) {
                    314:                                                return EOF;
                    315:                                        }
                    316:                                }
                    317:                                if (c == '>') {
                    318:                                        /* Newline before command prompt */
                    319:                                        if (x != 0) putchar('\n');
                    320:                                        x = 0;
                    321:                                }
                    322:                                setindent(x);
                    323:                                fflush(stdout);
                    324:                                return c;
                    325:                        }
                    326:                }
                    327:        }
                    328: }
                    329: 
                    330: 
                    331: /*
                    332:  * Send the child a termination signal (SIGTERM).
                    333:  */
                    334: 
                    335: Visible Procedure
                    336: termchild()
                    337: {
                    338:        if (pid) {
                    339:                kill(pid, SIGTERM);
                    340:                pid = 0;
                    341:        }
                    342: }
                    343: 
                    344: 
                    345: /*
                    346:  * Send the child an interrupt signal.  (By convention, this is SIGTRAP).
                    347:  */
                    348: 
                    349: Visible Procedure
                    350: intrchild()
                    351: {
                    352:        if (pid) {
                    353:                kill(pid, INTRCHILD);
                    354:                fflush(stdout);
                    355:        }
                    356: }
                    357: 
                    358: 
                    359: /*
                    360:  * Wait for child process and report abnormal exit statuses.
                    361:  */
                    362: 
                    363: Visible Procedure
                    364: waitchild()
                    365: {
                    366:        int k;
                    367:        int status;
                    368: 
                    369:        if (pid) {
                    370:                while ((k = wait(&status)) != -1) {
                    371:                        if (k != pid)
                    372: #ifndef SMALLSYS
                    373:                                fprintf(stderr, "*** [Pid %d status 0%o]\n", pid, status)
                    374: #endif SMALLSYS
                    375:                                ;
                    376:                        else {
                    377: #ifndef SMALLSYS
                    378:                                if (status&0377)
                    379:                                        fprintf(stderr, "*** Interpreter killed by signal %d%s\n",
                    380:                                                status&0177, status&0200 ? " - core dumped" : "");
                    381:                                else if (status)
                    382:                                        fprintf(stderr, "*** Interpreter exit(%d)\n", status>>8);
                    383: #endif SMALLSYS
                    384:                                pid = 0;
                    385:                                break;
                    386:                        }
                    387:                }
                    388: #ifndef SMALLSYS
                    389:                if (pid)
                    390:                        fprintf(stderr, "*** Can't get interpreter status\n");
                    391: #endif SMALLSYS
                    392:                pid = 0;
                    393:        }
                    394: }
                    395: 
                    396: #endif BTOP

unix.superglobalmegacorp.com

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