Subject: bashism for ksh
To: None <tech-userlevel@NetBSD.org>
From: Christian Biere <christianbiere@gmx.de>
List: tech-userlevel
Date: 01/29/2007 08:36:18
--jI8keyz6grp/JLjh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,

I'm a fan of this particular bashism:

make >& make.log 

In bash this causes both standard output and standard error output to be
redirected to make.log. Thus it's a short-cut for

make > make.log 2>&1

This is not only longer, but the combination 2>&1 is rather awkward to type,
IMHO. The attached patch adds this feature to ksh. This feature isn't POSIX
but POSIX doesn't seem to forbid it either. There's only a minor clash
with ksh's co-process feature, so make >& p (the whitespace is irrelevant)
does not write to file "p" but rather the co-process respectively causes
an error if there's none. I'd think this is neglible.

If checked a couple of cases and couldn't find a problem with my patch so
far. If there are no objections, I'd like to commit it.

For what's it's worth, the following are acceptable and last one wins:

 >& /dev/null >& blah
 >& /dev/null >& /dev/null
 >& /dev/null > blah 
 >& /dev/null 2> /dev/tty

-- 
Christian

--jI8keyz6grp/JLjh
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="exec.c.udif"

Index: exec.c
===================================================================
RCS file: /cvsroot/src/bin/ksh/exec.c,v
retrieving revision 1.13
diff -u -p -r1.13 exec.c
--- exec.c	24 Apr 2006 19:58:20 -0000	1.13
+++ exec.c	29 Jan 2007 07:11:07 -0000
@@ -1309,6 +1309,7 @@ iosetup(iop, tp)
 	int do_open = 1, do_close = 0, UNINITIALIZED(flags);
 	struct ioword iotmp;
 	struct stat statb;
+	int redir_both = 0;
 
 	if (iotype != IOHERE)
 		cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0));
@@ -1361,13 +1362,27 @@ iosetup(iop, tp)
 		if (*cp == '-' && !cp[1]) {
 			u = 1009;	 /* prevent error return below */
 			do_close = 1;
-		} else if ((u = check_fd(cp,
+		} else if (
+		    (iop->flag & IORDUP) ||
+		    (iop->unit != STDOUT_FILENO) ||
+#ifdef KSH
+		    (*cp == 'p' && !cp[1]) ||
+#endif
+		    isdigit((unsigned char) *cp)) {
+			if ((u = check_fd(cp,
 				X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK),
 				&emsg)) < 0)
-		{
-			warningf(TRUE, "%s: %s",
-				snptreef((char *) 0, 32, "%R", &iotmp), emsg);
-			return -1;
+			{
+				warningf(TRUE, "%s: %s",
+				  snptreef((char *) 0, 32, "%R", &iotmp), emsg);
+				return -1;
+			}
+		} else {
+			u = -1;
+			redir_both = 1;
+			do_open = 1;
+			flags = O_WRONLY | O_CREAT | O_TRUNC;
+
 		}
 		if (u == iop->unit)
 			return 0;		/* "dup from" == "dup to" */
@@ -1435,7 +1450,18 @@ iosetup(iop, tp)
 		}
 #endif /* KSH */
 	}
-	if (u == 2) /* Clear any write errors */
+	if (u >= 0 && redir_both) {
+		if (e->savefd[STDERR_FILENO] == 0)
+			e->savefd[STDERR_FILENO] = savefd(STDERR_FILENO, 0);
+		if (ksh_dup2(u, STDERR_FILENO, TRUE) < 0) {
+			warningf(TRUE,
+				"could not finish (dup) redirection %s: %s",
+				snptreef((char *) 0, 32, "%R", &iotmp),
+				strerror(errno));
+			return -1;
+		}
+	}
+	if (u == 2 || redir_both) /* Clear any write errors */
 		shf_reopen(2, SHF_WR, shl_out);
 	return 0;
 }

--jI8keyz6grp/JLjh--