How to call execute command line in C++ - c++

For example, I have a script ./helloworld.sh
I would like to call it in C++, how do I do that? Which library can be used?

try
system("./helloworld.sh");

If you just want to run it (and nothing else)
system("./helloworld.sh");
If you need to get the stdin/stdout then you need to use popen()
FILE* f = popen("./helloworld.sh","r");

try system().

In C there are also the execxxx functions from unistd.h. They have a big advantage over the simple system as you can specify environment variables for your process to run in among other levels of control for the arguments management.

There are at least two possible ways.
(I suppose you are asking about Unix-like systems when using shell scripts).
The first one is very simple, but is blocking (it returns after the command has been completed):
/* Example in pure C++ */
#include <cstdlib>
int ret = std::system("/home/<user>/helloworld.sh");
/* Example in C/C++ */
#include <stdlib.h>
int ret = system("/home/<user>/helloworld.sh");
The second way is not that easy, but could be non-blocking (script can be run as parallel process):
/* Example in C/C++ */
#include <unistd.h>
pid_t fork(void);
int execv(const char *path, char *const argv[]);
/* You have to fork process first. Search for it, if you don't know how to do it.
* In child process you have to execute shell (eg. /bin/sh) with one of these
* exec* functions and you have to pass path-to-your-script as the argument.
* If you want to get script output (stdout) on-the-fly, you can do that with
* pipes. Just create the reading pipe in parent process before forking
* the process and redirect stdout to the writing pipe in the child process.
* Then you can just use read() function to read the output whenever you want.
*/

if you also want to get the output of the script do
char fbuf[256];
char ret[2555];
FILE *fh;
if ((fh = popen("./helloworld.sh", "r")) == NULL) {
return 0;
}else{
while ( fgets(fbuf, sizeof(fbuf), fh) ) {
strcat(ret, fbuf);
}
}
pclose(fh);

Related

Subprocess communication. C++

I'm trying to write a C++ program which will start new process (some script, programm, command) like daemon and gets some info from it (stdout). I'm trying to use popen(). But subprocess finishing when main program complete. I dont know, does C++ have something easy in use like Python (subprocessing). There is my code:
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
FILE *in;
char buff[512];
in = popen(argv[1], "r");
fgets(buff, sizeof(buff), in);
cout << buff;
}
P.S: & in the end of executive command doesn't helps.
fgets doesn't wait for the subprocess to complete, and neither does popen.
You need to read until the end of in:
while (fgets(buff, sizeof(buff), in))
{
cout << buff;
}
Reference for popen function: http://man7.org/linux/man-pages/man3/popen.3.html
Excerpt:
"The popen() function opens a process by creating a pipe, forking, and invoking the shell."
I think that because of the fork mechanism, when your (calling) process ends, its child process (the called one) is stopped too, at least as default behaviour.
One option is to keep reading from the pipe (and keep the caller process running) until the child process ends.
Your code is also missing a pclose(in) before exiting.
See also this other post on StackOverflow.
Have a look here https://github.com/arun11299/cpp-subprocess
This library can be exactly what you're looking for.

Returning output from bash script to calling C++ function

I am writing a baby program for practice. What I am trying to accomplish is basically a simple little GUI which displays services (for Linux); with buttons to start, stop, enable, and disable services (Much like the msconfig application "Services" tab in Windows). I am using C++ with Qt Creator on Fedora 21.
I want to create the GUI with C++, and populating the GUI with the list of services by calling bash scripts, and calling bash scripts on button clicks to do the appropriate action (enable, disable, etc.)
But when the C++ GUI calls the bash script (using system("path/to/script.sh")) the return value is only for exit success. How do I receive the output of the script itself, so that I can in turn use it to display on the GUI?
For conceptual example: if I were trying to display the output of (systemctl --type service | cut -d " " -f 1) into a GUI I have created in C++, how would I go about doing that? Is this even the correct way to do what I am trying to accomplish? If not,
What is the right way? and
Is there still a way to do it using my current method?
I have looked for a solution to this problem but I can't find information on how to return values from Bash to C++, only how to call Bash scripts from C++.
We're going to take advantage of the popen function, here.
std::string exec(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
This function takes a command as an argument, and returns the output as a string.
NOTE: this will not capture stderr! A quick and easy workaround is to redirect stderr to stdout, with 2>&1 at the end of your command.
Here is documentation on popen. Happy coding :)
You have to run the commands using popen instead of system and then loop through the returned file pointer.
Here is a simple example for the command ls -l
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *process;
char buff[1024];
process = popen("ls -l", "r");
if (process != NULL) {
while (!feof(process)) {
fgets(buff, sizeof(buff), process);
printf("%s", buff);
}
pclose(process);
}
return 0;
}
The long approach - which gives you complete control of stdin, stdout, and stderr of the child process, at the cost of fairly significant complexity - involves using fork and execve directly.
Before forking, set up your endpoints for communication - pipe works well, or socketpair. I'll assume you've invoked something like below:
int childStdin[2], childStdout[2], childStderr[2];
pipe(childStdin);
pipe(childStdout);
pipe(childStderr);
After fork, in child process before execve:
dup2(childStdin[0], 0); // childStdin read end to fd 0 (stdin)
dup2(childStdout[1], 1); // childStdout write end to fd 1 (stdout)
dup2(childStderr[1], 2); // childStderr write end to fd 2 (stderr)
.. then close all of childStdin, childStdout, and childStderr.
After fork, in parent process:
close(childStdin[0]); // parent cannot read from stdin
close(childStdout[1]); // parent cannot write to stdout/stderr
close(childStderr[1]);
Now, your parent process has complete control of the std i/o of the child process - and must safely multiplex childStdin[1], childStdout[0], and childStderr[0], while also monitoring for SIGCLD and eventually using a wait-series call to check the process termination code. pselect is particularly good for dealing with SIGCLD while dealing with std i/o asynchronously. See also select or poll of course.
If you want to merge the child's stdout and stderr, just dup2(childStdout[1], 2) and get rid of childStderr entirely.
The man pages should fill in the blanks from here. So that's the hard way, should you need it.

Capturing child stdout to a buffer

I'm developing a cross platform project currently. On windows i had a class that ran a process/script (using a commandline), waited for it to end, and read everything from it's stdout/stderr to a buffer. I then printed the output to a custom 'console'. Note: This was not a redirection of child stdout to parent stdout, just a pipe from child stdout to parent.
I'm new to OSX/unix-like api's but i can understand the canonical way of doing something like this is forking and piping stdouts together. However, i dont want to redirect it to stdout and i would like to capture the output.. It should work pretty much like this (pseudocode, resemblance with unix functions purely coincidental):
class program
{
string name, cmdline;
string output;
program(char * name, char * cmdline)
: name(name), cmdline(cmdline) {};
int run()
{
// run program - spawn it as a new process
int pid = exec(name, cmdline);
// wait for it to finish
wait(pid);
char buf[size];
int n;
// read output of program's stdout
// keep appending data until there's nothing left to read
while (read(pid, buf, size, &n))
output.append(buf, n);
// return exit code of process
return getexitcode(pid);
}
const string & getOutput() { return output; }
};
How would i go about doing this on OSX?
E:
Okay so i studied the relevant api's and it seems that some kind of fork/exec combo is unavoidable. Problem at hand is that my process is very large and forking it really seems like a bad idea (i see that some unix implementations can't do it if the parent process takes up 50%+ of the system ram).
Can't i avoid this scheme in any way? I see that vfork() might be a possible contender, so maybe i could try to mimic the popen() function using vfork. But then again, most man pages state that vfork might very well just be fork()
You have a library call to do just that: popen. It will provide you with a return value of a file descriptor, and you can read that descriptor till eof. It's part of stdio, so you can do that on OSX, but other systems as well. Just remember to pclose() the descriptor.
#include <stdio.h>
FILE * popen(const char *command, const char *mode);
int pclose(FILE *stream);
if you want to keep output with absolutely no redirection, the only thing we can think of is using something like "tee" - a command which splits the output to a file but maintains its own stdout. It's fairly easy to implement that in code as well, but it might not be necessary in this case.

Manually getting the output instead of output redirection in cmd line

I have a C++ program which has the prototype of the main function as follows:
int main(int argc, char * argv[])
The code hasn't been written by me, but this is a single C file available here.
When I compile this code, and through the command line run it as:
someexe in.txt > out.txt
This gives me an output out.txt which is generated in the same directory by operating on some input from in.txt.
someexe in.txt out.txt
This gives me an output on the command line itself. (without using > operator)
However, instead of passing the command line argument and without using the output redirection > operator, I have been trying to call the main function from another function and passing the parameters myself. If I pass an array of char* {fileDirName, in.txt}, I am not sure how to go about generating an out.txt (since I think > output redirection is an operating system level function available in command line).
Any suggestions would be greatly appreciated
The program in the link is readily available as copy paste and can be tried (main function is written at the last in the above program)
Assuming the aim is to mimic the output redirection feature (> out.txt) of the shell you can do something like:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <unistd.h>
#include <iostream>
int main() {
int fd = open("out.txt", O_WRONLY|O_CREAT|O_TRUNC, 0660);
assert(fd >= 0);
const int ret = dup2(fd, 1);
assert(ret >= 0);
std::cout << "Hello redirected world!" << std::endl;
close(fd);
}
You can do similar for stdin also, to mimic the input redirection (< in.txt). These will be preserved across calls to exec() too.
Of course it would be simpler to modify the program to write to the place you wanted given you have the source available.
Note though that dup2(), which "swap" the stdout fd for the one we just opened is non-portable. IIRC open() (as opposed to fopen()) is UNIX specific also)
You can't call another main() from inside the source another program - main() is special.
If you want to reuse this source code as a library you need to rename main() to something else.
However if it is handling input from either a pipe or a file (eg myprog < input.txt or myprog input.txt) in the normal Unix way then that's a little trickier to handle transparently.
The best way would be to call the compiled program as a separate process from within your new program, passing the correct commandline parameters - see the exec() family of calls

How to read/redirect output of a dos command to a program variable in C/C++?

I want to run a dos command from my program for example "dir" command.
I am doing it like,
system("dir");
Is there any way to read the output of that command directly into a program variable?
We can always redirect the output to a file and then read that file, by doing
system("dir > command.out");
And then reading command.out file. But how can we do it directly rather than redirectling to a file and then reading?
You can't redirect it to a variable, but you can do a trick similar to how pipes are used in Unix for chaining commands. Call CreateProcess(), and pass it a STARTUPINFO instance with accordingly set handles and STARTF_USESTDHANDLES in STARTUPINFO::dwFlags. Then read the data coming from the spawned process through the set handles.
If your library has popen() POSIX function, that's what you need. You can read command output from pipe and parse it any way you like.
FILE *dir;
char direntry[80];
dir = popen("dir", "r");
while (!feof(dir)) {
fgets(direntry, sizeof(direntry), dir);
/* do something with direntry */
}
Found an alternate way or rather windows equivalent of popen. It is _popen(). This works just right for me and moreover it's easy to use.
char psBuffer[128];
FILE *pPipe;
if( (pPipe = _popen( "dir", "rt" )) != NULL)
{
while(fgets(psBuffer, 128, pPipe))
{
printf(psBuffer);
}
}
Find the details with full example here.
You can't. The programs run in different memory spaces, as they are different processes. Generally, in modern operating systems, processes don't share memory.
Also, it would be difficult to define a variable in C that can hold the output of a command such as "dir"; it's would need to dynamically grow to make room.
The best way is to use a pipe, that will make it possible to read the command's output from a stream, from which you can store it as you see fit.
Use popen() it does exactly what you want.
It creates a bidirectional pipe, forks the processes. In the child it then connects the pipe to standard in and standard out then execs the command specified as the first parameter to popen().
#include <stdio.h>
#include <string>
#include <iostream>
int main()
{
std::string output;
FILE* data = popen("cat PLOP","r");
for(char c = getc(data);c != EOF;c = getc(data))
{
output += c;
}
pclose(data);
std::cout << "Data(" << output << ")\n";
}