Add the SUSv3 -L and -P options to the cd and pwd builtin utilities. `Logical'
handling of .. is now the default.
This commit is contained in:
parent
a0cfa93972
commit
178897f127
102
bin/sh/cd.c
102
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;
|
||||
|
||||
nextopt(nullstr);
|
||||
if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
|
||||
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");
|
||||
|
||||
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,22 +300,48 @@ 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');
|
||||
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');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define MAXPWD 256
|
||||
|
||||
/*
|
||||
* Find out what the current directory is. If we already know the current
|
||||
* directory, this routine returns immediately.
|
||||
|
34
bin/sh/sh.1
34
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user