From: Smylers
Date: 18:30 on 04 Jan 2008
Subject: Debian Bash Command-Not-Found Extension
Debian/Ubuntu supply Bash with an extension that lets you define a
function to be run whenever a command in an interactive shell hasn't
been found. As shipped it does things like this, which can be handy:
$ echo znetnerg gungpure | rot13
The program 'rot13' is currently not installed. You can install it by
typing: sudo apt-get install bsdgames
bash: rot13: command not found
This feature's documentation in its entirety, is an item in the 'Shell
Variables' list in bash(1):
command_not_found_handle
The name of a shell function to be called if a command cannot be
found. The return value of this function should be 0, if the
command is available after execution of the function, otherwise 127
(EX_NOTFOUND). Enabled only in interactive, non POSIX mode shells.
This is a Debian extension.
Points of hate:
* The docs suggest that you set $command_not_found_handle to the name of
the function you want to run. I couldn't get this to work.
The shipped function is called command_not_found_handle (and
$command_not_found_handle doesn't appear to be set anywhere); so far
as I can tell you simply define your function with that name for it to
work, and the documented variable simply doesn't exist.
* Because the API only provides for a single function, not an array of
them, it's needlessly hard to set up a series of fallbacks -- for
example to try the shipped 'uninstalled package' thing first and then
something else.
To get this your function has to duplicate the default behaviour
before adding in its own check. This obviously doesn't scale, and
makes assumptions about what the default behaviour is.
* The default function in its entirety is this:
command_not_found_handle ()
{
/usr/bin/python /usr/lib/command-not-found -- $1;
return $?
}
It only has two lines, and the second is entirely redundant! And the
underlying Python program that determines whether the command is a
program in an uninstalled package has the generic name
command-not-found rather than something which indicates what this
particular not-found handler does.
* Whether that program knows about the command (and successfully tells
you which package to install) or it can't help at all, the spec says
it has to return 127 (because in neither case has the command been
installed, for next time). This makes using it in a chain of
fallbacks more work than necessary, because you have to capture its
output to see if it's worked.
(Then save its exit code, check if there was any output, and if so
echo the output and exit with the exit code.)
How hard would it'd've been to come up with different exit codes to
distinguish these situations? Perhaps this 'uninstalled package'
scenario isn't one the authors of the feature considered -- except
that this is a Debian extension that appears to have been written
especially to provide this behaviour!
Grrr!
Smylers
From: Peter da Silva Date: 18:50 on 04 Jan 2008 Subject: Re: Debian Bash Command-Not-Found Extension On 2008-01-04, at 12:30, Smylers wrote: > * The docs suggest that you set $command_not_found_handle to the > name of > the function you want to run. I couldn't get this to work. It does actually say that it's the name of a function, not a variable, but putting it in the shell variable section seems pretty hateful, yes. > To get this your function has to duplicate the default behaviour > before adding in its own check. This obviously doesn't scale, and > makes assumptions about what the default behaviour is. The normal way to do this is to rename the old function and call it from the new. Unfortunately there doesn't seem to be a way to rename functions in bash.
From: Aaron Crane
Date: 19:50 on 04 Jan 2008
Subject: Re: Debian Bash Command-Not-Found Extension
Peter da Silva writes:
> Unfortunately there doesn't seem to be a way to rename functions in
> bash.
I beg to differ.
function rename_function {
local old=$1 new=$2
eval "$(declare -f $old | sed "1s/^$old/$new/")"
unset -f $old
}
From: Peter da Silva
Date: 20:04 on 04 Jan 2008
Subject: Re: Debian Bash Command-Not-Found Extension
On 2008-01-04, at 13:50, Aaron Crane wrote:
> function rename_function {
> local old=$1 new=$2
> eval "$(declare -f $old | sed "1s/^$old/$new/")"
> unset -f $old
> }
Neat trick!
I would make that "1s/^$old /$new /" myself, and quote "$old" and
"$1" and so on...
From: Aaron Crane
Date: 20:33 on 04 Jan 2008
Subject: Re: Debian Bash Command-Not-Found Extension
Peter da Silva writes:
> On 2008-01-04, at 13:50, Aaron Crane wrote:
>> function rename_function {
>> local old=$1 new=$2
>> eval "$(declare -f $old | sed "1s/^$old/$new/")"
>> unset -f $old
>> }
>
>
> Neat trick!
>
> I would make that "1s/^$old /$new /" myself,
Yes. The first version I wrote used Perl to do the munging, and used
\b in the regex to achieve the same effect.
> and quote "$old" and "$1" and so on...
It's not necessary to quote a variable on the right-hand side of an
assignment:
$ f() { local x=$1; echo "[$x]"; }
$ f 'foo bar'
[foo bar]
Also, I decided I didn't care about any brokenness resulting from
however the user might have managed to persuade the shell to create a
function with a non-identifier-syntax name. After all:
$ foo\ bar() { echo blah; }
-bash: `foo\ bar': not a valid identifier
$ function foo\ bar { echo blah; }
-bash: `foo\ bar': not a valid identifier
From: Peter da Silva
Date: 20:43 on 04 Jan 2008
Subject: Re: Debian Bash Command-Not-Found Extension
On 2008-01-04, at 14:33, Aaron Crane wrote:
> It's not necessary to quote a variable on the right-hand side of an
> assignment:
> $ f() { local x=$1; echo "[$x]"; }
> $ f 'foo bar'
> [foo bar]
I'm not sure I entirely approve of that, because it seems to make the
syntax less regular, and I'll continue to quote them in my own
code... but 'declare -f "$old"' and 'unset -f "$old"' seem no-brainers.
> Also, I decided I didn't care about any brokenness resulting from
> however the user might have managed to persuade the shell to create a
> function with a non-identifier-syntax name.
I'm more coming from the point of view of never writing scripts that
expose a quoting attack, even if you never think they should ever be
exposed to untrusted strings.
From: Phil Pennock
Date: 00:43 on 05 Jan 2008
Subject: Re: Debian Bash Command-Not-Found Extension
On 2008-01-04 at 20:33 +0000, Aaron Crane wrote:
> Also, I decided I didn't care about any brokenness resulting from
> however the user might have managed to persuade the shell to create a
> function with a non-identifier-syntax name. After all:
>
> $ foo\ bar() { echo blah; }
> -bash: `foo\ bar': not a valid identifier
> $ function foo\ bar { echo blah; }
> -bash: `foo\ bar': not a valid identifier
% 'foo bar'() { echo blah }
% foo\ bar
blah
% rename_func() { functions[$2]=$functions[$1] }
% rename_func 'foo bar' fred
% fred
blah
To get the $functions array in zsh you do need to have zmodload'd
zsh/parameter. Could { zmodload -i zsh/parameter } to silently load
it if not already loaded. I have it loaded for one of the fields in my
prompt anyway.
ObHate: These two don't produce the same result:
$functions['foo bar']
x='foo bar'; $functions[$x]
-Phil
From: Peter da Silva Date: 00:57 on 05 Jan 2008 Subject: Re: Debian Bash Command-Not-Found Extension On 2008-01-04, at 18:43, Phil Pennock wrote: > ObHate: These two don't produce the same result: > $functions['foo bar'] > x='foo bar'; $functions[$x] I think I know why, and if so that's probably the only "C" like feature in csh. Typical that zsh would decide that was something to inherit from csh. I hate zsh. It's like perl without style.
From: Jarkko Hietaniemi
Date: 20:07 on 04 Jan 2008
Subject: Re: Debian Bash Command-Not-Found Extension
On Jan 4, 2008 2:50 PM, Aaron Crane <hateful@xxxxxxxxxx.xx.xx> wrote:
> Peter da Silva writes:
> > Unfortunately there doesn't seem to be a way to rename functions in
> > bash.
>
> I beg to differ.
>
> function rename_function {
> local old=$1 new=$2
> eval "$(declare -f $old | sed "1s/^$old/$new/")"
> unset -f $old
> }
rename_function foo foo
rename_function bar
> --
> Aaron Crane
>
>
From: Tony Finch Date: 11:37 on 08 Jan 2008 Subject: Re: Debian Bash Command-Not-Found Extension On Fri, 4 Jan 2008, Peter da Silva wrote: > > It does actually say that it's the name of a function, not a variable, but > putting it in the shell variable section seems pretty hateful, yes. It implies it's a variable containing the name of a function. It should just say that it is a shell function. Tony.
From: Juerd Waalboer Date: 18:53 on 04 Jan 2008 Subject: Re: Debian Bash Command-Not-Found Extension Smylers skribis 2008-01-04 18:30 (+0000): > The program 'rot13' is currently not installed. You can install it by > typing: sudo apt-get install bsdgames > bash: rot13: command not found I haven't tried or even wanted to change the feature yet, but I must say, even though this is a hatelist, that I absolutely LOVE this thing. > except that this is a Debian extension that appears to have been > written especially to provide this behaviour! Indeed it seems to have been written for this single use. I'm sure the authors would like to know about your suggested uses and changes to the mechanism. Have you considered sending them a note?
From: demerphq Date: 19:19 on 04 Jan 2008 Subject: Re: Debian Bash Command-Not-Found Extension On 04/01/2008, Juerd Waalboer <juerd@xxxxxxxxxxx.xx> wrote: > Smylers skribis 2008-01-04 18:30 (+0000): > > The program 'rot13' is currently not installed. You can install it by > > typing: sudo apt-get install bsdgames > > bash: rot13: command not found > > I haven't tried or even wanted to change the feature yet, but I must > say, even though this is a hatelist, that I absolutely LOVE this thing. > > > except that this is a Debian extension that appears to have been > > written especially to provide this behaviour! > > Indeed it seems to have been written for this single use. I'm sure the > authors would like to know about your suggested uses and changes to the > mechanism. Have you considered sending them a note? . o O ( they rejected the idea on the grounds it was insufficiently hateful )
Generated at 10:27 on 16 Apr 2008 by mariachi