From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-0.8 required=5.0 tests=DKIM_ADSP_CUSTOM_MED, DKIM_INVALID,DKIM_SIGNED,FREEMAIL_FROM,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from primenet.com.au (ns1.primenet.com.au [203.24.36.2]) by inbox.vuxu.org (OpenSMTPD) with ESMTP id a6f462d2 for ; Wed, 31 Jul 2019 19:41:52 +0000 (UTC) Received: (qmail 12448 invoked by alias); 31 Jul 2019 19:41:45 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: List-Unsubscribe: X-Seq: 44629 Received: (qmail 11610 invoked by uid 1010); 31 Jul 2019 19:41:45 -0000 X-Qmail-Scanner-Diagnostics: from mail-lj1-f181.google.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.101.2/25524. spamassassin: 3.4.2. Clear:RC:0(209.85.208.181):SA:0(-2.0/5.0):. Processed in 2.807032 secs); 31 Jul 2019 19:41:45 -0000 X-Envelope-From: timothee.mazzucotelli@gmail.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _netblocks.google.com designates 209.85.208.181 as permitted sender) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=0DnizECzac3+nYq3md7bJ6ewjgVNGP+l93ZSOuM0x/k=; b=Nn2I+TIRQzPsghE21/0xZH05f4ygXFhQ4aKuABtSN1w2Jbem2upgslOPQSWfBYdEWN byf+wOBVQKyKkpOTus1umXiCpCX3FUl1/dsgmpR5d5835AJFDL+KisMtFxgWN+SJEL/s wmvilhcSzw9MrkkyhfNLea2TvcNvC/3TVC2CmmcUvGu9bgrRbk5UjSaOQMdlKCaDY5e9 ejbEugPNyc3MyFi1cOyrKbPtnzcIVu4N3FVsRQ7hHZemMs2+CUgTqxT5Wt7PwoFP4ZOb 5nUBV9tkfEoKcvYK4x5Lpy1efXpWcJ7ZTwBKzZcJmIMa207CFlXEUwgZTRvlH3ZAFuM/ Ix6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=0DnizECzac3+nYq3md7bJ6ewjgVNGP+l93ZSOuM0x/k=; b=mrmoQ5khGlNLaTEyRNq1lGMMrOsnwJfdIiAdCcrSP0bhY8VGB/LYmiNygTuf5XB9io 24EG08VzybKpsTpASOYsDYDbFHCthMSAsiIHsltzswIAlP1wgX2vQr1jC2viTZ2XJ1IU blL7zIE892TgqcFaOqowarHi0ilMN1wfetn/73b8+RnRlNT6sQbDfcVSLbdcg2ru4kCo XkzbtAdwBYGDjNDWgLaEzQ0mF48WeeUyjDmz6W0IE0QVT4HjOSXym4H2rNZjhKlgC1+J UrWD3PAdTkmjzq5qWGiV4IEhiC35DdqOrILUEy3/hwKxR/mstC2LGSLPpAssWBu5/G5x PniQ== X-Gm-Message-State: APjAAAUqV+O/xziZoFnr2Dm1E60d1M7ig1nO9W97n6ym1GFJhTolKtH6 6BWIDSZS0M3Z/27XCGEF2WfmlgOSkKwmnIVDpHK4DpYX8VQ= X-Google-Smtp-Source: APXvYqwUY7+mvjTXlrvi4sgCJhP7gQydq7BuxuEB+J2Ou+U1UocmpuZgc5vZ0wVPbuLeI/fnfzeGLvF3Xc8QpHxywbg= X-Received: by 2002:a2e:b167:: with SMTP id a7mr66945715ljm.26.1564602066827; Wed, 31 Jul 2019 12:41:06 -0700 (PDT) MIME-Version: 1.0 References: <20190518075514.hbygmb5dl5wz23h5@chaz.gmail.com> <20190520103444.qyih7lvoigvf3rfx@chaz.gmail.com> <1563722540.4311.24.camel@samsung.com> In-Reply-To: <1563722540.4311.24.camel@samsung.com> From: =?UTF-8?Q?Timoth=C3=A9e_Mazzucotelli?= Date: Wed, 31 Jul 2019 21:40:56 +0200 Message-ID: Subject: Re: Feature request: ZSH_XTRACEFD variable To: Peter Stephenson Cc: zsh-workers@zsh.org Content-Type: multipart/alternative; boundary="000000000000688050058eff4e69" --000000000000688050058eff4e69 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Thank you Peter for your hints. Here is a first draft: diff --git a/Src/exec.c b/Src/exec.c index 2acb2c0bc..5e550cb24 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -5393,7 +5393,7 @@ execshfunc(Shfunc shf, LinkList args) cmdsp =3D 0; if ((osfc =3D sfcontext) =3D=3D SFC_NONE) sfcontext =3D SFC_DIRECT; - xtrerr =3D stderr; + xtrerr =3D fdopen(zsh_xtracefd, "w"); doshfunc(shf, args, 0); diff --git a/Src/init.c b/Src/init.c index 445cd3937..396f13556 100644 --- a/Src/init.c +++ b/Src/init.c @@ -609,8 +609,10 @@ init_io(char *cmd) SHTTY =3D -1; } - /* Send xtrace output to stderr -- see execcmd() */ - xtrerr =3D stderr; + /* Send xtrace output to zsh_xtracefd file descriptor -- see execcmd() */ + if (zsh_xtracefd =3D=3D 0) + zsh_xtracefd =3D 2; + xtrerr =3D fdopen(zsh_xtracefd, "w"); /* Make sure the tty is opened read/write. */ if (isatty(0)) { diff --git a/Src/params.c b/Src/params.c index 1499e3a40..5e3f5cdbf 100644 --- a/Src/params.c +++ b/Src/params.c @@ -102,7 +102,8 @@ zlong lastval, /* $? */ zterm_lines, /* $LINES */ rprompt_indent, /* $ZLE_RPROMPT_INDENT */ ppid, /* $PPID */ - zsh_subshell; /* $ZSH_SUBSHELL */ + zsh_subshell, /* $ZSH_SUBSHELL */ + zsh_xtracefd; /* $ZSH_XTRACEFD */ /* $FUNCNEST */ /**/ @@ -264,6 +265,9 @@ static const struct gsu_array pipestatus_gsu =3D static const struct gsu_integer rprompt_indent_gsu =3D { intvargetfn, zlevarsetfn, rprompt_indent_unsetfn }; +static const struct gsu_integer xtracefd_gsu =3D +{ intvargetfn, xtracefdsetfn, xtracefdunsetfn }; + /* Nodes for special parameters for parameter hash table */ #ifdef HAVE_UNION_INIT @@ -353,6 +357,7 @@ IPDEF5("LINES", &zterm_lines, zlevar_gsu), IPDEF5U("ZLE_RPROMPT_INDENT", &rprompt_indent, rprompt_indent_gsu), IPDEF5("SHLVL", &shlvl, varinteger_gsu), IPDEF5("FUNCNEST", &zsh_funcnest, varinteger_gsu), +IPDEF5("ZSH_XTRACEFD", &zsh_xtracefd, xtracefd_gsu), /* Don't import internal integer status variables. */ #define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0} @@ -4387,6 +4392,45 @@ setsecondstype(Param pm, int on, int off) return 0; } +/* Function to set value of special parameter `ZSH_XTRACEFD' */ + +/**/ +void +xtracefdsetfn(Param pm, zlong fd) +{ + int current_fd; + + /* Check that the given file descriptor is valid */ + if (fcntl(fd, F_GETFD) !=3D -1 || errno !=3D EBADF) { + current_fd =3D intvargetfn(pm); + /* We never close file descriptors 0 (stdin), 1 (stdout) or 2 (stderr) */ + if (current_fd > 2) { + close(current_fd); + fclose(xtrerr); + } + intvarsetfn(pm, fd); + xtrerr =3D fdopen(fd, "w"); + } else + zwarn("file descriptor %d is not valid", fd); + +} + +/* Function to unset value of special parameter `ZSH_XTRACEFD' */ + +/**/ +void +xtracefdunsetfn(Param pm, UNUSED(int exp)) +{ + int current_fd =3D intvargetfn(pm); + if (current_fd =3D=3D 2) /* Nothing to do, already using stderr */ + return; + else { /* Reset to file descriptor 2 (stderr) */ + intvarsetfn(pm, 2); + if (current_fd > 1) fclose(xtrerr); /* Never close stdin or stdout */ + xtrerr =3D stderr; + } +} + /* Function to get value for special parameter `USERNAME' */ /**/ diff --git a/Src/utils.c b/Src/utils.c index 46cf7bcf6..93ea8044f 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -1765,7 +1765,7 @@ void printprompt4(void) { if (!xtrerr) - xtrerr =3D stderr; + xtrerr =3D fdopen(zsh_xtracefd, "w"); if (prompt4) { int l, t =3D opts[XTRACE]; char *s =3D dupstring(prompt4); And some notes: There is one place where I didn't change the code, because I wasn't sure it was needed: > Doing this without creating leaks or crashes on bad file descriptors could be interesting. About leaks, I think file pointers are all freed in the params.c set and unset functions. However I'm not sure about exec.c, line 5396, in function execshfunc, where xtrerr was previously always reassigned to stderr. Now it is reassigned to a new file pointer obtained with fdopen(zsh_xtracefd, "w") each time, and maybe this could cause memory leaks. About crashes on bad file descriptors, I used if (fcntl(fd, F_GETFD) !=3D -= 1 || errno !=3D EBADF) as a condition to test the validity of a file descriptor, but I'm not sure it can handle all the cases, or if it even makes sense. It's working with basic cases though. On Sun, Jul 21, 2019 at 5:23 PM Peter Stephenson wrote: > On Sun, 2019-07-21 at 17:08 +0200, Timoth=C3=A9e Mazzucotelli wrote: > > I'm willing to help implementing this feature (equivalent of Bash's > > BASH_XTRACEFD). Any advice where I should start? Who I should get in > touch > > with? > > This is the right place. Certainly feel free to investigate. > > Have a look at the way the FILE *xtrerr is handed in the source code. Th= is > is going to need some more careful management. Doing this without creati= ng > leaks or crashes on bad file descriptors could be interesting. > In most places, once it is reopened to a different file the redirection > should "just work", but there maybe some interesting special cases > as we do do slightly funny things with xtrerr at some points. > > I think you're going to need a special integer variable that manages > this file based on someone setting the FD. params.c has this sort > of handling --- see various special integer variables with > their own get / set functions, e.g. intsecondssetfn shows you > what happens when someone sets SECONDS. You're going to have > a function of that sort that instead closes and reopens > xtrerr. > > I guess ZSH_XTRACEFD is the obvious name. > > Cheers > pws > > --000000000000688050058eff4e69--