Hallo
Wollte mir eine Klasse schreiben von der ich aus ich ein Programm starten kann und dann auf STDIN schreiben und von STDOUT lesen kann. AUs diesen Gründen konnte ich nicht popen() nutzen. Leider gibt mir read immer ein falsche string-länge zurück und es kommt immer ein völliger quatsch zum schluß des strings raus. Vielleicht kann mir ja jemand schlaues helfen.
C
#include <stdio.h>
#include <sys/wait.h>
#include <string>
#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#define iSize 255
class cExecute
{
private:
bool m_stoprequested;
bool m_running;
int exitstatus;
int rpipes[2];
int wpipes[2];
pthread_mutex_t m_mutex;
pthread_t m_thread;
std::string strCommand;
static void* start_thread(void *obj)
{reinterpret_cast<cExecute *>(obj)->do_work();}
void do_work();
public:
cExecute();
~cExecute();
bool running() {return m_running;}
void go();
void stop();
void setcmd(std::string newcmd)
{strCommand = newcmd;}
int getexitstatus()
{return WEXITSTATUS(exitstatus);}
std::string getdata();
int setdata(std::string newData);
};
cExecute::cExecute()
{
exitstatus = 0;
m_stoprequested = false;
m_running = false;
pthread_mutex_init(&m_mutex, NULL);
}
cExecute::~cExecute()
{
stop();
pthread_mutex_destroy(&m_mutex);
}
void cExecute::go()
{
if(!m_running)
{
m_running = true;
m_stoprequested = false;
pthread_create(&m_thread, NULL, &cExecute::start_thread, this);
}
}
void cExecute::stop()
{
if(m_running)
{
m_stoprequested = true;
pthread_join(m_thread, NULL);
m_running = false;
}
}
std::string cExecute::getdata()
{
char cBuffer[iSize];
int rv;
if ( (rv = read(rpipes[0], cBuffer, iSize)) < 0 )
{
std::cerr << "READ ERROR FROM PIPE" << std::endl;
return "";
}
else if (rv == 0)
{
std::cerr << "Child Closed Pipe" << std::endl;
return "";
}
int test = strlen(cBuffer);
std::cout << test << std::endl;
return cBuffer;
}
int cExecute::setdata(std::string newData)
{
if ( write(wpipes[1], newData.c_str(), strlen(newData.c_str()) ) != strlen(newData.c_str()) )
{
std::cerr << "READ ERROR FROM PIPE" << std::endl;
return -1;
}
return 0;
}
void cExecute::do_work()
{
pid_t childpid;
if ( ( pipe(rpipes) < 0 ) || ( pipe(wpipes) < 0 ) )
{
std::cerr << "PIPE ERROR" << std::endl;
exit(1);
}
if((childpid = fork()) < 0 )
{
std::cerr << "FORK ERROR" << std::endl;
exit(2);
}
else if(childpid == 0)
{
// open write pipe
if (wpipes[0] != STDIN_FILENO)
{
if (dup2(wpipes[0], STDIN_FILENO) != STDIN_FILENO)
{
std::cerr << "dup2 error to stdin" << std::endl;
}
close(wpipes[0]);
}
// open read pipe
if (rpipes[1] != STDOUT_FILENO)
{
if (dup2(rpipes[1], STDOUT_FILENO) != STDOUT_FILENO)
{
std::cerr << "dup2 error to stdout" << std::endl;
}
close(rpipes[1]);
}
// start Programm
execl("/bin/ls", "ls", (char *) 0);
}
else
{
close(wpipes[0]);
close(rpipes[1]);
pid_t ws;
ws = waitpid(childpid, &exitstatus, 0);
if (!m_stoprequested)
stop();
}
}
int main(int argc, char *argv[])
{
cExecute lirc;
lirc.setcmd("/home/sebastian/test/test.sh");
lirc.go();
while(lirc.running())
{
usleep(100000);
std::cout << "a" << std::endl;
std::cout << lirc.getdata() << std::endl;
}
std::cout << lirc.getdata() << "exitstatus:" << lirc.getexitstatus() <<std::endl;
return 0;
}
Alles anzeigen
Vielen dank für die Hilfe