mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-11-17 23:51:06 +01:00
users/19667: whence -S shows intermediate steps in symlink expansion
This commit is contained in:
parent
b83aa727ca
commit
33d1439fdb
4 changed files with 76 additions and 15 deletions
|
|
@ -1,5 +1,8 @@
|
|||
2015-01-02 Peter Stephenson <p.w.stephenson@ntlworld.com>
|
||||
|
||||
* users/19667: Doc/Zsh/builtins.yo, Src/builtin.c, Src/utils.c:
|
||||
whence -S shows intermediate steps in symlink expansion.
|
||||
|
||||
* 34077: Test/A07control.ztst: add some further tests for
|
||||
return status from "for" loops.
|
||||
|
||||
|
|
|
|||
|
|
@ -1667,7 +1667,7 @@ See also the shell variable tt(STTY) for a means of initialising
|
|||
the tty before running external commands.
|
||||
)
|
||||
findex(type)
|
||||
item(tt(type) [ tt(-wfpams) ] var(name) ...)(
|
||||
item(tt(type) [ tt(-wfpamsS) ] var(name) ...)(
|
||||
Equivalent to tt(whence -v).
|
||||
)
|
||||
findex(typeset)
|
||||
|
|
@ -2083,7 +2083,7 @@ the user is potentially interested in both, so this problem is intrinsic
|
|||
to process IDs.
|
||||
)
|
||||
findex(whence)
|
||||
item(tt(whence) [ tt(-vcwfpams) ] var(name) ...)(
|
||||
item(tt(whence) [ tt(-vcwfpamsS) ] var(name) ...)(
|
||||
For each name, indicate how it would be interpreted if used as a
|
||||
command name.
|
||||
|
||||
|
|
@ -2126,6 +2126,11 @@ of these patterns.
|
|||
item(tt(-s))(
|
||||
If a pathname contains symlinks, print the symlink-free pathname as well.
|
||||
)
|
||||
item(tt(-S))(
|
||||
As tt(-s), but if the pathname had to be resolved by following
|
||||
multiple symlinks, the intermediate steps are printed, too. The
|
||||
symlink resolved at each step might be anywhere in the path.
|
||||
)
|
||||
enditem()
|
||||
)
|
||||
findex(where)
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("times", BINF_PSPECIAL, bin_times, 0, 0, 0, NULL, NULL),
|
||||
BUILTIN("trap", BINF_PSPECIAL | BINF_HANDLES_OPTS, bin_trap, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
|
||||
BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsw", "v"),
|
||||
BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsSw", "v"),
|
||||
BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klprtuxmz", NULL),
|
||||
BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
|
||||
BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "ms", "a"),
|
||||
|
|
@ -128,7 +128,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("unset", BINF_PSPECIAL, bin_unset, 1, -1, 0, "fmv", NULL),
|
||||
BUILTIN("unsetopt", 0, bin_setopt, 0, -1, BIN_UNSETOPT, NULL, NULL),
|
||||
BUILTIN("wait", 0, bin_fg, 0, -1, BIN_WAIT, NULL, NULL),
|
||||
BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsw", NULL),
|
||||
BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsSw", NULL),
|
||||
BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsw", "ca"),
|
||||
BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
|
||||
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "AFRILP:abcfdilmpue", NULL),
|
||||
|
|
@ -3331,8 +3331,8 @@ bin_whence(char *nam, char **argv, Options ops, int func)
|
|||
if (v && !csh)
|
||||
zputs(*argv, stdout), fputs(" is ", stdout);
|
||||
zputs(buf, stdout);
|
||||
if (OPT_ISSET(ops,'s'))
|
||||
print_if_link(buf);
|
||||
if (OPT_ISSET(ops,'s') || OPT_ISSET(ops, 'S'))
|
||||
print_if_link(buf, OPT_ISSET(ops, 'S'));
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
informed = 1;
|
||||
|
|
@ -3352,8 +3352,8 @@ bin_whence(char *nam, char **argv, Options ops, int func)
|
|||
if (v && !csh)
|
||||
zputs(*argv, stdout), fputs(" is ", stdout);
|
||||
zputs(cnam, stdout);
|
||||
if (OPT_ISSET(ops,'s'))
|
||||
print_if_link(cnam);
|
||||
if (OPT_ISSET(ops,'s') || OPT_ISSET(ops,'S'))
|
||||
print_if_link(cnam, OPT_ISSET(ops,'S'));
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
65
Src/utils.c
65
Src/utils.c
|
|
@ -719,7 +719,7 @@ slashsplit(char *s)
|
|||
|
||||
/**/
|
||||
static int
|
||||
xsymlinks(char *s)
|
||||
xsymlinks(char *s, int full)
|
||||
{
|
||||
char **pp, **opp;
|
||||
char xbuf2[PATH_MAX*3], xbuf3[PATH_MAX*2];
|
||||
|
|
@ -758,14 +758,49 @@ xsymlinks(char *s)
|
|||
} else {
|
||||
ret = 1;
|
||||
metafy(xbuf3, t0, META_NOALLOC);
|
||||
if (!full) {
|
||||
/*
|
||||
* If only one expansion requested, ensure the
|
||||
* full path is in xbuf.
|
||||
*/
|
||||
zulong len = xbuflen;
|
||||
if (*xbuf3 == '/')
|
||||
strcpy(xbuf, xbuf3);
|
||||
else if ((len += strlen(xbuf3) + 1) < sizeof(xbuf)) {
|
||||
strcpy(xbuf + xbuflen, "/");
|
||||
strcpy(xbuf + xbuflen + 1, xbuf3);
|
||||
} else {
|
||||
*xbuf = 0;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
while (*++pp) {
|
||||
zulong newlen = len + strlen(*pp) + 1;
|
||||
if (newlen < sizeof(xbuf)) {
|
||||
strcpy(xbuf + len, "/");
|
||||
strcpy(xbuf + len + 1, *pp);
|
||||
len = newlen;
|
||||
} else {
|
||||
*xbuf = 01;
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* No need to update xbuflen, we're finished
|
||||
* the expansion (for now).
|
||||
*/
|
||||
break;
|
||||
}
|
||||
if (*xbuf3 == '/') {
|
||||
strcpy(xbuf, "");
|
||||
if (xsymlinks(xbuf3 + 1) < 0)
|
||||
if (xsymlinks(xbuf3 + 1, 0) < 0)
|
||||
ret = -1;
|
||||
else
|
||||
xbuflen = strlen(xbuf);
|
||||
} else
|
||||
if (xsymlinks(xbuf3) < 0)
|
||||
if (xsymlinks(xbuf3, 0) < 0)
|
||||
ret = -1;
|
||||
else
|
||||
xbuflen = strlen(xbuf);
|
||||
|
|
@ -787,7 +822,7 @@ xsymlink(char *s)
|
|||
if (*s != '/')
|
||||
return NULL;
|
||||
*xbuf = '\0';
|
||||
if (xsymlinks(s + 1) < 0)
|
||||
if (xsymlinks(s + 1, 1) < 0)
|
||||
zwarn("path expansion failed, using root directory");
|
||||
if (!*xbuf)
|
||||
return ztrdup("/");
|
||||
|
|
@ -796,13 +831,31 @@ xsymlink(char *s)
|
|||
|
||||
/**/
|
||||
void
|
||||
print_if_link(char *s)
|
||||
print_if_link(char *s, int all)
|
||||
{
|
||||
if (*s == '/') {
|
||||
*xbuf = '\0';
|
||||
if (xsymlinks(s + 1) > 0)
|
||||
if (all) {
|
||||
char *start = s + 1;
|
||||
char xbuflink[PATH_MAX];
|
||||
for (;;) {
|
||||
if (xsymlinks(start, 0) > 0) {
|
||||
printf(" -> ");
|
||||
zputs(*xbuf ? xbuf : "/", stdout);
|
||||
if (!*xbuf)
|
||||
break;
|
||||
strcpy(xbuflink, xbuf);
|
||||
start = xbuflink + 1;
|
||||
*xbuf = '\0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (xsymlinks(s + 1, 1) > 0)
|
||||
printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* print a directory */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue