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