mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-24 04:50:27 +02:00
17265: make the jobs command work in subshells
This commit is contained in:
parent
5d010ca81a
commit
5ef61a44b1
4 changed files with 86 additions and 26 deletions
|
|
@ -1,5 +1,9 @@
|
||||||
2002-06-05 Peter Stephenson <pws@csr.com>
|
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>:
|
* 17285: David Wolfe <dwolfe@gforcetech.com>:
|
||||||
Src/Builtins/rlimits.c: finally fix 16145 to eliminate duplicate
|
Src/Builtins/rlimits.c: finally fix 16145 to eliminate duplicate
|
||||||
case statement also in ulimit.
|
case statement also in ulimit.
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ bin_clone(char *nam, char **args, char *ops, int func)
|
||||||
}
|
}
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (!pid) {
|
if (!pid) {
|
||||||
clearjobtab();
|
clearjobtab(0);
|
||||||
ppid = getppid();
|
ppid = getppid();
|
||||||
mypid = getpid();
|
mypid = getpid();
|
||||||
#ifdef HAVE_SETSID
|
#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);
|
zwarnnam(nam, "failed to create new session: %e", NULL, errno);
|
||||||
#endif
|
#endif
|
||||||
#ifdef TIOCNOTTY
|
#ifdef TIOCNOTTY
|
||||||
if (ioctl(SHTTY, TIOCNOTTY))
|
if (ioctl(SHTTY, TIOCNOTTY, 0))
|
||||||
zwarnnam(nam, "%e", NULL, errno);
|
zwarnnam(nam, "%e", NULL, errno);
|
||||||
setpgrp(0L, mypid);
|
setpgrp(0L, mypid);
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -98,18 +98,29 @@ static struct builtin bintab[] = {
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
boot_clone(Module m)
|
setup_(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
boot_(Module m)
|
||||||
{
|
{
|
||||||
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE
|
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
int
|
int
|
||||||
cleanup_clone(Module m)
|
cleanup_(Module m)
|
||||||
{
|
{
|
||||||
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
/**/
|
||||||
|
int
|
||||||
|
finish_(Module m)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2507,13 +2507,13 @@ forklevel;
|
||||||
static void
|
static void
|
||||||
entersubsh(int how, int cl, int fake)
|
entersubsh(int how, int cl, int fake)
|
||||||
{
|
{
|
||||||
int sig;
|
int sig, monitor;
|
||||||
|
|
||||||
if (cl != 2)
|
if (cl != 2)
|
||||||
for (sig = 0; sig < VSIGCOUNT; sig++)
|
for (sig = 0; sig < VSIGCOUNT; sig++)
|
||||||
if (!(sigtrapped[sig] & ZSIG_FUNC))
|
if (!(sigtrapped[sig] & ZSIG_FUNC))
|
||||||
unsettrap(sig);
|
unsettrap(sig);
|
||||||
if (unset(MONITOR)) {
|
if (!(monitor = isset(MONITOR))) {
|
||||||
if (how & Z_ASYNC) {
|
if (how & Z_ASYNC) {
|
||||||
settrap(SIGINT, NULL);
|
settrap(SIGINT, NULL);
|
||||||
settrap(SIGQUIT, NULL);
|
settrap(SIGQUIT, NULL);
|
||||||
|
|
@ -2569,7 +2569,7 @@ entersubsh(int how, int cl, int fake)
|
||||||
opts[MONITOR] = opts[USEZLE] = 0;
|
opts[MONITOR] = opts[USEZLE] = 0;
|
||||||
zleactive = 0;
|
zleactive = 0;
|
||||||
if (cl)
|
if (cl)
|
||||||
clearjobtab();
|
clearjobtab(monitor);
|
||||||
times(&shtms);
|
times(&shtms);
|
||||||
forklevel = locallevel;
|
forklevel = locallevel;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
77
Src/jobs.c
77
Src/jobs.c
|
|
@ -55,6 +55,12 @@ mod_export int prevjob;
|
||||||
/**/
|
/**/
|
||||||
mod_export struct job jobtab[MAXJOB];
|
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 */
|
/* shell timings */
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
|
|
@ -612,13 +618,18 @@ void
|
||||||
printjob(Job jn, int lng, int synch)
|
printjob(Job jn, int lng, int synch)
|
||||||
{
|
{
|
||||||
Process pn;
|
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;
|
int conted = 0, lineleng = columns, skip = 0, doputnl = 0;
|
||||||
FILE *fout = (synch == 2) ? stdout : shout;
|
FILE *fout = (synch == 2) ? stdout : shout;
|
||||||
|
|
||||||
if (jn->stat & STAT_NOPRINT)
|
if (jn->stat & STAT_NOPRINT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (jn < jobtab || jn >= jobtab + MAXJOB)
|
||||||
|
job = jn - oldjobtab;
|
||||||
|
else
|
||||||
|
job = jn - jobtab;
|
||||||
|
|
||||||
if (lng < 0) {
|
if (lng < 0) {
|
||||||
conted = 1;
|
conted = 1;
|
||||||
lng = 0;
|
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 ||
|
if (synch == 2 ||
|
||||||
job != thisjob)) {
|
(interact && jobbing &&
|
||||||
|
((jn->stat & STAT_STOPPED) || sflag || job != thisjob))) {
|
||||||
int len2, fline = 1;
|
int len2, fline = 1;
|
||||||
|
/* use special format for current job, except in `jobs' */
|
||||||
|
int thisfmt = job == thisjob && synch != 2;
|
||||||
Process qn;
|
Process qn;
|
||||||
|
|
||||||
if (!synch)
|
if (!synch)
|
||||||
|
|
@ -667,7 +681,7 @@ printjob(Job jn, int lng, int synch)
|
||||||
if (doputnl && !synch)
|
if (doputnl && !synch)
|
||||||
putc('\n', fout);
|
putc('\n', fout);
|
||||||
for (pn = jn->procs; pn;) {
|
for (pn = jn->procs; pn;) {
|
||||||
len2 = ((job == thisjob) ? 5 : 10) + len; /* 2 spaces */
|
len2 = (thisfmt ? 5 : 10) + len; /* 2 spaces */
|
||||||
if (lng & 3)
|
if (lng & 3)
|
||||||
qn = pn->next;
|
qn = pn->next;
|
||||||
else
|
else
|
||||||
|
|
@ -678,10 +692,10 @@ printjob(Job jn, int lng, int synch)
|
||||||
break;
|
break;
|
||||||
len2 += strlen(qn->text) + 2;
|
len2 += strlen(qn->text) + 2;
|
||||||
}
|
}
|
||||||
if (job != thisjob) {
|
if (!thisfmt) {
|
||||||
if (fline)
|
if (fline)
|
||||||
fprintf(fout, "[%ld] %c ",
|
fprintf(fout, "[%ld] %c ",
|
||||||
(long)(jn - jobtab),
|
(long)job,
|
||||||
(job == curjob) ? '+'
|
(job == curjob) ? '+'
|
||||||
: (job == prevjob) ? '-' : ' ');
|
: (job == prevjob) ? '-' : ' ');
|
||||||
else
|
else
|
||||||
|
|
@ -956,13 +970,32 @@ waitjobs(void)
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
mod_export void
|
mod_export void
|
||||||
clearjobtab(void)
|
clearjobtab(int monitor)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 1; i < MAXJOB; i++)
|
for (i = 1; i < MAXJOB; i++) {
|
||||||
if (jobtab[i].ty)
|
if (jobtab[i].ty) {
|
||||||
zfree(jobtab[i].ty, sizeof(struct ttyinfo));
|
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 */
|
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))
|
if (unset(NOTIFY))
|
||||||
scanjobs();
|
scanjobs();
|
||||||
|
|
||||||
setcurjob();
|
if (func != BIN_JOBS || isset(MONITOR) || !oldmaxjob)
|
||||||
|
setcurjob();
|
||||||
|
|
||||||
if (func == BIN_JOBS)
|
if (func == BIN_JOBS)
|
||||||
/* If you immediately type "exit" after "jobs", this *
|
/* If you immediately type "exit" after "jobs", this *
|
||||||
|
|
@ -1274,13 +1308,24 @@ bin_fg(char *name, char **argv, char *ops, int func)
|
||||||
firstjob = curjob;
|
firstjob = curjob;
|
||||||
} else if (func == BIN_JOBS) {
|
} else if (func == BIN_JOBS) {
|
||||||
/* List jobs. */
|
/* List jobs. */
|
||||||
for (job = 0; job != MAXJOB; job++)
|
struct job *jobptr;
|
||||||
if (job != thisjob && jobtab[job].stat) {
|
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']) ||
|
if ((!ops['r'] && !ops['s']) ||
|
||||||
(ops['r'] && ops['s']) ||
|
(ops['r'] && ops['s']) ||
|
||||||
(ops['r'] && !(jobtab[job].stat & STAT_STOPPED)) ||
|
(ops['r'] && !(jobptr->stat & STAT_STOPPED)) ||
|
||||||
(ops['s'] && jobtab[job].stat & STAT_STOPPED))
|
(ops['s'] && jobptr->stat & STAT_STOPPED))
|
||||||
printjob(job + jobtab, lng, 2);
|
printjob(jobptr, lng, 2);
|
||||||
}
|
}
|
||||||
unqueue_signals();
|
unqueue_signals();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue