about summary refs log tree commit diff
path: root/Src/utils.c
diff options
context:
space:
mode:
authorPeter Stephenson <p.w.stephenson@ntlworld.com>2015-01-02 21:32:51 +0000
committerPeter Stephenson <p.w.stephenson@ntlworld.com>2015-01-02 21:32:51 +0000
commit33d1439fdbf56ec100dbddfa9f7472a0da59d183 (patch)
tree4f9ef9a7d791de0a0cc865f9a0551182cfdbf4a8 /Src/utils.c
parentb83aa727ca745137817e40e766ada815beb93d88 (diff)
downloadzsh-33d1439fdbf56ec100dbddfa9f7472a0da59d183.tar.gz
zsh-33d1439fdbf56ec100dbddfa9f7472a0da59d183.tar.xz
zsh-33d1439fdbf56ec100dbddfa9f7472a0da59d183.zip
users/19667: whence -S shows intermediate steps in symlink expansion
Diffstat (limited to 'Src/utils.c')
-rw-r--r--Src/utils.c67
1 files changed, 60 insertions, 7 deletions
diff --git a/Src/utils.c b/Src/utils.c
index 893a8ca02..2b2a815a8 100644
--- a/Src/utils.c
+++ b/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,12 +831,30 @@ 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)
-	    printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout);
+	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);
+	}
     }
 }