[v2 PATCH] jobs: Allow monitor mode without a tty in non-interactive mode

Herbert Xu <[email protected]>
Newsgroups org.kernel.vger.dash
Message-ID <[email protected]>
On Mon, Jan 30, 2023 at 10:15:40PM +0100, Steffen Nurpmeso wrote:
> This is a take-over of the FreeBSD bin/sh
> 
>   commit cd60e2c67d52e1f957841af19128c7227880743a
>   Author:     Jilles Tjoelker <[email protected]>
>   AuthorDate: 2014-09-04 21:48:33 +0000
>   Commit:     Jilles Tjoelker <[email protected]>
>   CommitDate: 2014-09-04 21:48:33 +0000
> 
>       sh: Allow enabling job control without a tty in non-interactive mode.
> 
>       If no tty is available, 'set -m' is still useful to put jobs in their own
>       process groups.
> ---
> 
> Dear Ganael, it seems it requires an inline patch?
> Let me try this -- thanks!!
> Ciao.
> 
>  src/jobs.c | 114 +++++++++++++++++++++++++++++++----------------------
>  1 file changed, 67 insertions(+), 47 deletions(-)

Thanks for the patch.  I've rewritten it to minimise the impact.
However, the end result should be fairly similar.

Please test this and let me know if there are any issues.

---8<---
When a tty is unavailable, or the shell is in the background,
job control could still be used for the purpose of setting
process groups.

This is based on work by Jilles Tjoelker from FreeBSD and Steffen
Nurpmeso.

Reported-by: Steffen Nurpmeso <[email protected]>
Reported-by: Ganael Laplanche <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>

diff --git a/src/jobs.c b/src/jobs.c
index a0f4d47..2a2fe22 100644
--- a/src/jobs.c
+++ b/src/jobs.c
@@ -187,11 +187,21 @@ set_curjob(struct job *jp, unsigned mode)
 
 int jobctl;
 
+static void xxtcsetpgrp(pid_t pgrp)
+{
+	int fd = ttyfd;
+
+	if (fd < 0)
+		return;
+
+	xtcsetpgrp(fd, pgrp);
+}
+
 void
 setjobctl(int on)
 {
+	int pgrp = -1;
 	int fd;
-	int pgrp;
 
 	if (on == jobctl || rootshell == 0)
 		return;
@@ -207,36 +217,43 @@ setjobctl(int on)
 		fd = savefd(fd, ofd);
 		do { /* while we are in the background */
 			if ((pgrp = tcgetpgrp(fd)) < 0) {
+close:
+				close(fd);
+				fd = -1;
 out:
+				if (!iflag)
+					break;
 				sh_warnx("can't access tty; job control turned off");
 				mflag = on = 0;
-				goto close;
+				return;
 			}
 			if (pgrp == getpgrp())
 				break;
+			if (!iflag)
+				goto close;
 			killpg(0, SIGTTIN);
 		} while (1);
 		initialpgrp = pgrp;
-
-		setsignal(SIGTSTP);
-		setsignal(SIGTTOU);
-		setsignal(SIGTTIN);
 		pgrp = rootpid;
-		setpgid(0, pgrp);
-		xtcsetpgrp(fd, pgrp);
 	} else {
 		/* turning job control off */
 		fd = ttyfd;
 		pgrp = initialpgrp;
-		xtcsetpgrp(fd, pgrp);
-		setpgid(0, pgrp);
-		setsignal(SIGTSTP);
-		setsignal(SIGTTOU);
-		setsignal(SIGTTIN);
-close:
-		close(fd);
-		fd = -1;
 	}
+
+	setsignal(SIGTSTP);
+	setsignal(SIGTTOU);
+	setsignal(SIGTTIN);
+	if (fd >= 0) {
+		setpgid(0, pgrp);
+		xtcsetpgrp(fd, pgrp);
+
+		if (!on) {
+			close(fd);
+			fd = -1;
+		}
+	}
+
 	ttyfd = fd;
 	jobctl = on;
 }
@@ -391,7 +408,7 @@ restartjob(struct job *jp, int mode)
 	jp->state = JOBRUNNING;
 	pgid = jp->ps->pid;
 	if (mode == FORK_FG)
-		xtcsetpgrp(ttyfd, pgid);
+		xxtcsetpgrp(pgid);
 	killpg(pgid, SIGCONT);
 	ps = jp->ps;
 	i = jp->nprocs;
@@ -874,7 +891,7 @@ static void forkchild(struct job *jp, union node *n, int mode)
 		/* This can fail because we are doing it in the parent also */
 		(void)setpgid(0, pgrp);
 		if (mode == FORK_FG)
-			xtcsetpgrp(ttyfd, pgrp);
+			xxtcsetpgrp(pgrp);
 		setsignal(SIGTSTP);
 		setsignal(SIGTTOU);
 	} else
@@ -1014,7 +1031,7 @@ waitforjob(struct job *jp)
 	st = getstatus(jp);
 #if JOBS
 	if (jp->jobctl) {
-		xtcsetpgrp(ttyfd, rootpid);
+		xxtcsetpgrp(rootpid);
 		/*
 		 * This is truly gross.
 		 * If we're doing job control, then we did a TIOCSPGRP which
-- 
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.