introduce MKSH_NOPROSPECTOFWORK which is like pdksh’s JOB_SIGS in reverse, like MKSH_UNEMPLOYED is pdksh’s JOBS in reverse; allows mksh to work (hah! no pun intended…) with klibc (and possibly, Syllable Desktop and Plan 9) for now, until they fix their bugs

This commit is contained in:
tg
2011-01-30 01:35:35 +00:00
parent 07889fb0eb
commit bdfcdc56c8
5 changed files with 206 additions and 77 deletions

View File

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.467 2011/01/29 19:07:15 tg Exp $' srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.468 2011/01/30 01:35:29 tg Exp $'
#- #-
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
# Thorsten Glaser <tg@mirbsd.org> # Thorsten Glaser <tg@mirbsd.org>
@ -31,6 +31,7 @@ srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.467 2011/01/29 19:07:15 tg Exp $'
# MKSH_UNEMPLOYED MKSH_DEFAULT_EXECSHELL MKSHRC_PATH # MKSH_UNEMPLOYED MKSH_DEFAULT_EXECSHELL MKSHRC_PATH
# MKSH_DEFAULT_TMPDIR MKSH_CLRTOEOL_STRING MKSH_A4PB # MKSH_DEFAULT_TMPDIR MKSH_CLRTOEOL_STRING MKSH_A4PB
# MKSH_NO_DEPRECATED_WARNING MKSH_DONT_EMIT_IDSTRING # MKSH_NO_DEPRECATED_WARNING MKSH_DONT_EMIT_IDSTRING
# MKSH_NOPROSPECTOFWORK
LC_ALL=C LC_ALL=C
export LC_ALL export LC_ALL
@ -1061,6 +1062,9 @@ ac_ifcpp 'ifdef MKSH_BINSHREDUCED' isset_MKSH_BINSHREDUCED '' \
ac_ifcpp 'ifdef MKSH_UNEMPLOYED' isset_MKSH_UNEMPLOYED '' \ ac_ifcpp 'ifdef MKSH_UNEMPLOYED' isset_MKSH_UNEMPLOYED '' \
"if mksh will be built without job control" && \ "if mksh will be built without job control" && \
check_categories=$check_categories,arge check_categories=$check_categories,arge
ac_ifcpp 'ifdef MKSH_NOPROSPECTOFWORK' isset_MKSH_NOPROSPECTOFWORK '' \
"if mksh will be built without job signals" && \
check_categories=$check_categories,arge,nojsig
ac_ifcpp 'ifdef MKSH_ASSUME_UTF8' isset_MKSH_ASSUME_UTF8 '' \ ac_ifcpp 'ifdef MKSH_ASSUME_UTF8' isset_MKSH_ASSUME_UTF8 '' \
'if the default UTF-8 mode is specified' && : ${HAVE_SETLOCALE_CTYPE=0} 'if the default UTF-8 mode is specified' && : ${HAVE_SETLOCALE_CTYPE=0}
ac_ifcpp 'ifdef MKSH_CONSERVATIVE_FDS' isset_MKSH_CONSERVATIVE_FDS '' \ ac_ifcpp 'ifdef MKSH_CONSERVATIVE_FDS' isset_MKSH_CONSERVATIVE_FDS '' \

View File

@ -1,4 +1,4 @@
# $MirOS: src/bin/mksh/check.t,v 1.401 2011/01/22 20:33:11 tg Exp $ # $MirOS: src/bin/mksh/check.t,v 1.402 2011/01/30 01:35:32 tg Exp $
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
@ -5193,6 +5193,7 @@ expected-stdout:
name: pipeline-2 name: pipeline-2
description: description:
check that co-processes work with TCOMs, TPIPEs and TPARENs check that co-processes work with TCOMs, TPIPEs and TPARENs
category: !nojsig
stdin: stdin:
"$__progname" -c 'i=100; echo hi |& while read -p line; do echo "$((i++)) $line"; done' "$__progname" -c 'i=100; echo hi |& while read -p line; do echo "$((i++)) $line"; done'
"$__progname" -c 'i=200; echo hi | cat |& while read -p line; do echo "$((i++)) $line"; done' "$__progname" -c 'i=200; echo hi | cat |& while read -p line; do echo "$((i++)) $line"; done'

69
exec.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.84 2011/01/09 21:57:25 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/exec.c,v 1.85 2011/01/30 01:35:33 tg Exp $");
#ifndef MKSH_DEFAULT_EXECSHELL #ifndef MKSH_DEFAULT_EXECSHELL
#define MKSH_DEFAULT_EXECSHELL "/bin/sh" #define MKSH_DEFAULT_EXECSHELL "/bin/sh"
@ -114,14 +114,17 @@ execute(struct op * volatile t,
afree(cp, APERM); afree(cp, APERM);
} }
/* Clear subst_exstat before argument expansion. Used by /*
* Clear subst_exstat before argument expansion. Used by
* null commands (see comexec() and c_eval()) and by c_set(). * null commands (see comexec() and c_eval()) and by c_set().
*/ */
subst_exstat = 0; subst_exstat = 0;
current_lineno = t->lineno; /* for $LINENO */ /* for $LINENO */
current_lineno = t->lineno;
/* POSIX says expand command words first, then redirections, /*
* POSIX says expand command words first, then redirections,
* and assignments last.. * and assignments last..
*/ */
up = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE); up = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE);
@ -153,7 +156,8 @@ execute(struct op * volatile t,
for (iowp = t->ioact; *iowp != NULL; iowp++) { for (iowp = t->ioact; *iowp != NULL; iowp++) {
if (iosetup(*iowp, tp) < 0) { if (iosetup(*iowp, tp) < 0) {
exstat = rv = 1; exstat = rv = 1;
/* Redirection failures for special commands /*
* Redirection failures for special commands
* cause (non-interactive) shell to exit. * cause (non-interactive) shell to exit.
*/ */
if (tp && tp->type == CSHELL && if (tp && tp->type == CSHELL &&
@ -180,7 +184,8 @@ execute(struct op * volatile t,
e->savefd[1] = savefd(1); e->savefd[1] = savefd(1);
while (t->type == TPIPE) { while (t->type == TPIPE) {
openpipe(pv); openpipe(pv);
ksh_dup2(pv[1], 1, false); /* stdout of curr */ /* stdout of curr */
ksh_dup2(pv[1], 1, false);
/** /**
* Let exchild() close pv[0] in child * Let exchild() close pv[0] in child
* (if this isn't done, commands like * (if this isn't done, commands like
@ -189,13 +194,16 @@ execute(struct op * volatile t,
*/ */
exchild(t->left, flags | XPIPEO | XCCLOSE, exchild(t->left, flags | XPIPEO | XCCLOSE,
NULL, pv[0]); NULL, pv[0]);
ksh_dup2(pv[0], 0, false); /* stdin of next */ /* stdin of next */
ksh_dup2(pv[0], 0, false);
closepipe(pv); closepipe(pv);
flags |= XPIPEI; flags |= XPIPEI;
t = t->right; t = t->right;
} }
restfd(1, e->savefd[1]); /* stdout of last */ /* stdout of last */
e->savefd[1] = 0; /* no need to re-restore this */ restfd(1, e->savefd[1]);
/* no need to re-restore this */
e->savefd[1] = 0;
/* Let exchild() close 0 in parent, after fork, before wait */ /* Let exchild() close 0 in parent, after fork, before wait */
i = exchild(t, flags | XPCLOSE, xerrok, 0); i = exchild(t, flags | XPCLOSE, xerrok, 0);
if (!(flags&XBGND) && !(flags&XXCOM)) if (!(flags&XBGND) && !(flags&XXCOM))
@ -211,9 +219,11 @@ execute(struct op * volatile t,
break; break;
case TCOPROC: { case TCOPROC: {
#ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
/* Block sigchild as we are using things changed in the /*
* Block sigchild as we are using things changed in the
* signal handler * signal handler
*/ */
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
@ -225,6 +235,7 @@ execute(struct op * volatile t,
unwind(i); unwind(i);
/* NOTREACHED */ /* NOTREACHED */
} }
#endif
/* Already have a (live) co-process? */ /* Already have a (live) co-process? */
if (coproc.job && coproc.write >= 0) if (coproc.job && coproc.write >= 0)
errorf("coprocess already exists"); errorf("coprocess already exists");
@ -250,15 +261,20 @@ execute(struct op * volatile t,
openpipe(pv); openpipe(pv);
coproc.read = pv[0]; coproc.read = pv[0];
ksh_dup2(pv[1], 1, false); ksh_dup2(pv[1], 1, false);
coproc.readw = pv[1]; /* closed before first read */ /* closed before first read */
coproc.readw = pv[1];
coproc.njobs = 0; coproc.njobs = 0;
/* create new coprocess id */ /* create new coprocess id */
++coproc.id; ++coproc.id;
} }
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
e->type = E_EXEC; /* no more need for error handler */ /* no more need for error handler */
e->type = E_EXEC;
#endif
/* exchild() closes coproc.* in child after fork, /*
* exchild() closes coproc.* in child after fork,
* will also increment coproc.njobs when the * will also increment coproc.njobs when the
* job is actually created. * job is actually created.
*/ */
@ -269,7 +285,8 @@ execute(struct op * volatile t,
} }
case TASYNC: case TASYNC:
/* XXX non-optimal, I think - "(foo &)", forks for (), /*
* XXX non-optimal, I think - "(foo &)", forks for (),
* forks again for async... parent should optimise * forks again for async... parent should optimise
* this to "foo &"... * this to "foo &"...
*/ */
@ -327,13 +344,15 @@ execute(struct op * volatile t,
goto Break; goto Break;
} }
} }
rv = 0; /* in case of a continue */ /* in case of a continue */
rv = 0;
if (t->type == TFOR) { if (t->type == TFOR) {
while (*ap != NULL) { while (*ap != NULL) {
setstr(global(t->str), *ap++, KSH_UNWIND_ERROR); setstr(global(t->str), *ap++, KSH_UNWIND_ERROR);
rv = execute(t->left, flags & XERROK, xerrok); rv = execute(t->left, flags & XERROK, xerrok);
} }
} else { /* TSELECT */ } else {
/* TSELECT */
for (;;) { for (;;) {
if (!(ccp = do_selectargs(ap, is_first))) { if (!(ccp = do_selectargs(ap, is_first))) {
rv = 1; rv = 1;
@ -363,7 +382,8 @@ execute(struct op * volatile t,
goto Break; goto Break;
} }
} }
rv = 0; /* in case of a continue */ /* in case of a continue */
rv = 0;
while ((execute(t->left, XERROK, NULL) == 0) == while ((execute(t->left, XERROK, NULL) == 0) ==
(t->type == TWHILE)) (t->type == TWHILE))
rv = execute(t->right, flags & XERROK, xerrok); rv = execute(t->right, flags & XERROK, xerrok);
@ -372,7 +392,8 @@ execute(struct op * volatile t,
case TIF: case TIF:
case TELIF: case TELIF:
if (t->right == NULL) if (t->right == NULL)
break; /* should be error */ /* should be error */
break;
rv = execute(t->left, XERROK, NULL) == 0 ? rv = execute(t->left, XERROK, NULL) == 0 ?
execute(t->right->left, flags & XERROK, xerrok) : execute(t->right->left, flags & XERROK, xerrok) :
execute(t->right->right, flags & XERROK, xerrok); execute(t->right->right, flags & XERROK, xerrok);
@ -399,13 +420,15 @@ execute(struct op * volatile t,
break; break;
case TTIME: case TTIME:
/* Clear XEXEC so nested execute() call doesn't exit /*
* Clear XEXEC so nested execute() call doesn't exit
* (allows "ls -l | time grep foo"). * (allows "ls -l | time grep foo").
*/ */
rv = timex(t, flags & ~XEXEC, xerrok); rv = timex(t, flags & ~XEXEC, xerrok);
break; break;
case TEXEC: /* an eval'd TCOM */ case TEXEC:
/* an eval'd TCOM */
s = t->args[0]; s = t->args[0];
up = makenv(); up = makenv();
restoresigs(); restoresigs();
@ -425,9 +448,11 @@ execute(struct op * volatile t,
Break: Break:
exstat = rv; exstat = rv;
quitenv(NULL); /* restores IO */ /* restores IO */
quitenv(NULL);
if ((flags&XEXEC)) if ((flags&XEXEC))
unwind(LEXIT); /* exit child */ /* exit child */
unwind(LEXIT);
if (rv != 0 && !(flags & XERROK) && if (rv != 0 && !(flags & XERROK) &&
(xerrok == NULL || !*xerrok)) { (xerrok == NULL || !*xerrok)) {
trapsig(SIGERR_); trapsig(SIGERR_);

197
jobs.c
View File

@ -22,7 +22,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.73 2011/01/21 21:04:44 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/jobs.c,v 1.74 2011/01/30 01:35:34 tg Exp $");
#if HAVE_KILLPG #if HAVE_KILLPG
#define mksh_killpg killpg #define mksh_killpg killpg
@ -124,8 +124,10 @@ static int32_t njobs; /* # of jobs started */
#define CHILD_MAX 25 #define CHILD_MAX 25
#endif #endif
#ifndef MKSH_NOPROSPECTOFWORK
/* held_sigchld is set if sigchld occurs before a job is completely started */ /* held_sigchld is set if sigchld occurs before a job is completely started */
static volatile sig_atomic_t held_sigchld; static volatile sig_atomic_t held_sigchld;
#endif
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
static struct shf *shl_j; static struct shf *shl_j;
@ -157,6 +159,7 @@ j_init(void)
Flag(FMONITOR) = 0; Flag(FMONITOR) = 0;
#endif #endif
#ifndef MKSH_NOPROSPECTOFWORK
(void)sigemptyset(&sm_default); (void)sigemptyset(&sm_default);
sigprocmask(SIG_SETMASK, &sm_default, NULL); sigprocmask(SIG_SETMASK, &sm_default, NULL);
@ -165,6 +168,10 @@ j_init(void)
setsig(&sigtraps[SIGCHLD], j_sigchld, setsig(&sigtraps[SIGCHLD], j_sigchld,
SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
#else
/* Make sure SIGCHLD isn't ignored - can do odd things under SYSV */
setsig(&sigtraps[SIGCHLD], SIG_DFL, SS_RESTORE_ORIG|SS_FORCE);
#endif
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
if (!mflagset && Flag(FTALKING)) if (!mflagset && Flag(FTALKING))
@ -205,8 +212,8 @@ void
j_exit(void) j_exit(void)
{ {
/* kill stopped, and possibly running, jobs */ /* kill stopped, and possibly running, jobs */
Job *j; Job *j;
int killed = 0; bool killed = false;
for (j = job_list; j != NULL; j = j->next) { for (j = job_list; j != NULL; j = j->next) {
if (j->ppid == procpid && if (j->ppid == procpid &&
@ -214,7 +221,7 @@ j_exit(void)
(j->state == PRUNNING && (j->state == PRUNNING &&
((j->flags & JF_FG) || ((j->flags & JF_FG) ||
(Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid))))) { (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid))))) {
killed = 1; killed = true;
if (j->pgrp == 0) if (j->pgrp == 0)
kill_job(j, SIGHUP); kill_job(j, SIGHUP);
else else
@ -336,12 +343,16 @@ j_change(void)
int int
exchild(struct op *t, int flags, exchild(struct op *t, int flags,
volatile int *xerrok, volatile int *xerrok,
/* used if XPCLOSE or XCCLOSE */ int close_fd) /* used if XPCLOSE or XCCLOSE */
int close_fd)
{ {
static Proc *last_proc; /* for pipelines */ /* for pipelines */
static Proc *last_proc;
int rv = 0, forksleep; int rv = 0, forksleep;
#ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
#endif
Proc *p; Proc *p;
Job *j; Job *j;
pid_t cldpid; pid_t cldpid;
@ -353,8 +364,10 @@ exchild(struct op *t, int flags,
*/ */
return (execute(t, flags & (XEXEC | XERROK), xerrok)); return (execute(t, flags & (XEXEC | XERROK), xerrok));
#ifndef MKSH_NOPROSPECTOFWORK
/* no SIGCHLDs while messing with job and process lists */ /* no SIGCHLDs while messing with job and process lists */
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
p = new_proc(); p = new_proc();
p->next = NULL; p->next = NULL;
@ -400,7 +413,8 @@ exchild(struct op *t, int flags,
/* create child process */ /* create child process */
forksleep = 1; forksleep = 1;
while ((cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) { while ((cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
if (intrsig) /* allow user to ^C out... */ if (intrsig)
/* allow user to ^C out... */
break; break;
sleep(forksleep); sleep(forksleep);
forksleep <<= 1; forksleep <<= 1;
@ -411,7 +425,9 @@ exchild(struct op *t, int flags,
if (cldpid < 0) { if (cldpid < 0) {
kill_job(j, SIGKILL); kill_job(j, SIGKILL);
remove_job(j, "fork failed"); remove_job(j, "fork failed");
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
errorf("can't fork - try again"); errorf("can't fork - try again");
} }
p->pid = cldpid ? cldpid : (procpid = getpid()); p->pid = cldpid ? cldpid : (procpid = getpid());
@ -419,13 +435,15 @@ exchild(struct op *t, int flags,
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
/* job control set up */ /* job control set up */
if (Flag(FMONITOR) && !(flags&XXCOM)) { if (Flag(FMONITOR) && !(flags&XXCOM)) {
int dotty = 0; bool dotty = false;
if (j->pgrp == 0) { /* First process */ if (j->pgrp == 0) {
/* First process */
j->pgrp = p->pid; j->pgrp = p->pid;
dotty = 1; dotty = true;
} }
/* set pgrp in both parent and child to deal with race /*
* set pgrp in both parent and child to deal with race
* condition * condition
*/ */
setpgid(p->pid, j->pgrp); setpgid(p->pid, j->pgrp);
@ -444,10 +462,13 @@ exchild(struct op *t, int flags,
/* Do this before restoring signal */ /* Do this before restoring signal */
if (flags & XCOPROC) if (flags & XCOPROC)
coproc_cleanup(false); coproc_cleanup(false);
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
cleanup_parents_env(); cleanup_parents_env();
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
/* If FMONITOR or FTALKING is set, these signals are ignored, /*
* If FMONITOR or FTALKING is set, these signals are ignored,
* if neither FMONITOR nor FTALKING are set, the signals have * if neither FMONITOR nor FTALKING are set, the signals have
* their inherited values. * their inherited values.
*/ */
@ -476,7 +497,8 @@ exchild(struct op *t, int flags,
close(forksleep); close(forksleep);
} }
} }
remove_job(j, "child"); /* in case of $(jobs) command */ /* in case of $(jobs) command */
remove_job(j, "child");
nzombie = 0; nzombie = 0;
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
ttypgrp_ok = false; ttypgrp_ok = false;
@ -500,7 +522,8 @@ exchild(struct op *t, int flags,
} }
/* shell (parent) stuff */ /* shell (parent) stuff */
if (!(flags & XPIPEO)) { /* last process in a job */ if (!(flags & XPIPEO)) {
/* last process in a job */
j_startjob(j); j_startjob(j);
if (flags & XCOPROC) { if (flags & XCOPROC) {
j->coproc_id = coproc.id; j->coproc_id = coproc.id;
@ -523,7 +546,9 @@ exchild(struct op *t, int flags,
rv = j_waitj(j, JW_NONE, "jw:last proc"); rv = j_waitj(j, JW_NONE, "jw:last proc");
} }
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
return (rv); return (rv);
} }
@ -532,27 +557,34 @@ exchild(struct op *t, int flags,
void void
startlast(void) startlast(void)
{ {
#ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
if (last_job) { /* no need to report error - waitlast() will do it */ /* no need to report error - waitlast() will do it */
if (last_job) {
/* ensure it isn't removed by check_job() */ /* ensure it isn't removed by check_job() */
last_job->flags |= JF_WAITING; last_job->flags |= JF_WAITING;
j_startjob(last_job); j_startjob(last_job);
} }
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
} }
/* wait for last job: only used for $(command) jobs */ /* wait for last job: only used for $(command) jobs */
int int
waitlast(void) waitlast(void)
{ {
int rv; int rv;
Job *j; Job *j;
#ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
j = last_job; j = last_job;
if (!j || !(j->flags & JF_STARTED)) { if (!j || !(j->flags & JF_STARTED)) {
@ -560,13 +592,18 @@ waitlast(void)
warningf(true, "%s: %s", "waitlast", "no last job"); warningf(true, "%s: %s", "waitlast", "no last job");
else else
internal_warningf("%s: %s", "waitlast", "not started"); internal_warningf("%s: %s", "waitlast", "not started");
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
return (125); /* not so arbitrary, non-zero value */ #endif
/* not so arbitrary, non-zero value */
return (125);
} }
rv = j_waitj(j, JW_NONE, "waitlast"); rv = j_waitj(j, JW_NONE, "waitlast");
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
return (rv); return (rv);
} }
@ -575,13 +612,13 @@ waitlast(void)
int int
waitfor(const char *cp, int *sigp) waitfor(const char *cp, int *sigp)
{ {
int rv; int rv, ecode, flags = JW_INTERRUPT|JW_ASYNCNOTIFY;
Job *j; Job *j;
int ecode; #ifndef MKSH_NOPROSPECTOFWORK
int flags = JW_INTERRUPT|JW_ASYNCNOTIFY;
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
*sigp = 0; *sigp = 0;
@ -595,18 +632,24 @@ waitfor(const char *cp, int *sigp)
if (j->ppid == procpid && j->state == PRUNNING) if (j->ppid == procpid && j->state == PRUNNING)
break; break;
if (!j) { if (!j) {
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
return (-1); return (-1);
} }
} else if ((j = j_lookup(cp, &ecode))) { } else if ((j = j_lookup(cp, &ecode))) {
/* don't report normal job completion */ /* don't report normal job completion */
flags &= ~JW_ASYNCNOTIFY; flags &= ~JW_ASYNCNOTIFY;
if (j->ppid != procpid) { if (j->ppid != procpid) {
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
return (-1); return (-1);
} }
} else { } else {
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
if (ecode != JL_NOSUCH) if (ecode != JL_NOSUCH)
bi_errorf("%s: %s", cp, lookup_msgs[ecode]); bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
return (-1); return (-1);
@ -615,9 +658,12 @@ waitfor(const char *cp, int *sigp)
/* AT&T ksh will wait for stopped jobs - we don't */ /* AT&T ksh will wait for stopped jobs - we don't */
rv = j_waitj(j, flags, "jw:waitfor"); rv = j_waitj(j, flags, "jw:waitfor");
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
if (rv < 0) /* we were interrupted */ if (rv < 0)
/* we were interrupted */
*sigp = 128 + -rv; *sigp = 128 + -rv;
return (rv); return (rv);
@ -627,20 +673,24 @@ waitfor(const char *cp, int *sigp)
int int
j_kill(const char *cp, int sig) j_kill(const char *cp, int sig)
{ {
Job *j; Job *j;
int rv = 0; int rv = 0, ecode;
int ecode; #ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
if ((j = j_lookup(cp, &ecode)) == NULL) { if ((j = j_lookup(cp, &ecode)) == NULL) {
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
bi_errorf("%s: %s", cp, lookup_msgs[ecode]); bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
return (1); return (1);
} }
if (j->pgrp == 0) { /* started when !Flag(FMONITOR) */ if (j->pgrp == 0) {
/* started when !Flag(FMONITOR) */
if (kill_job(j, sig) < 0) { if (kill_job(j, sig) < 0) {
bi_errorf("%s: %s", cp, strerror(errno)); bi_errorf("%s: %s", cp, strerror(errno));
rv = 1; rv = 1;
@ -656,7 +706,9 @@ j_kill(const char *cp, int sig)
} }
} }
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
return (rv); return (rv);
} }
@ -666,11 +718,10 @@ j_kill(const char *cp, int sig)
int int
j_resume(const char *cp, int bg) j_resume(const char *cp, int bg)
{ {
Job *j; Job *j;
Proc *p; Proc *p;
int ecode; int ecode, rv = 0;
int running; bool running;
int rv = 0;
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
@ -690,12 +741,12 @@ j_resume(const char *cp, int bg)
if (bg) if (bg)
shprintf("[%d] ", j->job); shprintf("[%d] ", j->job);
running = 0; running = false;
for (p = j->proc_list; p != NULL; p = p->next) { for (p = j->proc_list; p != NULL; p = p->next) {
if (p->state == PSTOPPED) { if (p->state == PSTOPPED) {
p->state = PRUNNING; p->state = PRUNNING;
p->status = 0; p->status = 0;
running = 1; running = true;
} }
shf_puts(p->command, shl_stdout); shf_puts(p->command, shl_stdout);
if (p->next) if (p->next)
@ -721,8 +772,7 @@ j_resume(const char *cp, int bg)
rv = errno; rv = errno;
if (j->flags & JF_SAVEDTTY) if (j->flags & JF_SAVEDTTY)
tcsetattr(tty_fd, TCSADRAIN, &tty_state); tcsetattr(tty_fd, TCSADRAIN, &tty_state);
sigprocmask(SIG_SETMASK, &omask, sigprocmask(SIG_SETMASK, &omask, NULL);
NULL);
bi_errorf("%s %s(%d, %ld) %s: %s", bi_errorf("%s %s(%d, %ld) %s: %s",
"1st", "tcsetpgrp", tty_fd, "1st", "tcsetpgrp", tty_fd,
(long)((j->flags & JF_SAVEDTTYPGRP) ? (long)((j->flags & JF_SAVEDTTYPGRP) ?
@ -769,8 +819,8 @@ j_resume(const char *cp, int bg)
int int
j_stopped_running(void) j_stopped_running(void)
{ {
Job *j; Job *j;
int which = 0; int which = 0;
for (j = job_list; j != NULL; j = j->next) { for (j = job_list; j != NULL; j = j->next) {
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
@ -797,13 +847,17 @@ j_njobs(void)
{ {
Job *j; Job *j;
int nj = 0; int nj = 0;
#ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
for (j = job_list; j; j = j->next) for (j = job_list; j; j = j->next)
nj++; nj++;
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
return (nj); return (nj);
} }
@ -811,16 +865,19 @@ j_njobs(void)
/* list jobs for jobs built-in */ /* list jobs for jobs built-in */
int int
j_jobs(const char *cp, int slp, j_jobs(const char *cp, int slp,
int nflag) /* 0: short, 1: long, 2: pgrp */ /* 0: short, 1: long, 2: pgrp */
int nflag)
{ {
Job *j, *tmp; Job *j, *tmp;
int how; int how, zflag = 0;
int zflag = 0; #ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
if (nflag < 0) { /* kludge: print zombies */ if (nflag < 0) {
/* kludge: print zombies */
nflag = 0; nflag = 0;
zflag = 1; zflag = 1;
} }
@ -828,7 +885,9 @@ j_jobs(const char *cp, int slp,
int ecode; int ecode;
if ((j = j_lookup(cp, &ecode)) == NULL) { if ((j = j_lookup(cp, &ecode)) == NULL) {
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
bi_errorf("%s: %s", cp, lookup_msgs[ecode]); bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
return (1); return (1);
} }
@ -851,7 +910,9 @@ j_jobs(const char *cp, int slp,
if (j->flags & JF_REMOVE) if (j->flags & JF_REMOVE)
remove_job(j, "jobs"); remove_job(j, "jobs");
} }
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
return (0); return (0);
} }
@ -859,16 +920,19 @@ j_jobs(const char *cp, int slp,
void void
j_notify(void) j_notify(void)
{ {
Job *j, *tmp; Job *j, *tmp;
#ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
for (j = job_list; j; j = j->next) { for (j = job_list; j; j = j->next) {
#ifndef MKSH_UNEMPLOYED #ifndef MKSH_UNEMPLOYED
if (Flag(FMONITOR) && (j->flags & JF_CHANGED)) if (Flag(FMONITOR) && (j->flags & JF_CHANGED))
j_print(j, JP_MEDIUM, shl_out); j_print(j, JP_MEDIUM, shl_out);
#endif #endif
/* Remove job after doing reports so there aren't /*
* Remove job after doing reports so there aren't
* multiple +/- jobs. * multiple +/- jobs.
*/ */
if (j->state == PEXITED || j->state == PSIGNALLED) if (j->state == PEXITED || j->state == PSIGNALLED)
@ -880,21 +944,27 @@ j_notify(void)
remove_job(j, "notify"); remove_job(j, "notify");
} }
shf_flush(shl_out); shf_flush(shl_out);
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
} }
/* Return pid of last process in last asynchronous job */ /* Return pid of last process in last asynchronous job */
pid_t pid_t
j_async(void) j_async(void)
{ {
#ifndef MKSH_NOPROSPECTOFWORK
sigset_t omask; sigset_t omask;
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
#endif
if (async_job) if (async_job)
async_job->flags |= JF_KNOWN; async_job->flags |= JF_KNOWN;
#ifndef MKSH_NOPROSPECTOFWORK
sigprocmask(SIG_SETMASK, &omask, NULL); sigprocmask(SIG_SETMASK, &omask, NULL);
#endif
return (async_pid); return (async_pid);
} }
@ -951,11 +1021,13 @@ j_startjob(Job *j)
; ;
j->last_proc = p; j->last_proc = p;
#ifndef MKSH_NOPROSPECTOFWORK
if (held_sigchld) { if (held_sigchld) {
held_sigchld = 0; held_sigchld = 0;
/* Don't call j_sigchld() as it may remove job... */ /* Don't call j_sigchld() as it may remove job... */
kill(procpid, SIGCHLD); kill(procpid, SIGCHLD);
} }
#endif
} }
/* /*
@ -965,7 +1037,8 @@ j_startjob(Job *j)
*/ */
static int static int
j_waitj(Job *j, j_waitj(Job *j,
int flags, /* see JW_* */ /* see JW_* */
int flags,
const char *where) const char *where)
{ {
int rv; int rv;
@ -984,12 +1057,17 @@ j_waitj(Job *j,
while (j->state == PRUNNING || while (j->state == PRUNNING ||
((flags & JW_STOPPEDWAIT) && j->state == PSTOPPED)) { ((flags & JW_STOPPEDWAIT) && j->state == PSTOPPED)) {
#ifndef MKSH_NOPROSPECTOFWORK
sigsuspend(&sm_default); sigsuspend(&sm_default);
#else
j_sigchld(SIGCHLD);
#endif
if (fatal_trap) { if (fatal_trap) {
int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY); int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY);
j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY); j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
runtraps(TF_FATAL); runtraps(TF_FATAL);
j->flags |= oldf; /* not reached... */ /* not reached... */
j->flags |= oldf;
} }
if ((flags & JW_INTERRUPT) && (rv = trap_pending())) { if ((flags & JW_INTERRUPT) && (rv = trap_pending())) {
j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY); j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
@ -1115,6 +1193,7 @@ j_sigchld(int sig MKSH_A_UNUSED)
int status; int status;
struct rusage ru0, ru1; struct rusage ru0, ru1;
#ifndef MKSH_NOPROSPECTOFWORK
/* /*
* Don't wait for any processes if a job is partially started. * Don't wait for any processes if a job is partially started.
* This is so we don't do away with the process group leader * This is so we don't do away with the process group leader
@ -1126,10 +1205,15 @@ j_sigchld(int sig MKSH_A_UNUSED)
held_sigchld = 1; held_sigchld = 1;
return; return;
} }
#endif
getrusage(RUSAGE_CHILDREN, &ru0); getrusage(RUSAGE_CHILDREN, &ru0);
do { do {
#ifndef MKSH_NOPROSPECTOFWORK
pid = waitpid(-1, &status, (WNOHANG|WUNTRACED)); pid = waitpid(-1, &status, (WNOHANG|WUNTRACED));
#else
pid = wait(&status);
#endif
/* /*
* return if this would block (0) or no children * return if this would block (0) or no children
@ -1171,8 +1255,14 @@ j_sigchld(int sig MKSH_A_UNUSED)
else else
p->state = PEXITED; p->state = PEXITED;
check_job(j); /* check to see if entire job is done */ /* check to see if entire job is done */
} while (1); check_job(j);
}
#ifndef MKSH_NOPROSPECTOFWORK
while (1);
#else
while (0);
#endif
} }
/* /*
@ -1199,7 +1289,8 @@ check_job(Job *j)
jstate = PRUNNING; jstate = PRUNNING;
for (p=j->proc_list; p != NULL; p = p->next) { for (p=j->proc_list; p != NULL; p = p->next) {
if (p->state == PRUNNING) if (p->state == PRUNNING)
return; /* some processes still running */ /* some processes still running */
return;
if (p->state > jstate) if (p->state > jstate)
jstate = p->state; jstate = p->state;
} }
@ -1459,7 +1550,8 @@ j_lookup(const char *cp, int *ecodep)
return (j); return (j);
break; break;
case '?': /* %?string */ /* %?string */
case '?':
last_match = NULL; last_match = NULL;
for (j = job_list; j != NULL; j = j->next) for (j = job_list; j != NULL; j = j->next)
for (p = j->proc_list; p != NULL; p = p->next) for (p = j->proc_list; p != NULL; p = p->next)
@ -1475,7 +1567,8 @@ j_lookup(const char *cp, int *ecodep)
return (last_match); return (last_match);
break; break;
default: /* %string */ /* %string */
default:
len = strlen(cp); len = strlen(cp);
last_match = NULL; last_match = NULL;
for (j = job_list; j != NULL; j = j->next) for (j = job_list; j != NULL; j = j->next)

8
sh.h
View File

@ -154,7 +154,7 @@
#endif #endif
#ifdef EXTERN #ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.424 2011/01/22 20:33:14 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/sh.h,v 1.425 2011/01/30 01:35:35 tg Exp $");
#endif #endif
#define MKSH_VERSION "R39 2011/01/22" #define MKSH_VERSION "R39 2011/01/22"
@ -489,6 +489,10 @@ char *ucstrstr(char *, const char *);
#define MKSH_S_NOVI 0 #define MKSH_S_NOVI 0
#endif #endif
#if defined(MKSH_NOPROSPECTOFWORK) && !defined(MKSH_UNEMPLOYED)
#define MKSH_UNEMPLOYED
#endif
/* /*
* simple grouping allocator * simple grouping allocator
*/ */
@ -789,8 +793,10 @@ struct coproc {
}; };
EXTERN struct coproc coproc; EXTERN struct coproc coproc;
#ifndef MKSH_NOPROSPECTOFWORK
/* Used in jobs.c and by coprocess stuff in exec.c */ /* Used in jobs.c and by coprocess stuff in exec.c */
EXTERN sigset_t sm_default, sm_sigchld; EXTERN sigset_t sm_default, sm_sigchld;
#endif
/* name of called builtin function (used by error functions) */ /* name of called builtin function (used by error functions) */
EXTERN const char *builtin_argv0; EXTERN const char *builtin_argv0;