summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authortjr <tjr@FreeBSD.org>2002-05-20 07:54:39 +0000
committertjr <tjr@FreeBSD.org>2002-05-20 07:54:39 +0000
commitbc86a28ef99dc024f02f390d835d6933650a4dd3 (patch)
tree51cfa0ace2f194f589309f0b4345f84a9b3034b4 /bin
parent3eafd11a94317478ed072142843a3507e0844360 (diff)
downloadFreeBSD-src-bc86a28ef99dc024f02f390d835d6933650a4dd3.zip
FreeBSD-src-bc86a28ef99dc024f02f390d835d6933650a4dd3.tar.gz
Add the SUSv3 -L and -P options to the cd and pwd builtin utilities. `Logical'
handling of .. is now the default.
Diffstat (limited to 'bin')
-rw-r--r--bin/sh/cd.c100
-rw-r--r--bin/sh/sh.134
2 files changed, 110 insertions, 24 deletions
diff --git a/bin/sh/cd.c b/bin/sh/cd.c
index 26ad2f2..b7473ba 100644
--- a/bin/sh/cd.c
+++ b/bin/sh/cd.c
@@ -67,7 +67,7 @@ static const char rcsid[] =
#include "show.h"
#include "cd.h"
-STATIC int docd(char *, int);
+STATIC int docd(char *, int, int);
STATIC char *getcomponent(void);
STATIC void updatepwd(char *);
@@ -76,16 +76,36 @@ char *prevdir; /* previous working directory */
STATIC char *cdcomppath;
int
-cdcmd(int argc __unused, char **argv __unused)
+cdcmd(int argc, char **argv)
{
char *dest;
char *path;
char *p;
struct stat statb;
- int print = 0;
+ int ch, phys, print = 0;
+
+ optreset = 1; optind = 1; /* initialize getopt */
+ phys = 0;
+ while ((ch = getopt(argc, argv, "LP")) != -1) {
+ switch (ch) {
+ case 'L':
+ phys = 0;
+ break;
+ case 'P':
+ phys = 1;
+ break;
+ default:
+ error("unknown option: -%c", optopt);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1)
+ error("too many arguments");
- nextopt(nullstr);
- if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
+ if ((dest = *argv) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
error("HOME not set");
if (*dest == '\0')
dest = ".";
@@ -108,9 +128,8 @@ cdcmd(int argc __unused, char **argv __unused)
p += 2;
print = strcmp(p, dest);
}
- if (docd(p, print) >= 0)
+ if (docd(p, print, phys) >= 0)
return 0;
-
}
}
error("can't cd to %s", dest);
@@ -124,7 +143,7 @@ cdcmd(int argc __unused, char **argv __unused)
* directory name if "print" is nonzero.
*/
STATIC int
-docd(char *dest, int print)
+docd(char *dest, int print, int phys)
{
char *p;
char *q;
@@ -133,7 +152,20 @@ docd(char *dest, int print)
int first;
int badstat;
- TRACE(("docd(\"%s\", %d) called\n", dest, print));
+ TRACE(("docd(\"%s\", %d, %d) called\n", dest, print, phys));
+
+ if (phys) {
+ INTOFF;
+ if (chdir(dest) < 0) {
+ INTON;
+ return -1;
+ }
+ updatepwd(NULL);
+ INTON;
+ if (print && iflag && curdir)
+ out1fmt("%s\n", curdir);
+ return 0;
+ }
/*
* Check each component of the path. If we find a symlink or
@@ -161,20 +193,18 @@ docd(char *dest, int print)
if (equal(component, ".."))
continue;
STACKSTRNUL(p);
- if ((lstat(stackblock(), &statb) < 0)
- || (S_ISLNK(statb.st_mode))) {
- /* print = 1; */
+ if (lstat(stackblock(), &statb) < 0) {
badstat = 1;
break;
}
}
INTOFF;
- if (chdir(dest) < 0) {
+ updatepwd(badstat ? NULL : dest);
+ if (chdir(curdir) < 0) {
INTON;
return -1;
}
- updatepwd(badstat ? NULL : dest);
INTON;
if (print && iflag && curdir)
out1fmt("%s\n", curdir);
@@ -270,21 +300,47 @@ updatepwd(char *dir)
INTON;
}
+#define MAXPWD 256
int
pwdcmd(int argc __unused, char **argv __unused)
{
- if (!getpwd())
- error("getcwd() failed: %s", strerror(errno));
- out1str(curdir);
- out1c('\n');
- return 0;
-}
-
+ char buf[MAXPWD];
+ int ch, phys;
+
+ optreset = 1; optind = 1; /* initialize getopt */
+ phys = 0;
+ while ((ch = getopt(argc, argv, "LP")) != -1) {
+ switch (ch) {
+ case 'L':
+ phys = 0;
+ break;
+ case 'P':
+ phys = 1;
+ break;
+ default:
+ error("unknown option: -%c", optopt);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc != 0)
+ error("too many arguments");
+ if (!phys && getpwd()) {
+ out1str(curdir);
+ out1c('\n');
+ } else {
+ if (getcwd(buf, sizeof(buf)) == NULL)
+ error(".: %s", strerror(errno));
+ out1str(buf);
+ out1c('\n');
+ }
-#define MAXPWD 256
+ return 0;
+}
/*
* Find out what the current directory is. If we already know the current
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 54e4465..8518687 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -1317,7 +1317,11 @@ Execute the specified builtin command,
.Ar cmd .
This is useful when the user wishes to override a shell function
with the same name as a builtin command.
-.It Ic cd Op Ar directory
+.It Xo
+.Ic cd
+.Op Fl LP
+.Op Ar directory
+.Xc
Switch to the specified
.Ar directory ,
or to the directory specified in the
@@ -1351,6 +1355,20 @@ if this is different from the name that the user gave.
These may be different either because the
.Ev CDPATH
mechanism was used or because a symbolic link was crossed.
+.Pp
+If the
+.Fl P
+option is specified,
+.Dq \&..
+is handled physically and symbolic links are resolved before
+.Dq \&..
+components are processed.
+If the
+.Fl L
+option is specified,
+.Dq \&..
+is handled logically.
+This is the default.
.It Ic chdir
A synonym for the
.Ic cd
@@ -1622,7 +1640,10 @@ argument is omitted, use the current job.
.It Ic jobs
This command lists out all the background processes
which are children of the current shell process.
-.It Ic pwd
+.It Xo
+.Ic pwd
+.Op Fl LP
+.Xc
Print the path of the current directory. The builtin command may
differ from the program of the same name because the
builtin command remembers what the current directory
@@ -1632,6 +1653,15 @@ renamed,
the builtin version of
.Xr pwd 1
will continue to print the old name for the directory.
+.Pp
+If the
+.Fl P
+option is specified, symbolic links are resolved.
+If the
+.Fl L
+option is specified, the shell's notion of the current directory
+is printed (symbolic links are not resolved).
+This is the default.
.It Xo
.Ic read
.Op Fl p Ar prompt
OpenPOWER on IntegriCloud