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)
From e63ede983a138a3fc86fb51428b957dda1ae9157 Mon Sep 17 00:00:00 2001 Message-Id: <e63ede983a138a3fc86fb51428b957dda1ae9157.1673986875.git.stef...@sdaoden.eu> From: Steffen Nurpmeso <[email protected]> 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 <[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. 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 [email protected] http://lists.busybox.net/mailman/listinfo/busybox
