summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2002-06-05 14:57:05 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2002-06-05 14:57:05 +0000
commit5ef61a44b12773eccd5de43acb18118eca09de29 (patch)
treea64021870c673a272fad5cec118ff4fa0c565648
parent5d010ca81a11d65fca5029644a349a2cd12f6c3b (diff)
downloadzsh-5ef61a44b12773eccd5de43acb18118eca09de29.tar.gz
zsh-5ef61a44b12773eccd5de43acb18118eca09de29.zip
17265: make the jobs command work in subshells
-rw-r--r--ChangeLog4
-rw-r--r--Src/Modules/clone.c25
-rw-r--r--Src/exec.c6
-rw-r--r--Src/jobs.c77
4 files changed, 86 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index bd6638098..f8927c79d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/Src/Modules/clone.c b/Src/Modules/clone.c
index 11387fc90..1a41b7448 100644
--- a/Src/Modules/clone.c
+++ b/Src/Modules/clone.c
@@ -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 !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+ return 0;
}
-#ifdef MODULE
+/**/
+int
+boot_(Module m)
+{
+ return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
+}
/**/
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;
+}
diff --git a/Src/exec.c b/Src/exec.c
index d3b33e174..4888c9fb8 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -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;
}
diff --git a/Src/jobs.c b/Src/jobs.c
index fc3737fa9..548cdb923 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -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;