14b88c807SRodney W. Grimes /*- 24b88c807SRodney W. Grimes * Copyright (c) 1991, 1993 34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 44b88c807SRodney W. Grimes * 54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 64b88c807SRodney W. Grimes * Kenneth Almquist. 74b88c807SRodney W. Grimes * 84b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 94b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 104b88c807SRodney W. Grimes * are met: 114b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 124b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 134b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 154b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 164b88c807SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 174b88c807SRodney W. Grimes * must display the following acknowledgement: 184b88c807SRodney W. Grimes * This product includes software developed by the University of 194b88c807SRodney W. Grimes * California, Berkeley and its contributors. 204b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 214b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 224b88c807SRodney W. Grimes * without specific prior written permission. 234b88c807SRodney W. Grimes * 244b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344b88c807SRodney W. Grimes * SUCH DAMAGE. 3589730b29SDavid Greenman * 36afb033d5SSteve Price * $Id: cd.c,v 1.14 1997/02/22 13:58:22 peter Exp $ 374b88c807SRodney W. Grimes */ 384b88c807SRodney W. Grimes 394b88c807SRodney W. Grimes #ifndef lint 40ab0a2172SSteve Price static char const sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95"; 414b88c807SRodney W. Grimes #endif /* not lint */ 424b88c807SRodney W. Grimes 43aa9caaf6SPeter Wemm #include <sys/types.h> 44aa9caaf6SPeter Wemm #include <sys/stat.h> 45aa9caaf6SPeter Wemm #include <stdlib.h> 46ab0a2172SSteve Price #include <string.h> 47aa9caaf6SPeter Wemm #include <unistd.h> 48aa9caaf6SPeter Wemm #include <errno.h> 49aa9caaf6SPeter Wemm 504b88c807SRodney W. Grimes /* 514b88c807SRodney W. Grimes * The cd and pwd commands. 524b88c807SRodney W. Grimes */ 534b88c807SRodney W. Grimes 544b88c807SRodney W. Grimes #include "shell.h" 554b88c807SRodney W. Grimes #include "var.h" 564b88c807SRodney W. Grimes #include "nodes.h" /* for jobs.h */ 574b88c807SRodney W. Grimes #include "jobs.h" 584b88c807SRodney W. Grimes #include "options.h" 594b88c807SRodney W. Grimes #include "output.h" 604b88c807SRodney W. Grimes #include "memalloc.h" 614b88c807SRodney W. Grimes #include "error.h" 62ab0a2172SSteve Price #include "exec.h" 63aa9caaf6SPeter Wemm #include "redir.h" 644b88c807SRodney W. Grimes #include "mystring.h" 65aa9caaf6SPeter Wemm #include "show.h" 66ab0a2172SSteve Price #include "cd.h" 674b88c807SRodney W. Grimes 68aa9caaf6SPeter Wemm STATIC int docd __P((char *, int)); 69aa9caaf6SPeter Wemm STATIC char *getcomponent __P((void)); 70aa9caaf6SPeter Wemm STATIC void updatepwd __P((char *)); 714b88c807SRodney W. Grimes 72ab0a2172SSteve Price char *curdir = NULL; /* current working directory */ 734b88c807SRodney W. Grimes char *prevdir; /* previous working directory */ 744b88c807SRodney W. Grimes STATIC char *cdcomppath; 754b88c807SRodney W. Grimes 764b88c807SRodney W. Grimes int 77aa9caaf6SPeter Wemm cdcmd(argc, argv) 78aa9caaf6SPeter Wemm int argc; 79aa9caaf6SPeter Wemm char **argv; 80aa9caaf6SPeter Wemm { 814b88c807SRodney W. Grimes char *dest; 824b88c807SRodney W. Grimes char *path; 834b88c807SRodney W. Grimes char *p; 844b88c807SRodney W. Grimes struct stat statb; 854b88c807SRodney W. Grimes int print = 0; 864b88c807SRodney W. Grimes 874b88c807SRodney W. Grimes nextopt(nullstr); 884b88c807SRodney W. Grimes if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL) 894b88c807SRodney W. Grimes error("HOME not set"); 9061233bdcSBruce Evans if (*dest == '\0') 9161233bdcSBruce Evans dest = "."; 924b88c807SRodney W. Grimes if (dest[0] == '-' && dest[1] == '\0') { 934b88c807SRodney W. Grimes dest = prevdir ? prevdir : curdir; 948d7d5ceaSPeter Wemm if (dest) 954b88c807SRodney W. Grimes print = 1; 968d7d5ceaSPeter Wemm else 978d7d5ceaSPeter Wemm dest = "."; 984b88c807SRodney W. Grimes } 994b88c807SRodney W. Grimes if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL) 1004b88c807SRodney W. Grimes path = nullstr; 1014b88c807SRodney W. Grimes while ((p = padvance(&path, dest)) != NULL) { 102aa9caaf6SPeter Wemm if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { 1034b88c807SRodney W. Grimes if (!print) { 1044b88c807SRodney W. Grimes /* 1054b88c807SRodney W. Grimes * XXX - rethink 1064b88c807SRodney W. Grimes */ 1074b88c807SRodney W. Grimes if (p[0] == '.' && p[1] == '/') 1084b88c807SRodney W. Grimes p += 2; 1094b88c807SRodney W. Grimes print = strcmp(p, dest); 1104b88c807SRodney W. Grimes } 1114b88c807SRodney W. Grimes if (docd(p, print) >= 0) 1124b88c807SRodney W. Grimes return 0; 1134b88c807SRodney W. Grimes 1144b88c807SRodney W. Grimes } 1154b88c807SRodney W. Grimes } 1164b88c807SRodney W. Grimes error("can't cd to %s", dest); 117aa9caaf6SPeter Wemm /*NOTREACHED*/ 118aa9caaf6SPeter Wemm return 0; 1194b88c807SRodney W. Grimes } 1204b88c807SRodney W. Grimes 1214b88c807SRodney W. Grimes 1224b88c807SRodney W. Grimes /* 123958ba632SSteve Price * Actually do the chdir. In an interactive shell, print the 124958ba632SSteve Price * directory name if "print" is nonzero. 1254b88c807SRodney W. Grimes */ 1264b88c807SRodney W. Grimes STATIC int 1274b88c807SRodney W. Grimes docd(dest, print) 1284b88c807SRodney W. Grimes char *dest; 129aa9caaf6SPeter Wemm int print; 1304b88c807SRodney W. Grimes { 131ab0a2172SSteve Price 132ab0a2172SSteve Price TRACE(("docd(\"%s\", %d) called\n", dest, print)); 1334b88c807SRodney W. Grimes INTOFF; 1345e46e019SSteve Price updatepwd(dest); 1355e46e019SSteve Price if (chdir(stackblock()) < 0) { 1364b88c807SRodney W. Grimes INTON; 1374b88c807SRodney W. Grimes return -1; 1384b88c807SRodney W. Grimes } 1395e46e019SSteve Price hashcd(); /* update command hash table */ 1405e46e019SSteve Price if (prevdir) 1415e46e019SSteve Price ckfree(prevdir); 1425e46e019SSteve Price prevdir = curdir; 1435e46e019SSteve Price curdir = savestr(stackblock()); 1444b88c807SRodney W. Grimes INTON; 1454b88c807SRodney W. Grimes if (print && iflag) 1464b88c807SRodney W. Grimes out1fmt("%s\n", stackblock()); 1474b88c807SRodney W. Grimes return 0; 1484b88c807SRodney W. Grimes } 1494b88c807SRodney W. Grimes 1504b88c807SRodney W. Grimes 1514b88c807SRodney W. Grimes /* 1524b88c807SRodney W. Grimes * Get the next component of the path name pointed to by cdcomppath. 1534b88c807SRodney W. Grimes * This routine overwrites the string pointed to by cdcomppath. 1544b88c807SRodney W. Grimes */ 1554b88c807SRodney W. Grimes STATIC char * 156958ba632SSteve Price getcomponent() 157958ba632SSteve Price { 158afb033d5SSteve Price char *p; 1594b88c807SRodney W. Grimes char *start; 1604b88c807SRodney W. Grimes 1614b88c807SRodney W. Grimes if ((p = cdcomppath) == NULL) 1624b88c807SRodney W. Grimes return NULL; 1634b88c807SRodney W. Grimes start = cdcomppath; 1644b88c807SRodney W. Grimes while (*p != '/' && *p != '\0') 1654b88c807SRodney W. Grimes p++; 1664b88c807SRodney W. Grimes if (*p == '\0') { 1674b88c807SRodney W. Grimes cdcomppath = NULL; 1684b88c807SRodney W. Grimes } else { 1694b88c807SRodney W. Grimes *p++ = '\0'; 1704b88c807SRodney W. Grimes cdcomppath = p; 1714b88c807SRodney W. Grimes } 1724b88c807SRodney W. Grimes return start; 1734b88c807SRodney W. Grimes } 1744b88c807SRodney W. Grimes 1754b88c807SRodney W. Grimes 1764b88c807SRodney W. Grimes /* 1775e46e019SSteve Price * Determine the new working directory, but don't actually enforce 1785e46e019SSteve Price * any changes. 1794b88c807SRodney W. Grimes */ 1804b88c807SRodney W. Grimes STATIC void 1814b88c807SRodney W. Grimes updatepwd(dir) 1824b88c807SRodney W. Grimes char *dir; 1834b88c807SRodney W. Grimes { 1844b88c807SRodney W. Grimes char *new; 1854b88c807SRodney W. Grimes char *p; 1864b88c807SRodney W. Grimes 1874b88c807SRodney W. Grimes cdcomppath = stalloc(strlen(dir) + 1); 1884b88c807SRodney W. Grimes scopy(dir, cdcomppath); 1894b88c807SRodney W. Grimes STARTSTACKSTR(new); 1904b88c807SRodney W. Grimes if (*dir != '/') { 1914b88c807SRodney W. Grimes if (curdir == NULL) 1924b88c807SRodney W. Grimes return; 1934b88c807SRodney W. Grimes p = curdir; 1944b88c807SRodney W. Grimes while (*p) 1954b88c807SRodney W. Grimes STPUTC(*p++, new); 1964b88c807SRodney W. Grimes if (p[-1] == '/') 1974b88c807SRodney W. Grimes STUNPUTC(new); 1984b88c807SRodney W. Grimes } 1994b88c807SRodney W. Grimes while ((p = getcomponent()) != NULL) { 2004b88c807SRodney W. Grimes if (equal(p, "..")) { 2014b88c807SRodney W. Grimes while (new > stackblock() && (STUNPUTC(new), *new) != '/'); 2024b88c807SRodney W. Grimes } else if (*p != '\0' && ! equal(p, ".")) { 2034b88c807SRodney W. Grimes STPUTC('/', new); 2044b88c807SRodney W. Grimes while (*p) 2054b88c807SRodney W. Grimes STPUTC(*p++, new); 2064b88c807SRodney W. Grimes } 2074b88c807SRodney W. Grimes } 2084b88c807SRodney W. Grimes if (new == stackblock()) 2094b88c807SRodney W. Grimes STPUTC('/', new); 2104b88c807SRodney W. Grimes STACKSTRNUL(new); 2114b88c807SRodney W. Grimes } 2124b88c807SRodney W. Grimes 2134b88c807SRodney W. Grimes 2144b88c807SRodney W. Grimes int 215aa9caaf6SPeter Wemm pwdcmd(argc, argv) 216aa9caaf6SPeter Wemm int argc; 217aa9caaf6SPeter Wemm char **argv; 218aa9caaf6SPeter Wemm { 219958ba632SSteve Price if (!getpwd()) 220958ba632SSteve Price error("getcwd() failed: %s", strerror(errno)); 2214b88c807SRodney W. Grimes out1str(curdir); 2224b88c807SRodney W. Grimes out1c('\n'); 2234b88c807SRodney W. Grimes return 0; 2244b88c807SRodney W. Grimes } 2254b88c807SRodney W. Grimes 2264b88c807SRodney W. Grimes 2274b88c807SRodney W. Grimes /* 228958ba632SSteve Price * Find out what the current directory is. If we already know the current 2294b88c807SRodney W. Grimes * directory, this routine returns immediately. 2304b88c807SRodney W. Grimes */ 231958ba632SSteve Price char * 232ab0a2172SSteve Price getpwd() 233ab0a2172SSteve Price { 2344b88c807SRodney W. Grimes if (curdir) 235958ba632SSteve Price return (curdir); 2368df71a5aSSteve Price return ((curdir = getcwd(NULL, 0))); 2374b88c807SRodney W. Grimes } 238