Subprocess communication. C++ - 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.

Related

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.

Pipes between Python and C++ don't get closed

I am spawning a process in python using subprocess and want to read output from the program using pipes. The C++ program does not seem to close the pipe though, even when explicitly telling it to close.
#include <cstdlib>
#include <ext/stdio_filebuf.h>
#include <iostream>
int main(int argc, char **argv) {
int fd = atoi(argv[1]);
__gnu_cxx::stdio_filebuf<char> buffer(fd, std::ios::out);
std::ostream stream(&buffer);
stream << "Hello World" << std::endl;
buffer.close();
return 0;
}
I invoke this small program with this python snippet:
import os
import subprocess
read, write = os.pipe()
proc = subprocess.Popen(["./dummy", str(write)])
data = os.fdopen(read, "r").read()
print data
The read() method does not return, as the fd is not closed. Opening and closing the write fd in python solves the problem. But it seems like a hack to me. Is there a way to close the fd in my C++ process?
Thanks a lot!
Spawning a child process on Linux (all POSIX OSes, really) is usually accomplished via fork and exec. After fork, both processes have the file open. The C++ process closes it, but the file remains open until the parent process closes the fd also. This is normal for code using fork, and usually is handled by a wrapper around fork. Read the man page for pipe. I guess python has no way of knowing which files are being transferred to the child, though, and therefore doesn't know what to close in the parent vs the child process.
POSIX file descriptors are local to the process. The file descriptor write from the Python tool is not valid in the C++ process.
Perhaps the easiest way would be to have the C++ process write its output to stdout (like cout <<), and Python call Popen using stdout=PIPE and read proc.stdout (or use proc.communicate() instead of using fdopen. This should work in Windows, too.
For passing the file descriptor as a command-line argument, see Ben Voigt's answer.

How do I check if my program has data piped into it

Im writing a program that should read input via stdin, so I have the following contruct.
FILE *fp=stdin;
But this just hangs if the user hasn't piped anything into the program, how can I check if the user is actually piping data into my program like
gunzip -c file.gz |./a.out #should work
./a.out #should exit program with nice msg.
thanks
Since you're using file pointers, you'll need both isatty() and fileno() to do this:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
FILE* fp = stdin;
if(isatty(fileno(fp)))
{
fprintf(stderr, "A nice msg.\n");
exit(1);
}
/* carry on... */
return 0;
}
Actually, that's the long way. The short way is to not use file pointers:
#include <unistd.h>
int main(int argc, char* argv[])
{
if(isatty(STDIN_FILENO))
{
fprintf(stderr, "A nice msg.\n");
exit(1);
}
/* carry on... */
return 0;
}
Several standard Unix programs do this check to modify their behavior. For example, if you have ls set up to give you pretty colors, it will turn the colors off if you pipe its stdout to another program.
Try "man isatty", I think that function will tell you if you are talking to the user or not.
Passing stdin to select() or poll() should tell you if input is waiting. Under many OSes you can also tell if stdin is a tty or pipe.
EDIT: I see I'm going to have to emphasize the also part of the tty test. A fifo is not a tty, yet there might be no input ready for an indefinite amount of time.
Use isatty to detect that stdin is coming from a terminal rather than a redirect.
See the function "isatty" - if STDIN is a terminal, you can skip reading from it. If it's not a terminal, you're getting data piped or redirected and you can read until EOF.
An additional option you get with select() is setting a timeout for reading from stdin (with respect to either the first read from stdin or consecutive reads from stdin).
For a code example using select on stdin see:
How to check if stdin is still opened without blocking?

Getting the pid of my children using linux system calls in C++

I have a process that interfaces with a library that launches another process. Occasionally this process gets stuck and my program blocks in a call to the library. I would like to detect when this has happened (which I am doing currently), and send a kill signal to all these hung processes that are a child of me.
I know the commands to kill the processes, but I am having trouble getting the pids of my children. Does anyone know of a way to do this?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp = popen("ps -C *YOUR PROGRAM NAME HERE* --format '%P %p'" , "r");
if (fp == NULL)
{
printf("ERROR!\n");
}
char parentID[256];
char processID[256];
while (fscanf(fp, "%s %s", parentID, processID) != EOF)
{
printf("PID: %s Parent: %s\n", processID, parentID);
// Check the parentID to see if it that of your process
}
pclose(fp);
return 1;
}
This question is very similar to one asked the other day. I would suggest taking a look here to see if the answers are satisfactory in your case. Basically you will probably have to read through /proc.
I don't think "ps" is the answer. You could iterate the process list yourself to look for your own process's children, but it's a much better idea to modify the library so it provides the PIDs when you launch them.
This library must be pretty lame. What kind of deal do you have with its vendor? Can you not get on to their support to fix it?