Module Name:    src
Committed By:   kre
Date:           Fri Oct  6 21:09:45 UTC 2017

Modified Files:
        src/bin/sh: expand.c sh.1

Log Message:
Three fixes and a change to ~ expansions

1. A serious bug introduced 3 1/2 months ago (approx) (rev 1.116) which
   broke all but the simple cases of ~ expansions is fixed (amazingly,
   given the magnitude of this problem, no-one noticed!)

2. An ancient bug (probably from when ~ expansion was first addedin 1994, and
   certainly is in NetBSD-6 vintage shells) where ${UnSeT:-~} (and similar)
   does not expand the ~ is fixed (note that ${UnSeT:-~/} does expand,
   this should give a clue to the cause of the problem.

3. A fix/change to make the effects of ~ expansions on ${UnSeT:=whatever}
   identical to those in UnSeT=whatever   In particular, with HOME=/foo
   ${UnSeT:=~:~} now assigns, and expands to, /foo:/foo rather than ~:~
   just as VAR=~:~ assigns /foo:/foo to VAR.   Note this is even after the
   previous fix (ie: appending a '/' would not change the results here.)

   It is hard to call this one a bug fix for certain (though I believe it is)
   as many other shells also produce different results for the ${V:=...}
   expansions than  they do for V=... (though not all the same as we did).

   POSIX is not clear about this, expanding ~ after : in VAR=whatever
   assignments is clear, whether ${U:=whatever} assignments should be
   treated the same way is not stated, one way or the other.

4. Change to make ':' terminate the user name in a ~ expansion in all cases,
   not only in assignments.   This makes sense, as ':' is one character that
   cannot occur in user names, no matter how otherwise weird they become.
   bash (incl in posix mode) ksh93 and bosh all act this way, whereas most
   other shells (and POSIX) do not.   Because this is clearly an extension
   to POSIX, do this one only when not in posix mode (not set -o posix).


To generate a diff of this commit:
cvs rdiff -u -r1.120 -r1.121 src/bin/sh/expand.c
cvs rdiff -u -r1.166 -r1.167 src/bin/sh/sh.1

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/bin/sh/expand.c
diff -u src/bin/sh/expand.c:1.120 src/bin/sh/expand.c:1.121
--- src/bin/sh/expand.c:1.120	Mon Aug 21 13:20:49 2017
+++ src/bin/sh/expand.c	Fri Oct  6 21:09:45 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: expand.c,v 1.120 2017/08/21 13:20:49 kre Exp $	*/
+/*	$NetBSD: expand.c,v 1.121 2017/10/06 21:09:45 kre Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)expand.c	8.5 (Berkeley) 5/15/95";
 #else
-__RCSID("$NetBSD: expand.c,v 1.120 2017/08/21 13:20:49 kre Exp $");
+__RCSID("$NetBSD: expand.c,v 1.121 2017/10/06 21:09:45 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -361,6 +361,7 @@ exptilde(const char *p, int flag)
 #endif
 
 	setstackmark(&smark);
+	(void) grabstackstr(expdest);
 	user = stackblock();		/* we will just borrow top of stack */
 
 	while ((c = *++p) != '\0') {
@@ -372,16 +373,16 @@ exptilde(const char *p, int flag)
 		case CTLARI:		/* just leave original unchanged */
 		case CTLENDARI:
 		case CTLQUOTEMARK:
-		case CTLENDVAR:
 		case '\n':
 			popstackmark(&smark);
 			return (startp);
 		case CTLNONL:
 			continue;
 		case ':':
-			if (flag & EXP_VARTILDE)
+			if (!posix || flag & EXP_VARTILDE)
 				goto done;
 			break;
+		case CTLENDVAR:
 		case '/':
 			goto done;
 		}
@@ -682,7 +683,7 @@ subevalvar(const char *p, const char *st
 	herefd = -1;
 	VTRACE(DBG_EXPAND, ("subevalvar(%d) \"%.20s\" ${%.*s} sloc=%d vf=%x\n",
 	    subtype, p, p-str, str, startloc, varflags));
-	argstr(p, EXP_TILDE);
+	argstr(p, subtype == VSASSIGN ? EXP_VARTILDE : EXP_TILDE);
 	STACKSTRNUL(expdest);
 	herefd = saveherefd;
 	argbackq = saveargbackq;

Index: src/bin/sh/sh.1
diff -u src/bin/sh/sh.1:1.166 src/bin/sh/sh.1:1.167
--- src/bin/sh/sh.1:1.166	Sun Aug 27 20:37:59 2017
+++ src/bin/sh/sh.1	Fri Oct  6 21:09:45 2017
@@ -1,4 +1,4 @@
-.\"	$NetBSD: sh.1,v 1.166 2017/08/27 20:37:59 wiz Exp $
+.\"	$NetBSD: sh.1,v 1.167 2017/10/06 21:09:45 kre Exp $
 .\" Copyright (c) 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,7 +31,7 @@
 .\"
 .\"	@(#)sh.1	8.6 (Berkeley) 5/4/95
 .\"
-.Dd August 20, 2017
+.Dd October 6, 2017
 .Dt SH 1
 .\" everything except c o and s (keep them ordered)
 .ds flags abCEeFfhIiLmnpquVvx
@@ -477,6 +477,10 @@ opened using the
 built-in command are passed on to utilities executed
 .Dq ( yes
 in posix mode),
+whether a colon (:) terminates the user name in tilde (~) expansions
+other than in assignment statements
+.Dq ( no
+in posix mode),
 and whether the shell treats
 an empty brace-list compound statement as a syntax error
 (expected by POSIX) or permits it.
@@ -1555,14 +1559,22 @@ substitution, or arithmetic evaluation.
 .Ss Tilde Expansion (substituting a user's home directory)
 A word beginning with an unquoted tilde character (~) is
 subjected to tilde expansion.
-All the following characters in the word up to
-a slash (/) or the end of the word are treated as a user name
-and are replaced with the named user's home directory.
+Provided all of the subsequent characters in the word are unquoted
+up to an unquoted slash (/)
+or when in an assignment or not in posix mode, an unquoted colon (:),
+or if neither of those appear, the end of the word,
+they are treated as a user name
+and are replaced with the pathname of the named user's home directory.
 If the user name is missing (as in
 .Pa ~/foobar ) ,
 the tilde is replaced with the value of the
 .Va HOME
 variable (the current user's home directory).
+.Pp
+In variable assignments,
+an unquoted tilde immediately after the assignment operator (=), and
+each unquoted tilde immediately after an unquoted colon in the value
+to be assigned is also subject to tilde expansion as just stated.
 .Ss Parameter Expansion
 The format for parameter expansion is as follows:
 .Pp

Reply via email to