9

Related to question 3451993, is it possible to call a function which is internal to subst.c (in the Bash source code) in a Bash script?

Community
  • 1
  • 1
l0b0
  • 55,365
  • 30
  • 138
  • 223

6 Answers6

7

Bash supports loadable builtins. You might be able to make use of this to do what you want. See the files in your /usr/share/doc/bash/examples/loadables (or similar) directory.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
  • 1
    Good idea. Unfortunately `grep subst /usr/share/doc/bash/examples/loadables/*` returned nothing. – l0b0 Aug 11 '10 at 14:19
  • @l0b0: That just means you have to write your own. Also, `grep subst /usr/include/bash/*` gives `/usr/include/bash/shell.h:#include "subst.h"`, `grep shell.h /usr/share/doc/bash/examples/loadables/*` gives a bunch. Unfortunately, `grep prompt /usr/share/doc/bash/examples/loadables/*` gives nothing, but `grep prompt /usr/include/bash/subst.h` does look interesting. – Dennis Williamson Aug 11 '10 at 14:49
6

It even possible to use C data structures ;)

This is ctypes.sh, a foreign function interface for bash. ctypes.sh is a bash plugin that provides a foreign function interface directly in your shell. In other words, it allows you to call routines in shared libraries from within bash.

Check out https://github.com/taviso/ctypes.sh ;)

Black Rain
  • 61
  • 1
  • 2
  • This is the most interesting project I have seen in the past couple of years. Thanks for you answer! – mljrg Jul 29 '21 at 10:57
4

The simplest way to do this is to write a simple program that collects the input, feeds it to the function, then prints the result. Why don't you tell us what you are attempting to accomplish and perhaps we can suggest an easier way to "skin this cat".

Jay
  • 13,803
  • 4
  • 42
  • 69
  • I'm trying to call a function which is internal to Bash, but it looks like it's not compiled into a separate shell command. Please see the link for more info. – l0b0 Aug 10 '10 at 20:51
  • It's very difficult to do this and is usually very unreliable. You're better off trying to get what you want a different way. – Jay Aug 10 '10 at 20:57
  • @l0b0: restating the question is not equivalent to saying what you are trying to accomplish. – msw Aug 10 '10 at 20:57
  • 1
    `The simplest way to do this is to write a simple program that collects the input, feeds it to the function, then prints the result`How do you do this on chrome os? It is the case where all partitions are mounted with noexec except for the rootfs which is write protected. – user2284570 May 09 '17 at 23:06
  • Never used Chrome OS. It sounds like they don't allow you to execute anything. If that's true you won't have a simple hack. You'd probably have to write a plugin for chrome. – Jay May 10 '17 at 14:01
3

No.

You can't access a function internal to the shell binary from the shell if it is not exported as a shell function.

msw
  • 42,753
  • 9
  • 87
  • 112
  • "If it is not exported as a shell function" -- can you explain more about that option? I am asking for two reasons: 1) powershell provides this ability natively, eg `[System.DateTime]::Now`; 2) I am looking for a Linux/BASH analog that does not involve me writing more than the merest whisper of C code (I'll need an SOW or I'll be doing it in my free time). To complement this, I have reviewed `guile` and I am familiar with python's `cffi` library in addition to the python compiler `nuitka`. I can also use `go`...so any BASH/C version of this will need to be pretty easy or well-motivated – Chris Aug 03 '23 at 15:01
2

This code looks pretty elegant: (from here) Its the same solution @Jay pointed out.

bash$ cat testing.c 
#include <stdio.h>

char* say_hello()
{
   return "hello world";
}

float calc_xyzzy()
{
     return 6.234;
}

int main(int argc, char** argv)
{
   if (argc>1) {
      if (argv[1][0] =='1') {
        fprintf(stdout,"%s\n",say_hello());
      } else if ( argv[1][0] == '2') {
        fprintf(stdout,"%g\n",calc_xyzzy());
      }
    }
    return 0;
}
bash$ gcc -o testing testing.c 
bash$ ./testing 1
hello world
bash$ ./testing 2
6.234
bash$ var_1="$(./testing 1)"
bash$ var_2="$(./testing 2)"
bash$ echo $var_1
hello world
bash$ echo $var_2
6.234
bash$
H_7
  • 287
  • 1
  • 5
  • 18
1

No, you'll have to write a short C program, compile it and call it from the shell.

tomlogic
  • 11,489
  • 3
  • 33
  • 59