execmd uses netcon
This commit is contained in:
parent
29dd3fdf3d
commit
6f483ea1dd
@ -6,8 +6,8 @@ LIBS = librcl.a
|
||||
|
||||
all: $(LIBS)
|
||||
|
||||
OBJS = rclaspell.o rclconfig.o rclinit.o textsplit.o unacpp.o csguess.o indexer.o mimetype.o htmlparse.o myhtmlparse.o mimehandler.o internfile.o mh_exec.o mh_html.o mh_mail.o mh_mbox.o mh_text.o docseq.o docseqdb.o docseqhist.o filtseq.o history.o plaintorich.o recollq.o reslistpager.o sortseq.o wasastringtoquery.o wasatorcl.o rcldb.o rcldoc.o rclquery.o searchdata.o stemdb.o stoplist.o base64.o conftree.o copyfile.o debuglog.o execmd.o fstreewalk.o idfile.o fileudi.o md5.o mimeparse.o pathut.o pxattr.o readfile.o smallut.o transcode.o wipedir.o x11mon.o mime-getpart.o mime-parsefull.o mime-parseonlyheader.o mime-printbody.o mime-printdoc.o mime-printheader.o mime.o convert.o iodevice.o iofactory.o
|
||||
DEPS = rclaspell.dep.stamp rclconfig.dep.stamp rclinit.dep.stamp textsplit.dep.stamp unacpp.dep.stamp csguess.dep.stamp indexer.dep.stamp mimetype.dep.stamp htmlparse.dep.stamp myhtmlparse.dep.stamp mimehandler.dep.stamp internfile.dep.stamp mh_exec.dep.stamp mh_html.dep.stamp mh_mail.dep.stamp mh_mbox.dep.stamp mh_text.dep.stamp docseq.dep.stamp docseqdb.dep.stamp docseqhist.dep.stamp filtseq.dep.stamp history.dep.stamp plaintorich.dep.stamp recollq.dep.stamp reslistpager.dep.stamp sortseq.dep.stamp wasastringtoquery.dep.stamp wasatorcl.dep.stamp rcldb.dep.stamp rcldoc.dep.stamp rclquery.dep.stamp searchdata.dep.stamp stemdb.dep.stamp stoplist.dep.stamp base64.dep.stamp conftree.dep.stamp copyfile.dep.stamp debuglog.dep.stamp execmd.dep.stamp fstreewalk.dep.stamp idfile.dep.stamp fileudi.dep.stamp md5.dep.stamp mimeparse.dep.stamp pathut.dep.stamp pxattr.dep.stamp readfile.dep.stamp smallut.dep.stamp transcode.dep.stamp wipedir.dep.stamp x11mon.dep.stamp mime-getpart.dep.stamp mime-parsefull.dep.stamp mime-parseonlyheader.dep.stamp mime-printbody.dep.stamp mime-printdoc.dep.stamp mime-printheader.dep.stamp mime.dep.stamp convert.dep.stamp iodevice.dep.stamp iofactory.dep.stamp
|
||||
OBJS = rclaspell.o rclconfig.o rclinit.o textsplit.o unacpp.o csguess.o indexer.o mimetype.o htmlparse.o myhtmlparse.o mimehandler.o internfile.o mh_exec.o mh_html.o mh_mail.o mh_mbox.o mh_text.o docseq.o docseqdb.o docseqhist.o filtseq.o history.o plaintorich.o recollq.o reslistpager.o sortseq.o wasastringtoquery.o wasatorcl.o rcldb.o rcldoc.o rclquery.o searchdata.o stemdb.o stoplist.o base64.o conftree.o copyfile.o debuglog.o execmd.o fstreewalk.o idfile.o fileudi.o md5.o mimeparse.o netcon.o pathut.o pxattr.o readfile.o smallut.o transcode.o wipedir.o x11mon.o mime-getpart.o mime-parsefull.o mime-parseonlyheader.o mime-printbody.o mime-printdoc.o mime-printheader.o mime.o convert.o iodevice.o iofactory.o
|
||||
DEPS = rclaspell.dep.stamp rclconfig.dep.stamp rclinit.dep.stamp textsplit.dep.stamp unacpp.dep.stamp csguess.dep.stamp indexer.dep.stamp mimetype.dep.stamp htmlparse.dep.stamp myhtmlparse.dep.stamp mimehandler.dep.stamp internfile.dep.stamp mh_exec.dep.stamp mh_html.dep.stamp mh_mail.dep.stamp mh_mbox.dep.stamp mh_text.dep.stamp docseq.dep.stamp docseqdb.dep.stamp docseqhist.dep.stamp filtseq.dep.stamp history.dep.stamp plaintorich.dep.stamp recollq.dep.stamp reslistpager.dep.stamp sortseq.dep.stamp wasastringtoquery.dep.stamp wasatorcl.dep.stamp rcldb.dep.stamp rcldoc.dep.stamp rclquery.dep.stamp searchdata.dep.stamp stemdb.dep.stamp stoplist.dep.stamp base64.dep.stamp conftree.dep.stamp copyfile.dep.stamp debuglog.dep.stamp execmd.dep.stamp fstreewalk.dep.stamp idfile.dep.stamp fileudi.dep.stamp md5.dep.stamp mimeparse.dep.stamp netcon.dep.stamp pathut.dep.stamp pxattr.dep.stamp readfile.dep.stamp smallut.dep.stamp transcode.dep.stamp wipedir.dep.stamp x11mon.dep.stamp mime-getpart.dep.stamp mime-parsefull.dep.stamp mime-parseonlyheader.dep.stamp mime-printbody.dep.stamp mime-printdoc.dep.stamp mime-printheader.dep.stamp mime.dep.stamp convert.dep.stamp iodevice.dep.stamp iofactory.dep.stamp
|
||||
|
||||
librcl.a : $(DEPS) $(OBJS) unac.o
|
||||
ar ru librcl.a $(OBJS) unac.o
|
||||
@ -103,6 +103,8 @@ md5.o : ../utils/md5.cpp
|
||||
$(CXX) $(ALL_CXXFLAGS) -c ../utils/md5.cpp
|
||||
mimeparse.o : ../utils/mimeparse.cpp
|
||||
$(CXX) $(ALL_CXXFLAGS) -c ../utils/mimeparse.cpp
|
||||
netcon.o : ../utils/netcon.cpp
|
||||
$(CXX) $(ALL_CXXFLAGS) -c ../utils/netcon.cpp
|
||||
pathut.o : ../utils/pathut.cpp
|
||||
$(CXX) $(ALL_CXXFLAGS) -c ../utils/pathut.cpp
|
||||
pxattr.o : ../utils/pxattr.cpp
|
||||
@ -275,6 +277,9 @@ md5.dep.stamp : ../utils/md5.cpp
|
||||
mimeparse.dep.stamp : ../utils/mimeparse.cpp
|
||||
$(CXX) -M $(ALL_CXXFLAGS) ../utils/mimeparse.cpp > mimeparse.dep
|
||||
touch mimeparse.dep.stamp
|
||||
netcon.dep.stamp : ../utils/netcon.cpp
|
||||
$(CXX) -M $(ALL_CXXFLAGS) ../utils/netcon.cpp > netcon.dep
|
||||
touch netcon.dep.stamp
|
||||
pathut.dep.stamp : ../utils/pathut.cpp
|
||||
$(CXX) -M $(ALL_CXXFLAGS) ../utils/pathut.cpp > pathut.dep
|
||||
touch pathut.dep.stamp
|
||||
@ -340,6 +345,7 @@ include idfile.dep
|
||||
include fileudi.dep
|
||||
include md5.dep
|
||||
include mimeparse.dep
|
||||
include netcon.dep
|
||||
include pathut.dep
|
||||
include pxattr.dep
|
||||
include readfile.dep
|
||||
|
||||
@ -48,6 +48,7 @@ ${depth}/utils/idfile.cpp \
|
||||
${depth}/utils/fileudi.cpp \
|
||||
${depth}/utils/md5.cpp \
|
||||
${depth}/utils/mimeparse.cpp \
|
||||
${depth}/utils/netcon.cpp \
|
||||
${depth}/utils/pathut.cpp \
|
||||
${depth}/utils/pxattr.cpp \
|
||||
${depth}/utils/readfile.cpp \
|
||||
|
||||
@ -45,6 +45,7 @@ static char rcsid[] = "@(#$Id: execmd.cpp,v 1.27 2008-10-06 06:22:47 dockes Exp
|
||||
#include "pathut.h"
|
||||
#include "debuglog.h"
|
||||
#include "smallut.h"
|
||||
#include "netcon.h"
|
||||
|
||||
#ifndef NO_NAMESPACES
|
||||
using namespace std;
|
||||
@ -145,6 +146,8 @@ public:
|
||||
close(m_parent->m_pipeout[0]);
|
||||
if (m_parent->m_pipeout[1] >= 0)
|
||||
close(m_parent->m_pipeout[1]);
|
||||
m_parent->m_tocmd.release();
|
||||
m_parent->m_fromcmd.release();
|
||||
pthread_sigmask(SIG_UNBLOCK, &m_parent->m_blkcld, 0);
|
||||
m_parent->reset();
|
||||
}
|
||||
@ -152,11 +155,10 @@ private:
|
||||
ExecCmd *m_parent;
|
||||
bool m_active;
|
||||
};
|
||||
|
||||
ExecCmd::~ExecCmd()
|
||||
{
|
||||
{
|
||||
ExecCmdRsrc(this);
|
||||
}
|
||||
ExecCmdRsrc(this);
|
||||
}
|
||||
|
||||
int ExecCmd::startExec(const string &cmd, const list<string>& args,
|
||||
@ -171,6 +173,8 @@ int ExecCmd::startExec(const string &cmd, const list<string>& args,
|
||||
LOGDEB(("ExecCmd::startExec: (%d|%d) %s\n",
|
||||
has_input, has_output, command.c_str()));
|
||||
}
|
||||
|
||||
// The resource manager ensures resources are freed if we return early
|
||||
ExecCmdRsrc e(this);
|
||||
|
||||
if (has_input && pipe(m_pipein) < 0) {
|
||||
@ -202,128 +206,166 @@ int ExecCmd::startExec(const string &cmd, const list<string>& args,
|
||||
if (has_input) {
|
||||
close(m_pipein[0]);
|
||||
m_pipein[0] = -1;
|
||||
fcntl(m_pipein[1], F_SETFL, O_NONBLOCK);
|
||||
NetconCli *iclicon = new NetconCli();
|
||||
iclicon->setconn(m_pipein[1]);
|
||||
m_tocmd = NetconP(iclicon);
|
||||
m_pipein[1] = 0;
|
||||
}
|
||||
if (has_output) {
|
||||
close(m_pipeout[1]);
|
||||
m_pipeout[1] = -1;
|
||||
fcntl(m_pipeout[0], F_SETFL, O_NONBLOCK);
|
||||
NetconCli *oclicon = new NetconCli();
|
||||
oclicon->setconn(m_pipeout[0]);
|
||||
m_fromcmd = NetconP(oclicon);
|
||||
m_pipeout[0] = -1;
|
||||
}
|
||||
|
||||
/* Don't want to undo what we just did ! */
|
||||
e.inactivate();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Netcon callback. Send data to the command's input
|
||||
class ExecWriter : public NetconWorker {
|
||||
public:
|
||||
ExecWriter(const string *input, ExecCmdProvide *provide)
|
||||
: m_input(input), m_cnt(0), m_provide(provide)
|
||||
{}
|
||||
virtual int data(NetconData *con, Netcon::Event reason)
|
||||
{
|
||||
if (!m_input) return -1;
|
||||
LOGDEB(("ExecWriter: input m_cnt %d input length %d\n", m_cnt,
|
||||
m_input->length()));
|
||||
if (m_cnt >= m_input->length()) {
|
||||
// Fd ready for more but we got none.
|
||||
if (m_provide) {
|
||||
m_provide->newData();
|
||||
if (m_input->empty()) {
|
||||
return 0;
|
||||
} else {
|
||||
m_cnt = 0;
|
||||
}
|
||||
LOGDEB2(("ExecWriter: provide m_cnt %d input length %d\n",
|
||||
m_cnt, m_input->length()));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
int ret = con->send(m_input->c_str() + m_cnt,
|
||||
m_input->length() - m_cnt);
|
||||
LOGDEB2(("ExecWriter: wrote %d to command\n", ret));
|
||||
if (ret <= 0) {
|
||||
LOGERR(("ExecWriter: data: can't write\n"));
|
||||
return -1;
|
||||
}
|
||||
m_cnt += ret;
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
const string *m_input;
|
||||
unsigned int m_cnt; // Current offset inside m_input
|
||||
ExecCmdProvide *m_provide;
|
||||
};
|
||||
|
||||
// Netcon callback. Get data from the command output.
|
||||
class ExecReader : public NetconWorker {
|
||||
public:
|
||||
ExecReader(string *output, ExecCmdAdvise *advise)
|
||||
: m_output(output), m_advise(advise)
|
||||
{}
|
||||
virtual int data(NetconData *con, Netcon::Event reason)
|
||||
{
|
||||
char buf[8192];
|
||||
int n = con->receive(buf, 8192);
|
||||
LOGDEB(("ExecReader: got %d from command\n", n));
|
||||
if (n < 0) {
|
||||
LOGERR(("ExecCmd::doexec: receive failed. errno %d\n", errno));
|
||||
} else if (n > 0) {
|
||||
m_output->append(buf, n);
|
||||
if (m_advise)
|
||||
m_advise->newData(n);
|
||||
} // else n == 0, just return
|
||||
return n;
|
||||
}
|
||||
private:
|
||||
string *m_output;
|
||||
ExecCmdAdvise *m_advise;
|
||||
};
|
||||
|
||||
int ExecCmd::doexec(const string &cmd, const list<string>& args,
|
||||
const string *inputstring, string *output)
|
||||
const string *input, string *output)
|
||||
{
|
||||
if (startExec(cmd, args, inputstring != 0, output != 0) < 0) {
|
||||
if (startExec(cmd, args, input != 0, output != 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Need something to take note of my own errors (apart from the command's)
|
||||
bool haderror = false;
|
||||
const char *input = inputstring ? inputstring->data() : 0;
|
||||
unsigned int inputlen = inputstring ? inputstring->length() : 0;
|
||||
// Cleanup in case we return early
|
||||
ExecCmdRsrc e(this);
|
||||
|
||||
int ret = 0;
|
||||
if (input || output) {
|
||||
unsigned int nwritten = 0;
|
||||
int nfds = MAX(m_pipein[1], m_pipeout[0]) + 1;
|
||||
fd_set readfds, writefds;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = m_timeoutMs / 1000;
|
||||
tv.tv_usec = 1000 * (m_timeoutMs % 1000);
|
||||
for(; nfds > 0;) {
|
||||
if (m_cancelRequest)
|
||||
break;
|
||||
// Setup output
|
||||
if (output) {
|
||||
NetconCli *oclicon = dynamic_cast<NetconCli *>(m_fromcmd.getptr());
|
||||
if (!oclicon) {
|
||||
LOGERR(("ExecCmd::doexec: no connection from command\n"));
|
||||
return -1;
|
||||
}
|
||||
oclicon->setcallback(RefCntr<NetconWorker>
|
||||
(new ExecReader(output, m_advise)));
|
||||
Netcon::addselcon(m_fromcmd, Netcon::NETCONPOLL_READ);
|
||||
// Give up ownership
|
||||
m_fromcmd.release();
|
||||
}
|
||||
// Setup input
|
||||
if (input) {
|
||||
NetconCli *iclicon = dynamic_cast<NetconCli *>(m_tocmd.getptr());
|
||||
if (!iclicon) {
|
||||
LOGERR(("ExecCmd::doexec: no connection from command\n"));
|
||||
return -1;
|
||||
}
|
||||
iclicon->setcallback(RefCntr<NetconWorker>
|
||||
(new ExecWriter(input, m_provide)));
|
||||
Netcon::addselcon(m_tocmd, Netcon::NETCONPOLL_WRITE);
|
||||
// Give up ownership
|
||||
m_tocmd.release();
|
||||
}
|
||||
|
||||
FD_ZERO(&writefds);
|
||||
FD_ZERO(&readfds);
|
||||
if (m_pipein[1] >= 0)
|
||||
FD_SET(m_pipein[1], &writefds);
|
||||
if (m_pipeout[0] >= 0)
|
||||
FD_SET(m_pipeout[0], &readfds);
|
||||
nfds = MAX(m_pipein[1], m_pipeout[0]) + 1;
|
||||
//struct timeval to; to.tv_sec = 1;to.tv_usec=0;
|
||||
//cerr << "m_pipein[1] "<< m_pipein[1] << " m_pipeout[0] " <<
|
||||
//m_pipeout[0] << " nfds " << nfds << endl;
|
||||
int ss;
|
||||
if ((ss = select(nfds, &readfds, &writefds, 0, &tv)) <= 0) {
|
||||
if (ss == 0) {
|
||||
// Timeout, is ok.
|
||||
if (m_advise)
|
||||
m_advise->newData(0);
|
||||
continue;
|
||||
}
|
||||
LOGERR(("ExecCmd::doexec: select(2) failed. errno %d\n",
|
||||
errno));
|
||||
haderror = true;
|
||||
// Do the actual reading/writing/waiting
|
||||
Netcon::setperiodichandler(0, 0, m_timeoutMs);
|
||||
while ((ret = Netcon::selectloop()) > 0) {
|
||||
LOGDEB(("ExecCmd::doexec: selectloop returned %d\n", ret));
|
||||
if (m_advise)
|
||||
m_advise->newData(0);
|
||||
if (m_cancelRequest) {
|
||||
LOGINFO(("ExecCmd::doexec: cancel request\n"));
|
||||
break;
|
||||
}
|
||||
if (m_pipein[1] >= 0 && FD_ISSET(m_pipein[1], &writefds)) {
|
||||
int n = write(m_pipein[1], input + nwritten,
|
||||
inputlen - nwritten);
|
||||
if (n < 0) {
|
||||
LOGERR(("ExecCmd::doexec: write(2) failed. errno %d\n",
|
||||
errno));
|
||||
haderror = true;
|
||||
goto out;
|
||||
}
|
||||
nwritten += n;
|
||||
if (nwritten == inputlen) {
|
||||
if (m_provide) {
|
||||
m_provide->newData();
|
||||
if (inputstring->empty()) {
|
||||
close(m_pipein[1]);
|
||||
m_pipein[1] = -1;
|
||||
} else {
|
||||
input = inputstring->data();
|
||||
inputlen = inputstring->length();
|
||||
nwritten = 0;
|
||||
}
|
||||
} else {
|
||||
// cerr << "Closing output" << endl;
|
||||
close(m_pipein[1]);
|
||||
m_pipein[1] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_pipeout[0] > 0 && FD_ISSET(m_pipeout[0], &readfds)) {
|
||||
char buf[8192];
|
||||
int n = read(m_pipeout[0], buf, 8192);
|
||||
if (n == 0) {
|
||||
goto out;
|
||||
} else if (n < 0) {
|
||||
LOGERR(("ExecCmd::doexec: read(2) failed. errno %d\n",
|
||||
errno));
|
||||
haderror = true;
|
||||
goto out;
|
||||
} else if (n > 0) {
|
||||
// cerr << "READ: " << n << endl;
|
||||
output->append(buf, n);
|
||||
if (m_advise)
|
||||
m_advise->newData(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
LOGDEB(("ExecCmd::doexec: selectloop returned %d\n", ret));
|
||||
}
|
||||
|
||||
out:
|
||||
// Normal return: deactivate cleaner, wait() will do the cleanup
|
||||
e.inactivate();
|
||||
return wait(haderror);
|
||||
|
||||
return ExecCmd::wait(ret);
|
||||
}
|
||||
|
||||
int ExecCmd::send(const string& data)
|
||||
{
|
||||
NetconCli *con = dynamic_cast<NetconCli *>(m_tocmd.getptr());
|
||||
if (con == 0) {
|
||||
LOGERR(("ExecCmd::send: outpipe is closed\n"));
|
||||
return -1;
|
||||
}
|
||||
unsigned int nwritten = 0;
|
||||
while (nwritten < data.length()) {
|
||||
if (m_cancelRequest)
|
||||
break;
|
||||
int n = write(m_pipein[1], data.c_str() + nwritten,
|
||||
data.length() - nwritten);
|
||||
int n = con->send(data.c_str() + nwritten, data.length() - nwritten);
|
||||
if (n < 0) {
|
||||
LOGERR(("ExecCmd::doexec: write(2) failed. errno %d\n", errno));
|
||||
LOGERR(("ExecCmd::doexec: send failed\n"));
|
||||
return -1;
|
||||
}
|
||||
nwritten += n;
|
||||
@ -333,51 +375,29 @@ int ExecCmd::send(const string& data)
|
||||
|
||||
int ExecCmd::receive(string& data)
|
||||
{
|
||||
if (m_pipeout[0] < 0) {
|
||||
LOGERR(("ExecCmd::receive: pipe is closed\n"));
|
||||
return -1;
|
||||
}
|
||||
int nfds = m_pipeout[0] + 1;
|
||||
fd_set readfds;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = m_timeoutMs / 1000;
|
||||
tv.tv_usec = 1000 * (m_timeoutMs % 1000);
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(m_pipeout[0], &readfds);
|
||||
int ss;
|
||||
if ((ss = select(nfds, &readfds, 0, 0, &tv)) <= 0) {
|
||||
if (ss == 0) {
|
||||
// timeout
|
||||
return 0;
|
||||
}
|
||||
LOGERR(("ExecCmd::receive: select(2) failed. errno %d\n", errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!FD_ISSET(m_pipeout[0], &readfds)) {
|
||||
LOGERR(("ExecCmd::receive: fd not ready after select ??\n"));
|
||||
NetconCli *con = dynamic_cast<NetconCli *>(m_fromcmd.getptr());
|
||||
if (con == 0) {
|
||||
LOGERR(("ExecCmd::receive: outpipe is closed\n"));
|
||||
return -1;
|
||||
}
|
||||
char buf[8192];
|
||||
int n = read(m_pipeout[0], buf, 8192);
|
||||
if (n == 0) {
|
||||
return 0;
|
||||
} else if (n < 0) {
|
||||
LOGERR(("ExecCmd::doexec: read(2) failed. errno %d\n", errno));
|
||||
return -1;
|
||||
} else {
|
||||
// cerr << "READ: " << n << endl;
|
||||
data.assign(buf, n);
|
||||
int n = con->receive(buf, 8192);
|
||||
if (n < 0) {
|
||||
LOGERR(("ExecCmd::receive: error\n"));
|
||||
} else if (n > 0) {
|
||||
data.append(buf, n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
// Wait for command status and clean up all resources.
|
||||
int ExecCmd::wait(bool haderror)
|
||||
{
|
||||
ExecCmdRsrc e(this);
|
||||
int status = -1;
|
||||
if (!m_cancelRequest) {
|
||||
(void)waitpid(m_pid, &status, 0);
|
||||
if (waitpid(m_pid, &status, 0) < 0)
|
||||
status = -1;
|
||||
m_pid = -1;
|
||||
}
|
||||
LOGDEB(("ExecCmd::wait: got status 0x%x\n", status));
|
||||
@ -479,11 +499,23 @@ using namespace std;
|
||||
|
||||
#include "execmd.h"
|
||||
|
||||
static int op_flags;
|
||||
#define OPT_MOINS 0x1
|
||||
#define OPT_b 0x4
|
||||
#define OPT_w 0x8
|
||||
#define OPT_c 0x10
|
||||
|
||||
const char *data = "Une ligne de donnees\n";
|
||||
class MEAdv : public ExecCmdAdvise {
|
||||
public:
|
||||
ExecCmd *cmd;
|
||||
void newData(int cnt) {
|
||||
if (op_flags & OPT_c) {
|
||||
static int callcnt;
|
||||
if (callcnt++ == 3) {
|
||||
throw CancelExcept();
|
||||
}
|
||||
}
|
||||
cerr << "newData(" << cnt << ")" << endl;
|
||||
// CancelCheck::instance().setCancel();
|
||||
// CancelCheck::instance().checkCancel();
|
||||
@ -517,8 +549,9 @@ public:
|
||||
|
||||
static char *thisprog;
|
||||
static char usage [] =
|
||||
"execmd cmd [arg1 arg2 ...]\n"
|
||||
" \n\n"
|
||||
"trexecmd [-c] cmd [arg1 arg2 ...]\n"
|
||||
" -c : test cancellation (ie: trexecmd -c sleep 1000)\n"
|
||||
"trexecmd -w cmd : do the which thing\n"
|
||||
;
|
||||
static void Usage(void)
|
||||
{
|
||||
@ -526,14 +559,8 @@ static void Usage(void)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int op_flags;
|
||||
#define OPT_MOINS 0x1
|
||||
#define OPT_s 0x2
|
||||
#define OPT_b 0x4
|
||||
#define OPT_w 0x8
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int count = 10;
|
||||
thisprog = argv[0];
|
||||
argc--; argv++;
|
||||
|
||||
@ -544,13 +571,8 @@ int main(int argc, char **argv)
|
||||
Usage();
|
||||
while (**argv)
|
||||
switch (*(*argv)++) {
|
||||
case 'b': op_flags |= OPT_b; if (argc < 2) Usage();
|
||||
if ((sscanf(*(++argv), "%d", &count)) != 1)
|
||||
Usage();
|
||||
argc--;
|
||||
goto b1;
|
||||
case 's': op_flags |= OPT_s; break;
|
||||
case 'w': op_flags |= OPT_w; break;
|
||||
case 'c': op_flags |= OPT_c; break;
|
||||
default: Usage(); break;
|
||||
}
|
||||
b1: argc--; argv++;
|
||||
@ -567,7 +589,7 @@ int main(int argc, char **argv)
|
||||
|
||||
DebugLog::getdbl()->setloglevel(DEBDEB1);
|
||||
DebugLog::setfilename("stderr");
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
if (op_flags & OPT_w) {
|
||||
string path;
|
||||
if (ExecCmd::which(cmd, path)) {
|
||||
@ -580,7 +602,7 @@ int main(int argc, char **argv)
|
||||
MEAdv adv;
|
||||
adv.cmd = &mexec;
|
||||
mexec.setAdvise(&adv);
|
||||
mexec.setTimeout(500);
|
||||
mexec.setTimeout(5);
|
||||
mexec.setStderr("/tmp/trexecStderr");
|
||||
mexec.putenv("TESTVARIABLE1=TESTVALUE1");
|
||||
mexec.putenv("TESTVARIABLE2=TESTVALUE2");
|
||||
@ -598,11 +620,11 @@ int main(int argc, char **argv)
|
||||
try {
|
||||
status = mexec.doexec(cmd, l, ip, &output);
|
||||
} catch (CancelExcept) {
|
||||
cerr << "CANCELED" << endl;
|
||||
cerr << "CANCELLED" << endl;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Status: 0x%x\n", status);
|
||||
cout << "Output:[" << output << "]" << endl;
|
||||
cout << output;
|
||||
exit (status >> 8);
|
||||
}
|
||||
#endif // TEST
|
||||
|
||||
@ -27,12 +27,15 @@ using std::string;
|
||||
using std::vector;
|
||||
#endif
|
||||
|
||||
#include "netcon.h"
|
||||
|
||||
/**
|
||||
* Callback function object to advise of new data arrival, or just periodic
|
||||
* heartbeat if cnt is 0.
|
||||
*
|
||||
* The code using ExeCmd should raise an exception inside newData()
|
||||
* (and catch it doexec's caller) to interrupt the command.
|
||||
* To interrupt the command, the code using ExecCmd should either
|
||||
* raise an exception inside newData() (and catch it in doexec's caller), or
|
||||
* call ExecCmd::setCancel()
|
||||
*
|
||||
*/
|
||||
class ExecCmdAdvise {
|
||||
@ -75,7 +78,7 @@ class ExecCmd {
|
||||
* Add/replace environment variable before executing command. This must
|
||||
* be called before doexec() to have an effect (possibly multiple
|
||||
* times for several variables).
|
||||
* @param envassign an environment assignment string (name=value)
|
||||
* @param envassign an environment assignment string ("name=value")
|
||||
*/
|
||||
void putenv(const string &envassign);
|
||||
|
||||
@ -124,6 +127,10 @@ class ExecCmd {
|
||||
const string *input = 0,
|
||||
string *output = 0);
|
||||
|
||||
/*
|
||||
* The next four methods can be used when a Q/A dialog needs to be
|
||||
* performed with the command
|
||||
*/
|
||||
int startExec(const string &cmd, const list<string>& args,
|
||||
bool has_input, bool has_output);
|
||||
int send(const string& data);
|
||||
@ -152,8 +159,7 @@ class ExecCmd {
|
||||
* @param path exec seach path to use instead of getenv(PATH)
|
||||
* @return true if found
|
||||
*/
|
||||
static bool which(const string& cmd, string& exepath,
|
||||
const char* path = 0);
|
||||
static bool which(const string& cmd, string& exe, const char* path = 0);
|
||||
|
||||
friend class ExecCmdRsrc;
|
||||
private:
|
||||
@ -165,14 +171,17 @@ class ExecCmd {
|
||||
string m_stderrFile;
|
||||
// Pipe for data going to the command
|
||||
int m_pipein[2];
|
||||
NetconP m_tocmd;
|
||||
// Pipe for data coming out
|
||||
int m_pipeout[2];
|
||||
NetconP m_fromcmd;
|
||||
// Subprocess id
|
||||
pid_t m_pid;
|
||||
// Saved sigmask
|
||||
sigset_t m_blkcld;
|
||||
|
||||
// Reset internal execution state
|
||||
// Reset internal state indicators. Any resources should have been
|
||||
// previously freed
|
||||
void reset() {
|
||||
m_cancelRequest = false;
|
||||
m_pipein[0] = m_pipein[1] = m_pipeout[0] = m_pipeout[1] = -1;
|
||||
|
||||
1
src/utils/netcon.cpp
Symbolic link
1
src/utils/netcon.cpp
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../docklib/netcon.cpp
|
||||
1
src/utils/netcon.h
Symbolic link
1
src/utils/netcon.h
Symbolic link
@ -0,0 +1 @@
|
||||
../../../../docklib/netcon.h
|
||||
Loading…
x
Reference in New Issue
Block a user