Module Name:    src
Committed By:   christos
Date:           Sat Mar 12 14:59:26 UTC 2016

Modified Files:
        src/bin/sh: eval.c output.c

Log Message:
Improve quoting in the output from sh -x - use less unnecessary
quotes ('_' and '.' do not need quoting) and never quote the '=' in
an assignment (or it would not be one.) From kre, with some refactoring
to be blamed to me.


To generate a diff of this commit:
cvs rdiff -u -r1.115 -r1.116 src/bin/sh/eval.c
cvs rdiff -u -r1.34 -r1.35 src/bin/sh/output.c

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/eval.c
diff -u src/bin/sh/eval.c:1.115 src/bin/sh/eval.c:1.116
--- src/bin/sh/eval.c:1.115	Mon Feb 29 18:51:36 2016
+++ src/bin/sh/eval.c	Sat Mar 12 09:59:26 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: eval.c,v 1.115 2016/02/29 23:51:36 christos Exp $	*/
+/*	$NetBSD: eval.c,v 1.116 2016/03/12 14:59:26 christos Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)eval.c	8.9 (Berkeley) 6/8/95";
 #else
-__RCSID("$NetBSD: eval.c,v 1.115 2016/02/29 23:51:36 christos Exp $");
+__RCSID("$NetBSD: eval.c,v 1.116 2016/03/12 14:59:26 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -45,6 +45,7 @@ __RCSID("$NetBSD: eval.c,v 1.115 2016/02
 #include <stdlib.h>
 #include <signal.h>
 #include <stdio.h>
+#include <string.h>
 #include <errno.h>
 #include <limits.h>
 #include <unistd.h>
@@ -807,9 +808,25 @@ evalcommand(union node *cmd, int flgs, s
 		char sep = 0;
 		out2str(ps4val());
 		for (sp = varlist.list ; sp ; sp = sp->next) {
+			char *p;
+
 			if (sep != 0)
 				outc(sep, &errout);
-			out2shstr(sp->text);
+
+			/*
+			 * The "var=" part should not be quoted, regardless
+			 * of the value, or it would not represent an
+			 * assignment, but rather a command
+			 */
+			p = strchr(sp->text, '=');
+			if (p != NULL) {
+				*p = '\0';	/*XXX*/
+				out2shstr(sp->text);
+				out2c('=');
+				*p++ = '=';	/*XXX*/
+			} else
+				p = sp->text;
+			out2shstr(p);
 			sep = ' ';
 		}
 		for (sp = arglist.list ; sp ; sp = sp->next) {

Index: src/bin/sh/output.c
diff -u src/bin/sh/output.c:1.34 src/bin/sh/output.c:1.35
--- src/bin/sh/output.c:1.34	Sun Feb 28 18:12:23 2016
+++ src/bin/sh/output.c	Sat Mar 12 09:59:26 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: output.c,v 1.34 2016/02/28 23:12:23 christos Exp $	*/
+/*	$NetBSD: output.c,v 1.35 2016/03/12 14:59:26 christos Exp $	*/
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: output.c,v 1.34 2016/02/28 23:12:23 christos Exp $");
+__RCSID("$NetBSD: output.c,v 1.35 2016/03/12 14:59:26 christos Exp $");
 #endif
 #endif /* not lint */
 
@@ -146,29 +146,58 @@ out2shstr(const char *p)
 }
 
 
+static const char norm_chars [] = \
+    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-=_.'";
+
+static int
+inquote(const char *p)
+{
+	size_t l = strspn(p, norm_chars);
+	char *s = strchr(p, '\'');
+
+	return s == NULL ? p[l] != '\0' : s - p > (off_t)l;
+}
+
+
 void
 outshstr(const char *p, struct output *file)
 {
-	static const char norm_chars [] \
-		= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-=";
+	/*
+	 * ' is in this list, not because it does not require quoting
+	 * (which applies to all the others) but because '' quoting cannot
+	 * be used to quote it.
+	 */
 	int need_q = p[0] == 0 || p[strspn(p, norm_chars)] != 0;
+	int inq;
 	char c;
 
-	if (need_q)
-		outc('\'', file);
+	/*
+	 * Don't emit ' unless something needs quoting before closing '
+	 */
+	if (need_q) {
+		if ((inq = inquote(p)) != 0)
+				outc('\'', file);
+	} else
+		inq = 0;
 
-	while (c = *p++, c != 0){
-		if (c != '\''){
-			outc(c, file);
-		}else{
-			outc('\'', file);
-			outc('\\', file);
+	while ((c = *p++) != '\0') {
+		if (c != '\'') {
 			outc(c, file);
-			outc('\'', file);
+			continue;
 		}
+
+		if (inq)
+			outc('\'', file);	/* inq = 0, implicit */
+		outc('\\', file);
+		outc(c, file);
+		if (need_q && *p != '\0') {
+			if ((inq = inquote(p)) != 0)
+				outc('\'', file);
+		} else
+			inq = 0;
 	}
 
-	if (need_q)
+	if (inq)
 		outc('\'', file);
 
 	if (file == out2)

Reply via email to