Annotation of 43BSD/ucb/ex/ex_io.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char *sccsid = "@(#)ex_io.c     7.11 (Berkeley) 6/7/85";
                      9: #endif not lint
                     10: 
                     11: #include "ex.h"
                     12: #include "ex_argv.h"
                     13: #include "ex_temp.h"
                     14: #include "ex_tty.h"
                     15: #include "ex_vis.h"
                     16: 
                     17: /*
                     18:  * File input/output, source, preserve and recover
                     19:  */
                     20: 
                     21: /*
                     22:  * Following remember where . was in the previous file for return
                     23:  * on file switching.
                     24:  */
                     25: int    altdot;
                     26: int    oldadot;
                     27: bool   wasalt;
                     28: short  isalt;
                     29: 
                     30: long   cntch;                  /* Count of characters on unit io */
                     31: #ifndef VMUNIX
                     32: short  cntln;                  /* Count of lines " */
                     33: #else
                     34: int    cntln;
                     35: #endif
                     36: long   cntnull;                /* Count of nulls " */
                     37: long   cntodd;                 /* Count of non-ascii characters " */
                     38: 
                     39: /*
                     40:  * Parse file name for command encoded by comm.
                     41:  * If comm is E then command is doomed and we are
                     42:  * parsing just so user won't have to retype the name.
                     43:  */
                     44: filename(comm)
                     45:        int comm;
                     46: {
                     47:        register int c = comm, d;
                     48:        register int i;
                     49: 
                     50:        d = getchar();
                     51:        if (endcmd(d)) {
                     52:                if (savedfile[0] == 0 && comm != 'f')
                     53:                        error("No file|No current filename");
                     54:                CP(file, savedfile);
                     55:                wasalt = (isalt > 0) ? isalt-1 : 0;
                     56:                isalt = 0;
                     57:                oldadot = altdot;
                     58:                if (c == 'e' || c == 'E')
                     59:                        altdot = lineDOT();
                     60:                if (d == EOF)
                     61:                        ungetchar(d);
                     62:        } else {
                     63:                ungetchar(d);
                     64:                getone();
                     65:                eol();
                     66:                if (savedfile[0] == 0 && c != 'E' && c != 'e') {
                     67:                        c = 'e';
                     68:                        edited = 0;
                     69:                }
                     70:                wasalt = strcmp(file, altfile) == 0;
                     71:                oldadot = altdot;
                     72:                switch (c) {
                     73: 
                     74:                case 'f':
                     75:                        edited = 0;
                     76:                        /* fall into ... */
                     77: 
                     78:                case 'e':
                     79:                        if (savedfile[0]) {
                     80:                                altdot = lineDOT();
                     81:                                CP(altfile, savedfile);
                     82:                        }
                     83:                        CP(savedfile, file);
                     84:                        break;
                     85: 
                     86:                default:
                     87:                        if (file[0]) {
                     88:                                if (c != 'E')
                     89:                                        altdot = lineDOT();
                     90:                                CP(altfile, file);
                     91:                        }
                     92:                        break;
                     93:                }
                     94:        }
                     95:        if (hush && comm != 'f' || comm == 'E')
                     96:                return;
                     97:        if (file[0] != 0) {
                     98:                lprintf("\"%s\"", file);
                     99:                if (comm == 'f') {
                    100:                        if (value(READONLY))
                    101:                                printf(" [Read only]");
                    102:                        if (!edited)
                    103:                                printf(" [Not edited]");
                    104:                        if (tchng)
                    105:                                printf(" [Modified]");
                    106:                }
                    107:                flush();
                    108:        } else
                    109:                printf("No file ");
                    110:        if (comm == 'f') {
                    111:                if (!(i = lineDOL()))
                    112:                        i++;
                    113:                printf(" line %d of %d --%ld%%--", lineDOT(), lineDOL(),
                    114:                    (long) 100 * lineDOT() / i);
                    115:        }
                    116: }
                    117: 
                    118: /*
                    119:  * Get the argument words for a command into genbuf
                    120:  * expanding # and %.
                    121:  */
                    122: getargs()
                    123: {
                    124:        register int c;
                    125:        register char *cp, *fp;
                    126:        static char fpatbuf[32];        /* hence limit on :next +/pat */
                    127: 
                    128:        pastwh();
                    129:        if (peekchar() == '+') {
                    130:                for (cp = fpatbuf;;) {
                    131:                        c = *cp++ = getchar();
                    132:                        if (cp >= &fpatbuf[sizeof(fpatbuf)])
                    133:                                error("Pattern too long");
                    134:                        if (c == '\\' && isspace(peekchar()))
                    135:                                c = getchar();
                    136:                        if (c == EOF || isspace(c)) {
                    137:                                ungetchar(c);
                    138:                                *--cp = 0;
                    139:                                firstpat = &fpatbuf[1];
                    140:                                break;
                    141:                        }
                    142:                }
                    143:        }
                    144:        if (skipend())
                    145:                return (0);
                    146:        CP(genbuf, "echo "); cp = &genbuf[5];
                    147:        for (;;) {
                    148:                c = getchar();
                    149:                if (endcmd(c)) {
                    150:                        ungetchar(c);
                    151:                        break;
                    152:                }
                    153:                switch (c) {
                    154: 
                    155:                case '\\':
                    156:                        if (any(peekchar(), "#%|"))
                    157:                                c = getchar();
                    158:                        /* fall into... */
                    159: 
                    160:                default:
                    161:                        if (cp > &genbuf[LBSIZE - 2])
                    162: flong:
                    163:                                error("Argument buffer overflow");
                    164:                        *cp++ = c;
                    165:                        break;
                    166: 
                    167:                case '#':
                    168:                        fp = altfile;
                    169:                        if (*fp == 0)
                    170:                                error("No alternate filename@to substitute for #");
                    171:                        goto filexp;
                    172: 
                    173:                case '%':
                    174:                        fp = savedfile;
                    175:                        if (*fp == 0)
                    176:                                error("No current filename@to substitute for %%");
                    177: filexp:
                    178:                        while (*fp) {
                    179:                                if (cp > &genbuf[LBSIZE - 2])
                    180:                                        goto flong;
                    181:                                *cp++ = *fp++;
                    182:                        }
                    183:                        break;
                    184:                }
                    185:        }
                    186:        *cp = 0;
                    187:        return (1);
                    188: }
                    189: 
                    190: /*
                    191:  * Glob the argument words in genbuf, or if no globbing
                    192:  * is implied, just split them up directly.
                    193:  */
                    194: glob(gp)
                    195:        struct glob *gp;
                    196: {
                    197:        int pvec[2];
                    198:        register char **argv = gp->argv;
                    199:        register char *cp = gp->argspac;
                    200:        register int c;
                    201:        char ch;
                    202:        int nleft = NCARGS;
                    203: 
                    204:        gp->argc0 = 0;
                    205:        if (gscan() == 0) {
                    206:                register char *v = genbuf + 5;          /* strlen("echo ") */
                    207: 
                    208:                for (;;) {
                    209:                        while (isspace(*v))
                    210:                                v++;
                    211:                        if (!*v)
                    212:                                break;
                    213:                        *argv++ = cp;
                    214:                        while (*v && !isspace(*v))
                    215:                                *cp++ = *v++;
                    216:                        *cp++ = 0;
                    217:                        gp->argc0++;
                    218:                }
                    219:                *argv = 0;
                    220:                return;
                    221:        }
                    222:        if (pipe(pvec) < 0)
                    223:                error("Can't make pipe to glob");
                    224:        pid = fork();
                    225:        io = pvec[0];
                    226:        if (pid < 0) {
                    227:                close(pvec[1]);
                    228:                error("Can't fork to do glob");
                    229:        }
                    230:        if (pid == 0) {
                    231:                int oerrno;
                    232: 
                    233:                close(1);
                    234:                dup(pvec[1]);
                    235:                close(pvec[0]);
                    236:                close(2);       /* so errors don't mess up the screen */
                    237:                open("/dev/null", 1);
                    238:                execl(svalue(SHELL), "sh", "-c", genbuf, 0);
                    239:                oerrno = errno; close(1); dup(2); errno = oerrno;
                    240:                filioerr(svalue(SHELL));
                    241:        }
                    242:        close(pvec[1]);
                    243:        do {
                    244:                *argv = cp;
                    245:                for (;;) {
                    246:                        if (read(io, &ch, 1) != 1) {
                    247:                                close(io);
                    248:                                c = -1;
                    249:                        } else
                    250:                                c = ch & TRIM;
                    251:                        if (c <= 0 || isspace(c))
                    252:                                break;
                    253:                        *cp++ = c;
                    254:                        if (--nleft <= 0)
                    255:                                error("Arg list too long");
                    256:                }
                    257:                if (cp != *argv) {
                    258:                        --nleft;
                    259:                        *cp++ = 0;
                    260:                        gp->argc0++;
                    261:                        if (gp->argc0 >= NARGS)
                    262:                                error("Arg list too long");
                    263:                        argv++;
                    264:                }
                    265:        } while (c >= 0);
                    266:        waitfor();
                    267:        if (gp->argc0 == 0)
                    268:                error("No match");
                    269: }
                    270: 
                    271: /*
                    272:  * Scan genbuf for shell metacharacters.
                    273:  * Set is union of v7 shell and csh metas.
                    274:  */
                    275: gscan()
                    276: {
                    277:        register char *cp;
                    278: 
                    279:        for (cp = genbuf; *cp; cp++)
                    280:                if (any(*cp, "~{[*?$`'\"\\"))
                    281:                        return (1);
                    282:        return (0);
                    283: }
                    284: 
                    285: /*
                    286:  * Parse one filename into file.
                    287:  */
                    288: struct glob G;
                    289: getone()
                    290: {
                    291:        register char *str;
                    292: 
                    293:        if (getargs() == 0)
                    294:                error("Missing filename");
                    295:        glob(&G);
                    296:        if (G.argc0 > 1)
                    297:                error("Ambiguous|Too many file names");
                    298:        str = G.argv[G.argc0 - 1];
                    299:        if (strlen(str) > FNSIZE - 4)
                    300:                error("Filename too long");
                    301: samef:
                    302:        CP(file, str);
                    303: }
                    304: 
                    305: /*
                    306:  * Read a file from the world.
                    307:  * C is command, 'e' if this really an edit (or a recover).
                    308:  */
                    309: rop(c)
                    310:        int c;
                    311: {
                    312:        register int i;
                    313:        struct stat stbuf;
                    314:        short magic;
                    315:        static int ovro;        /* old value(READONLY) */
                    316:        static int denied;      /* 1 if READONLY was set due to file permissions */
                    317: 
                    318:        io = open(file, 0);
                    319:        if (io < 0) {
                    320:                if (c == 'e' && errno == ENOENT) {
                    321:                        edited++;
                    322:                        /*
                    323:                         * If the user just did "ex foo" he is probably
                    324:                         * creating a new file.  Don't be an error, since
                    325:                         * this is ugly, and it screws up the + option.
                    326:                         */
                    327:                        if (!seenprompt) {
                    328:                                printf(" [New file]");
                    329:                                noonl();
                    330:                                return;
                    331:                        }
                    332:                }
                    333:                syserror();
                    334:        }
                    335:        if (fstat(io, &stbuf))
                    336:                syserror();
                    337:        switch (stbuf.st_mode & S_IFMT) {
                    338: 
                    339:        case S_IFBLK:
                    340:                error(" Block special file");
                    341: 
                    342:        case S_IFCHR:
                    343:                if (isatty(io))
                    344:                        error(" Teletype");
                    345:                if (samei(&stbuf, "/dev/null"))
                    346:                        break;
                    347:                error(" Character special file");
                    348: 
                    349:        case S_IFDIR:
                    350:                error(" Directory");
                    351: 
                    352:        case S_IFREG:
                    353: #ifdef CRYPT
                    354:                if (xflag)
                    355:                        break;
                    356: #endif
                    357:                i = read(io, (char *) &magic, sizeof(magic));
                    358:                lseek(io, 0l, 0);
                    359:                if (i != sizeof(magic))
                    360:                        break;
                    361:                switch (magic) {
                    362: 
                    363:                case 0405:      /* data overlay on exec */
                    364:                case 0407:      /* unshared */
                    365:                case 0410:      /* shared text */
                    366:                case 0411:      /* separate I/D */
                    367:                case 0413:      /* VM/Unix demand paged */
                    368:                case 0430:      /* PDP-11 Overlay shared */
                    369:                case 0431:      /* PDP-11 Overlay sep I/D */
                    370:                        error(" Executable");
                    371: 
                    372:                /*
                    373:                 * We do not forbid the editing of portable archives
                    374:                 * because it is reasonable to edit them, especially
                    375:                 * if they are archives of text files.  This is
                    376:                 * especially useful if you archive source files together
                    377:                 * and copy them to another system with ~%take, since
                    378:                 * the files sometimes show up munged and must be fixed.
                    379:                 */
                    380:                case 0177545:
                    381:                case 0177555:
                    382:                        error(" Archive");
                    383: 
                    384:                default:
                    385: #ifdef mbb
                    386:                        /* C/70 has a 10 bit byte */
                    387:                        if (magic & 03401600)
                    388: #else
                    389:                        /* Everybody else has an 8 bit byte */
                    390:                        if (magic & 0100200)
                    391: #endif
                    392:                                error(" Non-ascii file");
                    393:                        break;
                    394:                }
                    395:        }
                    396:        if (c != 'r') {
                    397:                if (value(READONLY) && denied) {
                    398:                        value(READONLY) = ovro;
                    399:                        denied = 0;
                    400:                }
                    401:                if ((stbuf.st_mode & 0222) == 0 || access(file, 2) < 0) {
                    402:                        ovro = value(READONLY);
                    403:                        denied = 1;
                    404:                        value(READONLY) = 1;
                    405:                }
                    406:        }
                    407:        if (value(READONLY)) {
                    408:                printf(" [Read only]");
                    409:                flush();
                    410:        }
                    411:        if (c == 'r')
                    412:                setdot();
                    413:        else
                    414:                setall();
                    415:        if (FIXUNDO && inopen && c == 'r')
                    416:                undap1 = undap2 = dot + 1;
                    417:        rop2();
                    418:        rop3(c);
                    419: }
                    420: 
                    421: rop2()
                    422: {
                    423:        line *first, *last, *a;
                    424:        struct stat statb;
                    425: 
                    426:        deletenone();
                    427:        clrstats();
                    428:        first = addr2 + 1;
                    429:        if (fstat(io, &statb) < 0)
                    430:                bsize = LBSIZE;
                    431:        else {
                    432:                bsize = statb.st_blksize;
                    433:                if (bsize <= 0)
                    434:                        bsize = LBSIZE;
                    435:        }
                    436:        ignore(append(getfile, addr2));
                    437:        last = dot;
                    438:        /*
                    439:         *      if the modeline variable is set,
                    440:         *      check the first and last five lines of the file
                    441:         *      for a mode line.
                    442:         */
                    443:        if (value(MODELINE)) {
                    444:                for (a=first; a<=last; a++) {
                    445:                        if (a==first+5 && last-first > 10)
                    446:                                a = last - 4;
                    447:                        getline(*a);
                    448:                        checkmodeline(linebuf);
                    449:                }
                    450:        }
                    451: }
                    452: 
                    453: rop3(c)
                    454:        int c;
                    455: {
                    456: 
                    457:        if (iostats() == 0 && c == 'e')
                    458:                edited++;
                    459:        if (c == 'e') {
                    460:                if (wasalt || firstpat) {
                    461:                        register line *addr = zero + oldadot;
                    462: 
                    463:                        if (addr > dol)
                    464:                                addr = dol;
                    465:                        if (firstpat) {
                    466:                                globp = (*firstpat) ? firstpat : "$";
                    467:                                commands(1,1);
                    468:                                firstpat = 0;
                    469:                        } else if (addr >= one) {
                    470:                                if (inopen)
                    471:                                        dot = addr;
                    472:                                markpr(addr);
                    473:                        } else
                    474:                                goto other;
                    475:                } else
                    476: other:
                    477:                        if (dol > zero) {
                    478:                                if (inopen)
                    479:                                        dot = one;
                    480:                                markpr(one);
                    481:                        }
                    482:                if(FIXUNDO)
                    483:                        undkind = UNDNONE;
                    484:                if (inopen) {
                    485:                        vcline = 0;
                    486:                        vreplace(0, LINES, lineDOL());
                    487:                }
                    488:        }
                    489: }
                    490: 
                    491: /*
                    492:  * Are these two really the same inode?
                    493:  */
                    494: samei(sp, cp)
                    495:        struct stat *sp;
                    496:        char *cp;
                    497: {
                    498:        struct stat stb;
                    499: 
                    500:        if (stat(cp, &stb) < 0 || sp->st_dev != stb.st_dev)
                    501:                return (0);
                    502:        return (sp->st_ino == stb.st_ino);
                    503: }
                    504: 
                    505: /* Returns from edited() */
                    506: #define        EDF     0               /* Edited file */
                    507: #define        NOTEDF  -1              /* Not edited file */
                    508: #define        PARTBUF 1               /* Write of partial buffer to Edited file */
                    509: 
                    510: /*
                    511:  * Write a file.
                    512:  */
                    513: wop(dofname)
                    514: bool dofname;  /* if 1 call filename, else use savedfile */
                    515: {
                    516:        register int c, exclam, nonexist;
                    517:        line *saddr1, *saddr2;
                    518:        struct stat stbuf;
                    519: 
                    520:        c = 0;
                    521:        exclam = 0;
                    522:        if (dofname) {
                    523:                if (peekchar() == '!')
                    524:                        exclam++, ignchar();
                    525:                ignore(skipwh());
                    526:                while (peekchar() == '>')
                    527:                        ignchar(), c++, ignore(skipwh());
                    528:                if (c != 0 && c != 2)
                    529:                        error("Write forms are 'w' and 'w>>'");
                    530:                filename('w');
                    531:        } else {
                    532:                if (savedfile[0] == 0)
                    533:                        error("No file|No current filename");
                    534:                saddr1=addr1;
                    535:                saddr2=addr2;
                    536:                addr1=one;
                    537:                addr2=dol;
                    538:                CP(file, savedfile);
                    539:                if (inopen) {
                    540:                        vclrech(0);
                    541:                        splitw++;
                    542:                }
                    543:                lprintf("\"%s\"", file);
                    544:        }
                    545:        nonexist = stat(file, &stbuf);
                    546:        switch (c) {
                    547: 
                    548:        case 0:
                    549:                if (!exclam && (!value(WRITEANY) || value(READONLY)))
                    550:                switch (edfile()) {
                    551:                
                    552:                case NOTEDF:
                    553:                        if (nonexist)
                    554:                                break;
                    555:                        if ((stbuf.st_mode & S_IFMT) == S_IFCHR) {
                    556:                                if (samei(&stbuf, "/dev/null"))
                    557:                                        break;
                    558:                                if (samei(&stbuf, "/dev/tty"))
                    559:                                        break;
                    560:                        }
                    561:                        io = open(file, 1);
                    562:                        if (io < 0)
                    563:                                syserror();
                    564:                        if (!isatty(io))
                    565:                                serror(" File exists| File exists - use \"w! %s\" to overwrite", file);
                    566:                        close(io);
                    567:                        break;
                    568: 
                    569:                case EDF:
                    570:                        if (value(READONLY))
                    571:                                error(" File is read only");
                    572:                        break;
                    573: 
                    574:                case PARTBUF:
                    575:                        if (value(READONLY))
                    576:                                error(" File is read only");
                    577:                        error(" Use \"w!\" to write partial buffer");
                    578:                }
                    579: cre:
                    580: /*
                    581:                synctmp();
                    582: */
                    583: #ifdef V6
                    584:                io = creat(file, 0644);
                    585: #else
                    586:                io = creat(file, 0666);
                    587: #endif
                    588:                if (io < 0)
                    589:                        syserror();
                    590:                writing = 1;
                    591:                if (hush == 0)
                    592:                        if (nonexist)
                    593:                                printf(" [New file]");
                    594:                        else if (value(WRITEANY) && edfile() != EDF)
                    595:                                printf(" [Existing file]");
                    596:                break;
                    597: 
                    598:        case 2:
                    599:                io = open(file, 1);
                    600:                if (io < 0) {
                    601:                        if (exclam || value(WRITEANY))
                    602:                                goto cre;
                    603:                        syserror();
                    604:                }
                    605:                lseek(io, 0l, 2);
                    606:                break;
                    607:        }
                    608:        putfile(0);
                    609:        ignore(iostats());
                    610:        if (c != 2 && addr1 == one && addr2 == dol) {
                    611:                if (eq(file, savedfile))
                    612:                        edited = 1;
                    613:                sync();
                    614:        }
                    615:        if (!dofname) {
                    616:                addr1 = saddr1;
                    617:                addr2 = saddr2;
                    618:        }
                    619:        writing = 0;
                    620: }
                    621: 
                    622: /*
                    623:  * Is file the edited file?
                    624:  * Work here is that it is not considered edited
                    625:  * if this is a partial buffer, and distinguish
                    626:  * all cases.
                    627:  */
                    628: edfile()
                    629: {
                    630: 
                    631:        if (!edited || !eq(file, savedfile))
                    632:                return (NOTEDF);
                    633:        return (addr1 == one && addr2 == dol ? EDF : PARTBUF);
                    634: }
                    635: 
                    636: /*
                    637:  * Extract the next line from the io stream.
                    638:  */
                    639: char *nextip;
                    640: 
                    641: getfile()
                    642: {
                    643:        register short c;
                    644:        register char *lp, *fp;
                    645: 
                    646:        lp = linebuf;
                    647:        fp = nextip;
                    648:        do {
                    649:                if (--ninbuf < 0) {
                    650:                        ninbuf = read(io, genbuf, bsize) - 1;
                    651:                        if (ninbuf < 0) {
                    652:                                if (lp != linebuf) {
                    653:                                        lp++;
                    654:                                        printf(" [Incomplete last line]");
                    655:                                        break;
                    656:                                }
                    657:                                return (EOF);
                    658:                        }
                    659: #ifdef CRYPT
                    660:                        if (kflag) {
                    661:                                fp = genbuf;
                    662:                                while(fp < &genbuf[ninbuf]) {
                    663:                                        if (*fp++ & 0200) {
                    664:                                                crblock(perm, genbuf, ninbuf+1,
                    665:        cntch);
                    666:                                                break;
                    667:                                        }
                    668:                                }
                    669:                        }
                    670: #endif
                    671:                        fp = genbuf;
                    672:                        cntch += ninbuf+1;
                    673:                }
                    674:                if (lp >= &linebuf[LBSIZE]) {
                    675:                        error(" Line too long");
                    676:                }
                    677:                c = *fp++;
                    678:                if (c == 0) {
                    679:                        cntnull++;
                    680:                        continue;
                    681:                }
                    682:                if (c & QUOTE) {
                    683:                        cntodd++;
                    684:                        c &= TRIM;
                    685:                        if (c == 0)
                    686:                                continue;
                    687:                }
                    688:                *lp++ = c;
                    689:        } while (c != '\n');
                    690:        *--lp = 0;
                    691:        nextip = fp;
                    692:        cntln++;
                    693:        return (0);
                    694: }
                    695: 
                    696: /*
                    697:  * Write a range onto the io stream.
                    698:  */
                    699: putfile(isfilter)
                    700: int isfilter;
                    701: {
                    702:        line *a1;
                    703:        register char *fp, *lp;
                    704:        register int nib;
                    705:        struct stat statb;
                    706: 
                    707:        a1 = addr1;
                    708:        clrstats();
                    709:        cntln = addr2 - a1 + 1;
                    710:        if (cntln == 0)
                    711:                return;
                    712:        if (fstat(io, &statb) < 0)
                    713:                bsize = LBSIZE;
                    714:        else {
                    715:                bsize = statb.st_blksize;
                    716:                if (bsize <= 0)
                    717:                        bsize = LBSIZE;
                    718:        }
                    719:        nib = bsize;
                    720:        fp = genbuf;
                    721:        do {
                    722:                getline(*a1++);
                    723:                lp = linebuf;
                    724:                for (;;) {
                    725:                        if (--nib < 0) {
                    726:                                nib = fp - genbuf;
                    727: #ifdef CRYPT
                    728:                                if(kflag && !isfilter)
                    729:                                         crblock(perm, genbuf, nib, cntch);
                    730: #endif
                    731:                                if (write(io, genbuf, nib) != nib) {
                    732:                                        wrerror();
                    733:                                }
                    734:                                cntch += nib;
                    735:                                nib = bsize - 1;
                    736:                                fp = genbuf;
                    737:                        }
                    738:                        if ((*fp++ = *lp++) == 0) {
                    739:                                fp[-1] = '\n';
                    740:                                break;
                    741:                        }
                    742:                }
                    743:        } while (a1 <= addr2);
                    744:        nib = fp - genbuf;
                    745: #ifdef CRYPT
                    746:        if(kflag && !isfilter)
                    747:                crblock(perm, genbuf, nib, cntch);
                    748: #endif
                    749:        if (write(io, genbuf, nib) != nib) {
                    750:                wrerror();
                    751:        }
                    752:        cntch += nib;
                    753: }
                    754: 
                    755: /*
                    756:  * A write error has occurred;  if the file being written was
                    757:  * the edited file then we consider it to have changed since it is
                    758:  * now likely scrambled.
                    759:  */
                    760: wrerror()
                    761: {
                    762: 
                    763:        if (eq(file, savedfile) && edited)
                    764:                change();
                    765:        syserror();
                    766: }
                    767: 
                    768: /*
                    769:  * Source command, handles nested sources.
                    770:  * Traps errors since it mungs unit 0 during the source.
                    771:  */
                    772: short slevel;
                    773: short ttyindes;
                    774: 
                    775: source(fil, okfail)
                    776:        char *fil;
                    777:        bool okfail;
                    778: {
                    779:        jmp_buf osetexit;
                    780:        register int saveinp, ointty, oerrno;
                    781:        char *saveglobp;
                    782:        short savepeekc;
                    783: 
                    784:        signal(SIGINT, SIG_IGN);
                    785:        saveinp = dup(0);
                    786:        savepeekc = peekc;
                    787:        saveglobp = globp;
                    788:        peekc = 0; globp = 0;
                    789:        if (saveinp < 0)
                    790:                error("Too many nested sources");
                    791:        if (slevel <= 0)
                    792:                ttyindes = saveinp;
                    793:        close(0);
                    794:        if (open(fil, 0) < 0) {
                    795:                oerrno = errno;
                    796:                setrupt();
                    797:                dup(saveinp);
                    798:                close(saveinp);
                    799:                errno = oerrno;
                    800:                if (!okfail)
                    801:                        filioerr(fil);
                    802:                return;
                    803:        }
                    804:        slevel++;
                    805:        ointty = intty;
                    806:        intty = isatty(0);
                    807:        oprompt = value(PROMPT);
                    808:        value(PROMPT) &= intty;
                    809:        getexit(osetexit);
                    810:        setrupt();
                    811:        if (setexit() == 0)
                    812:                commands(1, 1);
                    813:        else if (slevel > 1) {
                    814:                close(0);
                    815:                dup(saveinp);
                    816:                close(saveinp);
                    817:                slevel--;
                    818:                resexit(osetexit);
                    819:                reset();
                    820:        }
                    821:        intty = ointty;
                    822:        value(PROMPT) = oprompt;
                    823:        close(0);
                    824:        dup(saveinp);
                    825:        close(saveinp);
                    826:        globp = saveglobp;
                    827:        peekc = savepeekc;
                    828:        slevel--;
                    829:        resexit(osetexit);
                    830: }
                    831: 
                    832: /*
                    833:  * Clear io statistics before a read or write.
                    834:  */
                    835: clrstats()
                    836: {
                    837: 
                    838:        ninbuf = 0;
                    839:        cntch = 0;
                    840:        cntln = 0;
                    841:        cntnull = 0;
                    842:        cntodd = 0;
                    843: }
                    844: 
                    845: /*
                    846:  * Io is finished, close the unit and print statistics.
                    847:  */
                    848: iostats()
                    849: {
                    850: 
                    851:        (void) fsync(io);
                    852:        close(io);
                    853:        io = -1;
                    854:        if (hush == 0) {
                    855:                if (value(TERSE))
                    856:                        printf(" %d/%D", cntln, cntch);
                    857:                else
                    858:                        printf(" %d line%s, %D character%s", cntln, plural((long) cntln),
                    859:                            cntch, plural(cntch));
                    860:                if (cntnull || cntodd) {
                    861:                        printf(" (");
                    862:                        if (cntnull) {
                    863:                                printf("%D null", cntnull);
                    864:                                if (cntodd)
                    865:                                        printf(", ");
                    866:                        }
                    867:                        if (cntodd)
                    868:                                printf("%D non-ASCII", cntodd);
                    869:                        putchar(')');
                    870:                }
                    871:                noonl();
                    872:                flush();
                    873:        }
                    874:        return (cntnull != 0 || cntodd != 0);
                    875: }
                    876: 
                    877: #if USG | USG3TTY
                    878: /* It's so wonderful how we all speak the same language... */
                    879: # define index strchr
                    880: # define rindex strrchr
                    881: #endif
                    882: 
                    883: checkmodeline(line)
                    884: char *line;
                    885: {
                    886:        char *beg, *end;
                    887:        char cmdbuf[1024];
                    888:        char *index(), *rindex();
                    889: 
                    890:        beg = index(line, ':');
                    891:        if (beg == NULL)
                    892:                return;
                    893:        if (&beg[-3] < line)
                    894:                return;
                    895:        if (!(  ( (beg[-3] == ' ' || beg[-3] == '\t')
                    896:                && beg[-2] == 'e'
                    897:                && beg[-1] == 'x')
                    898:             || ( (beg[-3] == ' ' || beg[-3] == '\t')
                    899:                && beg[-2] == 'v'
                    900:                && beg[-1] == 'i'))) return;
                    901:        strncpy(cmdbuf, beg+1, sizeof cmdbuf);
                    902:        end = rindex(cmdbuf, ':');
                    903:        if (end == NULL)
                    904:                return;
                    905:        *end = 0;
                    906:        globp = cmdbuf;
                    907:        commands(1, 1);
                    908: }

unix.superglobalmegacorp.com

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