|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.