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 '%')