Manipulating result from "system" call in C++ program - c++

Say that I execute some command to run in the terminal within a C++ program. For instance:
int main(){
std::system("./myprog");
return 0;
}
Assume that myprog produces some output that is printed to the console. Can I make use of this output within my C++ program? For example:
int main(){
some_var = std::system("./myprog");
if (some_var == "something")
// Do something.
return 0;
}
Any help would be very much appreciated. Thanks again.

You need to use the popen function:
FILE *fp = popen("./myprog", "r");
char buffer[128];
while (fgets(buffer, sizeof(buffer), fp))
{
std::cout << "Output from program: " << buffer << '\n';
}
pclose(fp);

Related

unexpected getline behavior

Originally was trying to read data using char* but switched to string cause was getting behavior as if there was a missing null terminator. made the problem minimal below but still getting very weird output
int main(int argc, char * argv[]){
// file one: flightData
std::ifstream inFile1(argv[1]);
if (!inFile1.is_open())
{
std::cout << "Could not open the file 1." << std::endl;
return -1;
}
// file two: flightPlans
std::ifstream inFile2(argv[2]);
if (!inFile2.is_open())
{
std::cout << "Could not open the file 2." << std::endl;
return -1;
}
//File three: output
std::ofstream outputfile(argv[3]);
if (!outputfile.is_open())
{
std::cout << "Could not open the output file" << std::endl;
return -1;
}
std::string buffer;
getline(inFile1, buffer);
std::cout<<buffer<<std::endl;
while (getline(inFile1, buffer)) {
std::cout<<buffer;
std::cout<<"help";
}
// flightPlanner system(inFile1);
// system.printF();
// system.planFlights(inFile2,outputfile);
return 0;
}
output is
4
helpDallas|Austin|50|50help
which i'm pretty sure is incorrect, interestingly when i add endl to cout buffer it gives me output i would expect not really sure whats going on
inFile1
4
Dallas|Austin|50|50
Dallas|Austin|50|50
Dallas|Austin|50|50
Dallas|Austin|50|50
When i run in debugger i get the output i expect:
4
Dallas|Houston|50|50
helpDallas|Houston|50|50
helpDallas|Houston|50|50
helpDallas|Houston|50|50help
any idea what could be going on?
Do you need flushing your stdout?
std::cout << std::flush;
Any chance your shell ate your outputs?
Try pipping the output to "cat -A":
./a.out | cat -A
(Drive by comment - I may not know what I'm talking about ^_^)

Creating a pseudo terminal in C++ that can be used by other programs

I have created a pseudo terminal in C++ using the following code:
int main(int, char const *[])
{
int master, slave;
char name[1024];
char mode[] = "0777"; //I know this isn't good, it is for testing at the moment
int access;
int e = openpty(&master, &slave, &name[0], 0, 0);
if(0 > e) {
std::printf("Error: %s\n", strerror(errno));
return -1;
}
if( 0 != unlockpt(slave) )
{
perror("Slave Error");
}
access = strtol(mode, 0, 8);
if( 0 > chmod(name, access) )
{
perror("Permission Error");
}
//std::cout << "Master: " << master << std::endl;
std::printf("Slave PTY: %s\n", name);
int r;
prompt = "login: ";
while(true)
{
std::cout << prompt << std::flush;
r = read(master, &name[0], sizeof(name)-1);
checkInput(name);
name[r] = '\0';
std::printf("%s", &name[0]);
std::printf("\n");
}
close(slave);
close(master);
return 0;
}
It works pretty well in the sense that from another terminal, I can do:
printf 'username' > /dev/pts/x
and it will appear and be processed as it should.
My question is: when I try to use screen, nothing appears on the screen terminal. Then when I type, it comes through to my slave 1 character at a time.
Does anyone know why this is? Or how I can fix it.
I can provide more detail if required.
Thank you :)
Because you're not flushing the buffer after you use printf.
As pauls answer already suggest you need to flush the buffer.
To do so you can use the tcflush function.
The first argument is the int of the file descriptor and the second can be one of the following:
TCIFLUSH Flushes input data that has been received by the system but
not read by an application.
TCOFLUSH Flushes output data that has been written by an application
but not sent to the terminal.
TCIOFLUSH Flushes both input and output data.
For more information see: https://www.ibm.com/docs/en/zos/2.3.0?topic=functions-tcflush-flush-input-output-terminal

is it possible to grab data from an .exe file in c++?

I am new at C/C++,
So basically I want to call an .exe file that displays 2 numbers and be able to grab those two numbers to use them in my code.
To call the .exe file I've used the system command, but I am still not able to grab those two numbers that are displayed by the .exe file
char *files = "MyPath\file.exe";
system (files);
I think this is better aproach:
Here you just create new process, and you read data that process gives you. I tested this on OS X 10.11 with .sh file and works like a charm. I think that this would probably work on Windows also.
FILE *fp = popen("path to exe","r");
if (fp == NULL)
{
std::cout << "Popen is null" << std::endl;
}else
{
char buff[100];
while ( fgets( buff, sizeof(buff), fp ) != NULL )
{
std::cout << buff;
}
}
You need to escapr back slashes in C++ string literals so:
// note the double "\\"
char* files = "MyPath\\file.exe";
Or just use forward slashes:
char* files = "MyPath/file.exe";
Its not very efficient but one thing you can to with std::system is redirect the output to a file and then read the file:
#include <cstdlib>
#include <fstream>
#include <iostream>
int main()
{
// redirect > the output to a file called output.txt
if(std::system("MyPath\\file.exe > output.txt") != 0)
{
std::cerr << "ERROR: calling system\n";
return 1; // error code
}
// open a file to the output data
std::ifstream ifs("output.txt");
if(!ifs.is_open())
{
std::cerr << "ERROR: opening output file\n";
return 1; // error code
}
int num1, num2;
if(!(ifs >> num1 >> num2))
{
std::cerr << "ERROR: reading numbers\n";
return 1; // error code
}
// do something with the numbers here
std::cout << "num1: " << num1 << '\n';
std::cout << "num2: " << num2 << '\n';
}
NOTE: (thnx #VermillionAzure)
Note that system doesn't always work everywhere because unicorn
environments. Also, shells can differ from each other, like cmd.exe
and bash. – VermillionAzure
When using std::system the results are platform dependant and not all shells will have redirection or use the same syntax or even exist!

Continuously write to subprocess using popen in C++

I need to open a subprocess using popen, the process will continuously ask for user input... The main process need to send that data over the pipe.
This is my first attempt:
FILE *in;
char buff[1024];
if(!(in = popen("cd FIX/fix2/src; java -cp .:./* com.fix.bot", "w"))){
return 1;
}
while(1){
char buffer[] = { 'x' };
fwrite(buffer, sizeof(char), sizeof(buffer), in);
cout << "Wrote!" << endl;
usleep(1000000);
}
However the data is not sent! I need to close the pipe with pclose() so that the data is written to the process. How can I make sure to write the data without having to close the pipe everytime?
You'll want to call fflush(in) to make sure that the buffered data is actually written to the stream.
Also check that java -cp .:./* in the command isn't expanding to an invalid classpath. I think that'll end up expanding to several arguments if there's more than one file in the current directory, and not actual classpath entries.
This works for me:
#include <stdio.h>
#include <unistd.h>
#include <iostream>
int main(int argc, char ** argv) {
FILE *in;
char buff[1024];
if(!(in = popen("./2.sh", "w"))){
return 1;
}
while(1) {
char buffer[] = "xx\n";
fwrite(buffer, sizeof(char), sizeof(buffer), in);
fflush(in);
std::cout << "Wrote!" << std::endl;
usleep(1000000);
}
}
where 2.sh is:
#!/bin/sh
read INP
echo 'read: ' $INP
So I am really suspecting that the problem is missing \n.

Really slow output when using popen?

I am getting performance issues when using popen in C++. The output shown on the screen looks REALLY slow compared to when I open the subprocess directly. It looks like if it was refreshing every second and not constantly... I even tried not using endl, and sync_with_stdio(false) but nothing seems to make the output faster.
Here is my code:
int main() {
FILE *in;
char buff[4096];
//cout.sync_with_stdio(false);
if(!(in = popen("python websocket/test.py", "r"))){
return 1;
}
while(fgets(buff, sizeof(buff), in)!=NULL){
cout << "====>>" << buff << endl;
}
pclose(in);
return 0;
}
What could be wrong with my code?