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:         if (*sp == '\0') {  /* if component is null */
 309:             if (--sp != cp)
 310:                 *sp = '\0';
 311:             break;
 312:         }
 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 (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: }

Defined functions

dcanon defined in line 294; used 1 times
dfind defined in line 219; used 4 times
dfollow defined in line 121; used 3 times
dfree defined in line 279; used 3 times
dinit defined in line 19; used 1 times
dnewcwd defined in line 346; used 4 times
dochngd defined in line 84; used 3 times
dodirs defined in line 42; used 4 times
dopopd defined in line 249; used 3 times
dopushd defined in line 179; used 3 times
dtildepr defined in line 71; used 3 times

Defined variables

dhead defined in line 12; used 11 times
fakev defined in line 14; used 2 times
printd defined in line 13; used 8 times
sccsid defined in line 1; never used
Last modified: 1982-10-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1138
Valid CSS Valid XHTML 1.0 Strict