BSD 4_4_Lite2 release
[unix-history] / usr / src / bin / sh / cd.c
index a9bba57..4f363a3 100644 (file)
@@ -1,17 +1,49 @@
 /*-
 /*-
- * Copyright (c) 1991 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
  *
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)cd.c       5.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)cd.c       8.2 (Berkeley) 5/4/95";
 #endif /* not lint */
 
 #endif /* not lint */
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
 /*
  * The cd and pwd commands.
  */
 /*
  * The cd and pwd commands.
  */
@@ -24,52 +56,58 @@ static char sccsid[] = "@(#)cd.c    5.1 (Berkeley) %G%";
 #include "output.h"
 #include "memalloc.h"
 #include "error.h"
 #include "output.h"
 #include "memalloc.h"
 #include "error.h"
+#include "redir.h"
 #include "mystring.h"
 #include "mystring.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-
-#ifdef __STDC__
-STATIC int docd(char *, int);
-STATIC void updatepwd(char *);
-STATIC void getpwd(void);
-STATIC char *getcomponent(void);
-#else
-STATIC int docd();
-STATIC void updatepwd();
-STATIC void getpwd();
-STATIC char *getcomponent();
-#endif
+#include "show.h"
 
 
+STATIC int docd __P((char *, int));
+STATIC char *getcomponent __P((void));
+STATIC void updatepwd __P((char *));
+STATIC void getpwd __P((void));
 
 char *curdir;                  /* current working directory */
 
 char *curdir;                  /* current working directory */
+char *prevdir;                 /* previous working directory */
 STATIC char *cdcomppath;
 
 STATIC char *cdcomppath;
 
-#if UDIR
-extern int didudir;            /* set if /u/logname expanded */
-#endif
-
-
 int
 int
-cdcmd(argc, argv)  char **argv; {
+cdcmd(argc, argv)
+       int argc;
+       char **argv; 
+{
        char *dest;
        char *path;
        char *p;
        struct stat statb;
        char *padvance();
        char *dest;
        char *path;
        char *p;
        struct stat statb;
        char *padvance();
+       int print = 0;
 
 
-       if ((dest = argv[1]) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
+       nextopt(nullstr);
+       if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
                error("HOME not set");
                error("HOME not set");
+       if (dest[0] == '-' && dest[1] == '\0') {
+               dest = prevdir ? prevdir : curdir;
+               print = 1;
+       }
        if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
                path = nullstr;
        while ((p = padvance(&path, dest)) != NULL) {
        if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
                path = nullstr;
        while ((p = padvance(&path, dest)) != NULL) {
-               if (stat(p, &statb) >= 0
-                && (statb.st_mode & S_IFMT) == S_IFDIR
-                && docd(p, strcmp(p, dest)) >= 0)
-                       return 0;
+               if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
+                       if (!print) {
+                               /*
+                                * XXX - rethink
+                                */
+                               if (p[0] == '.' && p[1] == '/')
+                                       p += 2;
+                               print = strcmp(p, dest);
+                       }
+                       if (docd(p, print) >= 0)
+                               return 0;
+
+               }
        }
        error("can't cd to %s", dest);
        }
        error("can't cd to %s", dest);
+       /*NOTREACHED*/
+       return 0;
 }
 
 
 }
 
 
@@ -88,10 +126,6 @@ STATIC int
 docd(dest, print)
        char *dest;
        {
 docd(dest, print)
        char *dest;
        {
-#if UDIR
-       if (didudir)
-               print = 1;
-#endif
        INTOFF;
        if (chdir(dest) < 0) {
                INTON;
        INTOFF;
        if (chdir(dest) < 0) {
                INTON;
@@ -111,7 +145,8 @@ docd(dest, print)
 STATIC int
 docd(dest, print)
        char *dest;
 STATIC int
 docd(dest, print)
        char *dest;
-       {
+       int print;
+{
        register char *p;
        register char *q;
        char *symlink;
        register char *p;
        register char *q;
        char *symlink;
@@ -121,10 +156,6 @@ docd(dest, print)
        int i;
 
        TRACE(("docd(\"%s\", %d) called\n", dest, print));
        int i;
 
        TRACE(("docd(\"%s\", %d) called\n", dest, print));
-#if UDIR
-       if (didudir)
-               print = 1;
-#endif
 
 top:
        cdcomppath = dest;
 
 top:
        cdcomppath = dest;
@@ -135,7 +166,7 @@ top:
        }
        first = 1;
        while ((q = getcomponent()) != NULL) {
        }
        first = 1;
        while ((q = getcomponent()) != NULL) {
-               if (q[0] == '\0' || q[0] == '.' && q[1] == '\0')
+               if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
                        continue;
                if (! first)
                        STPUTC('/', p);
                        continue;
                if (! first)
                        STPUTC('/', p);
@@ -148,7 +179,7 @@ top:
                STACKSTRNUL(p);
                if (lstat(stackblock(), &statb) < 0)
                        error("lstat %s failed", stackblock());
                STACKSTRNUL(p);
                if (lstat(stackblock(), &statb) < 0)
                        error("lstat %s failed", stackblock());
-               if ((statb.st_mode & S_IFMT) != S_IFLNK)
+               if (!S_ISLNK(statb.st_mode))
                        continue;
 
                /* Hit a symbolic link.  We have to start all over again. */
                        continue;
 
                /* Hit a symbolic link.  We have to start all over again. */
@@ -267,15 +298,21 @@ updatepwd(dir)
        if (new == stackblock())
                STPUTC('/', new);
        STACKSTRNUL(new);
        if (new == stackblock())
                STPUTC('/', new);
        STACKSTRNUL(new);
-       if (curdir)
-               ckfree(curdir);
+       INTOFF;
+       if (prevdir)
+               ckfree(prevdir);
+       prevdir = curdir;
        curdir = savestr(stackblock());
        curdir = savestr(stackblock());
+       INTON;
 }
 
 
 
 int
 }
 
 
 
 int
-pwdcmd(argc, argv)  char **argv; {
+pwdcmd(argc, argv)
+       int argc;
+       char **argv; 
+{
        getpwd();
        out1str(curdir);
        out1c('\n');
        getpwd();
        out1str(curdir);
        out1c('\n');
@@ -322,7 +359,7 @@ getpwd() {
        pip[1] = -1;
        p = buf;
        while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
        pip[1] = -1;
        p = buf;
        while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
-            || i == -1 && errno == EINTR) {
+            || (i == -1 && errno == EINTR)) {
                if (i > 0)
                        p += i;
        }
                if (i > 0)
                        p += i;
        }