Annotation of coherent/d/bin/ed/ed2.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * An editor.
                      3:  * Commands.
                      4:  */
                      5: #include <stdio.h>
                      6: #include <ctype.h>
                      7: #include "ed.h"
                      8: 
                      9: /*
                     10:  * Edit a file.  The filename is stored in `file'.
                     11:  */
                     12: edit()
                     13: {
                     14:        register int ret, i;
                     15: 
                     16:        if (doladd > 0)
                     17:                delete(1, doladd);
                     18:        tmpseek = CLSIZE;
                     19:        rcurbno = -1;
                     20:        wcurbno = -1;
                     21:        if ((fp=xfopen(file, "r")) == NULL) {
                     22:                derror("Cannot open file");
                     23:                return (0);
                     24:        }
                     25: #if RSX
                     26:        if ((i=fp->v_efbk+1-tmp->v_hibk) > 0) {
                     27:                if (grow(i) == 0) {
                     28:                        terror("Temp file error");
                     29:                        return (0);
                     30:                }
                     31:        }
                     32: #endif
                     33:        ret = 1;
                     34:        if (append(0, readfil) == 0)
                     35:                ret = 0;
                     36:        else if (ferror(fp)) {
                     37:                derror("Read error");
                     38:                ret = 0;
                     39:        }
                     40:        fclose(fp);
                     41:        for (i=0; i<MKSIZE; i++)
                     42:                marklin[i] = 0;
                     43:        saved = 1;
                     44:        if (cflag != 0) {
                     45:                printl(stdout, !oflag ? cct : lct);
                     46:                printc(stdout, '\n');
                     47:        }
                     48:        return (ret);
                     49: }
                     50: 
                     51: /*
                     52:  * Make sure that the previous command is terminated either
                     53:  * immediately by a newline or has a 'p' or a 'l' which is
                     54:  * then terminated by a newline.  The variable `vcom' is set
                     55:  * to the verify command.  A zero is returned if there were
                     56:  * bad characters before the newline, otherwise a one.
                     57:  */
                     58: verify(flag)
                     59: {
                     60:        register int c;
                     61: 
                     62:        vcom = ' ';
                     63:        if (flag==0 && mflag!=0)
                     64:                return (1);
                     65:        if ((c=getx()) == '\n') {
                     66:                ungetx(c);
                     67:                return (1);
                     68:        }
                     69:        if (c=='l' || c=='p') {
                     70:                if (getx() == '\n') {
                     71:                        ungetx('\n');
                     72:                        vcom = c;
                     73:                        return (1);
                     74:                }
                     75:        }
                     76:        derror("Bad command");
                     77:        return (0);
                     78: }
                     79: 
                     80: /*
                     81:  * Get a filename of the form required for the r command.
                     82:  * which is returned in `name'.  If no name is specified,
                     83:  * the one stored in `file' is copied.  If a file name is
                     84:  * specified and none exists in `file', it is copied to
                     85:  * `file'.  If an illegal name is given, an error is derrord.
                     86:  */
                     87: getfile(name)
                     88: char name[FNSIZE+1];
                     89: {
                     90:        register int c;
                     91:        register char *p1, *p2;
                     92: 
                     93:        switch (c=getx()) {
                     94:        case '\n':
                     95:                p1 = name;
                     96:                p2 = file;
                     97:                while (*p1++ = *p2++)
                     98:                        ;
                     99:                break;
                    100:        case ' ':
                    101:        case '\t':
                    102:                p1 = name;
                    103:                p2 = &name[FNSIZE];
                    104:                while ((c=getx()) == ' ' || c == '\t')
                    105:                        ;
                    106:                *p1++ = c;
                    107:                while ((c=getx()) != EOF && c != '\n') {
                    108:                        if (p1 >= p2) {
                    109:                                derror("File name too long");
                    110:                                name[0] = '\0';
                    111:                                return (0);
                    112:                        }
                    113:                        *p1++ = c;
                    114:                }
                    115:                *p1 = '\0';
                    116:                if (c == EOF) {
                    117:                        derror("EOF in file name");
                    118:                        name[0] = '\0';
                    119:                        return (0);
                    120:                }
                    121:                if (file[0] == '\0') {
                    122:                        p1 = file;
                    123:                        p2 = name;
                    124:                        while (*p1++ = *p2++)
                    125:                                ;
                    126:                }
                    127:                break;
                    128:        default:
                    129:                while (getx() != '\n')
                    130:                        ;
                    131:                derror("Bad command");
                    132:                return (0);
                    133:        }
                    134:        if (name[0] == '\0') {
                    135:                derror("Null file name");
                    136:                return (0);
                    137:        }
                    138:        return (1);
                    139: }
                    140: 
                    141: /*
                    142:  * Read the rest of the input line into `tempbuf'.
                    143:  */
                    144: rest()
                    145: {
                    146:        register int c;
                    147:        register char *cp;
                    148: 
                    149:        cp = tempbuf;
                    150:        while ((c=getx())!=EOF && c!='\n') {
                    151:                if (cp >= &tempbuf[TBSIZE-1]) {
                    152:                        derror("Line too long");
                    153:                        return (0);
                    154:                }
                    155:                *cp++ = c;
                    156:        }
                    157:        *cp = '\0';
                    158:        return (1);
                    159: }
                    160: 
                    161: /*
                    162:  * Append text after the given address.  A line of text is gotten
                    163:  * by calling the given function until it returns NULL.
                    164:  */
                    165: append(a, f)
                    166: int (*f)();
                    167: {
                    168:        int seek;
                    169:        register int n;
                    170: 
                    171:        cct = 0;
                    172:        lct = 0;
                    173:        if (a<0 || a>doladd) {
                    174:                derror("Address out of range");
                    175:                return (0);
                    176:        }
                    177:        dotadd = a;
                    178:        while ((n=(*f)()) != 0) {
                    179:                if (intflag)
                    180:                        return (1);
                    181:                seek = linead();
                    182:                if (putline(linebuf, n) == 0)
                    183:                        return (0);
                    184:                saved = 0;
                    185:                cct += n;
                    186:                lct++;
                    187:                if (expand(dotadd) == 0)
                    188:                        return (0);
                    189:                line[++dotadd] = seek;
                    190:        }
                    191:        return (1);
                    192: }
                    193: 
                    194: /*
                    195:  * Expand the line table and leave a hole at the given address.
                    196:  */
                    197: expand(a)
                    198: {
                    199:        register LINE *lp1;
                    200:        register LINE *lp2;
                    201:        register int n;
                    202: 
                    203:        if (doladd+3 >= lnsize) {
                    204:                lp1 = (LINE *)realloc(line, (n=lnsize*2)*sizeof(LINE));
                    205:                if (lp1 == NULL) {
                    206:                        derror("Line table overflow");
                    207:                        return (0);
                    208:                }
                    209:                line = lp1;
                    210:                lnsize = n;
                    211:        }
                    212:        lp1 = &line[doladd+2];
                    213:        lp2 = &line[doladd+1];
                    214:        n = doladd++ - a;
                    215:        while (n--)
                    216:                *--lp1 = *--lp2;
                    217:        return (1);
                    218: }
                    219: 
                    220: /*
                    221:  * Get a line of text from the terminal.  The number of characters
                    222:  * including the null terminator at the end of the string is returned.
                    223:  * If end of file or a line containing only a single dot is found,
                    224:  * 0 is returned.
                    225:  */
                    226: readtty()
                    227: {
                    228:        register int c;
                    229:        register char *lp;
                    230: 
                    231:        appflag++;
                    232:        lp = linebuf;
                    233:        while ((c=getx())!=EOF && c!='\n') {
                    234:                if (lp < &linebuf[LBSIZE-1])
                    235:                        *lp++ = c;
                    236:        }
                    237:        --appflag;
                    238:        if (c==EOF && lp==linebuf) {
                    239:                lastchr = '\n';
                    240:                if (gcp == NULL)
                    241:                        clearerr(stdin);
                    242:                return (0);
                    243:        }
                    244:        if (linebuf[0]=='.' && lp==linebuf+1)
                    245:                return (0);
                    246:        *lp++ = '\0';
                    247:        return (lp-linebuf);
                    248: }
                    249: 
                    250: /*
                    251:  * Get a line of text from the file open on file pointer `fp'.
                    252:  * Return the number of characters in the line including the
                    253:  * null terminator at the end.  On end of file, 0 is returned.
                    254:  */
                    255: readfil()
                    256: {
                    257:        register int c, n;
                    258:        register char *lp;
                    259: 
                    260:        if ((c=getc(fp)) == EOF)
                    261:                return (0);
                    262:        lp = linebuf;
                    263:        n = LBSIZE-1;
                    264:        while (c!=EOF && c!='\n') {
                    265:                *lp++ = c;
                    266:                if (--n == 0)
                    267:                        break;
                    268:                c = getc(fp);
                    269:        }
                    270:        *lp++ = '\0';
                    271:        return (lp-linebuf);
                    272: }
                    273: 
                    274: /*
                    275:  * Delete the given line range.
                    276:  */
                    277: delete(a1, a2)
                    278: {
                    279:        register LINE *p1, *p2;
                    280:        register int n;
                    281: 
                    282:        if (a1>a2 || a1<1 || a2>doladd) {
                    283:                derror("Address out of range");
                    284:                return (0);
                    285:        }
                    286:        p1 = &line[a1];
                    287:        p2 = &line[a2+1];
                    288:        n = doladd - a2;
                    289:        while (n--)
                    290:                *p1++ = *p2++;
                    291:        doladd -= (a2+1) - a1;
                    292:        if ((dotadd=a1) > doladd)
                    293:                --dotadd;
                    294:        saved = doladd==0;
                    295:        return (1);
                    296: }
                    297: 
                    298: /*
                    299:  * Concatenate the lines in the given range to form
                    300:  * a single line.
                    301:  */
                    302: join(a1, a2)
                    303: {
                    304:        long seek;
                    305:        int bn, a;
                    306:        register int n;
                    307:        register char *lp, *tp;
                    308: 
                    309:        if (a1>a2 || a1<1 || a2>doladd) {
                    310:                derror("Address out of range");
                    311:                return (0);
                    312:        }
                    313:        bn = 0;
                    314:        lp = linebuf;
                    315:        for (a=a1; a<=a2; a++) {
                    316:                if ((n=getline(a, tempbuf)) == 0)
                    317:                        return (0);
                    318:                if ((bn+=--n) >= LBSIZE-1) {
                    319:                        derror("Temporary buffer overflow");
                    320:                        return (0);
                    321:                }
                    322:                tp = tempbuf;
                    323:                while (n--)
                    324:                        *lp++ = *tp++;
                    325:        }
                    326:        *lp++ = '\0';
                    327:        seek = linead();
                    328:        if (putline(linebuf, ++bn) == 0)
                    329:                return (0);
                    330:        line[a1] = seek;
                    331:        a = doladd - a2;
                    332:        for (n=0; n<a; n++)
                    333:                line[a1+1+n] = line[a2+1+n];
                    334:        dotadd = a1;
                    335:        doladd -= a2 - a1;
                    336:        return (1);
                    337: }
                    338: 
                    339: /*
                    340:  * List the given line range.  All non-printing characters are
                    341:  * escaped.
                    342:  */
                    343: list(a1, a2)
                    344: {
                    345:        int a;
                    346:        register int n;
                    347:        register char *p;
                    348: 
                    349:        if (a1>a2 || a1<1 || a2>doladd) {
                    350:                derror("Address out of range");
                    351:                return (0);
                    352:        }
                    353:        for (a=a1; a<=a2; a++) {
                    354:                if (intflag)
                    355:                        return (1);
                    356:                if (getline(a, linebuf) == 0)
                    357:                        break;
                    358:                n = 0;
                    359:                for (p=linebuf; *p; p++) {
                    360:                        if (n++ >= 72) {
                    361:                                n = 0;
                    362:                                prints(stdout, "\\\n");
                    363:                        }
                    364:                        switch (*p) {
                    365:                        case '\b':
                    366:                                prints(stdout, "-\b<");
                    367:                                continue;
                    368:                        case '\t':
                    369:                                prints(stdout, "-\b>");
                    370:                                continue;
                    371:                        case '\\':
                    372:                                prints(stdout, "\\\\");
                    373:                                continue;
                    374:                        default:
                    375:                                if (isascii(*p) && !iscntrl(*p)) {
                    376:                                        printc(stdout, *p);
                    377:                                        continue;
                    378:                                }
                    379:                                printc(stdout, '\\');
                    380:                                printo(stdout, *p);
                    381:                                n += 3;
                    382:                        }
                    383:                }
                    384:                prints(stdout, "\\n");
                    385:                printc(stdout, '\n');
                    386:                dotadd = a;
                    387:        }
                    388:        return (1);
                    389: }
                    390: 
                    391: /*
                    392:  * Take the text that is between lines `a1' and `a2' and
                    393:  * place it after line `a3'.
                    394:  */
                    395: move(a1, a2, a3)
                    396: int a1, a2, a3;
                    397: {
                    398:        LINE l;
                    399:        register int a, n, x;
                    400: 
                    401:        if (a1>a2 || a1<1 || a2>doladd || a3<0 || a3>doladd) {
                    402:                derror("Address out of range");
                    403:                return (0);
                    404:        }
                    405:        if (a3>=a1-1 && a3<=a2) {
                    406:                dotadd = a2;
                    407:                return (1);
                    408:        }
                    409:        if (a3 < a1) {
                    410:                for (a=a1, x=a3+1; a<=a2; a++, x++) {
                    411:                        l = line[a];
                    412:                        for (n=a; n>x; --n)
                    413:                                line[n] = line[n-1];
                    414:                        line[x] = l;
                    415:                }
                    416:                dotadd = a3 + a2+1 - a1;
                    417:        } else {
                    418:                for (a=a2, x=a3; a>=a1; --a, --x) {
                    419:                        l = line[a];
                    420:                        for (n=a; n<x; n++)
                    421:                                line[n] = line[n+1];
                    422:                        line[x] = l;
                    423:                }
                    424:                dotadd = a3;
                    425:        }
                    426:        saved = 0;
                    427:        return (1);
                    428: }
                    429: 
                    430: /*
                    431:  * Given a string describing a set of options, set them.
                    432:  */
                    433: setoptf(sp)
                    434: register char *sp;
                    435: {
                    436:        register int t;
                    437: 
                    438:        t = 1;
                    439:        while (*sp != '\0') {
                    440:                switch (*sp++) {
                    441:                case '+':
                    442:                        t = 1;
                    443:                        continue;
                    444:                case '-':
                    445:                        t = 0;
                    446:                        continue;
                    447:                case 'c':
                    448:                        cflag = t;
                    449:                        continue;
                    450:                case 'm':
                    451:                        mflag = t;
                    452:                        continue;
                    453:                case 'o':
                    454:                        oflag = t;
                    455:                        continue;
                    456:                case 'p':
                    457:                        pflag = t;
                    458:                        continue;
                    459:                case 's':
                    460:                        sflag = t;
                    461:                        continue;
                    462:                case 'v':
                    463:                        vflag = t;
                    464:                        continue;
                    465:                default:
                    466:                        derror("Bad option");
                    467:                        return;
                    468:                }
                    469:        }
                    470: }
                    471: 
                    472: /*
                    473:  * Display options.
                    474:  */
                    475: disoptf()
                    476: {
                    477:        if (cflag)
                    478:                printc(stdout, 'c');
                    479:        if (mflag)
                    480:                printc(stdout, 'm');
                    481:        if (oflag)
                    482:                printc(stdout, 'o');
                    483:        if (pflag)
                    484:                printc(stdout, 'p');
                    485:        if (sflag)
                    486:                printc(stdout, 's');
                    487:        if (vflag)
                    488:                printc(stdout, 'v');
                    489:        if (keyp != NULL)
                    490:                printc(stdout, 'x');
                    491:        printc(stdout, '\n');
                    492: }
                    493: 
                    494: /*
                    495:  * Print the given line range.
                    496:  */
                    497: print(a1, a2)
                    498: {
                    499:        register int a;
                    500:        register char *p;
                    501: 
                    502:        if (a1>a2 || a1<1 || a2>doladd) {
                    503:                derror("Address out of range");
                    504:                return (0);
                    505:        }
                    506:        for (a=a1; a<=a2; a++) {
                    507:                if (intflag)
                    508:                        return (1);
                    509:                if (getline(a, linebuf) == 0)
                    510:                        break;
                    511:                p = linebuf;
                    512:                while (*p)
                    513:                        printc(stdout, *p++);
                    514:                printc(stdout, '\n');
                    515:                dotadd = a;
                    516:        }
                    517:        return (1);
                    518: }
                    519: 
                    520: /*
                    521:  * Make a copy of the text between lines `a1' and `a2'
                    522:  * and place them after `a3'.
                    523:  */
                    524: copy(a1, a2, a3)
                    525: {
                    526:        register int i, j, n;
                    527: 
                    528:        if (a1>a2 || a1<1 || a2>doladd || a3<0 || a3>doladd) {
                    529:                derror("Address out of range");
                    530:                return (0);
                    531:        }
                    532:        n = (a2+1) - a1;
                    533:        if (doladd+n+2 > lnsize) {
                    534:                derror("Line table overflow");
                    535:                return (0);
                    536:        }
                    537:        for (i=doladd; i>a3; --i)
                    538:                line[i+n] = line[i];
                    539:        for (i=0; i<n; i++) {
                    540:                if ((j=i+a1) > a3)
                    541:                        j += n;
                    542:                if ((j=getline(j, linebuf)) == 0)
                    543:                        goto err;
                    544:                line[a3+1+i] = linead();
                    545:                if (putline(linebuf, j) == 0)
                    546:                        goto err;
                    547:        }
                    548:        dotadd = a3+n;
                    549:        doladd += n;
                    550:        saved = 0;
                    551:        return (1);
                    552: 
                    553: err:
                    554:        for (i=a3+1; i<=doladd; i++)
                    555:                line[i] = line[i+n];
                    556:        return (0);
                    557: }
                    558: 
                    559: /*
                    560:  * Write the given line range onto the file whose name is
                    561:  * stored in `file'.  `perm' is the permission string we
                    562:  * want the file opened with.
                    563:  */
                    564: wfile(a1, a2, name, perm, sflag)
                    565: char *name, *perm;
                    566: {
                    567:        register int a;
                    568:        register char *cp;
                    569: 
                    570:        if (doladd!=0 || addspec!=0) {
                    571:                if (a1>a2 || a1<1 || a2>doladd) {
                    572:                        derror("Address out of range");
                    573:                        return (0);
                    574:                }
                    575:        }
                    576:        if ((fp=xfopen(name, perm)) == NULL) {
                    577:                derror("Cannot open file");
                    578:                return (0);
                    579:        }
                    580:        cct = 0;
                    581:        lct = 0;
                    582:        for (a=a1; a<=a2; a++) {
                    583:                if (getline(a, linebuf) == 0)
                    584:                        break;
                    585:                cp = linebuf;
                    586:                while (*cp) {
                    587:                        printc(fp, *cp++);
                    588:                        cct++;
                    589:                }
                    590:                printc(fp, '\n');
                    591:                if (ferror(fp))
                    592:                        break;
                    593:                cct++;
                    594:                lct++;
                    595:        }
                    596:        if (sflag==0 && cflag!=0) {
                    597:                printl(stdout, !oflag ? cct : lct);
                    598:                printc(stdout, '\n');
                    599:        }
                    600:        if ((a=ferror(fp)) == 0)
                    601:                saved = 1;
                    602:        else {
                    603:                if (sflag == 0)
                    604:                        derror("Write error");
                    605:        }
                    606:        fclose(fp);
                    607: #if COHERENT
                    608:        sync();
                    609: #endif
                    610:        return (!a);
                    611: }
                    612: 
                    613: /*
                    614:  * Open a file.  If we are in encryption mode, the open unit is really a
                    615:  * file descriptor piped to the crypt command.
                    616:  */
                    617: FILE *
                    618: xfopen(fn, mode)
                    619: char *fn;
                    620: char *mode;
                    621: {
                    622: #if COHERENT
                    623:        register FILE *fp;
                    624:        register int f;
                    625:        register int u;
                    626:        register int a;
                    627:        register int b;
                    628:        int pv[2];
                    629: 
                    630:        if (keyp == NULL)
                    631:                fp = fopen(fn, mode);
                    632:        else {
                    633:                switch (mode[0]) {
                    634:                case 'a':
                    635:                        return (NULL);
                    636:                case 'r':
                    637:                        a = 0;
                    638:                        b = 1;
                    639:                        break;
                    640:                case 'w':
                    641:                        a = 1;
                    642:                        b = 0;
                    643:                        break;
                    644:                }
                    645:                if (pipe(pv) < 0)
                    646:                        return (NULL);
                    647:                if ((f=fork()) < 0) {
                    648:                        close(pv[0]);
                    649:                        close(pv[1]);
                    650:                        return (NULL);
                    651:                }
                    652:                if (f == 0) {
                    653:                        if ((u=(a==0)?open(fn, 0):creat(fn, 0644)) < 0)
                    654:                                exit(1);
                    655:                        dup2(u, a);
                    656:                        dup2(pv[b], b);
                    657:                        close(u);
                    658:                        close(pv[0]);
                    659:                        close(pv[1]);
                    660:                        execl("/bin/crypt", "crypt", keyp, NULL);
                    661:                        exit(1);
                    662:                }
                    663:                close(pv[b]);
                    664:                fp = fdopen(pv[a], mode);
                    665:        }
                    666:        return (fp);
                    667: #else
                    668:        return(fopen(fn, mode));
                    669: #endif
                    670: }
                    671: 
                    672: /*
                    673:  * Read a key from the standard input.
                    674:  */
                    675: setkey()
                    676: {
                    677: #if COHERENT
                    678:        register int n;
                    679: 
                    680:        keyp = getpass("key? ");
                    681:        if ((n=strlen(keyp)) > CKSIZE) {
                    682:                derror("Key too long");
                    683:                keyp = NULL;
                    684:                return (0);
                    685:        }
                    686:        if (n == 0)
                    687:                keyp = NULL;
                    688:        return (1);
                    689: #else
                    690:        derror("Cannot set key");
                    691:        return (0);
                    692: #endif
                    693: }

unix.superglobalmegacorp.com

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