Date: Thu, 4 Sep 2014 21:48:34 +0000 (UTC) From: Jilles Tjoelker <jilles@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271144 - head/bin/sh Message-ID: <201409042148.s84LmYe7072285@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jilles Date: Thu Sep 4 21:48:33 2014 New Revision: 271144 URL: http://svnweb.freebsd.org/changeset/base/271144 Log: 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. Modified: head/bin/sh/jobs.c head/bin/sh/sh.1 Modified: head/bin/sh/jobs.c ============================================================================== --- head/bin/sh/jobs.c Thu Sep 4 21:48:33 2014 (r271143) +++ head/bin/sh/jobs.c Thu Sep 4 21:48:33 2014 (r271144) @@ -118,6 +118,24 @@ static void showjob(struct job *, int); static int jobctl; #if JOBS +static void +jobctl_notty(void) +{ + if (ttyfd >= 0) { + close(ttyfd); + ttyfd = -1; + } + if (!iflag) { + setsignal(SIGTSTP); + setsignal(SIGTTOU); + setsignal(SIGTTIN); + jobctl = 1; + return; + } + out2fmt_flush("sh: can't access tty; job control turned off\n"); + mflag = 0; +} + void setjobctl(int on) { @@ -133,8 +151,10 @@ setjobctl(int on) while (i <= 2 && !isatty(i)) i++; if (i > 2 || - (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) - goto out; + (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) { + jobctl_notty(); + return; + } } if (ttyfd < 10) { /* @@ -142,9 +162,8 @@ setjobctl(int on) * the user's redirections. */ if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) { - close(ttyfd); - ttyfd = -1; - goto out; + jobctl_notty(); + return; } close(ttyfd); ttyfd = i; @@ -152,11 +171,15 @@ setjobctl(int on) do { /* while we are in the background */ initialpgrp = tcgetpgrp(ttyfd); if (initialpgrp < 0) { -out: out2fmt_flush("sh: can't access tty; job control turned off\n"); - mflag = 0; + jobctl_notty(); return; } if (initialpgrp != getpgrp()) { + if (!iflag) { + initialpgrp = -1; + jobctl_notty(); + return; + } kill(0, SIGTTIN); continue; } @@ -168,9 +191,11 @@ out: out2fmt_flush("sh: can't access tcsetpgrp(ttyfd, rootpid); } else { /* turning job control off */ setpgid(0, initialpgrp); - tcsetpgrp(ttyfd, initialpgrp); - close(ttyfd); - ttyfd = -1; + if (ttyfd >= 0) { + tcsetpgrp(ttyfd, initialpgrp); + close(ttyfd); + ttyfd = -1; + } setsignal(SIGTSTP); setsignal(SIGTTOU); setsignal(SIGTTIN); @@ -195,7 +220,8 @@ fgcmd(int argc __unused, char **argv __u printjobcmd(jp); flushout(&output); pgrp = jp->ps[0].pid; - tcsetpgrp(ttyfd, pgrp); + if (ttyfd >= 0) + tcsetpgrp(ttyfd, pgrp); restartjob(jp); jp->foreground = 1; INTOFF; @@ -847,7 +873,8 @@ forkshell(struct job *jp, union node *n, pgrp = getpid(); else pgrp = jp->ps[0].pid; - if (setpgid(0, pgrp) == 0 && mode == FORK_FG) { + if (setpgid(0, pgrp) == 0 && mode == FORK_FG && + ttyfd >= 0) { /*** this causes superfluous TIOCSPGRPS ***/ if (tcsetpgrp(ttyfd, pgrp) < 0) error("tcsetpgrp failed, errno=%d", errno); @@ -1007,7 +1034,7 @@ waitforjob(struct job *jp, int *origstat dotrap(); #if JOBS if (jp->jobctl) { - if (tcsetpgrp(ttyfd, rootpid) < 0) + if (ttyfd >= 0 && tcsetpgrp(ttyfd, rootpid) < 0) error("tcsetpgrp failed, errno=%d\n", errno); } if (jp->state == JOBSTOPPED) Modified: head/bin/sh/sh.1 ============================================================================== --- head/bin/sh/sh.1 Thu Sep 4 21:48:33 2014 (r271143) +++ head/bin/sh/sh.1 Thu Sep 4 21:48:33 2014 (r271144) @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd January 26, 2014 +.Dd September 4, 2014 .Dt SH 1 .Os .Sh NAME @@ -259,6 +259,12 @@ from input when in interactive mode. Force the shell to behave interactively. .It Fl m Li monitor Turn on job control (set automatically when interactive). +A new process group is created for each pipeline (called a job). +It is possible to suspend jobs or to have them run in the foreground or +in the background. +In a non-interactive shell, +this option can be set even if no terminal is available +and is useful to place processes in separate process groups. .It Fl n Li noexec If not interactive, read commands but do not execute them.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409042148.s84LmYe7072285>