From mboxrd@z Thu Jan 1 00:00:00 1970
X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org
X-Spam-Level:
X-Spam-Status: No, score=-3.4 required=5.0 tests=DKIM_SIGNED,DKIM_VALID,
DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED,
T_SCC_BODY_TEXT_LINE,UNPARSEABLE_RELAY autolearn=ham
autolearn_force=no version=3.4.4
Received: (qmail 6631 invoked from network); 1 Mar 2022 10:41:15 -0000
Received: from zero.zsh.org (2a02:898:31:0:48:4558:7a:7368)
by inbox.vuxu.org with ESMTPUTF8; 1 Mar 2022 10:41:15 -0000
ARC-Seal: i=1; cv=none; a=rsa-sha256; d=zsh.org; s=rsa-20210803; t=1646131275;
b=ciPYnOrtCG6Ov3c+ujvqmj3kjPLGM0xDsTBx2SV0kLHOl0egnI9+vnIL9FxYKpS8EaM5YZLnkQ
JCm5Rsb6fJD0Rdc8xUI044p98X+BbFm2nET0XLtBiVXIaZsWEXHnXRXTVlvk8KjAjUAsn8guyr
o9O+IOzuBP8ISuDvPOcMkkJ+j4pe0lhYr2XB6xPTS/FP+jssrqOETeICvWAVfMSIkH7wgL3eAF
WI6/6FRcby02J+R7G2/lxtuBrsN7IP9m20qLO7AHmfTS0k6j/p7Uol6IO4dfuGRLvppKsehhQs
nK/L9IvP363QLJhi97S7l2TkTAb+Qb4GCqiVCt5cvYC3wA==;
ARC-Authentication-Results: i=1; zsh.org;
iprev=pass (smtpq2.tb.ukmail.iss.as9143.net) smtp.remote-ip=212.54.57.97;
dkim=pass header.d=ntlworld.com header.s=meg.feb2017 header.a=rsa-sha256;
dmarc=pass header.from=ntlworld.com;
arc=none
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed; d=zsh.org; s=rsa-20210803; t=1646131275;
bh=8dw8t1TWs4hABZGw60HaWMWq2cXtH+biC6C1slBhBdY=;
h=List-Archive:List-Owner:List-Post:List-Unsubscribe:List-Subscribe:List-Help:
List-Id:Sender:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:
References:In-Reply-To:Message-ID:To:From:Date:DKIM-Signature:
DKIM-Signature;
b=iHfSDA4Fn/gl8RbprS/U/0mBgRubu7pex0lO/zAKQ4/IMWgaotPyMT5ucAy6IRZlJwxFxqchJi
rJouqiIWbShxBY2ivbZceUztnxkTOstP1+6t3eOUSkQmgj9tCCEq8WmGiOIKhQAzKm3ocvwhjJ
3l9whFuHjvZA2Zr3MFFMTqaJvWcNgtqq4FrbjNBpyjZCNwkJqKWNZtdVPLdzZAlv6BxTX2gEr0
/7huBAtJ+pD6u5RdIBY/gL+hxFzu5ucO2UUHHDV7mBrjotVoOs8KmFwVFm2gKAaq79Iqq+3g/T
dCi6W7V0qbsJiV9cO+gi98rEHdif/1Fr8PPBSyFHlEUrjg==;
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=zsh.org;
s=rsa-20210803; h=List-Archive:List-Owner:List-Post:List-Unsubscribe:
List-Subscribe:List-Help:List-Id:Sender:Content-Transfer-Encoding:
Content-Type:MIME-Version:Subject:References:In-Reply-To:Message-ID:To:From:
Date:Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From:
Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID;
bh=5/ntLA8Hqwftrpj64mx3Tgdl941qL8yo/wHwoav7MA8=; b=Rv80TCfmXcdCVpRy8N+uA876zA
k8ZDLFelv5FnJ7rkk9YlCYCedGBNd4SwrHKw+CtKHgKzpcCT1V3hYxUIPyVo9hGk+KwcJUqzXvhdT
SD7v9TCpp4/RWxAiOEWB+WrCmR+0MKdLhDklDkaSIM0n7URRNC4b9Hdw1nmGooiLuQaQgV4B11AIk
uChujiGKi5tAzcXpbRZGDjANoWzS2ywgm/Um0iaWvjFgqiIQILmIjAMGD4GMyyPQXt0HDhHQVKXoz
Sc+7bLU3aqUrN2bJtJ3hP+F223MfL17LC8VIjKRHLSYA0uMbSybqOW28ysM4QgxEFcD8owWhyU74N
6mFfUNzA==;
Received: from authenticated user by zero.zsh.org with local
id 1nOzwP-0004ju-Sv; Tue, 01 Mar 2022 10:41:14 +0000
Authentication-Results: zsh.org;
iprev=pass (smtpq2.tb.ukmail.iss.as9143.net) smtp.remote-ip=212.54.57.97;
dkim=pass header.d=ntlworld.com header.s=meg.feb2017 header.a=rsa-sha256;
dmarc=pass header.from=ntlworld.com;
arc=none
Received: from smtpq2.tb.ukmail.iss.as9143.net ([212.54.57.97]:38754)
by zero.zsh.org with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256)
id 1nOzw3-0004PT-VU; Tue, 01 Mar 2022 10:40:52 +0000
Received: from [212.54.57.81] (helo=smtp2.tb.ukmail.iss.as9143.net)
by smtpq2.tb.ukmail.iss.as9143.net with esmtp (Exim 4.90_1)
(envelope-from
)
id 1nOzw3-0006rv-90
for zsh-workers@zsh.org; Tue, 01 Mar 2022 11:40:51 +0100
Received: from oxbe7.tb.ukmail.iss.as9143.net ([172.25.160.138])
by smtp2.tb.ukmail.iss.as9143.net with ESMTP
id Ozw2naIV7fHYvOzw3ndYWc; Tue, 01 Mar 2022 11:40:51 +0100
X-Env-Mailfrom: p.w.stephenson@ntlworld.com
X-Env-Rcptto: zsh-workers@zsh.org
X-SourceIP: 172.25.160.138
X-CNFS-Analysis: v=2.4 cv=Wbkf1mtX c=1 sm=1 tr=0 ts=621df833 cx=a_exe
a=fsVlV1GYKS3C/xnq+HX56g==:117 a=xNnLE9zTUD1jbiPY:21 a=wbvTLvLwOfMA:10
a=IkcTkHD0fZMA:10 a=7H6ixmLU1AQA:10 a=pGLkceISAAAA:8 a=pBFu8Sfzi2z9XQLEI18A:9
a=QEXdDO2ut3YA:10 a=zXeNQK-WQ8sVPEEfHoKV:22
X-Authenticated-Sender: p.w.stephenson@ntlworld.com
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ntlworld.com;
s=meg.feb2017; t=1646131251;
bh=8dw8t1TWs4hABZGw60HaWMWq2cXtH+biC6C1slBhBdY=;
h=Date:From:To:In-Reply-To:References:Subject;
b=5cB0CBtFbeakIKDBZHpYzeFxFu4E7cDyfbiXOisNxLGWt4q5HfGyJtTXhGvhpeEtI
6wygv4ZowwaCtwkVbB7HJwv80BO79tdLLlkmKI+55pXT7m93OqbRZdML+bzZqII/pm
S2in9jX/XykdgTwP4UxSYKzKoymZe3E9okEW0aj6ODyzBKQ2YaRmphqdxZjNnxPl1d
EMMX0qjoYf7xzGrobDJ3ZmImkK9tVyVKcd7yJu+LHvnVOOPGOrpmv8N1ftvSep8Avq
Kcy2ffgyW6roAa9awZOjqvJk9LuKJSuvKOI/ww/5BNqnmdHMgLdBMhvB4rDr2LbKcm
SHt0hpoGvVxwg==
Date: Tue, 1 Mar 2022 10:40:50 +0000 (GMT)
From: Peter Stephenson
To: Carl Agrell , zsh-workers
Message-ID: <1912988517.1110378.1646131250968@mail2.virginmedia.com>
In-Reply-To:
References:
Subject: Re: [Bug] $jobstates does not work in $()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
X-Priority: 3
Importance: Medium
X-Mailer: Open-Xchange Mailer v7.8.4-Rev72
X-Originating-IP: 147.161.167.85
X-Originating-Client: open-xchange-appsuite
X-CMAE-Envelope: MS4xfGcpnDcRdtjUvQG2szKnAxPgqd8n6X3s+4VBc5KatyEHCMPhxqsecBMU06GQIETxmQQ/XreKbUlrVy7AdNZQFZF24Ed0CXCdKOFaIWKP3UOvwK9g7Msf
bZ88Yh+8/9VXYyTPSrmNhh2Bwimjg7Ixk7y8jkIkuE6lLW3FSN/7HqSR3bsfLsTcdznDgUwPexEJwUBcXWy1pYoDnXFejmiEAPRWOKh0djS/BXqtSf4xVxe0
p0xE+yageT4tqEl+VgMW/g==
X-Seq: 49783
Archived-At:
X-Loop: zsh-workers@zsh.org
Errors-To: zsh-workers-owner@zsh.org
Precedence: list
Precedence: bulk
Sender: zsh-workers-request@zsh.org
X-no-archive: yes
List-Id:
List-Help:
List-Subscribe:
List-Unsubscribe:
List-Post:
List-Owner:
List-Archive:
> On 01 March 2022 at 00:46 Carl Agrell wrote:
>=20
>=20
> It appears that zsh/parameter's $jobstates is always empty inside $(),
> probably because it's a subshell of some sort. `jobs` still works
> however, making it rather incongruous. Having access to $jobstates
> would be useful for prompts for example, rather than having to parse
> the output of `jobs`.
>=20
> To reproduce:
> =E2=9D=AF sleep 1000 &
> [1] 210460
> =E2=9D=AF jobs
> [1] + running sleep 1000
> =E2=9D=AF echo $jobstates
> running:+:210460=3Drunning
> =E2=9D=AF echo $(jobs)
> [1] + running sleep 1000
> =E2=9D=AF echo $(echo $jobstates)
> (empty)
Yes, we store the old job table for use with the builtin, but not with
parameters, which is inconsistent.
What is probably worse is that some parameters (not, as it happens,
jobstates) call getjob(), which does have the logic to switch to the old
table, but then make no attempt to switch to the right table for the
remainder of the processing, which could result in undefined behaviour.
This fixes it up with a function selectjobtab() used to query job states
in the parameter functions as well as getjob().
pws
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -1244,19 +1244,19 @@ histwgetfn(UNUSED(Param pm))
=20
/**/
static char *
-pmjobtext(int job)
+pmjobtext(Job jtab, int job)
{
Process pn;
int len =3D 1;
char *ret;
=20
- for (pn =3D jobtab[job].procs; pn; pn =3D pn->next)
+ for (pn =3D jtab[job].procs; pn; pn =3D pn->next)
=09len +=3D strlen(pn->text) + 3;
=20
ret =3D (char *) zhalloc(len);
ret[0] =3D '\0';
=20
- for (pn =3D jobtab[job].procs; pn; pn =3D pn->next) {
+ for (pn =3D jtab[job].procs; pn; pn =3D pn->next) {
=09strcat(ret, pn->text);
=09if (pn->next)
=09 strcat(ret, " | ");
@@ -1269,22 +1269,25 @@ static HashNode
getpmjobtext(UNUSED(HashTable ht), const char *name)
{
Param pm =3D NULL;
- int job;
+ int job, jmax;
char *pend;
+ Job jtab;
=20
pm =3D (Param) hcalloc(sizeof(struct param));
pm->node.nam =3D dupstring(name);
pm->node.flags =3D PM_SCALAR | PM_READONLY;
pm->gsu.s =3D &nullsetscalar_gsu;
=20
+ selectjobtab(&jtab, &jmax);
+
job =3D strtod(name, &pend);
/* Non-numeric keys are looked up by job name */
if (*pend)
=09job =3D getjob(name, NULL);
- if (job >=3D 1 && job <=3D maxjob &&
-=09jobtab[job].stat && jobtab[job].procs &&
-=09!(jobtab[job].stat & STAT_NOPRINT))
-=09pm->u.str =3D pmjobtext(job);
+ if (job >=3D 1 && job <=3D jmax &&
+=09jtab[job].stat && jtab[job].procs &&
+=09!(jtab[job].stat & STAT_NOPRINT))
+=09pm->u.str =3D pmjobtext(jtab, job);
else {
=09pm->u.str =3D dupstring("");
=09pm->node.flags |=3D (PM_UNSET|PM_SPECIAL);
@@ -1297,22 +1300,25 @@ static void
scanpmjobtexts(UNUSED(HashTable ht), ScanFunc func, int flags)
{
struct param pm;
- int job;
+ int job, jmax;
char buf[40];
+ Job jtab;
=20
memset((void *)&pm, 0, sizeof(struct param));
pm.node.flags =3D PM_SCALAR | PM_READONLY;
pm.gsu.s =3D &nullsetscalar_gsu;
=20
- for (job =3D 1; job <=3D maxjob; job++) {
-=09if (jobtab[job].stat && jobtab[job].procs &&
-=09 !(jobtab[job].stat & STAT_NOPRINT)) {
+ selectjobtab(&jtab, &jmax);
+
+ for (job =3D 1; job <=3D jmax; job++) {
+=09if (jtab[job].stat && jtab[job].procs &&
+=09 !(jtab[job].stat & STAT_NOPRINT)) {
=09 if (func !=3D scancountparams) {
=09=09sprintf(buf, "%d", job);
=09=09pm.node.nam =3D dupstring(buf);
=09=09if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
=09=09 !(flags & SCANPM_WANTKEYS))
-=09=09 pm.u.str =3D pmjobtext(job);
+=09=09 pm.u.str =3D pmjobtext(jtab, job);
=09 }
=09 func(&pm.node, flags);
=09}
@@ -1323,7 +1329,7 @@ scanpmjobtexts(UNUSED(HashTable ht), ScanFunc func, i=
nt flags)
=20
/**/
static char *
-pmjobstate(int job)
+pmjobstate(Job jtab, int job)
{
Process pn;
char buf[256], buf2[128], *ret, *state, *cp;
@@ -1335,14 +1341,14 @@ pmjobstate(int job)
else
=09cp =3D ":";
=20
- if (jobtab[job].stat & STAT_DONE)
+ if (jtab[job].stat & STAT_DONE)
=09ret =3D dyncat("done", cp);
- else if (jobtab[job].stat & STAT_STOPPED)
+ else if (jtab[job].stat & STAT_STOPPED)
=09ret =3D dyncat("suspended", cp);
else
=09ret =3D dyncat("running", cp);
=20
- for (pn =3D jobtab[job].procs; pn; pn =3D pn->next) {
+ for (pn =3D jtab[job].procs; pn; pn =3D pn->next) {
=20
=09if (pn->status =3D=3D SP_RUNNING)
=09 state =3D "running";
@@ -1371,21 +1377,24 @@ static HashNode
getpmjobstate(UNUSED(HashTable ht), const char *name)
{
Param pm =3D NULL;
- int job;
+ int job, jmax;
char *pend;
+ Job jtab;
=20
pm =3D (Param) hcalloc(sizeof(struct param));
pm->node.nam =3D dupstring(name);
pm->node.flags =3D PM_SCALAR | PM_READONLY;
pm->gsu.s =3D &nullsetscalar_gsu;
=20
+ selectjobtab(&jtab, &jmax);
+
job =3D strtod(name, &pend);
if (*pend)
=09job =3D getjob(name, NULL);
- if (job >=3D 1 && job <=3D maxjob &&
-=09jobtab[job].stat && jobtab[job].procs &&
-=09!(jobtab[job].stat & STAT_NOPRINT))
-=09pm->u.str =3D pmjobstate(job);
+ if (job >=3D 1 && job <=3D jmax &&
+=09jtab[job].stat && jtab[job].procs &&
+=09!(jtab[job].stat & STAT_NOPRINT))
+=09pm->u.str =3D pmjobstate(jtab, job);
else {
=09pm->u.str =3D dupstring("");
=09pm->node.flags |=3D (PM_UNSET|PM_SPECIAL);
@@ -1398,22 +1407,25 @@ static void
scanpmjobstates(UNUSED(HashTable ht), ScanFunc func, int flags)
{
struct param pm;
- int job;
+ int job, jmax;
+ Job jtab;
char buf[40];
=20
+ selectjobtab(&jtab, &jmax);
+
memset((void *)&pm, 0, sizeof(struct param));
pm.node.flags =3D PM_SCALAR | PM_READONLY;
pm.gsu.s =3D &nullsetscalar_gsu;
=20
- for (job =3D 1; job <=3D maxjob; job++) {
-=09if (jobtab[job].stat && jobtab[job].procs &&
-=09 !(jobtab[job].stat & STAT_NOPRINT)) {
+ for (job =3D 1; job <=3D jmax; job++) {
+=09if (jtab[job].stat && jtab[job].procs &&
+=09 !(jtab[job].stat & STAT_NOPRINT)) {
=09 if (func !=3D scancountparams) {
=09=09sprintf(buf, "%d", job);
=09=09pm.node.nam =3D dupstring(buf);
=09=09if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
=09=09 !(flags & SCANPM_WANTKEYS))
-=09=09 pm.u.str =3D pmjobstate(job);
+=09=09 pm.u.str =3D pmjobstate(jtab, job);
=09 }
=09 func(&pm.node, flags);
=09}
@@ -1424,11 +1436,11 @@ scanpmjobstates(UNUSED(HashTable ht), ScanFunc func=
, int flags)
=20
/**/
static char *
-pmjobdir(int job)
+pmjobdir(Job jtab, int job)
{
char *ret;
=20
- ret =3D dupstring(jobtab[job].pwd ? jobtab[job].pwd : pwd);
+ ret =3D dupstring(jtab[job].pwd ? jtab[job].pwd : pwd);
return ret;
}
=20
@@ -1437,21 +1449,24 @@ static HashNode
getpmjobdir(UNUSED(HashTable ht), const char *name)
{
Param pm =3D NULL;
- int job;
+ int job, jmax;
char *pend;
+ Job jtab;
=20
pm =3D (Param) hcalloc(sizeof(struct param));
pm->node.nam =3D dupstring(name);
pm->node.flags =3D PM_SCALAR | PM_READONLY;
pm->gsu.s =3D &nullsetscalar_gsu;
=20
+ selectjobtab(&jtab, &jmax);
+
job =3D strtod(name, &pend);
if (*pend)
=09job =3D getjob(name, NULL);
- if (job >=3D 1 && job <=3D maxjob &&
-=09jobtab[job].stat && jobtab[job].procs &&
-=09!(jobtab[job].stat & STAT_NOPRINT))
-=09pm->u.str =3D pmjobdir(job);
+ if (job >=3D 1 && job <=3D jmax &&
+=09jtab[job].stat && jtab[job].procs &&
+=09!(jtab[job].stat & STAT_NOPRINT))
+=09pm->u.str =3D pmjobdir(jtab, job);
else {
=09pm->u.str =3D dupstring("");
=09pm->node.flags |=3D (PM_UNSET|PM_SPECIAL);
@@ -1464,22 +1479,25 @@ static void
scanpmjobdirs(UNUSED(HashTable ht), ScanFunc func, int flags)
{
struct param pm;
- int job;
+ int job, jmax;
char buf[40];
+ Job jtab;
=20
memset((void *)&pm, 0, sizeof(struct param));
pm.node.flags =3D PM_SCALAR | PM_READONLY;
pm.gsu.s =3D &nullsetscalar_gsu;
=20
- for (job =3D 1; job <=3D maxjob; job++) {
- if (jobtab[job].stat && jobtab[job].procs &&
- !(jobtab[job].stat & STAT_NOPRINT)) {
+ selectjobtab(&jtab, &jmax);
+
+ for (job =3D 1; job <=3D jmax; job++) {
+ if (jtab[job].stat && jtab[job].procs &&
+ !(jtab[job].stat & STAT_NOPRINT)) {
if (func !=3D scancountparams) {
=09 sprintf(buf, "%d", job);
=09 pm.node.nam =3D dupstring(buf);
if ((flags & (SCANPM_WANTVALS|SCANPM_MATCHVAL)) ||
=09=09 !(flags & SCANPM_WANTKEYS))
-=09=09 pm.u.str =3D pmjobdir(job);
+=09=09 pm.u.str =3D pmjobdir(jtab, job);
=09 }
func(&pm.node, flags);
}
diff --git a/Src/jobs.c b/Src/jobs.c
index f0b337110..18e43f03c 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -98,10 +98,12 @@ mod_export int jobtabsize;
mod_export int maxjob;
=20
/* If we have entered a subshell, the original shell's job table. */
-static struct job *oldjobtab;
+/**/
+mod_export struct job *oldjobtab;
=20
/* The size of that. */
-static int oldmaxjob;
+/**/
+mod_export int oldmaxjob;
=20
/* shell timings */
=20
@@ -1894,6 +1896,26 @@ setcurjob(void)
}
}
=20
+/* Find the job table for reporting jobs */
+
+/**/
+mod_export void
+selectjobtab(Job *jtabp, int *jmaxp)
+{
+ if (oldjobtab)
+ {
+=09/* In subshell --- use saved job table to report */
+=09*jtabp =3D oldjobtab;
+=09*jmaxp =3D oldmaxjob;
+ }
+ else
+ {
+=09/* Use main job table */
+=09*jtabp =3D jobtab;
+=09*jmaxp =3D maxjob;
+ }
+}
+
/* Convert a job specifier ("%%", "%1", "%foo", "%?bar?", etc.) *
* to a job number. */
=20
@@ -1904,13 +1926,7 @@ getjob(const char *s, const char *prog)
int jobnum, returnval, mymaxjob;
Job myjobtab;
=20
- if (oldjobtab) {
-=09myjobtab =3D oldjobtab;
-=09mymaxjob =3D oldmaxjob;
- } else {
-=09myjobtab=3D jobtab;
-=09mymaxjob =3D maxjob;
- }
+ selectjobtab(&myjobtab, &mymaxjob);
=20
/* if there is no %, treat as a name */
if (*s !=3D '%')