about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2003-03-07 12:17:49 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2003-03-07 12:17:49 +0000
commita7dc5d386cb46ba7fc3fec583442d63c1cee4f75 (patch)
treee25b14241c7f62f317916b539450077d0279a08f
parent1c300357f50b3786b3086b6d729bdef1abac7e08 (diff)
downloadzsh-a7dc5d386cb46ba7fc3fec583442d63c1cee4f75.tar.gz
zsh-a7dc5d386cb46ba7fc3fec583442d63c1cee4f75.tar.xz
zsh-a7dc5d386cb46ba7fc3fec583442d63c1cee4f75.zip
18319: Philippe Troin: fix use of process groups with su and suspend
-rw-r--r--ChangeLog7
-rw-r--r--Src/exec.c24
-rw-r--r--Src/init.c34
-rw-r--r--Src/jobs.c76
4 files changed, 92 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index 5b5f1098f..fdfe13e78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2003-03-07  Peter Stephenson  <pws@csr.com>
+
+	* 18319: Philippe Troin: Src/exec.c, Src/init.c, Src/jobs.c:
+	Fix various process group problems associated with certain
+	versions of `su'.  In particular, this improves `suspend'
+	behaviour.
+
 2003-03-06  Doug Kearns  <djkea2@mugca.its.monash.edu.au>
 
 	* 18314: Completion/Unix/Command/_ruby: allow -I, -r, -e and script
diff --git a/Src/exec.c b/Src/exec.c
index 978470251..289c7b1fd 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1149,7 +1149,7 @@ execpline(Estate state, wordcode slcode, int how, int last1)
 		    }
 		    else {
 			close(synch[0]);
-			entersubsh(Z_ASYNC, 0, 0);
+			entersubsh(Z_ASYNC, 0, 0, 0);
 			if (jobtab[list_pipe_job].procs) {
 			    if (setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader)
 				== -1) {
@@ -1258,7 +1258,7 @@ execpline2(Estate state, wordcode pcode,
 	    } else {
 		zclose(pipes[0]);
 		close(synch[0]);
-		entersubsh(how, 2, 0);
+		entersubsh(how, 2, 0, 0);
 		close(synch[1]);
 		execcmd(state, input, pipes[1], how, 0);
 		_exit(lastval);
@@ -2060,7 +2060,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
 	}
 	/* pid == 0 */
 	close(synch[0]);
-	entersubsh(how, (type != WC_SUBSH) && !(how & Z_ASYNC) ? 2 : 1, 0);
+	entersubsh(how, (type != WC_SUBSH) && !(how & Z_ASYNC) ? 2 : 1, 0, 0);
 	close(synch[1]);
 	forked = 1;
 	if (sigtrapped[SIGINT] & ZSIG_IGNORED)
@@ -2277,7 +2277,9 @@ execcmd(Estate state, int input, int output, int how, int last1)
 	 * exit) in case there is an error return.
 	 */
 	if (is_exec)
-	    entersubsh(how, (type != WC_SUBSH) ? 2 : 1, 1);
+	    entersubsh(how, (type != WC_SUBSH) ? 2 : 1, 1,
+		       (do_exec || (type >= WC_CURSH && last1 == 1)) 
+		       && !forked);
 	if (type >= WC_CURSH) {
 	    if (last1 == 1)
 		do_exec = 1;
@@ -2536,7 +2538,7 @@ forklevel;
 
 /**/
 static void
-entersubsh(int how, int cl, int fake)
+entersubsh(int how, int cl, int fake, int revertpgrp)
 {
     int sig, monitor;
 
@@ -2580,6 +2582,8 @@ entersubsh(int how, int cl, int fake)
     }
     if (!fake)
 	subsh = 1;
+    if (revertpgrp && getpid() == mypgrp)
+	release_pgrp();
     if (SHTTY != -1) {
 	shout = NULL;
 	zclose(SHTTY);
@@ -2769,7 +2773,7 @@ getoutput(char *cmd, int qt)
     zclose(pipes[0]);
     redup(pipes[1], 1);
     opts[MONITOR] = 0;
-    entersubsh(Z_SYNC, 1, 0);
+    entersubsh(Z_SYNC, 1, 0, 0);
     cmdpush(CS_CMDSUBST);
     execode(prog, 0, 1);
     cmdpop();
@@ -2900,7 +2904,7 @@ getoutputfile(char *cmd)
     /* pid == 0 */
     redup(fd, 1);
     opts[MONITOR] = 0;
-    entersubsh(Z_SYNC, 1, 0);
+    entersubsh(Z_SYNC, 1, 0, 0);
     cmdpush(CS_CMDSUBST);
     execode(prog, 0, 1);
     cmdpop();
@@ -2980,10 +2984,10 @@ getproc(char *cmd)
 	zerr("can't open %s: %e", pnam, errno);
 	_exit(1);
     }
-    entersubsh(Z_ASYNC, 1, 0);
+    entersubsh(Z_ASYNC, 1, 0, 0);
     redup(fd, out);
 #else
-    entersubsh(Z_ASYNC, 1, 0);
+    entersubsh(Z_ASYNC, 1, 0, 0);
     redup(pipes[out], out);
     closem(0);   /* this closes pipes[!out] as well */
 #endif
@@ -3012,7 +3016,7 @@ getpipe(char *cmd)
 	zclose(pipes[out]);
 	return pipes[!out];
     }
-    entersubsh(Z_ASYNC, 1, 0);
+    entersubsh(Z_ASYNC, 1, 0, 0);
     redup(pipes[out], out);
     closem(0);	/* this closes pipes[!out] as well */
     cmdpush(CS_CMDSUBST);
diff --git a/Src/init.c b/Src/init.c
index 939c4619f..2118a5f5f 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -354,7 +354,6 @@ printhelp(void)
 mod_export void
 init_io(void)
 {
-    long ttpgrp;
     static char outbuf[BUFSIZ], errbuf[BUFSIZ];
 
 #ifdef RSH_BUG_WORKAROUND
@@ -462,37 +461,8 @@ init_io(void)
      */
     mypid = (zlong)getpid();
     if (opts[MONITOR] && interact && (SHTTY != -1)) {
-	if ((mypgrp = GETPGRP()) > 0) {
-	    sigset_t blockset, oldset;
-	    sigemptyset(&blockset);
-	    sigaddset(&blockset, SIGTTIN);
-	    sigaddset(&blockset, SIGTTOU);
-	    sigaddset(&blockset, SIGTSTP);
-	    oldset = signal_block(blockset);
-	    while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) {
-		mypgrp = GETPGRP();
-		if (mypgrp == mypid) {
-		    signal_setmask(oldset);
-		    attachtty(mypgrp); /* Might generate SIGT* */
-		    signal_block(blockset);
-		}
-		if (mypgrp == gettygrp())
-		    break;
-		signal_setmask(oldset);
-		read(0, NULL, 0); /* Might generate SIGT* */
-		signal_block(blockset);
-		mypgrp = GETPGRP();
-	    }
-	    if (mypgrp != mypid) {
-	        if (setpgrp(0, 0) == 0) {
-		    mypgrp = mypid;
-		    attachtty(mypgrp);
-                } else
-		    opts[MONITOR] = 0;
-	    }
-	    signal_setmask(oldset);
-	} else
-	    opts[MONITOR] = 0;
+	origpgrp = GETPGRP();
+        acquire_pgrp(); /* might also clear opts[MONITOR] */
     } else
 	opts[MONITOR] = 0;
 #else
diff --git a/Src/jobs.c b/Src/jobs.c
index fba7fd26e..359e1564e 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -30,6 +30,12 @@
 #include "zsh.mdh"
 #include "jobs.pro"
 
+/* the process group of the shell at startup (equal to mypgprp, except
+   when we started without being process group leader */
+
+/**/
+mod_export pid_t origpgrp;
+
 /* the process group of the shell */
 
 /**/
@@ -1663,16 +1669,16 @@ bin_suspend(char *name, char **argv, Options ops, int func)
 	signal_default(SIGTTIN);
 	signal_default(SIGTSTP);
 	signal_default(SIGTTOU);
+
+	/* Move ourselves back to the process group we came from */
+	release_pgrp();
     }
+
     /* suspend ourselves with a SIGTSTP */
-    kill(0, SIGTSTP);
+    killpg(origpgrp, SIGTSTP);
+
     if (jobbing) {
-	/* stay suspended */
-	while (gettygrp() != mypgrp) {
-	    sleep(1);
-	    if (gettygrp() != mypgrp)
-		kill(0, SIGTTIN);
-	}
+	acquire_pgrp();
 	/* restore signal handling */
 	signal_ignore(SIGTTOU);
 	signal_ignore(SIGTSTP);
@@ -1696,3 +1702,59 @@ findjobnam(char *s)
 	    return jobnum;
     return -1;
 }
+
+
+/* make sure we are a process group leader by creating a new process
+   group if necessary */
+
+/**/
+void
+acquire_pgrp(void)
+{
+    long ttpgrp;
+    sigset_t blockset, oldset;
+
+    if ((mypgrp = GETPGRP()) > 0) {
+	sigemptyset(&blockset);
+	sigaddset(&blockset, SIGTTIN);
+	sigaddset(&blockset, SIGTTOU);
+	sigaddset(&blockset, SIGTSTP);
+	oldset = signal_block(blockset);
+	while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) {
+	    mypgrp = GETPGRP();
+	    if (mypgrp == mypid) {
+		signal_setmask(oldset);
+		attachtty(mypgrp); /* Might generate SIGT* */
+		signal_block(blockset);
+	    }
+	    if (mypgrp == gettygrp())
+		break;
+	    signal_setmask(oldset);
+	    read(0, NULL, 0); /* Might generate SIGT* */
+	    signal_block(blockset);
+	    mypgrp = GETPGRP();
+	}
+	if (mypgrp != mypid) {
+	    if (setpgrp(0, 0) == 0) {
+		mypgrp = mypid;
+		attachtty(mypgrp);
+	    } else
+		opts[MONITOR] = 0;
+	}
+	signal_setmask(oldset);
+    } else
+	opts[MONITOR] = 0;
+}
+
+/* revert back to the process group we came from (before acquire_pgrp) */
+
+/**/
+void
+release_pgrp(void)
+{
+    if (origpgrp != mypgrp) {
+	attachtty(origpgrp);
+	setpgrp(0, origpgrp);
+	mypgrp = origpgrp;
+    }
+}