zsh-workers
 help / color / mirror / code / Atom feed
From: "Timothée Mazzucotelli" <timothee.mazzucotelli@gmail.com>
To: Peter Stephenson <p.stephenson@samsung.com>, zsh-workers@zsh.org
Subject: Re: Feature request: ZSH_XTRACEFD variable
Date: Sun, 19 Apr 2020 12:30:33 +0200	[thread overview]
Message-ID: <CAD8ZDTotCLBANtzppSbCcgKyLhkXaVWysjqv99xS6bnLypBViA@mail.gmail.com> (raw)
In-Reply-To: <1565710707.5633.11.camel@samsung.com>


[-- Attachment #1.1: Type: text/plain, Size: 5452 bytes --]

Hello :)

I managed to write a test for the ZSH_XTRACEFD feature in A04redirect.ztst,
and am planning to add more tests, but maybe you'd have some hints on what
I should test?

Patch in attachment.





On Tue, Aug 13, 2019 at 5:39 PM Peter Stephenson <p.stephenson@samsung.com>
wrote:

> How about this?
>
> I've tried to make it so that if the fd is 2 or less it always uses
> the standard file, if it's greater it always creates or frees one, and
> it only creates a new file when it's requested to switch.
>
> One other fix is that we only need to fclose(xtrerr) which then closes
> the file descriptor.  There's no way of just closing the file and not
> the file descriptor --- we'll need to document that the file descriptor
> is closed if ZSH_XTRACEFD changes again since it's a bit illogical given
> that the user opened the fd in the first place.
>
> pws
>
> diff --git a/Src/exec.c b/Src/exec.c
> index e81053d67..fe702b644 100644
> --- a/Src/exec.c
> +++ b/Src/exec.c
> @@ -5394,7 +5394,7 @@ execshfunc(Shfunc shf, LinkList args)
>      cmdsp = 0;
>      if ((osfc = sfcontext) == SFC_NONE)
>         sfcontext = SFC_DIRECT;
> -    xtrerr = stderr;
> +    xtrerr = xtrace_file;
>
>      doshfunc(shf, args, 0);
>
> diff --git a/Src/init.c b/Src/init.c
> index 445cd3937..c51197079 100644
> --- a/Src/init.c
> +++ b/Src/init.c
> @@ -609,8 +609,10 @@ init_io(char *cmd)
>         SHTTY = -1;
>      }
>
> -    /* Send xtrace output to stderr -- see execcmd() */
> -    xtrerr = stderr;
> +    /* Send xtrace output to zsh_xtracefd file descriptor -- see
> execcmd() */
> +    if (zsh_xtracefd == 0)
> +       zsh_xtracefd = 2;
> +    xtracefdassign();
>
>      /* Make sure the tty is opened read/write. */
>      if (isatty(0)) {
> diff --git a/Src/params.c b/Src/params.c
> index 1499e3a40..2347ee9c3 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 =
>  static const struct gsu_integer rprompt_indent_gsu =
>  { intvargetfn, zlevarsetfn, rprompt_indent_unsetfn };
>
> +static const struct gsu_integer xtracefd_gsu =
> +{ 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,71 @@ setsecondstype(Param pm, int on, int off)
>      return 0;
>  }
>
> +/* Open / assign the XTRACE fd */
> +
> +/**/
> +void xtracefdassign(void)
> +{
> +    int fd = (int)zsh_xtracefd;
> +    switch (fd)
> +    {
> +    case 0:                    /* bizarre, but handle for consistency */
> +       xtrerr = stdin;
> +       break;
> +
> +    case 1:
> +       xtrerr = stdout;
> +       break;
> +
> +    case 2:
> +       xtrerr = stderr;
> +       break;
> +
> +    default:
> +       xtrerr = fdopen(fd, "w");
> +       break;
> +    }
> +    xtrace_file = xtrerr;
> +}
> +
> +/* 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) != -1 || errno != EBADF) {
> +      current_fd = intvargetfn(pm);
> +      /* We never close file descriptors 0 (stdin), 1 (stdout) or 2
> stderr) */
> +      if (current_fd > 2)
> +        fclose(xtrerr);
> +      intvarsetfn(pm, fd);
> +      xtracefdassign();
> +    } 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 = intvargetfn(pm);
> +    if (current_fd == 2)  /* Nothing to do, already using stderr */
> +      return;
> +    else {  /* Reset to file descriptor 2 (stderr) */
> +      intvarsetfn(pm, 2);
> +      if (current_fd > 2)
> +         fclose(xtrerr);  /* Never close standard descriptors */
> +      xtrerr = xtrace_file = stderr;
> +    }
> +}
> +
>  /* Function to get value for special parameter `USERNAME' */
>
>  /**/
> diff --git a/Src/utils.c b/Src/utils.c
> index 46cf7bcf6..2eee27697 100644
> --- a/Src/utils.c
> +++ b/Src/utils.c
> @@ -1760,12 +1760,19 @@ checkmailpath(char **s)
>  /**/
>  FILE *xtrerr = 0;
>
> +/* This records the last file XTRACE was open too.
> + * It's used for restoring XTRACE after a possible redirection.gggg
> + */
> +
> +/**/
> +FILE *xtrace_file;
> +
>  /**/
>  void
>  printprompt4(void)
>  {
>      if (!xtrerr)
> -       xtrerr = stderr;
> +       xtracefdassign();
>      if (prompt4) {
>         int l, t = opts[XTRACE];
>         char *s = dupstring(prompt4);
>

[-- Attachment #1.2: Type: text/html, Size: 7005 bytes --]

[-- Attachment #2: 0001-44752-Implement-ZSH_XTRACEFD-feature.patch --]
[-- Type: text/x-patch, Size: 5280 bytes --]

From 70a069a43fc15eff5163290ecaa79d7c71708460 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= <pawamoy@pm.me>
Date: Sat, 18 Apr 2020 17:22:03 +0200
Subject: [PATCH] 44752: Implement ZSH_XTRACEFD feature

---
 Src/exec.c            |  2 +-
 Src/init.c            |  6 ++--
 Src/params.c          | 72 ++++++++++++++++++++++++++++++++++++++++++-
 Src/utils.c           |  9 +++++-
 Test/A04redirect.ztst | 10 ++++++
 5 files changed, 94 insertions(+), 5 deletions(-)

diff --git a/Src/exec.c b/Src/exec.c
index 2b8e2167f..0e34f5f96 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -5421,7 +5421,7 @@ execshfunc(Shfunc shf, LinkList args)
     cmdsp = 0;
     if ((osfc = sfcontext) == SFC_NONE)
 	sfcontext = SFC_DIRECT;
-    xtrerr = stderr;
+    xtrerr = xtrace_file;
 
     doshfunc(shf, args, 0);
 
diff --git a/Src/init.c b/Src/init.c
index 3d6c94d04..89c50b17e 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -616,8 +616,10 @@ init_io(char *cmd)
 	SHTTY = -1;
     }
 
-    /* Send xtrace output to stderr -- see execcmd() */
-    xtrerr = stderr;
+    /* Send xtrace output to zsh_xtracefd file descriptor -- see execcmd() */
+    if (zsh_xtracefd == 0)
+       zsh_xtracefd = 2;
+    xtracefdassign();
 
     /* Make sure the tty is opened read/write. */
     if (isatty(0)) {
diff --git a/Src/params.c b/Src/params.c
index 863b32600..569c21304 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -106,7 +106,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    */
 /**/
@@ -268,6 +269,9 @@ static const struct gsu_array pipestatus_gsu =
 static const struct gsu_integer rprompt_indent_gsu =
 { intvargetfn, zlevarsetfn, rprompt_indent_unsetfn };
 
+static const struct gsu_integer xtracefd_gsu =
+{ intvargetfn, xtracefdsetfn, xtracefdunsetfn };
+
 /* Nodes for special parameters for parameter hash table */
 
 #ifdef HAVE_UNION_INIT
@@ -357,6 +361,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}
@@ -4399,6 +4404,71 @@ setsecondstype(Param pm, int on, int off)
     return 0;
 }
 
+/* Open / assign the XTRACE fd */
+
+/**/
+void xtracefdassign(void)
+{
+    int fd = (int)zsh_xtracefd;
+    switch (fd)
+    {
+    case 0:                    /* bizarre, but handle for consistency */
+       xtrerr = stdin;
+       break;
+
+    case 1:
+       xtrerr = stdout;
+       break;
+
+    case 2:
+       xtrerr = stderr;
+       break;
+
+    default:
+       xtrerr = fdopen(fd, "w");
+       break;
+    }
+    xtrace_file = xtrerr;
+}
+
+/* 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) != -1 || errno != EBADF) {
+      current_fd = intvargetfn(pm);
+      /* We never close file descriptors 0 (stdin), 1 (stdout) or 2 stderr) */
+      if (current_fd > 2)
+        fclose(xtrerr);
+      intvarsetfn(pm, fd);
+      xtracefdassign();
+    } 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 = intvargetfn(pm);
+    if (current_fd == 2)  /* Nothing to do, already using stderr */
+      return;
+    else {  /* Reset to file descriptor 2 (stderr) */
+      intvarsetfn(pm, 2);
+      if (current_fd > 2)
+         fclose(xtrerr);  /* Never close standard descriptors */
+      xtrerr = xtrace_file = stderr;
+    }
+}
+
 /* Function to get value for special parameter `USERNAME' */
 
 /**/
diff --git a/Src/utils.c b/Src/utils.c
index 69885fed3..a817c9aa8 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1760,12 +1760,19 @@ checkmailpath(char **s)
 /**/
 FILE *xtrerr = 0;
 
+/* This records the last file XTRACE was open too.
+ * It's used for restoring XTRACE after a possible redirection.
+ */
+
+/**/
+FILE *xtrace_file;
+
 /**/
 void
 printprompt4(void)
 {
     if (!xtrerr)
-	xtrerr = stderr;
+	xtracefdassign();
     if (prompt4) {
 	int l, t = opts[XTRACE];
 	char *s = dupstring(prompt4);
diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst
index d60519064..fd06854e1 100644
--- a/Test/A04redirect.ztst
+++ b/Test/A04redirect.ztst
@@ -708,3 +708,13 @@
   cat <&$testfd
 0:Regression test for here document with fd declarator
 >  This is, in some sense, a here document.
+
+  rm -f redir
+  set -x
+  ZSH_XTRACEFD=4 print 'This is ZSH_XTRACEFD redir' 4>redir
+  set +x
+  cat redir
+0:Redirect xtrace output to ZSH_XTRACEFD file descriptor
+>This is ZSH_XTRACEFD redir
+>+(eval):3> print 'This is ZSH_XTRACEFD redir'
+?+(eval):3> ZSH_XTRACEFD=4 +(eval):4> set +x
-- 
2.26.0


  parent reply	other threads:[~2020-04-19 10:31 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-17 15:08 Timothée Mazzucotelli
2019-05-18  7:55 ` Stephane Chazelas
2019-05-20 10:34   ` Stephane Chazelas
2019-07-21 15:08     ` Timothée Mazzucotelli
2019-07-21 15:22       ` Peter Stephenson
2019-07-31 19:40         ` Timothée Mazzucotelli
2019-07-31 19:45           ` Timothée Mazzucotelli
2019-07-31 21:12             ` Sebastian Gniazdowski
2019-08-13  9:14           ` Peter Stephenson
2019-08-13 15:38           ` Peter Stephenson
2019-09-10 22:19             ` Timothée Mazzucotelli
2019-09-11  8:45               ` Peter Stephenson
2020-04-19 10:30             ` Timothée Mazzucotelli [this message]
2020-04-20 14:09               ` Peter Stephenson
2020-05-02 18:02                 ` Timothée Mazzucotelli
2020-05-02 21:15                   ` Bart Schaefer
2020-05-03  0:06                     ` Daniel Shahaf
2020-05-03  4:43                       ` Roman Perepelitsa
2020-05-03 16:21                         ` Daniel Shahaf
2020-05-03 19:54                         ` Peter Stephenson
2020-05-03 21:06                           ` Daniel Shahaf
2020-05-04  8:35                             ` Peter Stephenson
2020-05-05  0:03                               ` Daniel Shahaf
2020-05-05 16:36                                 ` Timothée Mazzucotelli
2020-05-05 16:47                                   ` Peter Stephenson
2020-05-05 22:19                                     ` Bart Schaefer
2020-09-03 13:51                                       ` Timothée Mazzucotelli
2020-09-04 19:48                                         ` Daniel Shahaf
2020-09-04 19:53                                           ` Bart Schaefer
2020-09-05  9:24                                             ` Timothée Mazzucotelli
2020-05-05 22:11                                   ` Bart Schaefer
2020-05-03  6:01                       ` Stephane Chazelas
2020-05-03  7:07                         ` Stephane Chazelas
2020-05-03 17:30                   ` Peter Stephenson
2020-05-03 21:23                     ` Daniel Shahaf
2020-05-04  8:26                       ` Peter Stephenson
2020-05-05 20:50               ` Daniel Shahaf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAD8ZDTotCLBANtzppSbCcgKyLhkXaVWysjqv99xS6bnLypBViA@mail.gmail.com \
    --to=timothee.mazzucotelli@gmail.com \
    --cc=p.stephenson@samsung.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).