[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: ash: support "set -m" monitor mode even when not interactive
From: Steffen Nurpmeso <steffen () sdaoden ! eu>
Date: 2023-01-17 20:27:31
Message-ID: 20230117202731.6q006%steffen () sdaoden ! eu
[Download RAW message or body]
Hello.
This came up on the dash list, and so i took over Jilles
Tjoelker's FreeBSD commit from 2014 to busybox ash.
Note i have no idea of what i am doing, but from testing it seems
to work; i have simply taken it over, which is a cleanup really.
(This is on top of my arithmetic patch but it should not really
interfere, .. in case linenumber shifts are seen.)
Ciao!
--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)
["ash_monitor_non_imode.patch" (text/x-diff)]
From e63ede983a138a3fc86fb51428b957dda1ae9157 Mon Sep 17 00:00:00 2001
Message-Id: <e63ede983a138a3fc86fb51428b957dda1ae9157.1673986875.git.steffen@sdaoden.eu>
From: Steffen Nurpmeso <steffen@sdaoden.eu>
Date: Tue, 17 Jan 2023 21:07:07 +0100
Subject: [PATCH] ash: Allow enabling job control without a tty in
non-interactive mode..
This is a take-over of the FreeBSD bin/sh
commit cd60e2c67d52e1f957841af19128c7227880743a
Author: Jilles Tjoelker <jilles@FreeBSD.org>
AuthorDate: 2014-09-04 21:48:33 +0000
Commit: Jilles Tjoelker <jilles@FreeBSD.org>
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.
and makes a script of
#!/bin/bash
#!/tmp/busybox ash
set -m
(
echo >&2 "inner shell has: $(ps -o pid,pgid $$ | tail -n1)"
) &
echo >&2 "outer shell has: $(ps -o pid,pgid $$ | tail -n1)"
echo >&2 "x is $$, job is $!: $(ps -o pid,pgid $! | tail -n1)"
behave identical (including $(|) pipe races) when invoked in the
background via "./SCRIPT &".
---
shell/ash.c | 135 +++++++++++++++++++++++++++++++---------------------
1 file changed, 80 insertions(+), 55 deletions(-)
diff --git a/shell/ash.c b/shell/ash.c
index 342cbadd92..b9eb0bfc86 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -4058,9 +4058,9 @@ freejob(struct job *jp)
#if JOBS
static void
-xtcsetpgrp(int fd, pid_t pgrp)
+xtcsetpgrp(pid_t pgrp)
{
- if (tcsetpgrp(fd, pgrp))
+ if (ttyfd >= 0 && tcsetpgrp(ttyfd, pgrp))
ash_msg_and_raise_perror("can't set tty process group");
}
@@ -4074,71 +4074,93 @@ xtcsetpgrp(int fd, pid_t pgrp)
* Called with interrupts off.
*/
static void
+jobctl_notty(void)
+{
+ if (ttyfd >= 0) {
+ close(ttyfd);
+ ttyfd = -1;
+ }
+ if (!iflag) {
+ /* Allow enabling job control without a tty in non-interactive mode.
+ * 'set -m' is still useful to create per-job process groups */
+ setsignal(SIGTSTP);
+ setsignal(SIGTTOU);
+ setsignal(SIGTTIN);
+ doing_jobctl = 1;
+ return;
+ }
+ ash_msg("can't access tty; job control turned off");
+ mflag = 0;
+}
+
+void
setjobctl(int on)
{
- int fd;
- int pgrp;
+ int i;
if (on == doing_jobctl || rootshell == 0)
return;
if (on) {
- int ofd;
- ofd = fd = open(_PATH_TTY, O_RDWR);
- if (fd < 0) {
- /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
- * That sometimes helps to acquire controlling tty.
- * Obviously, a workaround for bugs when someone
- * failed to provide a controlling tty to bash! :) */
- fd = 2;
- while (!isatty(fd))
- if (--fd < 0)
- goto out;
- }
- /* fd is a tty at this point */
- fd = fcntl(fd, F_DUPFD_CLOEXEC, 10);
- if (ofd >= 0) /* if it is "/dev/tty", close. If 0/1/2, don't */
- close(ofd);
- if (fd < 0)
- goto out; /* F_DUPFD failed */
- if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
- close_on_exec_on(fd);
- while (1) { /* while we are in the background */
- pgrp = tcgetpgrp(fd);
- if (pgrp < 0) {
- out:
- ash_msg("can't access tty; job control turned off");
- mflag = on = 0;
- goto close;
+ if (ttyfd != -1)
+ close(ttyfd);
+ if ((ttyfd = open(_PATH_TTY, O_RDWR)) < 0) {
+ i = 0;
+ while (i <= 2 && !isatty(i))
+ i++;
+ if (i > 2 ||
+ (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) {
+ jobctl_notty();
+ return;
}
- if (pgrp == getpgrp())
- break;
- killpg(0, SIGTTIN);
}
- initialpgrp = pgrp;
-
+ if (ttyfd < 10) {
+ /*
+ * Keep our TTY file descriptor out of the way of
+ * the user's redirections.
+ */
+ if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) {
+ jobctl_notty();
+ return;
+ }
+ close(ttyfd);
+ ttyfd = i;
+ }
+ if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
+ close_on_exec_on(ttyfd);
+ do { /* while we are in the background */
+ initialpgrp = tcgetpgrp(ttyfd);
+ if (initialpgrp < 0) {
+ jobctl_notty();
+ return;
+ }
+ if (initialpgrp != getpgrp()) {
+ if (!iflag) {
+ initialpgrp = -1;
+ jobctl_notty();
+ return;
+ }
+ kill(0, SIGTTIN);
+ continue;
+ }
+ } while (0);
setsignal(SIGTSTP);
setsignal(SIGTTOU);
setsignal(SIGTTIN);
- pgrp = rootpid;
- setpgid(0, pgrp);
- xtcsetpgrp(fd, pgrp);
- } else {
- /* turning job control off */
- fd = ttyfd;
- pgrp = initialpgrp;
- /* was xtcsetpgrp, but this can make exiting ash
- * loop forever if pty is already deleted */
- tcsetpgrp(fd, pgrp);
- setpgid(0, pgrp);
+ setpgid(0, rootpid);
+ xtcsetpgrp(rootpid);
+ } else { /* turning job control off */
+ setpgid(0, initialpgrp);
+ if (ttyfd >= 0) {
+ /* was xtcsetpgrp, but this can make exiting ash loop forever if
+ * pty is already deleted */
+ tcsetpgrp(ttyfd, initialpgrp);
+ close(ttyfd);
+ ttyfd = -1;
+ }
setsignal(SIGTSTP);
setsignal(SIGTTOU);
setsignal(SIGTTIN);
- close:
- if (fd >= 0)
- close(fd);
- fd = -1;
}
- ttyfd = fd;
doing_jobctl = on;
}
@@ -4225,7 +4247,7 @@ restartjob(struct job *jp, int mode)
pgid = jp->ps[0].ps_pid;
if (mode == FORK_FG) {
get_tty_state();
- xtcsetpgrp(ttyfd, pgid);
+ xtcsetpgrp(pgid);
}
killpg(pgid, SIGCONT);
ps = jp->ps;
@@ -4492,6 +4514,9 @@ showjob(struct job *jp, int mode)
char s[16 + 16 + 48];
FILE *out = (mode & SHOW_STDERR ? stderr : stdout);
+ if (!iflag)
+ return;
+
ps = jp->ps;
if (mode & SHOW_ONLY_PGID) { /* jobs -p */
@@ -5250,7 +5275,7 @@ forkchild(struct job *jp, union node *n, int mode)
/* this can fail because we are doing it in the parent also */
setpgid(0, pgrp);
if (mode == FORK_FG)
- xtcsetpgrp(ttyfd, pgrp);
+ xtcsetpgrp(pgrp);
setsignal(SIGTSTP);
setsignal(SIGTTOU);
} else
@@ -5421,7 +5446,7 @@ waitforjob(struct job *jp)
st = getstatus(jp);
#if JOBS
if (jp->jobctl) {
- xtcsetpgrp(ttyfd, rootpid);
+ xtcsetpgrp(rootpid);
restore_tty_if_stopped_or_signaled(jp);
/*
--
2.39.0
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic