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
dinit
defined in line
19; used 1 times
Defined variables
dhead
defined in line
12; used 11 times
fakev
defined in line
14; used 2 times
sccsid
defined in line
1;
never used