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:
parent
07889fb0eb
commit
bdfcdc56c8
6
Build.sh
6
Build.sh
@ -1,5 +1,5 @@
|
||||
#!/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
|
||||
# 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_DEFAULT_TMPDIR MKSH_CLRTOEOL_STRING MKSH_A4PB
|
||||
# MKSH_NO_DEPRECATED_WARNING MKSH_DONT_EMIT_IDSTRING
|
||||
# MKSH_NOPROSPECTOFWORK
|
||||
|
||||
LC_ALL=C
|
||||
export LC_ALL
|
||||
@ -1061,6 +1062,9 @@ ac_ifcpp 'ifdef MKSH_BINSHREDUCED' isset_MKSH_BINSHREDUCED '' \
|
||||
ac_ifcpp 'ifdef MKSH_UNEMPLOYED' isset_MKSH_UNEMPLOYED '' \
|
||||
"if mksh will be built without job control" && \
|
||||
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 '' \
|
||||
'if the default UTF-8 mode is specified' && : ${HAVE_SETLOCALE_CTYPE=0}
|
||||
ac_ifcpp 'ifdef MKSH_CONSERVATIVE_FDS' isset_MKSH_CONSERVATIVE_FDS '' \
|
||||
|
3
check.t
3
check.t
@ -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: 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 $
|
||||
@ -5193,6 +5193,7 @@ expected-stdout:
|
||||
name: pipeline-2
|
||||
description:
|
||||
check that co-processes work with TCOMs, TPIPEs and TPARENs
|
||||
category: !nojsig
|
||||
stdin:
|
||||
"$__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'
|
||||
|
69
exec.c
69
exec.c
@ -22,7 +22,7 @@
|
||||
|
||||
#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
|
||||
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
|
||||
@ -114,14 +114,17 @@ execute(struct op * volatile t,
|
||||
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().
|
||||
*/
|
||||
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..
|
||||
*/
|
||||
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++) {
|
||||
if (iosetup(*iowp, tp) < 0) {
|
||||
exstat = rv = 1;
|
||||
/* Redirection failures for special commands
|
||||
/*
|
||||
* Redirection failures for special commands
|
||||
* cause (non-interactive) shell to exit.
|
||||
*/
|
||||
if (tp && tp->type == CSHELL &&
|
||||
@ -180,7 +184,8 @@ execute(struct op * volatile t,
|
||||
e->savefd[1] = savefd(1);
|
||||
while (t->type == TPIPE) {
|
||||
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
|
||||
* (if this isn't done, commands like
|
||||
@ -189,13 +194,16 @@ execute(struct op * volatile t,
|
||||
*/
|
||||
exchild(t->left, flags | XPIPEO | XCCLOSE,
|
||||
NULL, pv[0]);
|
||||
ksh_dup2(pv[0], 0, false); /* stdin of next */
|
||||
/* stdin of next */
|
||||
ksh_dup2(pv[0], 0, false);
|
||||
closepipe(pv);
|
||||
flags |= XPIPEI;
|
||||
t = t->right;
|
||||
}
|
||||
restfd(1, e->savefd[1]); /* stdout of last */
|
||||
e->savefd[1] = 0; /* no need to re-restore this */
|
||||
/* stdout of last */
|
||||
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 */
|
||||
i = exchild(t, flags | XPCLOSE, xerrok, 0);
|
||||
if (!(flags&XBGND) && !(flags&XXCOM))
|
||||
@ -211,9 +219,11 @@ execute(struct op * volatile t,
|
||||
break;
|
||||
|
||||
case TCOPROC: {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
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
|
||||
*/
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
@ -225,6 +235,7 @@ execute(struct op * volatile t,
|
||||
unwind(i);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
#endif
|
||||
/* Already have a (live) co-process? */
|
||||
if (coproc.job && coproc.write >= 0)
|
||||
errorf("coprocess already exists");
|
||||
@ -250,15 +261,20 @@ execute(struct op * volatile t,
|
||||
openpipe(pv);
|
||||
coproc.read = pv[0];
|
||||
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;
|
||||
/* create new coprocess id */
|
||||
++coproc.id;
|
||||
}
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
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
|
||||
* job is actually created.
|
||||
*/
|
||||
@ -269,7 +285,8 @@ execute(struct op * volatile t,
|
||||
}
|
||||
|
||||
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
|
||||
* this to "foo &"...
|
||||
*/
|
||||
@ -327,13 +344,15 @@ execute(struct op * volatile t,
|
||||
goto Break;
|
||||
}
|
||||
}
|
||||
rv = 0; /* in case of a continue */
|
||||
/* in case of a continue */
|
||||
rv = 0;
|
||||
if (t->type == TFOR) {
|
||||
while (*ap != NULL) {
|
||||
setstr(global(t->str), *ap++, KSH_UNWIND_ERROR);
|
||||
rv = execute(t->left, flags & XERROK, xerrok);
|
||||
}
|
||||
} else { /* TSELECT */
|
||||
} else {
|
||||
/* TSELECT */
|
||||
for (;;) {
|
||||
if (!(ccp = do_selectargs(ap, is_first))) {
|
||||
rv = 1;
|
||||
@ -363,7 +382,8 @@ execute(struct op * volatile t,
|
||||
goto Break;
|
||||
}
|
||||
}
|
||||
rv = 0; /* in case of a continue */
|
||||
/* in case of a continue */
|
||||
rv = 0;
|
||||
while ((execute(t->left, XERROK, NULL) == 0) ==
|
||||
(t->type == TWHILE))
|
||||
rv = execute(t->right, flags & XERROK, xerrok);
|
||||
@ -372,7 +392,8 @@ execute(struct op * volatile t,
|
||||
case TIF:
|
||||
case TELIF:
|
||||
if (t->right == NULL)
|
||||
break; /* should be error */
|
||||
/* should be error */
|
||||
break;
|
||||
rv = execute(t->left, XERROK, NULL) == 0 ?
|
||||
execute(t->right->left, flags & XERROK, xerrok) :
|
||||
execute(t->right->right, flags & XERROK, xerrok);
|
||||
@ -399,13 +420,15 @@ execute(struct op * volatile t,
|
||||
break;
|
||||
|
||||
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").
|
||||
*/
|
||||
rv = timex(t, flags & ~XEXEC, xerrok);
|
||||
break;
|
||||
|
||||
case TEXEC: /* an eval'd TCOM */
|
||||
case TEXEC:
|
||||
/* an eval'd TCOM */
|
||||
s = t->args[0];
|
||||
up = makenv();
|
||||
restoresigs();
|
||||
@ -425,9 +448,11 @@ execute(struct op * volatile t,
|
||||
Break:
|
||||
exstat = rv;
|
||||
|
||||
quitenv(NULL); /* restores IO */
|
||||
/* restores IO */
|
||||
quitenv(NULL);
|
||||
if ((flags&XEXEC))
|
||||
unwind(LEXIT); /* exit child */
|
||||
/* exit child */
|
||||
unwind(LEXIT);
|
||||
if (rv != 0 && !(flags & XERROK) &&
|
||||
(xerrok == NULL || !*xerrok)) {
|
||||
trapsig(SIGERR_);
|
||||
|
197
jobs.c
197
jobs.c
@ -22,7 +22,7 @@
|
||||
|
||||
#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
|
||||
#define mksh_killpg killpg
|
||||
@ -124,8 +124,10 @@ static int32_t njobs; /* # of jobs started */
|
||||
#define CHILD_MAX 25
|
||||
#endif
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
/* held_sigchld is set if sigchld occurs before a job is completely started */
|
||||
static volatile sig_atomic_t held_sigchld;
|
||||
#endif
|
||||
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
static struct shf *shl_j;
|
||||
@ -157,6 +159,7 @@ j_init(void)
|
||||
Flag(FMONITOR) = 0;
|
||||
#endif
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
(void)sigemptyset(&sm_default);
|
||||
sigprocmask(SIG_SETMASK, &sm_default, NULL);
|
||||
|
||||
@ -165,6 +168,10 @@ j_init(void)
|
||||
|
||||
setsig(&sigtraps[SIGCHLD], j_sigchld,
|
||||
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
|
||||
if (!mflagset && Flag(FTALKING))
|
||||
@ -205,8 +212,8 @@ void
|
||||
j_exit(void)
|
||||
{
|
||||
/* kill stopped, and possibly running, jobs */
|
||||
Job *j;
|
||||
int killed = 0;
|
||||
Job *j;
|
||||
bool killed = false;
|
||||
|
||||
for (j = job_list; j != NULL; j = j->next) {
|
||||
if (j->ppid == procpid &&
|
||||
@ -214,7 +221,7 @@ j_exit(void)
|
||||
(j->state == PRUNNING &&
|
||||
((j->flags & JF_FG) ||
|
||||
(Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid))))) {
|
||||
killed = 1;
|
||||
killed = true;
|
||||
if (j->pgrp == 0)
|
||||
kill_job(j, SIGHUP);
|
||||
else
|
||||
@ -336,12 +343,16 @@ j_change(void)
|
||||
int
|
||||
exchild(struct op *t, int flags,
|
||||
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;
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
#endif
|
||||
Proc *p;
|
||||
Job *j;
|
||||
pid_t cldpid;
|
||||
@ -353,8 +364,10 @@ exchild(struct op *t, int flags,
|
||||
*/
|
||||
return (execute(t, flags & (XEXEC | XERROK), xerrok));
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
/* no SIGCHLDs while messing with job and process lists */
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
|
||||
p = new_proc();
|
||||
p->next = NULL;
|
||||
@ -400,7 +413,8 @@ exchild(struct op *t, int flags,
|
||||
/* create child process */
|
||||
forksleep = 1;
|
||||
while ((cldpid = fork()) < 0 && errno == EAGAIN && forksleep < 32) {
|
||||
if (intrsig) /* allow user to ^C out... */
|
||||
if (intrsig)
|
||||
/* allow user to ^C out... */
|
||||
break;
|
||||
sleep(forksleep);
|
||||
forksleep <<= 1;
|
||||
@ -411,7 +425,9 @@ exchild(struct op *t, int flags,
|
||||
if (cldpid < 0) {
|
||||
kill_job(j, SIGKILL);
|
||||
remove_job(j, "fork failed");
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
errorf("can't fork - try again");
|
||||
}
|
||||
p->pid = cldpid ? cldpid : (procpid = getpid());
|
||||
@ -419,13 +435,15 @@ exchild(struct op *t, int flags,
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
/* job control set up */
|
||||
if (Flag(FMONITOR) && !(flags&XXCOM)) {
|
||||
int dotty = 0;
|
||||
if (j->pgrp == 0) { /* First process */
|
||||
bool dotty = false;
|
||||
if (j->pgrp == 0) {
|
||||
/* First process */
|
||||
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
|
||||
*/
|
||||
setpgid(p->pid, j->pgrp);
|
||||
@ -444,10 +462,13 @@ exchild(struct op *t, int flags,
|
||||
/* Do this before restoring signal */
|
||||
if (flags & XCOPROC)
|
||||
coproc_cleanup(false);
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
cleanup_parents_env();
|
||||
#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
|
||||
* their inherited values.
|
||||
*/
|
||||
@ -476,7 +497,8 @@ exchild(struct op *t, int flags,
|
||||
close(forksleep);
|
||||
}
|
||||
}
|
||||
remove_job(j, "child"); /* in case of $(jobs) command */
|
||||
/* in case of $(jobs) command */
|
||||
remove_job(j, "child");
|
||||
nzombie = 0;
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
ttypgrp_ok = false;
|
||||
@ -500,7 +522,8 @@ exchild(struct op *t, int flags,
|
||||
}
|
||||
|
||||
/* shell (parent) stuff */
|
||||
if (!(flags & XPIPEO)) { /* last process in a job */
|
||||
if (!(flags & XPIPEO)) {
|
||||
/* last process in a job */
|
||||
j_startjob(j);
|
||||
if (flags & XCOPROC) {
|
||||
j->coproc_id = coproc.id;
|
||||
@ -523,7 +546,9 @@ exchild(struct op *t, int flags,
|
||||
rv = j_waitj(j, JW_NONE, "jw:last proc");
|
||||
}
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
|
||||
return (rv);
|
||||
}
|
||||
@ -532,27 +557,34 @@ exchild(struct op *t, int flags,
|
||||
void
|
||||
startlast(void)
|
||||
{
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t 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() */
|
||||
last_job->flags |= JF_WAITING;
|
||||
j_startjob(last_job);
|
||||
}
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* wait for last job: only used for $(command) jobs */
|
||||
int
|
||||
waitlast(void)
|
||||
{
|
||||
int rv;
|
||||
Job *j;
|
||||
int rv;
|
||||
Job *j;
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
|
||||
j = last_job;
|
||||
if (!j || !(j->flags & JF_STARTED)) {
|
||||
@ -560,13 +592,18 @@ waitlast(void)
|
||||
warningf(true, "%s: %s", "waitlast", "no last job");
|
||||
else
|
||||
internal_warningf("%s: %s", "waitlast", "not started");
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
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");
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
|
||||
return (rv);
|
||||
}
|
||||
@ -575,13 +612,13 @@ waitlast(void)
|
||||
int
|
||||
waitfor(const char *cp, int *sigp)
|
||||
{
|
||||
int rv;
|
||||
Job *j;
|
||||
int ecode;
|
||||
int flags = JW_INTERRUPT|JW_ASYNCNOTIFY;
|
||||
int rv, ecode, flags = JW_INTERRUPT|JW_ASYNCNOTIFY;
|
||||
Job *j;
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
|
||||
*sigp = 0;
|
||||
|
||||
@ -595,18 +632,24 @@ waitfor(const char *cp, int *sigp)
|
||||
if (j->ppid == procpid && j->state == PRUNNING)
|
||||
break;
|
||||
if (!j) {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
return (-1);
|
||||
}
|
||||
} else if ((j = j_lookup(cp, &ecode))) {
|
||||
/* don't report normal job completion */
|
||||
flags &= ~JW_ASYNCNOTIFY;
|
||||
if (j->ppid != procpid) {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
if (ecode != JL_NOSUCH)
|
||||
bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
|
||||
return (-1);
|
||||
@ -615,9 +658,12 @@ waitfor(const char *cp, int *sigp)
|
||||
/* AT&T ksh will wait for stopped jobs - we don't */
|
||||
rv = j_waitj(j, flags, "jw:waitfor");
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
|
||||
if (rv < 0) /* we were interrupted */
|
||||
if (rv < 0)
|
||||
/* we were interrupted */
|
||||
*sigp = 128 + -rv;
|
||||
|
||||
return (rv);
|
||||
@ -627,20 +673,24 @@ waitfor(const char *cp, int *sigp)
|
||||
int
|
||||
j_kill(const char *cp, int sig)
|
||||
{
|
||||
Job *j;
|
||||
int rv = 0;
|
||||
int ecode;
|
||||
Job *j;
|
||||
int rv = 0, ecode;
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
|
||||
if ((j = j_lookup(cp, &ecode)) == NULL) {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (j->pgrp == 0) { /* started when !Flag(FMONITOR) */
|
||||
if (j->pgrp == 0) {
|
||||
/* started when !Flag(FMONITOR) */
|
||||
if (kill_job(j, sig) < 0) {
|
||||
bi_errorf("%s: %s", cp, strerror(errno));
|
||||
rv = 1;
|
||||
@ -656,7 +706,9 @@ j_kill(const char *cp, int sig)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
|
||||
return (rv);
|
||||
}
|
||||
@ -666,11 +718,10 @@ j_kill(const char *cp, int sig)
|
||||
int
|
||||
j_resume(const char *cp, int bg)
|
||||
{
|
||||
Job *j;
|
||||
Proc *p;
|
||||
int ecode;
|
||||
int running;
|
||||
int rv = 0;
|
||||
Job *j;
|
||||
Proc *p;
|
||||
int ecode, rv = 0;
|
||||
bool running;
|
||||
sigset_t omask;
|
||||
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
@ -690,12 +741,12 @@ j_resume(const char *cp, int bg)
|
||||
if (bg)
|
||||
shprintf("[%d] ", j->job);
|
||||
|
||||
running = 0;
|
||||
running = false;
|
||||
for (p = j->proc_list; p != NULL; p = p->next) {
|
||||
if (p->state == PSTOPPED) {
|
||||
p->state = PRUNNING;
|
||||
p->status = 0;
|
||||
running = 1;
|
||||
running = true;
|
||||
}
|
||||
shf_puts(p->command, shl_stdout);
|
||||
if (p->next)
|
||||
@ -721,8 +772,7 @@ j_resume(const char *cp, int bg)
|
||||
rv = errno;
|
||||
if (j->flags & JF_SAVEDTTY)
|
||||
tcsetattr(tty_fd, TCSADRAIN, &tty_state);
|
||||
sigprocmask(SIG_SETMASK, &omask,
|
||||
NULL);
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
bi_errorf("%s %s(%d, %ld) %s: %s",
|
||||
"1st", "tcsetpgrp", tty_fd,
|
||||
(long)((j->flags & JF_SAVEDTTYPGRP) ?
|
||||
@ -769,8 +819,8 @@ j_resume(const char *cp, int bg)
|
||||
int
|
||||
j_stopped_running(void)
|
||||
{
|
||||
Job *j;
|
||||
int which = 0;
|
||||
Job *j;
|
||||
int which = 0;
|
||||
|
||||
for (j = job_list; j != NULL; j = j->next) {
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
@ -797,13 +847,17 @@ j_njobs(void)
|
||||
{
|
||||
Job *j;
|
||||
int nj = 0;
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
for (j = job_list; j; j = j->next)
|
||||
nj++;
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
return (nj);
|
||||
}
|
||||
|
||||
@ -811,16 +865,19 @@ j_njobs(void)
|
||||
/* list jobs for jobs built-in */
|
||||
int
|
||||
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;
|
||||
int how;
|
||||
int zflag = 0;
|
||||
Job *j, *tmp;
|
||||
int how, zflag = 0;
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
|
||||
if (nflag < 0) { /* kludge: print zombies */
|
||||
if (nflag < 0) {
|
||||
/* kludge: print zombies */
|
||||
nflag = 0;
|
||||
zflag = 1;
|
||||
}
|
||||
@ -828,7 +885,9 @@ j_jobs(const char *cp, int slp,
|
||||
int ecode;
|
||||
|
||||
if ((j = j_lookup(cp, &ecode)) == NULL) {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
bi_errorf("%s: %s", cp, lookup_msgs[ecode]);
|
||||
return (1);
|
||||
}
|
||||
@ -851,7 +910,9 @@ j_jobs(const char *cp, int slp,
|
||||
if (j->flags & JF_REMOVE)
|
||||
remove_job(j, "jobs");
|
||||
}
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -859,16 +920,19 @@ j_jobs(const char *cp, int slp,
|
||||
void
|
||||
j_notify(void)
|
||||
{
|
||||
Job *j, *tmp;
|
||||
Job *j, *tmp;
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
for (j = job_list; j; j = j->next) {
|
||||
#ifndef MKSH_UNEMPLOYED
|
||||
if (Flag(FMONITOR) && (j->flags & JF_CHANGED))
|
||||
j_print(j, JP_MEDIUM, shl_out);
|
||||
#endif
|
||||
/* Remove job after doing reports so there aren't
|
||||
/*
|
||||
* Remove job after doing reports so there aren't
|
||||
* multiple +/- jobs.
|
||||
*/
|
||||
if (j->state == PEXITED || j->state == PSIGNALLED)
|
||||
@ -880,21 +944,27 @@ j_notify(void)
|
||||
remove_job(j, "notify");
|
||||
}
|
||||
shf_flush(shl_out);
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Return pid of last process in last asynchronous job */
|
||||
pid_t
|
||||
j_async(void)
|
||||
{
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigset_t omask;
|
||||
|
||||
sigprocmask(SIG_BLOCK, &sm_sigchld, &omask);
|
||||
#endif
|
||||
|
||||
if (async_job)
|
||||
async_job->flags |= JF_KNOWN;
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||
#endif
|
||||
|
||||
return (async_pid);
|
||||
}
|
||||
@ -951,11 +1021,13 @@ j_startjob(Job *j)
|
||||
;
|
||||
j->last_proc = p;
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
if (held_sigchld) {
|
||||
held_sigchld = 0;
|
||||
/* Don't call j_sigchld() as it may remove job... */
|
||||
kill(procpid, SIGCHLD);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -965,7 +1037,8 @@ j_startjob(Job *j)
|
||||
*/
|
||||
static int
|
||||
j_waitj(Job *j,
|
||||
int flags, /* see JW_* */
|
||||
/* see JW_* */
|
||||
int flags,
|
||||
const char *where)
|
||||
{
|
||||
int rv;
|
||||
@ -984,12 +1057,17 @@ j_waitj(Job *j,
|
||||
|
||||
while (j->state == PRUNNING ||
|
||||
((flags & JW_STOPPEDWAIT) && j->state == PSTOPPED)) {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
sigsuspend(&sm_default);
|
||||
#else
|
||||
j_sigchld(SIGCHLD);
|
||||
#endif
|
||||
if (fatal_trap) {
|
||||
int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY);
|
||||
j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
|
||||
runtraps(TF_FATAL);
|
||||
j->flags |= oldf; /* not reached... */
|
||||
/* not reached... */
|
||||
j->flags |= oldf;
|
||||
}
|
||||
if ((flags & JW_INTERRUPT) && (rv = trap_pending())) {
|
||||
j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY);
|
||||
@ -1115,6 +1193,7 @@ j_sigchld(int sig MKSH_A_UNUSED)
|
||||
int status;
|
||||
struct rusage ru0, ru1;
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
/*
|
||||
* 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
|
||||
@ -1126,10 +1205,15 @@ j_sigchld(int sig MKSH_A_UNUSED)
|
||||
held_sigchld = 1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
getrusage(RUSAGE_CHILDREN, &ru0);
|
||||
do {
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
pid = waitpid(-1, &status, (WNOHANG|WUNTRACED));
|
||||
#else
|
||||
pid = wait(&status);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* return if this would block (0) or no children
|
||||
@ -1171,8 +1255,14 @@ j_sigchld(int sig MKSH_A_UNUSED)
|
||||
else
|
||||
p->state = PEXITED;
|
||||
|
||||
check_job(j); /* check to see if entire job is done */
|
||||
} while (1);
|
||||
/* check to see if entire job is done */
|
||||
check_job(j);
|
||||
}
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
while (1);
|
||||
#else
|
||||
while (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1199,7 +1289,8 @@ check_job(Job *j)
|
||||
jstate = PRUNNING;
|
||||
for (p=j->proc_list; p != NULL; p = p->next) {
|
||||
if (p->state == PRUNNING)
|
||||
return; /* some processes still running */
|
||||
/* some processes still running */
|
||||
return;
|
||||
if (p->state > jstate)
|
||||
jstate = p->state;
|
||||
}
|
||||
@ -1459,7 +1550,8 @@ j_lookup(const char *cp, int *ecodep)
|
||||
return (j);
|
||||
break;
|
||||
|
||||
case '?': /* %?string */
|
||||
/* %?string */
|
||||
case '?':
|
||||
last_match = NULL;
|
||||
for (j = job_list; j != NULL; j = j->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);
|
||||
break;
|
||||
|
||||
default: /* %string */
|
||||
/* %string */
|
||||
default:
|
||||
len = strlen(cp);
|
||||
last_match = NULL;
|
||||
for (j = job_list; j != NULL; j = j->next)
|
||||
|
8
sh.h
8
sh.h
@ -154,7 +154,7 @@
|
||||
#endif
|
||||
|
||||
#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
|
||||
#define MKSH_VERSION "R39 2011/01/22"
|
||||
|
||||
@ -489,6 +489,10 @@ char *ucstrstr(char *, const char *);
|
||||
#define MKSH_S_NOVI 0
|
||||
#endif
|
||||
|
||||
#if defined(MKSH_NOPROSPECTOFWORK) && !defined(MKSH_UNEMPLOYED)
|
||||
#define MKSH_UNEMPLOYED
|
||||
#endif
|
||||
|
||||
/*
|
||||
* simple grouping allocator
|
||||
*/
|
||||
@ -789,8 +793,10 @@ struct coproc {
|
||||
};
|
||||
EXTERN struct coproc coproc;
|
||||
|
||||
#ifndef MKSH_NOPROSPECTOFWORK
|
||||
/* Used in jobs.c and by coprocess stuff in exec.c */
|
||||
EXTERN sigset_t sm_default, sm_sigchld;
|
||||
#endif
|
||||
|
||||
/* name of called builtin function (used by error functions) */
|
||||
EXTERN const char *builtin_argv0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user