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