You probably shouldn't do this, but you can. Kusalananda's answer is better for the task at hand and explains the issue. Since you did ask specifically how to use any library calls inside the terminal, though, here's a few ways...
The Tiny C Compiler (tcc
) supports a -run
flag that lets you (in effect) interpret C code by writing a small program, so you can use any library calls inside the terminal through a single invocation of that.
You can run the strnlen
function like this:
$ tcc -run <(echo '#include <stdio.h>'; echo '#include <string.h>'; echo 'void main(int argc, char **argv) {printf("%i\n", strnlen(argv[1], 1024));}') "Hello world"
11
This uses process substitution from Bash, zsh, and other shells to give tcc
a file to read that appears to contain the results of all the echo
s; there are other options.
You could make a function to generate this for you:
call_library_function_s_i() {
func=$1
shift
tcc -run <(echo '#include <stdio.h>'; echo '#include <string.h>'; echo 'void main(int argc, char **argv) {printf("%i\n", '$func'(argv[1]));}') "$*"
}
$ call_library_function_s_i strlen hello world
(I've used strlen
here so that it's a unary function string->int - you'd need a separate function for each different arity and return type).
Another option is the ctypes.sh
Bash plugin by Tavis Ormandy, which wraps up dlopen
and dlsym
. This is probably the closest approximation to what you were trying. You can use, for example:
$ dlcall -r uint64 strlen "hello world"
and it will call the function as expected.
This is the most direct way to do it "from the terminal", but it's unlikely to be something your distribution packages up so you'd have to install it manually (which is nontrivial). Here are some informative quotes from ctypes.sh
's own website to give a general impression of how people feel about doing this:
- "that's disgusting"
- "this has got to stop"
- "you've gone too far with this"
There may be similar tools for other shells, but I don't know about them. In theory there's no reason there couldn't be a standalone command that did this exactly for the simple cases, but I'm somewhat surprised I haven't been able to find one...
... so I made one! dlcall
lets you call library functions from the command line:
$ dlcall strnlen "hello world" 6
$ dlcall sin 2.5
$ dlcall strchr "hello world" -c ' '
It supports a limited set of function prototypes, it's not terribly reliable or resilient currently, but it now exists.
You could also use, for example, Python and python -c 'import ctypes; import sys; print(ctypes.cdll.LoadLibrary("libc.so.6").strlen(" ".join(sys.argv[1:])))' hello world
, but it's certainly not the easiest way to go about it. Perl, Ruby, and other languages have similar features you could use.
So the answers to your questions are:
- Use one of the approaches above.
- You do need to use another command to bootstrap you into the library, or a piece of software that hooks into your shell.
All in all, you'll almost certainly be better off doing this any other way.