diff options
author | Peter Stephenson <pws@users.sourceforge.net> | 2003-03-07 12:17:49 +0000 |
---|---|---|
committer | Peter Stephenson <pws@users.sourceforge.net> | 2003-03-07 12:17:49 +0000 |
commit | a7dc5d386cb46ba7fc3fec583442d63c1cee4f75 (patch) | |
tree | e25b14241c7f62f317916b539450077d0279a08f | |
parent | 1c300357f50b3786b3086b6d729bdef1abac7e08 (diff) | |
download | zsh-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-- | ChangeLog | 7 | ||||
-rw-r--r-- | Src/exec.c | 24 | ||||
-rw-r--r-- | Src/init.c | 34 | ||||
-rw-r--r-- | Src/jobs.c | 76 |
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; + } +} |