Subject: Re: bashism for ksh
To: None <tech-userlevel@NetBSD.org>
From: Christian Biere <christianbiere@gmx.de>
List: tech-userlevel
Date: 01/30/2007 01:01:32
--UlVJffcvxoiEqYs2
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Jeremy C. Reed wrote:
> On Mon, 29 Jan 2007, Aymeric Vincent wrote:
> 
> > Christian Biere <christianbiere@gmx.de> writes:
> > 
> > > I'm a fan of this particular bashism:
> > >
> > > make >& make.log 
> 
> > Actually, it's a cshism (although it's a bit harder to pronounce).
> 
> Maybe also do:	|&
 
That's a problem because it's already used by ksh to create a co-process.
Maybe I can add this to sh instead.

> (Not for bash, but works in csh.)

The attached patch adds at least >>& to ksh as well.
 
-- 
Christian

--UlVJffcvxoiEqYs2
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ksh.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 23:50:18 -0000
@@ -1361,13 +1361,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;
+			iop->flag |= IOBOTH;
+			do_open = 1;
+			flags = O_WRONLY | O_CREAT | O_TRUNC;
+
 		}
 		if (u == iop->unit)
 			return 0;		/* "dup from" == "dup to" */
@@ -1435,7 +1449,18 @@ iosetup(iop, tp)
 		}
 #endif /* KSH */
 	}
-	if (u == 2) /* Clear any write errors */
+	if (u >= 0 && (iop->flag & IOBOTH)) {
+		if (e->savefd[STDERR_FILENO] == 0)
+			e->savefd[STDERR_FILENO] = savefd(STDERR_FILENO, 0);
+		if (ksh_dup2(iop->unit, 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 || (iop->flag & IOBOTH)) /* Clear any write errors */
 		shf_reopen(2, SHF_WR, shl_out);
 	return 0;
 }
Index: lex.c
===================================================================
RCS file: /cvsroot/src/bin/ksh/lex.c,v
retrieving revision 1.12
diff -u -p -r1.12 lex.c
--- lex.c	11 Sep 2005 22:16:00 -0000	1.12
+++ lex.c	29 Jan 2007 23:50:21 -0000
@@ -665,6 +665,11 @@ Done:
 				} else {
 					ungetsc(c2);
 				}
+			} else if (iop->flag == IOCAT) {
+				if ((c2 = getsc()) == '&')
+					iop->flag |= IOBOTH;
+				else
+					ungetsc(c2);
 			}
 		} else if (c2 == '&')
 			iop->flag = IODUP | (c == '<' ? IORDUP : 0);
Index: tree.h
===================================================================
RCS file: /cvsroot/src/bin/ksh/tree.h,v
retrieving revision 1.4
diff -u -p -r1.4 tree.h
--- tree.h	7 Jul 2004 19:20:09 -0000	1.4
+++ tree.h	29 Jan 2007 23:50:21 -0000
@@ -96,6 +96,7 @@ struct ioword {
 #define	IOCLOB	BIT(6)		/* >|, override -o noclobber */
 #define IORDUP	BIT(7)		/* x<&y (as opposed to x>&y) */
 #define IONAMEXP BIT(8)		/* name has been expanded */
+#define IOBOTH BIT(9)		/* stdout and stderr e.g., >>& */
 
 /* execute/exchild flags */
 #define	XEXEC	BIT(0)		/* execute without forking */

--UlVJffcvxoiEqYs2--