Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to embed a Sh/Bash session in C or C++?

Tags:

c++

c

bash

shell

As it can be done with Python.

I am interested not only in running single shell commands, but also in saving the current environment state.

For example, the following code:

system("a=2");
system("echo $a");

prints nothing, but I want to find a way by which the program would print "2".

The main goal is to keep the shell environment (that can be initialized, for example, using .bashrc) throughout the entire С/С++ program, as if you work in your terminal.

like image 765
Andrew Sonin Avatar asked Oct 31 '25 18:10

Andrew Sonin


1 Answers

Bash does not have an API in the same sense that Python does, but it's a shell. It has a text-based UI that is relatively easy for other programs to use. You cannot use system() because it requires you to specify all shell input up front and blocks until the shell exits, but you can use the same mechanism that system() does: run the shell in a separate process.

Details depend on the machine on which your program runs, but on machines where you typically find Bash or another Bourne-family shell -- Linux, Mac, and other POSIX systems -- you have at least two main alternatives:

  1. If you want the shell output to go (only) to the host program's standard output and standard error streams, then you can use popen() to open a stream connected to a shell:

    FILE *shell = popen("/bin/bash -i", "w");
    

    You could then write an arbitrary sequence of shell commands to the stream, and the shell will receive them on its standard input, execute them, and write the results to its standard output. The shell launched this way will share the caller's standard output and standard error.

  2. If the host program must both feed input to the shell and receive its output then you need to work at a lower level:

    • Use pipe() to create two pipes (three if you want to capture the shell's standard error separately).
    • fork() a child process in which to run the shell, and in it
      1. dup2() the appropriate pipe ends onto the child's standard in, out, and (optionally) error.
      2. close() the pipe ends that the child will not be using
      3. execl() the shell in the child process.
    • Back in the parent,
      • close() the pipe ends the parent will not be using
      • send commands to the shell over the pipe set up for doing so
      • read responses and / or error responses via the pipe(s)
      • when done with the shell close() the pipes and wait() for the child process to terminate. You can get its exit status at this point if you're interested in that.

Option (2) requires handling a lot more details -- more even than the above overview might suggest. You will find many answers here on SO that address them if you have need of that.

like image 146
John Bollinger Avatar answered Nov 02 '25 09:11

John Bollinger



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!