Annotation of 42BSD/bin/csh/sh.dir.c, revision 1.1.1.1

1.1       root        1: static char *sccsid = "@(#)sh.dir.c 4.2 2/3/83";
                      2: 
                      3: #include "sh.h"
                      4: #include "sh.dir.h"
                      5: 
                      6: /*
                      7:  * C Shell - directory management
                      8:  */
                      9: 
                     10: struct directory *dfind();
                     11: char   *dfollow();
                     12: struct directory dhead;                /* "head" of loop */
                     13: int    printd;                         /* force name to be printed */
                     14: static char *fakev[] = { "dirs", NOSTR };
                     15: 
                     16: /*
                     17:  * dinit - initialize current working directory
                     18:  */
                     19: dinit(hp)
                     20:        char *hp;
                     21: {
                     22:        register char *cp;
                     23:        register struct directory *dp;
                     24:        char path[BUFSIZ];
                     25: 
                     26:        if (loginsh && hp)
                     27:                cp = hp;
                     28:        else {
                     29:                cp = getwd(path);
                     30:                if (cp == NULL) {
                     31:                        write(2, path, strlen(path));
                     32:                        exit(1);
                     33:                }
                     34:        }
                     35:        dp = (struct directory *)calloc(sizeof (struct directory), 1);
                     36:        dp->di_name = savestr(cp);
                     37:        dp->di_count = 0;
                     38:        dhead.di_next = dhead.di_prev = dp;
                     39:        dp->di_next = dp->di_prev = &dhead;
                     40:        printd = 0;
                     41:        dnewcwd(dp);
                     42: }
                     43: 
                     44: /*
                     45:  * dodirs - list all directories in directory loop
                     46:  */
                     47: dodirs(v)
                     48:        char **v;
                     49: {
                     50:        register struct directory *dp;
                     51:        bool lflag;
                     52:        char *hp = value("home");
                     53: 
                     54:        if (*hp == '\0')
                     55:                hp = NOSTR;
                     56:        if (*++v != NOSTR)
                     57:                if (eq(*v, "-l") && *++v == NOSTR)
                     58:                        lflag = 1;
                     59:                else
                     60:                        error("Usage: dirs [ -l ]");
                     61:        else
                     62:                lflag = 0;
                     63:        dp = dcwd;
                     64:        do {
                     65:                if (dp == &dhead)
                     66:                        continue;
                     67:                if (!lflag && hp != NOSTR) {
                     68:                        dtildepr(hp, dp->di_name);
                     69:                } else
                     70:                        printf("%s", dp->di_name);
                     71:                printf(" ");
                     72:        } while ((dp = dp->di_prev) != dcwd);
                     73:        printf("\n");
                     74: }
                     75: 
                     76: dtildepr(home, dir)
                     77:        register char *home, *dir;
                     78: {
                     79: 
                     80:        if (!eq(home, "/") && prefix(home, dir))
                     81:                printf("~%s", dir + strlen(home));
                     82:        else
                     83:                printf("%s", dir);
                     84: }
                     85: 
                     86: /*
                     87:  * dochngd - implement chdir command.
                     88:  */
                     89: dochngd(v)
                     90:        char **v;
                     91: {
                     92:        register char *cp;
                     93:        register struct directory *dp;
                     94: 
                     95:        printd = 0;
                     96:        if (*++v == NOSTR) {
                     97:                if ((cp = value("home")) == NOSTR || *cp == 0)
                     98:                        bferr("No home directory");
                     99:                if (chdir(cp) < 0)
                    100:                        bferr("Can't change to home directory");
                    101:                cp = savestr(cp);
                    102:        } else if ((dp = dfind(*v)) != 0) {
                    103:                printd = 1;
                    104:                if (chdir(dp->di_name) < 0)
                    105:                        Perror(dp->di_name);
                    106:                dcwd->di_prev->di_next = dcwd->di_next;
                    107:                dcwd->di_next->di_prev = dcwd->di_prev;
                    108:                goto flushcwd;
                    109:        } else
                    110:                cp = dfollow(*v);
                    111:        dp = (struct directory *)calloc(sizeof (struct directory), 1);
                    112:        dp->di_name = cp;
                    113:        dp->di_count = 0;
                    114:        dp->di_next = dcwd->di_next;
                    115:        dp->di_prev = dcwd->di_prev;
                    116:        dp->di_prev->di_next = dp;
                    117:        dp->di_next->di_prev = dp;
                    118: flushcwd:
                    119:        dfree(dcwd);
                    120:        dnewcwd(dp);
                    121: }
                    122: 
                    123: /*
                    124:  * dfollow - change to arg directory; fall back on cdpath if not valid
                    125:  */
                    126: char *
                    127: dfollow(cp)
                    128:        register char *cp;
                    129: {
                    130:        register char **cdp;
                    131:        struct varent *c;
                    132:        
                    133:        cp = globone(cp);
                    134:        if (chdir(cp) == 0)
                    135:                goto gotcha;
                    136:        if (cp[0] != '/' && !prefix("./", cp) && !prefix("../", cp)
                    137:            && (c = adrof("cdpath"))) {
                    138:                for (cdp = c->vec; *cdp; cdp++) {
                    139:                        char buf[BUFSIZ];
                    140: 
                    141:                        strcpy(buf, *cdp);
                    142:                        strcat(buf, "/");
                    143:                        strcat(buf, cp);
                    144:                        if (chdir(buf) >= 0) {
                    145:                                printd = 1;
                    146:                                xfree(cp);
                    147:                                cp = savestr(buf);
                    148:                                goto gotcha;
                    149:                        }
                    150:                }
                    151:        }
                    152:        if (adrof(cp)) {
                    153:                char *dp = value(cp);
                    154: 
                    155:                if (dp[0] == '/' || dp[0] == '.')
                    156:                        if (chdir(dp) >= 0) {
                    157:                                xfree(cp);
                    158:                                cp = savestr(dp);
                    159:                                printd = 1;
                    160:                                goto gotcha;
                    161:                        }
                    162:        }
                    163:        xfree(cp);
                    164:        Perror(cp);
                    165: 
                    166: gotcha:
                    167:        if (*cp != '/') {
                    168:                char *dp = calloc(strlen(cp) + strlen(dcwd->di_name) + 2, 1);
                    169:                strcpy(dp, dcwd->di_name);
                    170:                strcat(dp, "/");
                    171:                strcat(dp, cp);
                    172:                xfree(cp);
                    173:                cp = dp;
                    174:        }
                    175:        dcanon(cp);
                    176:        return (cp);
                    177: }
                    178: 
                    179: /*
                    180:  * dopushd - push new directory onto directory stack.
                    181:  *     with no arguments exchange top and second.
                    182:  *     with numeric argument (+n) bring it to top.
                    183:  */
                    184: dopushd(v)
                    185:        char **v;
                    186: {
                    187:        register struct directory *dp;
                    188: 
                    189:        printd = 1;
                    190:        if (*++v == NOSTR) {
                    191:                if ((dp = dcwd->di_prev) == &dhead)
                    192:                        dp = dhead.di_prev;
                    193:                if (dp == dcwd)
                    194:                        bferr("No other directory");
                    195:                if (chdir(dp->di_name) < 0)
                    196:                        Perror(dp->di_name);
                    197:                dp->di_prev->di_next = dp->di_next;
                    198:                dp->di_next->di_prev = dp->di_prev;
                    199:                dp->di_next = dcwd->di_next;
                    200:                dp->di_prev = dcwd;
                    201:                dcwd->di_next->di_prev = dp;
                    202:                dcwd->di_next = dp;
                    203:        } else if (dp = dfind(*v)) {
                    204:                if (chdir(dp->di_name) < 0)
                    205:                        Perror(dp->di_name);
                    206:        } else {
                    207:                register char *cp;
                    208: 
                    209:                cp = dfollow(*v);
                    210:                dp = (struct directory *)calloc(sizeof (struct directory), 1);
                    211:                dp->di_name = cp;
                    212:                dp->di_count = 0;
                    213:                dp->di_prev = dcwd;
                    214:                dp->di_next = dcwd->di_next;
                    215:                dcwd->di_next = dp;
                    216:                dp->di_next->di_prev = dp;
                    217:        }
                    218:        dnewcwd(dp);
                    219: }
                    220: 
                    221: /*
                    222:  * dfind - find a directory if specified by numeric (+n) argument
                    223:  */
                    224: struct directory *
                    225: dfind(cp)
                    226:        register char *cp;
                    227: {
                    228:        register struct directory *dp;
                    229:        register int i;
                    230:        register char *ep;
                    231: 
                    232:        if (*cp++ != '+')
                    233:                return (0);
                    234:        for (ep = cp; digit(*ep); ep++)
                    235:                continue;
                    236:        if (*ep)
                    237:                return (0);
                    238:        i = getn(cp);
                    239:        if (i <= 0)
                    240:                return (0);
                    241:        for (dp = dcwd; i != 0; i--) {
                    242:                if ((dp = dp->di_prev) == &dhead)
                    243:                        dp = dp->di_prev;
                    244:                if (dp == dcwd)
                    245:                        bferr("Directory stack not that deep");
                    246:        }
                    247:        return (dp);
                    248: }
                    249: 
                    250: /*
                    251:  * dopopd - pop a directory out of the directory stack
                    252:  *     with a numeric argument just discard it.
                    253:  */
                    254: dopopd(v)
                    255:        char **v;
                    256: {
                    257:        register struct directory *dp, *p;
                    258: 
                    259:        printd = 1;
                    260:        if (*++v == NOSTR)
                    261:                dp = dcwd;
                    262:        else if ((dp = dfind(*v)) == 0)
                    263:                bferr("Bad directory");
                    264:        if (dp->di_prev == &dhead && dp->di_next == &dhead)
                    265:                bferr("Directory stack empty");
                    266:        if (dp == dcwd) {
                    267:                if ((p = dp->di_prev) == &dhead)
                    268:                        p = dhead.di_prev;
                    269:                if (chdir(p->di_name) < 0)
                    270:                        Perror(p->di_name);
                    271:        }
                    272:        dp->di_prev->di_next = dp->di_next;
                    273:        dp->di_next->di_prev = dp->di_prev;
                    274:        if (dp == dcwd)
                    275:                dnewcwd(p);
                    276:        else
                    277:                dodirs(fakev);
                    278:        dfree(dp);
                    279: }
                    280: 
                    281: /*
                    282:  * dfree - free the directory (or keep it if it still has ref count)
                    283:  */
                    284: dfree(dp)
                    285:        register struct directory *dp;
                    286: {
                    287: 
                    288:        if (dp->di_count != 0)
                    289:                dp->di_next = dp->di_prev = 0;
                    290:        else
                    291:                xfree(dp->di_name), xfree((char *)dp);
                    292: }
                    293: 
                    294: /*
                    295:  * dcanon - canonicalize the pathname, removing excess ./ and ../ etc.
                    296:  *     we are of course assuming that the file system is standardly
                    297:  *     constructed (always have ..'s, directories have links)
                    298:  */
                    299: dcanon(cp)
                    300:        char *cp;
                    301: {
                    302:        register char *p, *sp;
                    303:        register bool slash;
                    304: 
                    305:        if (*cp != '/')
                    306:                abort();
                    307:        for (p = cp; *p; ) {            /* for each component */
                    308:                sp = p;                 /* save slash address */
                    309:                while(*++p == '/')      /* flush extra slashes */
                    310:                        ;
                    311:                if (p != ++sp)
                    312:                        strcpy(sp, p);
                    313:                p = sp;                 /* save start of component */
                    314:                slash = 0;
                    315:                while(*++p)             /* find next slash or end of path */
                    316:                        if (*p == '/') {
                    317:                                slash = 1;
                    318:                                *p = 0;
                    319:                                break;
                    320:                        }
                    321:                if (*sp == '\0')        /* if component is null */
                    322:                        if (--sp == cp) /* if path is one char (i.e. /) */
                    323:                                break;
                    324:                        else
                    325:                                *sp = '\0';
                    326:                else if (eq(".", sp)) {
                    327:                        if (slash) {
                    328:                                strcpy(sp, ++p);
                    329:                                p = --sp;
                    330:                        } else if (--sp != cp)
                    331:                                *sp = '\0';
                    332:                } else if (eq("..", sp)) {
                    333:                        if (--sp != cp)
                    334:                                while (*--sp != '/')
                    335:                                        ;
                    336:                        if (slash) {
                    337:                                strcpy(++sp, ++p);
                    338:                                p = --sp;
                    339:                        } else if (cp == sp)
                    340:                                *++sp = '\0';
                    341:                        else
                    342:                                *sp = '\0';
                    343:                } else if (slash)
                    344:                        *p = '/';
                    345:        }
                    346: }
                    347: 
                    348: /*
                    349:  * dnewcwd - make a new directory in the loop the current one
                    350:  */
                    351: dnewcwd(dp)
                    352:        register struct directory *dp;
                    353: {
                    354: 
                    355:        dcwd = dp;
                    356:        set("cwd", savestr(dcwd->di_name));
                    357:        if (printd)
                    358:                dodirs(fakev);
                    359: }

unix.superglobalmegacorp.com

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