4

As I recently learned, it's possible to dynamically load custom builtins into Bash (see enable in the manual, and this answer). However I'm not sure how to take advantage of this feature.

The linked question points to https://mywiki.wooledge.org/BashLoadableBuiltins which provides some compilation instructions, but I'm not able to reproduce them (in Bash 5.0):

$ git clone https://git.savannah.gnu.org/git/bash.git
$ cd bash/
$ ./configure
$ make
$ exec ./bash
$ cd examples/loadables/
$ make
$ enable -f finfo finfo
bash: enable: cannot open shared object finfo: finfo: cannot open shared object file: No such file or directory

(Here's the full output just in case it's helpful)

Running make in the examples/loadables appears to be creating .o files, while (I think?) enable is looking for a .so file. Is there a step I've missed that would generate the appropriate artifacts? Is there an easier or more typical way to build custom builtins?

dimo414
  • 1,727
  • 1
  • 16
  • 37
  • The wiki page links to a dead article, but it's preserved on archive.org: https://web.archive.org/web/20160303032434/http://cfajohnson.com/shell/articles/dynamically-loadable/ – dimo414 Apr 25 '20 at 02:17

1 Answers1

2

The filename must be an "absolute" path (in this context, that's just a path with a slash in it), or it will be looked up in BASH_LOADABLES_PATH, falling back to dlopen(3)'s search mechanism (e.g., see the Linux manpage). It seems that, despite the comments in enable.def, these do not include the current directory (which is a good thing, IMO).

Just use a path:

bash-5.0$ enable -f print print
bash: enable: cannot open shared object print: print: cannot open shared object file: No such file or directory
bash-5.0$ enable -f ./print print
bash-5.0$ help print
print: print [-Rnprs] [-u unit] [-f format] [arguments]
    Display arguments.

    Output the arguments.  The -f option means to use the argument as a
    format string as would be supplied to printf(1).  The rest of the
    options are as in ksh.
muru
  • 69,900
  • 13
  • 192
  • 292
  • Interesting, that makes sense! Any idea if this used to behave differently? Or maybe something about my machine has `dlopen` configured differently? It's odd that both the Wooledge wiki page and the linked questions seemed to be able to use `enable` without making the filename "absolute" (seemingly without adjusting `BASH_LOADABLES_PATH`). – dimo414 Apr 25 '20 at 08:32
  • 1
    Going by [this post](https://serverfault.com/a/279069/229499), not in the past nine years. And in [the archived blog post](https://web.archive.org/web/20160303032434/http://cfajohnson.com/shell/articles/dynamically-loadable/) linked the Wooledge wiki, you'll see it says `enable -f filename` but actually runs `enable ./strftime strftime` in the example. O.o – muru Apr 25 '20 at 08:54
  • Thanks for the sleuthing :) this seems like such a useful feature, I wonder why it's gone mostly unused for so long (documentation is obviously a key reason...). – dimo414 Apr 25 '20 at 10:11