static char *sccsid
= "@(#)sh.dir.c 4.1 10/9/80";
* C Shell - directory management
struct directory
*dfind();
struct directory dhead
; /* "head" of loop */
int printd
; /* force name to be printed */
static char *fakev
[] = { "dirs", NOSTR
};
* dinit - initialize current working directory
register struct directory
*dp
;
dp
= (struct directory
*)calloc(sizeof (struct directory
), 1);
dp
->di_name
= savestr(cp
);
dhead
.di_next
= dhead
.di_prev
= dp
;
dp
->di_next
= dp
->di_prev
= &dhead
;
* dodirs - list all directories in directory loop
register struct directory
*dp
;
char *hp
= value("home");
if (eq(*v
, "-l") && *++v
== NOSTR
)
error("Usage: dirs [ -l ]");
if (!lflag
&& hp
!= NOSTR
) {
dtildepr(hp
, dp
->di_name
);
printf("%s", dp
->di_name
);
} while ((dp
= dp
->di_prev
) != dcwd
);
register char *home
, *dir
;
if (!eq(home
, "/") && prefix(home
, dir
))
printf("~%s", dir
+ strlen(home
));
* dochngd - implement chdir command.
register struct directory
*dp
;
if ((cp
= value("home")) == NOSTR
|| *cp
== 0)
bferr("No home directory");
bferr("Can't change to home directory");
} else if ((dp
= dfind(*v
)) != 0) {
if (chdir(dp
->di_name
) < 0)
dcwd
->di_prev
->di_next
= dcwd
->di_next
;
dcwd
->di_next
->di_prev
= dcwd
->di_prev
;
dp
= (struct directory
*)calloc(sizeof (struct directory
), 1);
dp
->di_next
= dcwd
->di_next
;
dp
->di_prev
= dcwd
->di_prev
;
dp
->di_prev
->di_next
= dp
;
dp
->di_next
->di_prev
= dp
;
* dfollow - change to arg directory; fall back on cdpath if not valid
if (cp
[0] != '/' && !prefix("./", cp
) && !prefix("../", cp
)
&& (c
= adrof("cdpath"))) {
for (cdp
= c
->vec
; *cdp
; cdp
++) {
if (dp
[0] == '/' || dp
[0] == '.')
char *dp
= calloc(strlen(cp
) + strlen(dcwd
->di_name
) + 2, 1);
strcpy(dp
, dcwd
->di_name
);
* dopushd - push new directory onto directory stack.
* with no arguments exchange top and second.
* with numeric argument (+n) bring it to top.
register struct directory
*dp
;
if ((dp
= dcwd
->di_prev
) == &dhead
)
bferr("No other directory");
if (chdir(dp
->di_name
) < 0)
dp
->di_prev
->di_next
= dp
->di_next
;
dp
->di_next
->di_prev
= dp
->di_prev
;
dp
->di_next
= dcwd
->di_next
;
dcwd
->di_next
->di_prev
= dp
;
} else if (dp
= dfind(*v
)) {
if (chdir(dp
->di_name
) < 0)
dp
= (struct directory
*)calloc(sizeof (struct directory
), 1);
dp
->di_next
= dcwd
->di_next
;
dp
->di_next
->di_prev
= dp
;
* dfind - find a directory if specified by numeric (+n) argument
register struct directory
*dp
;
for (ep
= cp
; digit(*ep
); ep
++)
for (dp
= dcwd
; i
!= 0; i
--) {
if ((dp
= dp
->di_prev
) == &dhead
)
bferr("Directory stack not that deep");
* dopopd - pop a directory out of the directory stack
* with a numeric argument just discard it.
register struct directory
*dp
, *p
;
else if ((dp
= dfind(*v
)) == 0)
if (dp
->di_prev
== &dhead
&& dp
->di_next
== &dhead
)
bferr("Directory stack empty");
if ((p
= dp
->di_prev
) == &dhead
)
if (chdir(p
->di_name
) < 0)
dp
->di_prev
->di_next
= dp
->di_next
;
dp
->di_next
->di_prev
= dp
->di_prev
;
* dfree - free the directory (or keep it if it still has ref count)
register struct directory
*dp
;
dp
->di_next
= dp
->di_prev
= 0;
xfree(dp
->di_name
), xfree((char *)dp
);
* dcanon - canonicalize the pathname, removing excess ./ and ../ etc.
* we are of course assuming that the file system is standardly
* constructed (always have ..'s, directories have links)
for (p
= cp
; *p
; ) { /* for each component */
sp
= p
; /* save slash address */
while(*++p
== '/') /* flush extra slashes */
p
= sp
; /* save start of component */
while(*++p
) /* find next slash or end of path */
if (*sp
== '\0') /* if component is null */
if (--sp
== cp
) /* if path is one char (i.e. /) */
} else if (eq("..", sp
)) {
* dnewcwd - make a new directory in the loop the current one
register struct directory
*dp
;
set("cwd", savestr(dcwd
->di_name
));