summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2014-10-08 15:24:23 +0800
committerHerbert Xu <herbert@gondor.apana.org.au>2014-10-08 15:24:23 +0800
commit3c06acdac0b1ba0e0acdda513a57ee6e31385dce (patch)
tree512a990a9da9643242a84d27ed3a3d11c2eda166 /src
parent[VAR] Use setvareq to set OPTIND initially (diff)
downloaddash-3c06acdac0b1ba0e0acdda513a57ee6e31385dce.tar.gz
dash-3c06acdac0b1ba0e0acdda513a57ee6e31385dce.zip
[EXPAND] Split unquoted $@/$* correctly when IFS is set but empty
Currently we do not field-split $@/$* when it isn't quoted and IFS
is set but empty.  This is obviously wrong.  This patch fixes this.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to '')
-rw-r--r--src/expand.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/src/expand.c b/src/expand.c
index 11fd7b7..51ba8a1 100644
--- a/src/expand.c
+++ b/src/expand.c
@@ -116,7 +116,7 @@ STATIC const char *subevalvar(char *, char *, int, int, int, int, int);
 STATIC char *evalvar(char *, int);
 STATIC size_t strtodest(const char *, const char *, int);
 STATIC void memtodest(const char *, size_t, const char *, int);
-STATIC ssize_t varvalue(char *, int, int);
+STATIC ssize_t varvalue(char *, int, int, int *);
 STATIC void expandmeta(struct strlist *, int);
 #ifdef HAVE_GLOB
 STATIC void addglob(const glob_t *);
@@ -722,6 +722,7 @@ evalvar(char *p, int flag)
 	ssize_t varlen;
 	int easy;
 	int quoted;
+	int nulonly;
 
 	varflags = *p++;
 	subtype = varflags & VSTYPE;
@@ -732,11 +733,12 @@ evalvar(char *p, int flag)
 	quoted = flag & EXP_QUOTED;
 	var = p;
 	easy = (!quoted || (*var == '@' && shellparam.nparam));
+	nulonly = easy;
 	startloc = expdest - (char *)stackblock();
 	p = strchr(p, '=') + 1;
 
 again:
-	varlen = varvalue(var, varflags, flag);
+	varlen = varvalue(var, varflags, flag, &nulonly);
 	if (varflags & VSNUL)
 		varlen--;
 
@@ -787,7 +789,7 @@ vsplus:
 		if (!easy)
 			goto end;
 record:
-		recordregion(startloc, expdest - (char *)stackblock(), quoted);
+		recordregion(startloc, expdest - (char *)stackblock(), nulonly);
 		goto end;
 	}
 
@@ -892,7 +894,7 @@ strtodest(p, syntax, quotes)
  */
 
 STATIC ssize_t
-varvalue(char *name, int varflags, int flags)
+varvalue(char *name, int varflags, int flags, int *nulonly)
 {
 	int num;
 	char *p;
@@ -907,7 +909,8 @@ varvalue(char *name, int varflags, int flags)
 	int quotes = (discard ? 0 : (flags & QUOTES_ESC)) | QUOTES_KEEPNUL;
 	ssize_t len = 0;
 
-	sep = quoted ? ((flags & EXP_FULL) << CHAR_BIT) : 0;
+	sep = *nulonly ? (flags & EXP_FULL) << CHAR_BIT : 0;
+	*nulonly = 0;
 	syntax = quoted ? DQSYNTAX : BASESYNTAX;
 
 	switch (*name) {
@@ -938,15 +941,16 @@ numvar:
 		expdest = p;
 		break;
 	case '@':
-		if (sep)
+		if (quoted)
 			goto param;
 		/* fall through */
 	case '*':
-		sep = ifsset() ? ifsval()[0] : ' ';
+		sep |= ifsset() ? ifsval()[0] : ' ';
 param:
 		if (!(ap = shellparam.p))
 			return -1;
 		sepc = sep;
+		*nulonly = !sepc;
 		while ((p = *ap++)) {
 			len += strtodest(p, syntax, quotes);