On Wed, Mar 22, 2017 at 07:39:21PM +0000, Thorsten Glaser wrote:
> 
> Dr. Werner Fink dixit:
> 
> >Just to be mentioned, I can mksh change in such a way that without job 
> >control
> >I can do
> >
> >   ~/rpmbuild/BUILD/mksh> ./mksh -c 'echo xxx | read yyy; echo $yyy'
> >   xxx
> >
> >that is it does work similar to the lastpipe shell option of the bash
> >I had initiated now 7 years back. The trick is to avouid forking the
> >last element in a pipe chain.
> 
> I’ve thought about this… years ago, too. But seeing as POSIX allows
> either behaviour, I decided that this (running all sides of pipelines
> in subshells) is a language feature now, for simplicity of user scripts
> (as they can just use co-processes when they don’t want it).
> 
> So, thanks but no. (I’ve got scripts that actually rely on that now.)

OK .. nevertheless, only for the records, the change might look
similar to that in the attachment I guess.

Werner

-- 
  "Having a smoking section in a restaurant is like having
          a peeing section in a swimming pool." -- Edward Burr
--- mksh/exec.c
+++ mksh/exec.c	2017-03-27 10:33:11.000000000 +0000
@@ -156,6 +156,8 @@ execute(struct op * volatile t,
 			}
 		}
 
+	flags &= ~XPIPELS;
+
 	switch (t->type) {
 	case TCOM:
 		rv = comexec(t, tp, (const char **)ap, flags, xerrok);
@@ -192,8 +194,23 @@ execute(struct op * volatile t,
 		restfd(1, e->savefd[1]);
 		/* no need to re-restore this */
 		e->savefd[1] = 0;
-		/* Let exchild() close 0 in parent, after fork, before wait */
-		i = exchild(t, flags | XPCLOSE | XPIPEST, xerrok, 0);
+
+		tp = NULL;
+		if (Flag(FLASTPIPE) && !Flag(FPIPEFAIL) && t->args) {
+			up = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE);
+			ap = (const char **)up;
+			if (ap[0])
+				tp = findcom(ap[0], FC_BI|FC_FUNC);
+		}
+
+		if (tp && tp->type == CSHELL) {
+			flags &= ~XFORK;
+			flags |= XPIPELS;
+			i = execute(t, flags | XPIPELS | XERROK, xerrok);
+		} else
+			/* Let exchild() close 0 in parent, after fork, before wait */
+			i = exchild(t, flags | XPCLOSE | XPIPEST, xerrok, 0);
+
 		if (!(flags&XBGND) && !(flags&XXCOM))
 			rv = i;
 		break;
@@ -453,6 +470,12 @@ execute(struct op * volatile t,
 
 	/* restores IO */
 	quitenv(NULL);
+
+#ifndef MKSH_UNEMPLOYED
+	if (flags & XPIPELS)
+		j_restore(flags);
+#endif
+
 	if ((flags&XEXEC))
 		/* exit child */
 		unwind(LEXIT);
--- mksh/jobs.c
+++ mksh/jobs.c	2017-03-27 10:34:26.000000000 +0000
@@ -641,6 +641,23 @@ exchild(struct op *t, int flags,
 	return (rv);
 }
 
+#ifndef MKSH_UNEMPLOYED
+void
+j_restore(int flags)
+{
+	if (!Flag(FMONITOR) || (flags&XXCOM))
+		return;
+	/* job control set up */
+
+	if (!ttypgrp_ok)
+		return;
+
+	if (kshpgrp == kshpid && kshpgrp != tcgetpgrp(tty_fd))
+		if (tcsetpgrp(tty_fd, kshpid) < 0)
+			ttypgrp_ok = false;
+}
+#endif
+
 /* start the last job: only used for $(command) jobs */
 void
 startlast(void)
--- mksh/main.c
+++ mksh/main.c	2017-03-27 10:45:27.000000000 +0000
@@ -250,6 +250,15 @@ main_init(int argc, const char *argv[],
 	 */
 	Flag(FBRACEEXPAND) = 1;
 
+#if 1
+	/*
+	 * Turn on lastpipe by default ??
+	 * If set the shell runs the last command of a pipeline  not
+	 * executed in the background in the current shell environment.
+	 */
+	Flag(FLASTPIPE) = 1;
+#endif
+
 	/*
 	 * Turn on "set -x" inheritance by default.
 	 */
--- mksh/mksh.1
+++ mksh/mksh.1	2017-03-27 10:58:39.0000000 +0000
@@ -4291,6 +4291,9 @@ Do not reset
 .Fl o Ic xtrace
 upon entering functions.
 This is enabled by default.
+.It Fl o Ic lastpipe
+If set the shell runs the last command of a pipeline not executed in the
+background in the current shell environment.
 .It Fl o Ic nohup
 Do not kill running jobs with a
 .Dv SIGHUP
--- mksh/sh.h
+++ mksh/sh.h	2017-03-27 10:47:08.000000000 +0000
@@ -1653,6 +1653,7 @@ struct op {
 #define TTIME		20	/* time pipeline */
 #define TEXEC		21	/* fork/exec eval'd TCOM */
 #define TCOPROC		22	/* coprocess |& */
+#define TLPIPE		23	/* last in pipe chain  */
 
 /*
  * prefix codes for words in command tree
@@ -1714,6 +1715,7 @@ struct ioword {
 #define XCOPROC BIT(9)		/* starting a co-process */
 #define XTIME	BIT(10)		/* timing TCOM command */
 #define XPIPEST	BIT(11)		/* want PIPESTATUS */
+#define XPIPELS	BIT(12)		/* Last element in pipe chain */
 
 /*
  * flags to control expansion of words (assumed by t->evalflags to fit
@@ -2142,6 +2144,7 @@ void j_init(void);
 void j_exit(void);
 #ifndef MKSH_UNEMPLOYED
 void j_change(void);
+void j_restore(int);
 #endif
 int exchild(struct op *, int, volatile int *, int);
 void startlast(void);
--- mksh/sh_flags.opt
+++ mksh/sh_flags.opt	2017-03-27 10:40:06.000000000 +0000
@@ -79,6 +79,10 @@ FN("interactive", FTALKING, OF_CMDLINE
 >k|
 FN("keyword", FKEYWORD, OF_ANY
 
+/* ./.	if set the shell runs the last command of a pipeline not executed in the background in the current shell environment */
+>|
+FN("lastpipe", FLASTPIPE, OF_ANY
+
 /* -l	login shell */
 >l|!SHFLAGS_NOT_CMD
 FN("login", FLOGIN, OF_CMDLINE

Attachment: signature.asc
Description: PGP signature

Reply via email to