/*ARGSUSED*/ void dochngd(Char **v, struct command *c) { Char *cp; struct directory *dp; int dflag = skipargs(&v, "plvn", "[-|<dir>]"); USE(c); printd = 0; cp = (dflag & DIR_OLD) ? varval(STRowd) : *v; if (cp == NULL) { if (!cdtohome) stderror(ERR_NAME | ERR_TOOFEW); else if ((cp = varval(STRhome)) == STRNULL || *cp == 0) stderror(ERR_NAME | ERR_NOHOMEDIR); if (chdir(short2str(cp)) < 0) stderror(ERR_NAME | ERR_CANTCHANGE); cp = Strsave(cp); } else if ((dflag & DIR_OLD) == 0 && v[1] != NULL) { stderror(ERR_NAME | ERR_TOOMANY); /* NOTREACHED */ return; } else if ((dp = dfind(cp)) != 0) { char *tmp; printd = 1; if (chdir(tmp = short2str(dp->di_name)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); dcwd->di_prev->di_next = dcwd->di_next; dcwd->di_next->di_prev = dcwd->di_prev; dfree(dcwd); dnewcwd(dp, dflag); return; } else if ((cp = dfollow(cp, dflag & DIR_OLD)) == NULL) return; dp = xcalloc(sizeof(struct directory), 1); dp->di_name = cp; dp->di_count = 0; dp->di_next = dcwd->di_next; dp->di_prev = dcwd->di_prev; dp->di_prev->di_next = dp; dp->di_next->di_prev = dp; dfree(dcwd); dnewcwd(dp, dflag); }
/* * dopopd - pop a directory out of the directory stack * with a numeric argument just discard it. */ void /*ARGSUSED*/ dopopd(Char **v, struct command *t) { struct directory *dp, *p = NULL; skipargs(&v, " [+<n>]"); printd = 1; if (*v == NULL) dp = dcwd; else if (v[1] != NULL) stderror(ERR_NAME | ERR_TOOMANY); else if ((dp = dfind(*v)) == 0) stderror(ERR_NAME | ERR_BADDIR); if (dp->di_prev == &dhead && dp->di_next == &dhead) stderror(ERR_NAME | ERR_EMPTY); if (dp == dcwd) { char *tmp; if ((p = dp->di_prev) == &dhead) p = dhead.di_prev; if (chdir(tmp = short2str(p->di_name)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); } dp->di_prev->di_next = dp->di_next; dp->di_next->di_prev = dp->di_prev; if (dp == dcwd) dnewcwd(p); else { printdirs(); } dfree(dp); }
/* * dochngd - implement chdir command. */ void /*ARGSUSED*/ dochngd(Char **v, struct command *t) { Char *cp; struct directory *dp; skipargs(&v, " [<dir>]"); printd = 0; if (*v == NULL) { if ((cp = value(STRhome)) == NULL || *cp == 0) stderror(ERR_NAME | ERR_NOHOMEDIR); if (chdir(short2str(cp)) < 0) stderror(ERR_NAME | ERR_CANTCHANGE); cp = Strsave(cp); } else if (v[1] != NULL) { stderror(ERR_NAME | ERR_TOOMANY); /* NOTREACHED */ return; } else if ((dp = dfind(*v)) != 0) { char *tmp; printd = 1; if (chdir(tmp = short2str(dp->di_name)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); dcwd->di_prev->di_next = dcwd->di_next; dcwd->di_next->di_prev = dcwd->di_prev; dfree(dcwd); dnewcwd(dp); return; } else cp = dfollow(*v); dp = xcalloc(1, sizeof(struct directory)); dp->di_name = cp; dp->di_count = 0; dp->di_next = dcwd->di_next; dp->di_prev = dcwd->di_prev; dp->di_prev->di_next = dp; dp->di_next->di_prev = dp; dfree(dcwd); dnewcwd(dp); }
/* * dopushd - push new directory onto directory stack. * with no arguments exchange top and second. * with numeric argument (+n) bring it to top. */ void /*ARGSUSED*/ dopushd(Char **v, struct command *t) { struct directory *dp; skipargs(&v, " [<dir>|+<n>]"); printd = 1; if (*v == NULL) { char *tmp; if ((dp = dcwd->di_prev) == &dhead) dp = dhead.di_prev; if (dp == dcwd) stderror(ERR_NAME | ERR_NODIR); if (chdir(tmp = short2str(dp->di_name)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); dp->di_prev->di_next = dp->di_next; dp->di_next->di_prev = dp->di_prev; dp->di_next = dcwd->di_next; dp->di_prev = dcwd; dcwd->di_next->di_prev = dp; dcwd->di_next = dp; } else if (v[1] != NULL) { stderror(ERR_NAME | ERR_TOOMANY); /* NOTREACHED */ return; } else if ((dp = dfind(*v)) != NULL) { char *tmp; if (chdir(tmp = short2str(dp->di_name)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); } else { Char *ccp; ccp = dfollow(*v); dp = xcalloc(1, sizeof(struct directory)); dp->di_name = ccp; dp->di_count = 0; dp->di_prev = dcwd; dp->di_next = dcwd->di_next; dcwd->di_next = dp; dp->di_next->di_prev = dp; } dnewcwd(dp); }
/*ARGSUSED*/ void dopopd(Char **v, struct command *c) { Char *cp; struct directory *dp, *p = NULL; int dflag = skipargs(&v, "plvn", " [-|+<n>]"); USE(c); printd = 1; cp = (dflag & DIR_OLD) ? varval(STRowd) : *v; if (cp == NULL) dp = dcwd; else if ((dflag & DIR_OLD) == 0 && v[1] != NULL) { stderror(ERR_NAME | ERR_TOOMANY); /* NOTREACHED */ return; } else if ((dp = dfind(cp)) == 0) stderror(ERR_NAME | ERR_BADDIR); if (dp->di_prev == &dhead && dp->di_next == &dhead) stderror(ERR_NAME | ERR_EMPTY); if (dp == dcwd) { char *tmp; if ((p = dp->di_prev) == &dhead) p = dhead.di_prev; if (chdir(tmp = short2str(p->di_name)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); } dp->di_prev->di_next = dp->di_next; dp->di_next->di_prev = dp->di_prev; dfree(dp); if (dp == dcwd) { dnewcwd(p, dflag); } else { printdirs(dflag); } }
/* * dinit - initialize current working directory */ void dinit(Char *hp) { char *tcp; Char *cp = NULL; struct directory *dp; char path[PATH_MAX]; static const char emsg[] = "csh: Trying to start from \"%s\"\n"; /* Don't believe the login shell home, because it may be a symlink */ tcp = getcwd(path, PATH_MAX); if (tcp == NULL || *tcp == '\0') { (void) fprintf(csherr, "csh: %s\n", strerror(errno)); if (hp && *hp) { tcp = short2str(hp); if (chdir(tcp) == 0) cp = hp; (void) fprintf(csherr, emsg, vis_str(hp)); } } else { struct stat swd, shp; if (stat(tcp, &swd) == -1) { (void) fprintf(csherr, "csh: %s: %s\n", tcp, strerror(errno)); } else { /* * See if $HOME is the working directory we got and use that */ if (hp && *hp && stat(short2str(hp), &shp) != -1 && swd.st_dev == shp.st_dev && swd.st_ino == shp.st_ino) cp = hp; else { char *cwd; /* * use PWD if we have it (for subshells) */ if ((cwd = getenv("PWD")) != NULL) { if (stat(cwd, &shp) != -1 && swd.st_dev == shp.st_dev && swd.st_ino == shp.st_ino) tcp = cwd; } cp = dcanon(SAVE(tcp), STRNULL); } } } if (cp == NULL) { (void) fprintf(csherr, emsg, "/"); if (chdir("/") == -1) /* I am not even try to print an error message! */ xexit(1); cp = SAVE("/"); } dp = xcalloc(1, sizeof(struct directory)); dp->di_name = Strsave(cp); dp->di_count = 0; dhead.di_next = dhead.di_prev = dp; dp->di_next = dp->di_prev = &dhead; printd = 0; dnewcwd(dp); }
/* * dinit - initialize current working directory */ void dinit(Char *hp) { Char *cp, *tcp; struct directory *dp; /* Don't believe the login shell home, because it may be a symlink */ tcp = agetcwd(); if (tcp == NULL) { xprintf("%s: %s\n", progname, strerror(errno)); if (hp && *hp) { char *xcp = short2str(hp); dstart(xcp); if (chdir(xcp) == -1) cp = NULL; else cp = Strsave(hp); } else cp = NULL; if (cp == NULL) { dstart("/"); if (chdir("/") == -1) /* I am not even try to print an error message! */ xexit(1); cp = SAVE("/"); } } else { #ifdef S_IFLNK struct stat swd, shp; int swd_ok; swd_ok = stat(short2str(tcp), &swd) == 0; /* * See if $HOME is the working directory we got and use that */ if (swd_ok && hp && *hp && stat(short2str(hp), &shp) != -1 && DEV_DEV_COMPARE(swd.st_dev, shp.st_dev) && swd.st_ino == shp.st_ino) cp = Strsave(hp); else { char *cwd; /* * use PWD if we have it (for subshells) */ if (swd_ok && (cwd = getenv("PWD")) != NULL) { if (stat(cwd, &shp) != -1 && DEV_DEV_COMPARE(swd.st_dev, shp.st_dev) && swd.st_ino == shp.st_ino) { tcp = SAVE(cwd); cleanup_push(tcp, xfree); } } cleanup_push(tcp, xfree); cp = dcanon(tcp, STRNULL); cleanup_ignore(tcp); cleanup_until(tcp); } #else /* S_IFLNK */ cleanup_push(tcp, xfree); cp = dcanon(tcp, STRNULL); cleanup_ignore(tcp); cleanup_until(tcp); #endif /* S_IFLNK */ } dp = xcalloc(sizeof(struct directory), 1); dp->di_name = cp; dp->di_count = 0; dhead.di_next = dhead.di_prev = dp; dp->di_next = dp->di_prev = &dhead; printd = 0; dnewcwd(dp, 0); setcopy(STRdirstack, dp->di_name, VAR_READWRITE|VAR_NOGLOB); }
/*ARGSUSED*/ void dopushd(Char **v, struct command *c) { struct directory *dp; Char *cp; int dflag = skipargs(&v, "plvn", " [-|<dir>|+<n>]"); USE(c); printd = 1; cp = (dflag & DIR_OLD) ? varval(STRowd) : *v; if (cp == NULL) { if (adrof(STRpushdtohome)) { if ((cp = varval(STRhome)) == STRNULL || *cp == 0) stderror(ERR_NAME | ERR_NOHOMEDIR); if (chdir(short2str(cp)) < 0) stderror(ERR_NAME | ERR_CANTCHANGE); if ((cp = dfollow(cp, dflag & DIR_OLD)) == NULL) return; dp = xcalloc(sizeof(struct directory), 1); dp->di_name = cp; dp->di_count = 0; dp->di_prev = dcwd; dp->di_next = dcwd->di_next; dcwd->di_next = dp; dp->di_next->di_prev = dp; } else { char *tmp; if ((dp = dcwd->di_prev) == &dhead) dp = dhead.di_prev; if (dp == dcwd) stderror(ERR_NAME | ERR_NODIR); if (chdir(tmp = short2str(dp->di_name)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); dp->di_prev->di_next = dp->di_next; dp->di_next->di_prev = dp->di_prev; dp->di_next = dcwd->di_next; dp->di_prev = dcwd; dcwd->di_next->di_prev = dp; dcwd->di_next = dp; } } else if ((dflag & DIR_OLD) == 0 && v[1] != NULL) { stderror(ERR_NAME | ERR_TOOMANY); /* NOTREACHED */ return; } else if ((dp = dfind(cp)) != NULL) { char *tmp; if (chdir(tmp = short2str(dp->di_name)) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); /* * kfk - 10 Feb 1984 - added new "extraction style" pushd +n */ if (adrof(STRdextract)) dextract(dp); } else { Char *ccp; if ((ccp = dfollow(cp, dflag & DIR_OLD)) == NULL) return; dp = xcalloc(sizeof(struct directory), 1); dp->di_name = ccp; dp->di_count = 0; dp->di_prev = dcwd; dp->di_next = dcwd->di_next; dcwd->di_next = dp; dp->di_next->di_prev = dp; } dnewcwd(dp, dflag); }