Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: zsh command_not_found_handler vs bash command_not_found_handle
On Tue, 04 Oct 2016 09:06:44 +0200
Tim Speetjens <tim.speetjens@xxxxxxxxx> 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"
Messages sorted by:
Reverse Date,
Date,
Thread,
Author