Annotation of 43BSDTahoe/etc/restore/interactive.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1985 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[] = "@(#)interactive.c      5.5 (Berkeley) 4/23/87";
                      9: #endif not lint
                     10: 
                     11: #include "restore.h"
                     12: #include <protocols/dumprestore.h>
                     13: #include <setjmp.h>
                     14: 
                     15: #define round(a, b) (((a) + (b) - 1) / (b) * (b))
                     16: 
                     17: /*
                     18:  * Things to handle interruptions.
                     19:  */
                     20: static jmp_buf reset;
                     21: static char *nextarg = NULL;
                     22: 
                     23: /*
                     24:  * Structure and routines associated with listing directories.
                     25:  */
                     26: struct afile {
                     27:        ino_t   fnum;           /* inode number of file */
                     28:        char    *fname;         /* file name */
                     29:        short   fflags;         /* extraction flags, if any */
                     30:        char    ftype;          /* file type, e.g. LEAF or NODE */
                     31: };
                     32: struct arglist {
                     33:        struct afile    *head;  /* start of argument list */
                     34:        struct afile    *last;  /* end of argument list */
                     35:        struct afile    *base;  /* current list arena */
                     36:        int             nent;   /* maximum size of list */
                     37:        char            *cmd;   /* the current command */
                     38: };
                     39: extern int fcmp();
                     40: extern char *fmtentry();
                     41: char *copynext();
                     42: 
                     43: /*
                     44:  * Read and execute commands from the terminal.
                     45:  */
                     46: runcmdshell()
                     47: {
                     48:        register struct entry *np;
                     49:        ino_t ino;
                     50:        static struct arglist alist = { 0, 0, 0, 0, 0 };
                     51:        char curdir[MAXPATHLEN];
                     52:        char name[MAXPATHLEN];
                     53:        char cmd[BUFSIZ];
                     54: 
                     55:        canon("/", curdir);
                     56: loop:
                     57:        if (setjmp(reset) != 0) {
                     58:                for (; alist.head < alist.last; alist.head++)
                     59:                        freename(alist.head->fname);
                     60:                nextarg = NULL;
                     61:                volno = 0;
                     62:        }
                     63:        getcmd(curdir, cmd, name, &alist);
                     64:        switch (cmd[0]) {
                     65:        /*
                     66:         * Add elements to the extraction list.
                     67:         */
                     68:        case 'a':
                     69:                if (strncmp(cmd, "add", strlen(cmd)) != 0)
                     70:                        goto bad;
                     71:                ino = dirlookup(name);
                     72:                if (ino == 0)
                     73:                        break;
                     74:                if (mflag)
                     75:                        pathcheck(name);
                     76:                treescan(name, ino, addfile);
                     77:                break;
                     78:        /*
                     79:         * Change working directory.
                     80:         */
                     81:        case 'c':
                     82:                if (strncmp(cmd, "cd", strlen(cmd)) != 0)
                     83:                        goto bad;
                     84:                ino = dirlookup(name);
                     85:                if (ino == 0)
                     86:                        break;
                     87:                if (inodetype(ino) == LEAF) {
                     88:                        fprintf(stderr, "%s: not a directory\n", name);
                     89:                        break;
                     90:                }
                     91:                (void) strcpy(curdir, name);
                     92:                break;
                     93:        /*
                     94:         * Delete elements from the extraction list.
                     95:         */
                     96:        case 'd':
                     97:                if (strncmp(cmd, "delete", strlen(cmd)) != 0)
                     98:                        goto bad;
                     99:                np = lookupname(name);
                    100:                if (np == NIL || (np->e_flags & NEW) == 0) {
                    101:                        fprintf(stderr, "%s: not on extraction list\n", name);
                    102:                        break;
                    103:                }
                    104:                treescan(name, np->e_ino, deletefile);
                    105:                break;
                    106:        /*
                    107:         * Extract the requested list.
                    108:         */
                    109:        case 'e':
                    110:                if (strncmp(cmd, "extract", strlen(cmd)) != 0)
                    111:                        goto bad;
                    112:                createfiles();
                    113:                createlinks();
                    114:                setdirmodes();
                    115:                if (dflag)
                    116:                        checkrestore();
                    117:                volno = 0;
                    118:                break;
                    119:        /*
                    120:         * List available commands.
                    121:         */
                    122:        case 'h':
                    123:                if (strncmp(cmd, "help", strlen(cmd)) != 0)
                    124:                        goto bad;
                    125:        case '?':
                    126:                fprintf(stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                    127:                        "Available commands are:\n",
                    128:                        "\tls [arg] - list directory\n",
                    129:                        "\tcd arg - change directory\n",
                    130:                        "\tpwd - print current directory\n",
                    131:                        "\tadd [arg] - add `arg' to list of",
                    132:                        " files to be extracted\n",
                    133:                        "\tdelete [arg] - delete `arg' from",
                    134:                        " list of files to be extracted\n",
                    135:                        "\textract - extract requested files\n",
                    136:                        "\tsetmodes - set modes of requested directories\n",
                    137:                        "\tquit - immediately exit program\n",
                    138:                        "\twhat - list dump header information\n",
                    139:                        "\tverbose - toggle verbose flag",
                    140:                        " (useful with ``ls'')\n",
                    141:                        "\thelp or `?' - print this list\n",
                    142:                        "If no `arg' is supplied, the current",
                    143:                        " directory is used\n");
                    144:                break;
                    145:        /*
                    146:         * List a directory.
                    147:         */
                    148:        case 'l':
                    149:                if (strncmp(cmd, "ls", strlen(cmd)) != 0)
                    150:                        goto bad;
                    151:                ino = dirlookup(name);
                    152:                if (ino == 0)
                    153:                        break;
                    154:                printlist(name, ino, curdir);
                    155:                break;
                    156:        /*
                    157:         * Print current directory.
                    158:         */
                    159:        case 'p':
                    160:                if (strncmp(cmd, "pwd", strlen(cmd)) != 0)
                    161:                        goto bad;
                    162:                if (curdir[1] == '\0')
                    163:                        fprintf(stderr, "/\n");
                    164:                else
                    165:                        fprintf(stderr, "%s\n", &curdir[1]);
                    166:                break;
                    167:        /*
                    168:         * Quit.
                    169:         */
                    170:        case 'q':
                    171:                if (strncmp(cmd, "quit", strlen(cmd)) != 0)
                    172:                        goto bad;
                    173:                return;
                    174:        case 'x':
                    175:                if (strncmp(cmd, "xit", strlen(cmd)) != 0)
                    176:                        goto bad;
                    177:                return;
                    178:        /*
                    179:         * Toggle verbose mode.
                    180:         */
                    181:        case 'v':
                    182:                if (strncmp(cmd, "verbose", strlen(cmd)) != 0)
                    183:                        goto bad;
                    184:                if (vflag) {
                    185:                        fprintf(stderr, "verbose mode off\n");
                    186:                        vflag = 0;
                    187:                        break;
                    188:                }
                    189:                fprintf(stderr, "verbose mode on\n");
                    190:                vflag++;
                    191:                break;
                    192:        /*
                    193:         * Just restore requested directory modes.
                    194:         */
                    195:        case 's':
                    196:                if (strncmp(cmd, "setmodes", strlen(cmd)) != 0)
                    197:                        goto bad;
                    198:                setdirmodes();
                    199:                break;
                    200:        /*
                    201:         * Print out dump header information.
                    202:         */
                    203:        case 'w':
                    204:                if (strncmp(cmd, "what", strlen(cmd)) != 0)
                    205:                        goto bad;
                    206:                printdumpinfo();
                    207:                break;
                    208:        /*
                    209:         * Turn on debugging.
                    210:         */
                    211:        case 'D':
                    212:                if (strncmp(cmd, "Debug", strlen(cmd)) != 0)
                    213:                        goto bad;
                    214:                if (dflag) {
                    215:                        fprintf(stderr, "debugging mode off\n");
                    216:                        dflag = 0;
                    217:                        break;
                    218:                }
                    219:                fprintf(stderr, "debugging mode on\n");
                    220:                dflag++;
                    221:                break;
                    222:        /*
                    223:         * Unknown command.
                    224:         */
                    225:        default:
                    226:        bad:
                    227:                fprintf(stderr, "%s: unknown command; type ? for help\n", cmd);
                    228:                break;
                    229:        }
                    230:        goto loop;
                    231: }
                    232: 
                    233: /*
                    234:  * Read and parse an interactive command.
                    235:  * The first word on the line is assigned to "cmd". If
                    236:  * there are no arguments on the command line, then "curdir"
                    237:  * is returned as the argument. If there are arguments
                    238:  * on the line they are returned one at a time on each
                    239:  * successive call to getcmd. Each argument is first assigned
                    240:  * to "name". If it does not start with "/" the pathname in
                    241:  * "curdir" is prepended to it. Finally "canon" is called to
                    242:  * eliminate any embedded ".." components.
                    243:  */
                    244: getcmd(curdir, cmd, name, ap)
                    245:        char *curdir, *cmd, *name;
                    246:        struct arglist *ap;
                    247: {
                    248:        register char *cp;
                    249:        static char input[BUFSIZ];
                    250:        char output[BUFSIZ];
                    251: #      define rawname input    /* save space by reusing input buffer */
                    252: 
                    253:        /*
                    254:         * Check to see if still processing arguments.
                    255:         */
                    256:        if (ap->head != ap->last) {
                    257:                strcpy(name, ap->head->fname);
                    258:                freename(ap->head->fname);
                    259:                ap->head++;
                    260:                return;
                    261:        }
                    262:        if (nextarg != NULL)
                    263:                goto getnext;
                    264:        /*
                    265:         * Read a command line and trim off trailing white space.
                    266:         */
                    267:        do      {
                    268:                fprintf(stderr, "restore > ");
                    269:                (void) fflush(stderr);
                    270:                (void) fgets(input, BUFSIZ, terminal);
                    271:        } while (!feof(terminal) && input[0] == '\n');
                    272:        if (feof(terminal)) {
                    273:                (void) strcpy(cmd, "quit");
                    274:                return;
                    275:        }
                    276:        for (cp = &input[strlen(input) - 2]; *cp == ' ' || *cp == '\t'; cp--)
                    277:                /* trim off trailing white space and newline */;
                    278:        *++cp = '\0';
                    279:        /*
                    280:         * Copy the command into "cmd".
                    281:         */
                    282:        cp = copynext(input, cmd);
                    283:        ap->cmd = cmd;
                    284:        /*
                    285:         * If no argument, use curdir as the default.
                    286:         */
                    287:        if (*cp == '\0') {
                    288:                (void) strcpy(name, curdir);
                    289:                return;
                    290:        }
                    291:        nextarg = cp;
                    292:        /*
                    293:         * Find the next argument.
                    294:         */
                    295: getnext:
                    296:        cp = copynext(nextarg, rawname);
                    297:        if (*cp == '\0')
                    298:                nextarg = NULL;
                    299:        else
                    300:                nextarg = cp;
                    301:        /*
                    302:         * If it an absolute pathname, canonicalize it and return it.
                    303:         */
                    304:        if (rawname[0] == '/') {
                    305:                canon(rawname, name);
                    306:        } else {
                    307:                /*
                    308:                 * For relative pathnames, prepend the current directory to
                    309:                 * it then canonicalize and return it.
                    310:                 */
                    311:                (void) strcpy(output, curdir);
                    312:                (void) strcat(output, "/");
                    313:                (void) strcat(output, rawname);
                    314:                canon(output, name);
                    315:        }
                    316:        expandarg(name, ap);
                    317:        strcpy(name, ap->head->fname);
                    318:        freename(ap->head->fname);
                    319:        ap->head++;
                    320: #      undef rawname
                    321: }
                    322: 
                    323: /*
                    324:  * Strip off the next token of the input.
                    325:  */
                    326: char *
                    327: copynext(input, output)
                    328:        char *input, *output;
                    329: {
                    330:        register char *cp, *bp;
                    331:        char quote;
                    332: 
                    333:        for (cp = input; *cp == ' ' || *cp == '\t'; cp++)
                    334:                /* skip to argument */;
                    335:        bp = output;
                    336:        while (*cp != ' ' && *cp != '\t' && *cp != '\0') {
                    337:                /*
                    338:                 * Handle back slashes.
                    339:                 */
                    340:                if (*cp == '\\') {
                    341:                        if (*++cp == '\0') {
                    342:                                fprintf(stderr,
                    343:                                        "command lines cannot be continued\n");
                    344:                                continue;
                    345:                        }
                    346:                        *bp++ = *cp++;
                    347:                        continue;
                    348:                }
                    349:                /*
                    350:                 * The usual unquoted case.
                    351:                 */
                    352:                if (*cp != '\'' && *cp != '"') {
                    353:                        *bp++ = *cp++;
                    354:                        continue;
                    355:                }
                    356:                /*
                    357:                 * Handle single and double quotes.
                    358:                 */
                    359:                quote = *cp++;
                    360:                while (*cp != quote && *cp != '\0')
                    361:                        *bp++ = *cp++ | 0200;
                    362:                if (*cp++ == '\0') {
                    363:                        fprintf(stderr, "missing %c\n", quote);
                    364:                        cp--;
                    365:                        continue;
                    366:                }
                    367:        }
                    368:        *bp = '\0';
                    369:        return (cp);
                    370: }
                    371: 
                    372: /*
                    373:  * Canonicalize file names to always start with ``./'' and
                    374:  * remove any imbedded "." and ".." components.
                    375:  */
                    376: canon(rawname, canonname)
                    377:        char *rawname, *canonname;
                    378: {
                    379:        register char *cp, *np;
                    380:        int len;
                    381: 
                    382:        if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0)
                    383:                (void) strcpy(canonname, "");
                    384:        else if (rawname[0] == '/')
                    385:                (void) strcpy(canonname, ".");
                    386:        else
                    387:                (void) strcpy(canonname, "./");
                    388:        (void) strcat(canonname, rawname);
                    389:        /*
                    390:         * Eliminate multiple and trailing '/'s
                    391:         */
                    392:        for (cp = np = canonname; *np != '\0'; cp++) {
                    393:                *cp = *np++;
                    394:                while (*cp == '/' && *np == '/')
                    395:                        np++;
                    396:        }
                    397:        *cp = '\0';
                    398:        if (*--cp == '/')
                    399:                *cp = '\0';
                    400:        /*
                    401:         * Eliminate extraneous "." and ".." from pathnames.
                    402:         */
                    403:        for (np = canonname; *np != '\0'; ) {
                    404:                np++;
                    405:                cp = np;
                    406:                while (*np != '/' && *np != '\0')
                    407:                        np++;
                    408:                if (np - cp == 1 && *cp == '.') {
                    409:                        cp--;
                    410:                        (void) strcpy(cp, np);
                    411:                        np = cp;
                    412:                }
                    413:                if (np - cp == 2 && strncmp(cp, "..", 2) == 0) {
                    414:                        cp--;
                    415:                        while (cp > &canonname[1] && *--cp != '/')
                    416:                                /* find beginning of name */;
                    417:                        (void) strcpy(cp, np);
                    418:                        np = cp;
                    419:                }
                    420:        }
                    421: }
                    422: 
                    423: /*
                    424:  * globals (file name generation)
                    425:  *
                    426:  * "*" in params matches r.e ".*"
                    427:  * "?" in params matches r.e. "."
                    428:  * "[...]" in params matches character class
                    429:  * "[...a-z...]" in params matches a through z.
                    430:  */
                    431: expandarg(arg, ap)
                    432:        char *arg;
                    433:        register struct arglist *ap;
                    434: {
                    435:        static struct afile single;
                    436:        struct entry *ep;
                    437:        int size;
                    438: 
                    439:        ap->head = ap->last = (struct afile *)0;
                    440:        size = expand(arg, 0, ap);
                    441:        if (size == 0) {
                    442:                ep = lookupname(arg);
                    443:                single.fnum = ep ? ep->e_ino : 0;
                    444:                single.fname = savename(arg);
                    445:                ap->head = &single;
                    446:                ap->last = ap->head + 1;
                    447:                return;
                    448:        }
                    449:        qsort((char *)ap->head, ap->last - ap->head, sizeof *ap->head, fcmp);
                    450: }
                    451: 
                    452: /*
                    453:  * Expand a file name
                    454:  */
                    455: expand(as, rflg, ap)
                    456:        char *as;
                    457:        int rflg;
                    458:        register struct arglist *ap;
                    459: {
                    460:        int             count, size;
                    461:        char            dir = 0;
                    462:        char            *rescan = 0;
                    463:        DIR             *dirp;
                    464:        register char   *s, *cs;
                    465:        int             sindex, rindex, lindex;
                    466:        struct direct   *dp;
                    467:        register char   slash; 
                    468:        register char   *rs; 
                    469:        register char   c;
                    470: 
                    471:        /*
                    472:         * check for meta chars
                    473:         */
                    474:        s = cs = as;
                    475:        slash = 0;
                    476:        while (*cs != '*' && *cs != '?' && *cs != '[') {        
                    477:                if (*cs++ == 0) {       
                    478:                        if (rflg && slash)
                    479:                                break; 
                    480:                        else
                    481:                                return (0) ;
                    482:                } else if (*cs == '/') {        
                    483:                        slash++;
                    484:                }
                    485:        }
                    486:        for (;;) {      
                    487:                if (cs == s) {  
                    488:                        s = "";
                    489:                        break;
                    490:                } else if (*--cs == '/') {      
                    491:                        *cs = 0;
                    492:                        if (s == cs)
                    493:                                s = "/";
                    494:                        break;
                    495:                }
                    496:        }
                    497:        if ((dirp = rst_opendir(s)) != NULL)
                    498:                dir++;
                    499:        count = 0;
                    500:        if (*cs == 0)
                    501:                *cs++ = 0200;
                    502:        if (dir) {
                    503:                /*
                    504:                 * check for rescan
                    505:                 */
                    506:                rs = cs;
                    507:                do {    
                    508:                        if (*rs == '/') { 
                    509:                                rescan = rs; 
                    510:                                *rs = 0; 
                    511:                        }
                    512:                } while (*rs++);
                    513:                sindex = ap->last - ap->head;
                    514:                while ((dp = rst_readdir(dirp)) != NULL && dp->d_ino != 0) {
                    515:                        if (!dflag && BIT(dp->d_ino, dumpmap) == 0)
                    516:                                continue;
                    517:                        if ((*dp->d_name == '.' && *cs != '.'))
                    518:                                continue;
                    519:                        if (gmatch(dp->d_name, cs)) {   
                    520:                                if (addg(dp, s, rescan, ap) < 0)
                    521:                                        return (-1);
                    522:                                count++;
                    523:                        }
                    524:                }
                    525:                if (rescan) {   
                    526:                        rindex = sindex; 
                    527:                        lindex = ap->last - ap->head;
                    528:                        if (count) {    
                    529:                                count = 0;
                    530:                                while (rindex < lindex) {       
                    531:                                        size = expand(ap->head[rindex].fname,
                    532:                                            1, ap);
                    533:                                        if (size < 0)
                    534:                                                return (size);
                    535:                                        count += size;
                    536:                                        rindex++;
                    537:                                }
                    538:                        }
                    539:                        bcopy((char *)&ap->head[lindex],
                    540:                             (char *)&ap->head[sindex],
                    541:                             (ap->last - &ap->head[rindex]) * sizeof *ap->head);
                    542:                        ap->last -= lindex - sindex;
                    543:                        *rescan = '/';
                    544:                }
                    545:        }
                    546:        s = as;
                    547:        while (c = *s)
                    548:                *s++ = (c&0177 ? c : '/');
                    549:        return (count);
                    550: }
                    551: 
                    552: /*
                    553:  * Check for a name match
                    554:  */
                    555: gmatch(s, p)
                    556:        register char   *s, *p;
                    557: {
                    558:        register int    scc;
                    559:        char            c;
                    560:        char            ok; 
                    561:        int             lc;
                    562: 
                    563:        if (scc = *s++)
                    564:                if ((scc &= 0177) == 0)
                    565:                        scc = 0200;
                    566:        switch (c = *p++) {
                    567: 
                    568:        case '[':
                    569:                ok = 0; 
                    570:                lc = 077777;
                    571:                while (c = *p++) {      
                    572:                        if (c == ']') {
                    573:                                return (ok ? gmatch(s, p) : 0);
                    574:                        } else if (c == '-') {  
                    575:                                if (lc <= scc && scc <= (*p++))
                    576:                                        ok++ ;
                    577:                        } else {        
                    578:                                if (scc == (lc = (c&0177)))
                    579:                                        ok++ ;
                    580:                        }
                    581:                }
                    582:                return (0);
                    583: 
                    584:        default:
                    585:                if ((c&0177) != scc)
                    586:                        return (0) ;
                    587:                /* falls through */
                    588: 
                    589:        case '?':
                    590:                return (scc ? gmatch(s, p) : 0);
                    591: 
                    592:        case '*':
                    593:                if (*p == 0)
                    594:                        return (1) ;
                    595:                s--;
                    596:                while (*s) {  
                    597:                        if (gmatch(s++, p))
                    598:                                return (1);
                    599:                }
                    600:                return (0);
                    601: 
                    602:        case 0:
                    603:                return (scc == 0);
                    604:        }
                    605: }
                    606: 
                    607: /*
                    608:  * Construct a matched name.
                    609:  */
                    610: addg(dp, as1, as3, ap)
                    611:        struct direct   *dp;
                    612:        char            *as1, *as3;
                    613:        struct arglist  *ap;
                    614: {
                    615:        register char   *s1, *s2;
                    616:        register int    c;
                    617:        char            buf[BUFSIZ];
                    618: 
                    619:        s2 = buf;
                    620:        s1 = as1;
                    621:        while (c = *s1++) {     
                    622:                if ((c &= 0177) == 0) { 
                    623:                        *s2++ = '/';
                    624:                        break;
                    625:                }
                    626:                *s2++ = c;
                    627:        }
                    628:        s1 = dp->d_name;
                    629:        while (*s2 = *s1++)
                    630:                s2++;
                    631:        if (s1 = as3) { 
                    632:                *s2++ = '/';
                    633:                while (*s2++ = *++s1)
                    634:                        /* void */;
                    635:        }
                    636:        if (mkentry(buf, dp->d_ino, ap) == FAIL)
                    637:                return (-1);
                    638: }
                    639: 
                    640: /*
                    641:  * Do an "ls" style listing of a directory
                    642:  */
                    643: printlist(name, ino, basename)
                    644:        char *name;
                    645:        ino_t ino;
                    646:        char *basename;
                    647: {
                    648:        register struct afile *fp;
                    649:        register struct direct *dp;
                    650:        static struct arglist alist = { 0, 0, 0, 0, "ls" };
                    651:        struct afile single;
                    652:        DIR *dirp;
                    653: 
                    654:        if ((dirp = rst_opendir(name)) == NULL) {
                    655:                single.fnum = ino;
                    656:                single.fname = savename(name + strlen(basename) + 1);
                    657:                alist.head = &single;
                    658:                alist.last = alist.head + 1;
                    659:        } else {
                    660:                alist.head = (struct afile *)0;
                    661:                fprintf(stderr, "%s:\n", name);
                    662:                while (dp = rst_readdir(dirp)) {
                    663:                        if (dp == NULL || dp->d_ino == 0)
                    664:                                break;
                    665:                        if (!dflag && BIT(dp->d_ino, dumpmap) == 0)
                    666:                                continue;
                    667:                        if (vflag == 0 &&
                    668:                            (strcmp(dp->d_name, ".") == 0 ||
                    669:                             strcmp(dp->d_name, "..") == 0))
                    670:                                continue;
                    671:                        if (!mkentry(dp->d_name, dp->d_ino, &alist))
                    672:                                return;
                    673:                }
                    674:        }
                    675:        if (alist.head != 0) {
                    676:                qsort((char *)alist.head, alist.last - alist.head,
                    677:                        sizeof *alist.head, fcmp);
                    678:                formatf(&alist);
                    679:                for (fp = alist.head; fp < alist.last; fp++)
                    680:                        freename(fp->fname);
                    681:        }
                    682:        if (dirp != NULL)
                    683:                fprintf(stderr, "\n");
                    684: }
                    685: 
                    686: /*
                    687:  * Read the contents of a directory.
                    688:  */
                    689: mkentry(name, ino, ap)
                    690:        char *name;
                    691:        ino_t ino;
                    692:        register struct arglist *ap;
                    693: {
                    694:        register struct afile *fp;
                    695: 
                    696:        if (ap->base == NULL) {
                    697:                ap->nent = 20;
                    698:                ap->base = (struct afile *)calloc((unsigned)ap->nent,
                    699:                        sizeof (struct afile));
                    700:                if (ap->base == NULL) {
                    701:                        fprintf(stderr, "%s: out of memory\n", ap->cmd);
                    702:                        return (FAIL);
                    703:                }
                    704:        }
                    705:        if (ap->head == 0)
                    706:                ap->head = ap->last = ap->base;
                    707:        fp = ap->last;
                    708:        fp->fnum = ino;
                    709:        fp->fname = savename(name);
                    710:        fp++;
                    711:        if (fp == ap->head + ap->nent) {
                    712:                ap->base = (struct afile *)realloc((char *)ap->base,
                    713:                    (unsigned)(2 * ap->nent * sizeof (struct afile)));
                    714:                if (ap->base == 0) {
                    715:                        fprintf(stderr, "%s: out of memory\n", ap->cmd);
                    716:                        return (FAIL);
                    717:                }
                    718:                ap->head = ap->base;
                    719:                fp = ap->head + ap->nent;
                    720:                ap->nent *= 2;
                    721:        }
                    722:        ap->last = fp;
                    723:        return (GOOD);
                    724: }
                    725: 
                    726: /*
                    727:  * Print out a pretty listing of a directory
                    728:  */
                    729: formatf(ap)
                    730:        register struct arglist *ap;
                    731: {
                    732:        register struct afile *fp;
                    733:        struct entry *np;
                    734:        int width = 0, w, nentry = ap->last - ap->head;
                    735:        int i, j, len, columns, lines;
                    736:        char *cp;
                    737: 
                    738:        if (ap->head == ap->last)
                    739:                return;
                    740:        for (fp = ap->head; fp < ap->last; fp++) {
                    741:                fp->ftype = inodetype(fp->fnum);
                    742:                np = lookupino(fp->fnum);
                    743:                if (np != NIL)
                    744:                        fp->fflags = np->e_flags;
                    745:                else
                    746:                        fp->fflags = 0;
                    747:                len = strlen(fmtentry(fp));
                    748:                if (len > width)
                    749:                        width = len;
                    750:        }
                    751:        width += 2;
                    752:        columns = 80 / width;
                    753:        if (columns == 0)
                    754:                columns = 1;
                    755:        lines = (nentry + columns - 1) / columns;
                    756:        for (i = 0; i < lines; i++) {
                    757:                for (j = 0; j < columns; j++) {
                    758:                        fp = ap->head + j * lines + i;
                    759:                        cp = fmtentry(fp);
                    760:                        fprintf(stderr, "%s", cp);
                    761:                        if (fp + lines >= ap->last) {
                    762:                                fprintf(stderr, "\n");
                    763:                                break;
                    764:                        }
                    765:                        w = strlen(cp);
                    766:                        while (w < width) {
                    767:                                w++;
                    768:                                fprintf(stderr, " ");
                    769:                        }
                    770:                }
                    771:        }
                    772: }
                    773: 
                    774: /*
                    775:  * Comparison routine for qsort.
                    776:  */
                    777: fcmp(f1, f2)
                    778:        register struct afile *f1, *f2;
                    779: {
                    780: 
                    781:        return (strcmp(f1->fname, f2->fname));
                    782: }
                    783: 
                    784: /*
                    785:  * Format a directory entry.
                    786:  */
                    787: char *
                    788: fmtentry(fp)
                    789:        register struct afile *fp;
                    790: {
                    791:        static char fmtres[BUFSIZ];
                    792:        static int precision = 0;
                    793:        int i;
                    794:        register char *cp, *dp;
                    795: 
                    796:        if (!vflag) {
                    797:                fmtres[0] = '\0';
                    798:        } else {
                    799:                if (precision == 0)
                    800:                        for (i = maxino; i > 0; i /= 10)
                    801:                                precision++;
                    802:                (void) sprintf(fmtres, "%*d ", precision, fp->fnum);
                    803:        }
                    804:        dp = &fmtres[strlen(fmtres)];
                    805:        if (dflag && BIT(fp->fnum, dumpmap) == 0)
                    806:                *dp++ = '^';
                    807:        else if ((fp->fflags & NEW) != 0)
                    808:                *dp++ = '*';
                    809:        else
                    810:                *dp++ = ' ';
                    811:        for (cp = fp->fname; *cp; cp++)
                    812:                if (!vflag && (*cp < ' ' || *cp >= 0177))
                    813:                        *dp++ = '?';
                    814:                else
                    815:                        *dp++ = *cp;
                    816:        if (fp->ftype == NODE)
                    817:                *dp++ = '/';
                    818:        *dp++ = 0;
                    819:        return (fmtres);
                    820: }
                    821: 
                    822: /*
                    823:  * respond to interrupts
                    824:  */
                    825: onintr()
                    826: {
                    827:        if (command == 'i')
                    828:                longjmp(reset, 1);
                    829:        if (reply("restore interrupted, continue") == FAIL)
                    830:                done(1);
                    831: }

unix.superglobalmegacorp.com

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