Annotation of 41BSD/cmd/csh/sh.dir.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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