summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
+ }
+}