Skip site navigation (1)Skip section navigation (2)
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>