C++ Execute a command line and get Result. - c++

I need some help with my situation. I want to execute a Terminal and get the Result. I have done it so far, but i want to do some other Commands after getting the Result. My Problem is, that everytime when i do a command, the console restarts, and i dont know how to write in a active prozess.
I have done it like that:
FILE *fp = popen(r.c_str(),"r");
char buf[2560];
while (fgets(buf, 2560, fp))
{
s->SendLine(buf);
}
fclose(fp);
I want to "send" another command in the same process. How can i do that?

Assuming I understood your question and comment. It sounds like you want your program to run in a loop until the user chooses to close it. You will want something like this:
bool keepProgramOpen = true;
public void main()
{
while(keepProgramOpen)
{
printf("Choose and option\n");
printf("Option 1: press 1\n");
printf("Option 2: press 2\n"); //etc
char result = getchar();
switch result
{
//code to select which option was picked
case 1:
fileFunction();
break;
case 2:
someOtherFunction();
break;
case 3:
closeProgram(); //set keepProgramOpen false in here to end program
break;
//etc
}
}
}
fileFunction()
{
FILE *fp = popen(r.c_str(),"r");
char buf[2560];
while (fgets(buf, 2560, fp))
{
s->SendLine(buf);
}
fclose(fp);
}

I think before fclose(fp) use r2 as
fputs(r2.c_str(),fp)

Related

Minimal sample of muxing two streams with no reencoding (av_interleaved_write_frame fails)

What I'm trying to do: having two files, one is video-only and the other is audio-only, with identical durations, I want to "join" them in a single container.
I previously made a routine which just copied all the streams inside a container to another one. No reencoding, etc. This works perfectly:
while(true) {
pkIn=av_packet_alloc();
if(NULL==pkIn) {
fprintf(stderr,"av_packet_alloc() failed");
break;
}
iError=av_read_frame(fcIn,pkIn);
if(0>iError)
if(AVERROR_EOF==iError)
break;
else {
fprintf(stderr,"av_read_frame() failed");
break;
}
stIn=fcIn->streams[pkIn->stream_index];
stOut=fcOut->streams[pkIn->stream_index];
log_packet(fcIn,pkIn,"in");
av_packet_rescale_ts(pkIn,stIn->time_base,stOut->time_base);
pkIn->pos=-1;
log_packet(fcOut,pkIn,"out");
iError=av_interleaved_write_frame(fcOut,pkIn);
if(0>iError) {
fprintf(stderr,"av_interleaved_write_frame() failed");
break;
}
av_packet_free(&pkIn);
}
I just did the analogy and tried to do the same, but taking each stream from a distinct container, like this:
while(true) {
if(!bVideoInEOF) {
pkVideoIn=av_packet_alloc();
if(NULL==pkVideoIn) {
fprintf(stderr,"av_packet_alloc(video in) failed");
break;
}
iError=av_read_frame(fcVideoIn,pkVideoIn);
if(0>iError)
if(AVERROR_EOF==iError)
bVideoInEOF=true;
else {
fprintf(stderr,"av_read_frame(video in) failed");
break;
}
if(!bVideoInEOF) {
log_packet(fcVideoIn,pkVideoIn,"video in");
av_packet_rescale_ts(pkVideoIn,stVideoIn->time_base,stVideoOut->time_base);
pkVideoIn->pos=-1;
pkVideoIn->stream_index=stVideoOut->index; // Edit (2022-07-19)
log_packet(fcVideoIn,pkVideoIn,"video out");
iError=av_interleaved_write_frame(fcOut,pkVideoIn);
if(0>iError) {
fprintf(stderr,"av_interleaved_write_frame(video out) failed");
break;
}
}
av_packet_free(&pkVideoIn);
}
if(!bAudioInEOF) {
pkAudioIn=av_packet_alloc();
if(NULL==pkAudioIn) {
fprintf(stderr,"av_packet_alloc(audio in) failed");
break;
}
iError=av_read_frame(fcAudioIn,pkAudioIn);
if(0>iError)
if(AVERROR_EOF==iError)
bAudioInEOF=true;
else {
fprintf(stderr,"av_read_frame(audio in) failed");
break;
}
if(!bAudioInEOF) {
log_packet(fcAudioIn,pkAudioIn,"audio in");
av_packet_rescale_ts(pkAudioIn,stAudioIn->time_base,stAudioOut->time_base);
pkAudioIn->pos=-1;
pkAudioIn->stream_index=stAudioOut->index; // Edit (2022-07-19)
log_packet(fcAudioIn,pkAudioIn,"audio out");
iError=av_interleaved_write_frame(fcOut,pkAudioIn);
if(0>iError) {
fprintf(stderr,"av_interleaved_write_frame(audio out) failed");
break;
}
}
av_packet_free(&pkAudioIn);
}
if(bVideoInEOF&&bAudioInEOF)
break;
}
I know the previous code looks like redundant but I wanted to leave both streams "processing" separated the way you understand my plans.
Anyway, that code ends quickly with "av_interleaved_write_frame(audio out) failed".
The error detail is "Invalid argument", and the debugger shows this:
Application provided invalid, non monotonically increasing dts to
muxer in stream 0.
If I disable any of the main blocks "if(!bVideoInEOF)" / "if(!bAudioInEOF)", the file is written successfully, with the obvious lack of the disabled stream.
I'm new into using this library so probably I'm doing something really stupid, or missing something obvious.
Suggestions?
Edit (2022-07-19):
By checking the logs, I noticed I was writing every frame to the stream #0. Hence, the horrible jumps in PTS/DTS.
Code edited by adding the corresponding "...->stream_index=" before each call to av_interleaved_write_frame().
...
Though it works, I still think my code is far from perfect. Comments are welcome.

MBed program gets stuck

I have written some code with the help of Mbed framework, which is either supposed to take user input and then display sensor values or display the value after 15mins. When I try to execute this code, it is getting stuck at line 21 (display.printf("Inside loop\n");).
I am not able to understand why is it so and what is the fix for this problem so that the switch block gets executed. How to I solve this? FYI, although not important, the microcontroller I am using is STM32 bluepill (STM32F103C8T6).
#include "mbed.h"
#include "Sensor_input.h"
#include "Ticker.h"
#include "Dht11.h"
//#include "USBSerial.h"
Serial display(PA_2, PA_3, 9600);
char* a;
Dht11 DhtSensor(PA_4);
Ticker t;
Sensor_input Soil(PB_7, PB_6, 8);
float *SensorData;
void getSensorData();
int main ( void ){
uint8_t choice = 0;
display.printf("Enter 1 or 2:\n1.Greenhouse stats\n2.Return Control to System");
choice = display.putc(display.getc());
while(1){
display.printf("Inside loop\n");
wait_ms(15000);
switch(choice)
{
case 1:
display.printf("Inside case 1");
a = Soil.readTemp();
display.printf("Temperature: %f\n",DhtSensor.getCelsius());
display.printf("Humidity: %f\n",DhtSensor.getHumidity());
display.printf("Soil water content: %c\n ",*a);
break;
case 2:
/*<GreenHouse object>*/
/*Might have to proceed with timer*/
display.printf("Inside case 2");
t.attach(&getSensorData,4500);
display.printf("Temperature: %f\n",a[0]);
display.printf("Humidity: %f\n",a[1]);
display.printf("Soil water content: %c\n ",a[2]);
break;
default:
break;
}
}
}
void getSensorData(){
static float a[3];
a[0]=DhtSensor.getCelsius();
a[1]=DhtSensor.getHumidity();
a[2]=(int)Soil.readTemp();
}
Your switch statement is probably being executed, but always in the 'default' case. You can test this out by putting a print statement in the default.
When you request a char from the display, it will return the input as an ASCII-character. This means, if you enter '1' on the display, it will give you (as the ASCII table says) 0x31 (decimal 49) and not the value of 1. So you have to change your case to "case '1':" or "case 0x31:" and the equivalent for the second case.

Knowing where is the segmentation fault happening comparing two files

I have the following structure:
int main(int argc, char **argv) {
try {
FX3USBConnection fx3USB3Connection = FX3USB3Connection();
fx3USB3Connection.send_text_file();
}
catch (ErrorOpeningLib& e) {
printf("Error opening library\n");
return -1;
}
catch (NoDeviceFound& e) {
printf("No device found\n");
return 0;
}
return 0;
}
Within send_text_files, the last thing I do is compare two txt files as follows:
printf("Loopback recieved, checking if I received the same that I sended\n");
files_match(out_text_filename, in_text_filename);
printf("Exited without problem");
return; // (actually implicit)
I already used 2 version of files_match function but the last one is an exact copy of this Compare two files
bool FX3USB3Connection::files_match(const std::string &p1, const std::string &p2) {
bool files_match;
std::ifstream f1(p1, std::ifstream::binary|std::ifstream::ate);
std::ifstream f2(p2, std::ifstream::binary|std::ifstream::ate);
if (f1.fail() || f2.fail()) {
return false; //file problem
}
if (f1.tellg() != f2.tellg()) {
return false; //size mismatch
}
//seek back to beginning and use std::equal to compare contents
f1.seekg(0, std::ifstream::beg);
f2.seekg(0, std::ifstream::beg);
files_match = std::equal(std::istreambuf_iterator<char>(f1.rdbuf()),
std::istreambuf_iterator<char>(),
std::istreambuf_iterator<char>(f2.rdbuf()));
f1.close();
f2.close();
if (files_match) { printf("Files match\n"); }
else { printf("Files not equal\n"); }
return files_match;
}
Sometimes I get an error and sometimes I don't. When I get the error I get:
Loopback recieved, checking if I received the same that I sended
Files match
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
So, the print after the call to files_match is not being print so I guess the problem was within the function. However, I do a print just before the return statement and it is printing correctly.
PS: I commented the function files_match and I have no problems.
PS1: The files can have whatever like this character: ¥
Yes, as #john suggested, I had to add the fflush() function. There I realize the error was actually outside all this loop but actually is when getting out of the try{} section. It seams to me that is not managing to destroy the fx3USBConnection.
Thank you! I was so mislead now knowing fprint was actually buffered.

Program flow and correctly returning control to main() in a safe and eloquent way

The entry point to my application is here:
int main(int argc, char* args[]) {
MainLoop::Start();
return 0;
}
This calls the init function which declares allocates resources and so on.
After initialization, my main loop is thus:
void MainLoop::RunLoop(){
while(1){
switch(programState){
case MainLoop::Uninitialized:{
break;
}
case MainLoop::RunningGame:{
MainLoop::RunGame();
break;
}
case MainLoop::Exiting:{
MainLoop::ExitSafely();
break;
}
}
return;
}
}
The MainLoop::ExitSafely() function performs some garbage collection and makes sure the initialized subsystems have shutdown properly.
The return statement at the end of the loop hands program flow back to the main() function, which behaves exactly as expected. I don't like it though.
Maybe my exit function should return true and terminate the loop?
This is a personal project, but I'd like to do things properly and what I have just doesn't 'feel' right.
Thanks for taking a look.
Thank you Bo Persson for your contribution. The suggested solution is readable and functional:
void MainLoop::RunLoop(){
while(programState != MainLoop::Shutdown){
switch(programState){
case MainLoop::Uninitialized:{
break;
}
case MainLoop::RunningGame:{
MainLoop::RunGame();
break;
}
case MainLoop::Exiting:{
MainLoop::ExitSafely();
programState = MainLoop::Shutdown;
break;
}
}
}
}

Execute command from cpp

The application I'm working on needs to execute commands. Commands can be console commands or 'GUI applications' (like notepad).
I need to get the return code in both cases, and in the case of console commands I also need to catch the output from stdin and stderr.
In order to implement this feature, I based my code on the stack overflow question 'How to execute a command and get output of command within C++ using POSIX?'.
My code:
int ExecuteCmdEx(const char* cmd, std::string &result)
{
char buffer[128];
int retCode = -1; // -1 if error ocurs.
std::string command(cmd);
command.append(" 2>&1"); // also redirect stderr to stdout
result = "";
FILE* pipe = _popen(command.c_str(), "r");
if (pipe != NULL) {
try {
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
}
catch (...) {
retCode = _pclose(pipe);
throw;
}
retCode = _pclose(pipe);
}
return retCode;
}
It works perfectly with console applications, but in the case of 'GUI applications' it doesn't work as expected...
With 'GUI applications', code stops on while (!feof(pipe)) expecting to get something from pipe.
I understand that 'GUI applications' like notepad don't finish until someone interacts with them (user closes the app, kills the process, etc.),
but when I launch console applications from Windows Console, prompt comes back immediately.
I would like to obtain the same behavior from 'GUI applications'...
One possible solution would be to add the isGui variable indicating when the code should read from the pipe, but I rejected this option, as I don't want to indicate if it is a 'GUI application' or not.
Well you don't have to indicate isGui yourself but detect it by checking the subsystem of the executable (windows/console) prior to executing the command, and in case of windows skip waiting on the redirected pipes.
For example, using SHGetFileInfo with the SHGFI_EXETYPE flag:
bool isGuiApplication(const std::string& command)
{
auto it = command.find_first_of(" \t");
const std::string& executable = (it == std::string::npos ? command : command.substr(0, it));
DWORD_PTR exetype = SHGetFileInfo(executable.c_str(), 0, nullptr, 0, SHGFI_EXETYPE);
if (!exetype) {
cerr << "Executable check failed\n";
}
return ((uintptr_t)exetype & 0xffff0000);
}
Then later in the code...
if (isGuiApplication(command)) {
cout << "GUI application\n";
system(command.c_str()); // don't wait on stdin
}
else {
cout << "Console application\n";
. . .
// _popen and stuff
}