17265: make the jobs command work in subshells

This commit is contained in:
Peter Stephenson 2002-06-05 14:57:05 +00:00
parent 5d010ca81a
commit 5ef61a44b1
4 changed files with 86 additions and 26 deletions

View file

@ -1,5 +1,9 @@
2002-06-05 Peter Stephenson <pws@csr.com>
* 17265: Src/exec.c, Src/jobs.c, Src/Modules/clone.c: Make the
`jobs' command work in a subshell of a shell with job control by
saving the valid bits of the job table.
* 17285: David Wolfe <dwolfe@gforcetech.com>:
Src/Builtins/rlimits.c: finally fix 16145 to eliminate duplicate
case statement also in ulimit.

View file

@ -53,7 +53,7 @@ bin_clone(char *nam, char **args, char *ops, int func)
}
pid = fork();
if (!pid) {
clearjobtab();
clearjobtab(0);
ppid = getppid();
mypid = getpid();
#ifdef HAVE_SETSID
@ -61,7 +61,7 @@ bin_clone(char *nam, char **args, char *ops, int func)
zwarnnam(nam, "failed to create new session: %e", NULL, errno);
#endif
#ifdef TIOCNOTTY
if (ioctl(SHTTY, TIOCNOTTY))
if (ioctl(SHTTY, TIOCNOTTY, 0))
zwarnnam(nam, "%e", NULL, errno);
setpgrp(0L, mypid);
#endif
@ -98,18 +98,29 @@ static struct builtin bintab[] = {
/**/
int
boot_clone(Module m)
setup_(Module m)
{
return 0;
}
/**/
int
boot_(Module m)
{
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
}
#ifdef MODULE
/**/
int
cleanup_clone(Module m)
cleanup_(Module m)
{
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
return 0;
}
#endif
/**/
int
finish_(Module m)
{
return 0;
}

View file

@ -2507,13 +2507,13 @@ forklevel;
static void
entersubsh(int how, int cl, int fake)
{
int sig;
int sig, monitor;
if (cl != 2)
for (sig = 0; sig < VSIGCOUNT; sig++)
if (!(sigtrapped[sig] & ZSIG_FUNC))
unsettrap(sig);
if (unset(MONITOR)) {
if (!(monitor = isset(MONITOR))) {
if (how & Z_ASYNC) {
settrap(SIGINT, NULL);
settrap(SIGQUIT, NULL);
@ -2569,7 +2569,7 @@ entersubsh(int how, int cl, int fake)
opts[MONITOR] = opts[USEZLE] = 0;
zleactive = 0;
if (cl)
clearjobtab();
clearjobtab(monitor);
times(&shtms);
forklevel = locallevel;
}

View file

@ -55,6 +55,12 @@ mod_export int prevjob;
/**/
mod_export struct job jobtab[MAXJOB];
/* If we have entered a subshell, the original shell's job table. */
static struct job *oldjobtab;
/* The size of that. */
static int oldmaxjob;
/* shell timings */
/**/
@ -612,13 +618,18 @@ void
printjob(Job jn, int lng, int synch)
{
Process pn;
int job = jn - jobtab, len = 9, sig, sflag = 0, llen;
int job, len = 9, sig, sflag = 0, llen;
int conted = 0, lineleng = columns, skip = 0, doputnl = 0;
FILE *fout = (synch == 2) ? stdout : shout;
if (jn->stat & STAT_NOPRINT)
return;
if (jn < jobtab || jn >= jobtab + MAXJOB)
job = jn - oldjobtab;
else
job = jn - jobtab;
if (lng < 0) {
conted = 1;
lng = 0;
@ -655,11 +666,14 @@ printjob(Job jn, int lng, int synch)
}
}
/* print if necessary */
/* print if necessary: ignore option state on explicit call to `jobs'. */
if (interact && jobbing && ((jn->stat & STAT_STOPPED) || sflag ||
job != thisjob)) {
if (synch == 2 ||
(interact && jobbing &&
((jn->stat & STAT_STOPPED) || sflag || job != thisjob))) {
int len2, fline = 1;
/* use special format for current job, except in `jobs' */
int thisfmt = job == thisjob && synch != 2;
Process qn;
if (!synch)
@ -667,7 +681,7 @@ printjob(Job jn, int lng, int synch)
if (doputnl && !synch)
putc('\n', fout);
for (pn = jn->procs; pn;) {
len2 = ((job == thisjob) ? 5 : 10) + len; /* 2 spaces */
len2 = (thisfmt ? 5 : 10) + len; /* 2 spaces */
if (lng & 3)
qn = pn->next;
else
@ -678,10 +692,10 @@ printjob(Job jn, int lng, int synch)
break;
len2 += strlen(qn->text) + 2;
}
if (job != thisjob) {
if (!thisfmt) {
if (fline)
fprintf(fout, "[%ld] %c ",
(long)(jn - jobtab),
(long)job,
(job == curjob) ? '+'
: (job == prevjob) ? '-' : ' ');
else
@ -956,13 +970,32 @@ waitjobs(void)
/**/
mod_export void
clearjobtab(void)
clearjobtab(int monitor)
{
int i;
for (i = 1; i < MAXJOB; i++)
if (jobtab[i].ty)
for (i = 1; i < MAXJOB; i++) {
if (jobtab[i].ty) {
zfree(jobtab[i].ty, sizeof(struct ttyinfo));
jobtab[i].ty = NULL;
}
if (monitor) {
/*
* See if there is a jobtable worth saving.
* We never free the saved version; it only happens
* once for each subshell of a shell with job control,
* so doesn't create a leak.
*/
if (jobtab[i].stat)
oldmaxjob = i+1;
}
}
if (monitor && oldmaxjob) {
int sz = oldmaxjob * sizeof(struct job);
oldjobtab = (struct job *)zalloc(sz);
memcpy(oldjobtab, jobtab, sz);
}
memset(jobtab, 0, sizeof(jobtab)); /* zero out table */
}
@ -1253,7 +1286,8 @@ bin_fg(char *name, char **argv, char *ops, int func)
if (unset(NOTIFY))
scanjobs();
setcurjob();
if (func != BIN_JOBS || isset(MONITOR) || !oldmaxjob)
setcurjob();
if (func == BIN_JOBS)
/* If you immediately type "exit" after "jobs", this *
@ -1274,13 +1308,24 @@ bin_fg(char *name, char **argv, char *ops, int func)
firstjob = curjob;
} else if (func == BIN_JOBS) {
/* List jobs. */
for (job = 0; job != MAXJOB; job++)
if (job != thisjob && jobtab[job].stat) {
struct job *jobptr;
int maxjob, ignorejob;
if (unset(MONITOR) && oldmaxjob) {
jobptr = oldjobtab;
maxjob = oldmaxjob;
ignorejob = 0;
} else {
jobptr = jobtab;
maxjob = MAXJOB;
ignorejob = thisjob;
}
for (job = 0; job != maxjob; job++, jobptr++)
if (job != ignorejob && jobptr->stat) {
if ((!ops['r'] && !ops['s']) ||
(ops['r'] && ops['s']) ||
(ops['r'] && !(jobtab[job].stat & STAT_STOPPED)) ||
(ops['s'] && jobtab[job].stat & STAT_STOPPED))
printjob(job + jobtab, lng, 2);
(ops['r'] && !(jobptr->stat & STAT_STOPPED)) ||
(ops['s'] && jobptr->stat & STAT_STOPPED))
printjob(jobptr, lng, 2);
}
unqueue_signals();
return 0;