zsh-workers
 help / color / mirror / code / Atom feed
* zsh command_not_found_handler vs bash command_not_found_handle
@ 2016-10-04  7:06 ` Tim Speetjens
  2016-10-05  9:24   ` Peter Stephenson
  0 siblings, 1 reply; 3+ messages in thread
From: Tim Speetjens @ 2016-10-04  7:06 UTC (permalink / raw)
  To: zsh-workers

Hi all,

Some while ago, I documented [1] the minor changes in zsh
command_not_found_handler, compared to the bash
command_not_found_handle mechanism:
- If the handler returns non-zero, zsh itself returns 127, regardless
- If the handler returns non-zero, zsh itself prints the 'command not
found' message.

This behaviour does not distinguish between the handler and the
installed/substituted program returning non-zero. This is handled
better in bash, where:
- Regardless of the handler's return code, bash returns it. This
allows the user to distinguish between 127 - something went wrong with
the handler code, or anything else, from the called program.
- It is the handler that is responsible for printing the error code.
The handler has better knowledge of what went wrong.

Do you consider changing this behaviour, to match functionality with
bash? It would also simplify writing the handler.

Kind regards
Tim

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1358372


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: zsh command_not_found_handler vs bash command_not_found_handle
  2016-10-04  7:06 ` zsh command_not_found_handler vs bash command_not_found_handle Tim Speetjens
@ 2016-10-05  9:24   ` Peter Stephenson
  2016-10-13  8:33     ` Tim Speetjens
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Stephenson @ 2016-10-05  9:24 UTC (permalink / raw)
  To: zsh-workers

On Tue, 04 Oct 2016 09:06:44 +0200
Tim Speetjens <tim.speetjens@gmail.com> wrote:
> Some while ago, I documented [1] the minor changes in zsh
> command_not_found_handler, compared to the bash
> command_not_found_handle mechanism:
> - If the handler returns non-zero, zsh itself returns 127, regardless
> - If the handler returns non-zero, zsh itself prints the 'command not
> found' message.
> 
> This behaviour does not distinguish between the handler and the
> installed/substituted program returning non-zero. This is handled
> better in bash, where:
> - Regardless of the handler's return code, bash returns it. This
> allows the user to distinguish between 127 - something went wrong with
> the handler code, or anything else, from the called program.
> - It is the handler that is responsible for printing the error code.
> The handler has better knowledge of what went wrong.

It's easy to change --- I suppose since you can fix up the function if
you want the old behaviour this isn't a major issue, plus the fact that
you can't return a non-zero status to the shell from a command you *do*
execute is a pretty big hole in the design.

diff --git a/Doc/Zsh/exec.yo b/Doc/Zsh/exec.yo
index 30e4a61..5f79967 100644
--- a/Doc/Zsh/exec.yo
+++ b/Doc/Zsh/exec.yo
@@ -28,10 +28,11 @@ not handle this executable format in the kernel.
 
 If no external command is found but a function tt(command_not_found_handler)
 exists the shell executes this function with all
-command line arguments.  The function should return status zero if it
-successfully handled the command, or non-zero status if it failed.
-In the latter case the standard handling is applied: `command not
-found' is printed to standard error and the shell exits with status 127.
-Note that the handler is executed in a subshell forked to execute
-an external command, hence changes to directories, shell parameters,
-etc. have no effect on the main shell.
+command line arguments.  The return status of the function becomes the
+status of the command.  If the function wishes to mimic the
+behaviour of the shell when the command is not found, it should
+print the message `tt(command not found:) var(cmd)' to standard error
+and return status 127.  Note that the handler is executed in a
+subshell forked to execute an external command, hence changes to
+directories, shell parameters, etc. have no effect on the main shell.
+
diff --git a/README b/README
index d146d4b..ed2183d 100644
--- a/README
+++ b/README
@@ -101,6 +101,15 @@ For the more common case of non-repeatable options that take a single
 argument, completion functions now have to unescape not only colons but
 also backslashes when obtaining the option's argument from $opt_args.
 
+6) Previously, if the function command_not_found_handler was run
+in place of a command-not-found error, and the function returned
+non-zero status, zsh set the status to 127 and printed an error message
+anyway.  Now, the status from the handler is retained and no additional
+message is printed.  The main reasons for this change are that it was not
+possible to return a non-zero status to the parent shell from a command
+executed as a replacement, and the new implementation is more consistent
+with other shells.
+
 Incompatibilities between 5.0.8 and 5.2
 ---------------------------------------
 
diff --git a/Src/exec.c b/Src/exec.c
index 9890286..f248ca2 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -568,11 +568,14 @@ commandnotfound(char *arg0, LinkList args)
     Shfunc shf = (Shfunc)
 	shfunctab->getnode(shfunctab, "command_not_found_handler");
 
-    if (!shf)
-	return 127;
+    if (!shf) {
+	lastval = 127;
+	return 1;
+    }
 
     pushnode(args, arg0);
-    return doshfunc(shf, args, 1);
+    lastval = doshfunc(shf, args, 1);
+    return 0;
 }
 
 /*
@@ -703,7 +706,7 @@ execute(LinkList args, int flags, int defpath)
 
 	if (!search_defpath(arg0, pbuf, PATH_MAX)) {
 	    if (commandnotfound(arg0, args) == 0)
-		_exit(0);
+		_exit(lastval);
 	    zerr("command not found: %s", arg0);
 	    _exit(127);
 	}
@@ -767,7 +770,7 @@ execute(LinkList args, int flags, int defpath)
     if (eno)
 	zerr("%e: %s", eno, arg0);
     else if (commandnotfound(arg0, args) == 0)
-	_exit(0);
+	_exit(lastval);
     else
 	zerr("command not found: %s", arg0);
     _exit((eno == EACCES || eno == ENOEXEC) ? 126 : 127);
diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst
index 9f15e04..ab7b429 100644
--- a/Test/C04funcdef.ztst
+++ b/Test/C04funcdef.ztst
@@ -120,14 +120,13 @@
      print "Your command:" >&2
      print "$1" >&2
      print "has gone down the tubes.  Sorry." >&2
-     return 1
+     return 42
   }
   ThisCommandDoesNotExistEither
-127:Command not found handler, failure
+42:Command not found handler, failure
 ?Your command:
 ?ThisCommandDoesNotExistEither
 ?has gone down the tubes.  Sorry.
-?(eval):7: command not found: ThisCommandDoesNotExistEither
 
   local variable=outside
   print "I am $variable"


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: zsh command_not_found_handler vs bash command_not_found_handle
  2016-10-05  9:24   ` Peter Stephenson
@ 2016-10-13  8:33     ` Tim Speetjens
  0 siblings, 0 replies; 3+ messages in thread
From: Tim Speetjens @ 2016-10-13  8:33 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers

Hi Peter,

Thanks for taking my suggestions into consideration and implementing them.

Cheers
Tim

2016-10-05 11:24 GMT+02:00 Peter Stephenson <p.stephenson@samsung.com>:
> On Tue, 04 Oct 2016 09:06:44 +0200
> Tim Speetjens <tim.speetjens@gmail.com> wrote:
>> Some while ago, I documented [1] the minor changes in zsh
>> command_not_found_handler, compared to the bash
>> command_not_found_handle mechanism:
>> - If the handler returns non-zero, zsh itself returns 127, regardless
>> - If the handler returns non-zero, zsh itself prints the 'command not
>> found' message.
>>
>> This behaviour does not distinguish between the handler and the
>> installed/substituted program returning non-zero. This is handled
>> better in bash, where:
>> - Regardless of the handler's return code, bash returns it. This
>> allows the user to distinguish between 127 - something went wrong with
>> the handler code, or anything else, from the called program.
>> - It is the handler that is responsible for printing the error code.
>> The handler has better knowledge of what went wrong.
>
> It's easy to change --- I suppose since you can fix up the function if
> you want the old behaviour this isn't a major issue, plus the fact that
> you can't return a non-zero status to the shell from a command you *do*
> execute is a pretty big hole in the design.
>
> diff --git a/Doc/Zsh/exec.yo b/Doc/Zsh/exec.yo
> index 30e4a61..5f79967 100644
> --- a/Doc/Zsh/exec.yo
> +++ b/Doc/Zsh/exec.yo
> @@ -28,10 +28,11 @@ not handle this executable format in the kernel.
>
>  If no external command is found but a function tt(command_not_found_handler)
>  exists the shell executes this function with all
> -command line arguments.  The function should return status zero if it
> -successfully handled the command, or non-zero status if it failed.
> -In the latter case the standard handling is applied: `command not
> -found' is printed to standard error and the shell exits with status 127.
> -Note that the handler is executed in a subshell forked to execute
> -an external command, hence changes to directories, shell parameters,
> -etc. have no effect on the main shell.
> +command line arguments.  The return status of the function becomes the
> +status of the command.  If the function wishes to mimic the
> +behaviour of the shell when the command is not found, it should
> +print the message `tt(command not found:) var(cmd)' to standard error
> +and return status 127.  Note that the handler is executed in a
> +subshell forked to execute an external command, hence changes to
> +directories, shell parameters, etc. have no effect on the main shell.
> +
> diff --git a/README b/README
> index d146d4b..ed2183d 100644
> --- a/README
> +++ b/README
> @@ -101,6 +101,15 @@ For the more common case of non-repeatable options that take a single
>  argument, completion functions now have to unescape not only colons but
>  also backslashes when obtaining the option's argument from $opt_args.
>
> +6) Previously, if the function command_not_found_handler was run
> +in place of a command-not-found error, and the function returned
> +non-zero status, zsh set the status to 127 and printed an error message
> +anyway.  Now, the status from the handler is retained and no additional
> +message is printed.  The main reasons for this change are that it was not
> +possible to return a non-zero status to the parent shell from a command
> +executed as a replacement, and the new implementation is more consistent
> +with other shells.
> +
>  Incompatibilities between 5.0.8 and 5.2
>  ---------------------------------------
>
> diff --git a/Src/exec.c b/Src/exec.c
> index 9890286..f248ca2 100644
> --- a/Src/exec.c
> +++ b/Src/exec.c
> @@ -568,11 +568,14 @@ commandnotfound(char *arg0, LinkList args)
>      Shfunc shf = (Shfunc)
>         shfunctab->getnode(shfunctab, "command_not_found_handler");
>
> -    if (!shf)
> -       return 127;
> +    if (!shf) {
> +       lastval = 127;
> +       return 1;
> +    }
>
>      pushnode(args, arg0);
> -    return doshfunc(shf, args, 1);
> +    lastval = doshfunc(shf, args, 1);
> +    return 0;
>  }
>
>  /*
> @@ -703,7 +706,7 @@ execute(LinkList args, int flags, int defpath)
>
>         if (!search_defpath(arg0, pbuf, PATH_MAX)) {
>             if (commandnotfound(arg0, args) == 0)
> -               _exit(0);
> +               _exit(lastval);
>             zerr("command not found: %s", arg0);
>             _exit(127);
>         }
> @@ -767,7 +770,7 @@ execute(LinkList args, int flags, int defpath)
>      if (eno)
>         zerr("%e: %s", eno, arg0);
>      else if (commandnotfound(arg0, args) == 0)
> -       _exit(0);
> +       _exit(lastval);
>      else
>         zerr("command not found: %s", arg0);
>      _exit((eno == EACCES || eno == ENOEXEC) ? 126 : 127);
> diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst
> index 9f15e04..ab7b429 100644
> --- a/Test/C04funcdef.ztst
> +++ b/Test/C04funcdef.ztst
> @@ -120,14 +120,13 @@
>       print "Your command:" >&2
>       print "$1" >&2
>       print "has gone down the tubes.  Sorry." >&2
> -     return 1
> +     return 42
>    }
>    ThisCommandDoesNotExistEither
> -127:Command not found handler, failure
> +42:Command not found handler, failure
>  ?Your command:
>  ?ThisCommandDoesNotExistEither
>  ?has gone down the tubes.  Sorry.
> -?(eval):7: command not found: ThisCommandDoesNotExistEither
>
>    local variable=outside
>    print "I am $variable"


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-10-14  9:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20161004071248eucas1p1ec9430cc4d19ecec28df28f564bb39fe@eucas1p1.samsung.com>
2016-10-04  7:06 ` zsh command_not_found_handler vs bash command_not_found_handle Tim Speetjens
2016-10-05  9:24   ` Peter Stephenson
2016-10-13  8:33     ` Tim Speetjens

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).