execmd uses netcon

This commit is contained in:
dockes 2009-09-26 09:30:17 +00:00
parent 29dd3fdf3d
commit 6f483ea1dd
6 changed files with 190 additions and 150 deletions

View File

@ -6,8 +6,8 @@ LIBS = librcl.a
all: $(LIBS) 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 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 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 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 librcl.a : $(DEPS) $(OBJS) unac.o
ar ru librcl.a $(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 $(CXX) $(ALL_CXXFLAGS) -c ../utils/md5.cpp
mimeparse.o : ../utils/mimeparse.cpp mimeparse.o : ../utils/mimeparse.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../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 pathut.o : ../utils/pathut.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../utils/pathut.cpp $(CXX) $(ALL_CXXFLAGS) -c ../utils/pathut.cpp
pxattr.o : ../utils/pxattr.cpp pxattr.o : ../utils/pxattr.cpp
@ -275,6 +277,9 @@ md5.dep.stamp : ../utils/md5.cpp
mimeparse.dep.stamp : ../utils/mimeparse.cpp mimeparse.dep.stamp : ../utils/mimeparse.cpp
$(CXX) -M $(ALL_CXXFLAGS) ../utils/mimeparse.cpp > mimeparse.dep $(CXX) -M $(ALL_CXXFLAGS) ../utils/mimeparse.cpp > mimeparse.dep
touch mimeparse.dep.stamp 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 pathut.dep.stamp : ../utils/pathut.cpp
$(CXX) -M $(ALL_CXXFLAGS) ../utils/pathut.cpp > pathut.dep $(CXX) -M $(ALL_CXXFLAGS) ../utils/pathut.cpp > pathut.dep
touch pathut.dep.stamp touch pathut.dep.stamp
@ -340,6 +345,7 @@ include idfile.dep
include fileudi.dep include fileudi.dep
include md5.dep include md5.dep
include mimeparse.dep include mimeparse.dep
include netcon.dep
include pathut.dep include pathut.dep
include pxattr.dep include pxattr.dep
include readfile.dep include readfile.dep

View File

@ -48,6 +48,7 @@ ${depth}/utils/idfile.cpp \
${depth}/utils/fileudi.cpp \ ${depth}/utils/fileudi.cpp \
${depth}/utils/md5.cpp \ ${depth}/utils/md5.cpp \
${depth}/utils/mimeparse.cpp \ ${depth}/utils/mimeparse.cpp \
${depth}/utils/netcon.cpp \
${depth}/utils/pathut.cpp \ ${depth}/utils/pathut.cpp \
${depth}/utils/pxattr.cpp \ ${depth}/utils/pxattr.cpp \
${depth}/utils/readfile.cpp \ ${depth}/utils/readfile.cpp \

View File

@ -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 "pathut.h"
#include "debuglog.h" #include "debuglog.h"
#include "smallut.h" #include "smallut.h"
#include "netcon.h"
#ifndef NO_NAMESPACES #ifndef NO_NAMESPACES
using namespace std; using namespace std;
@ -145,6 +146,8 @@ public:
close(m_parent->m_pipeout[0]); close(m_parent->m_pipeout[0]);
if (m_parent->m_pipeout[1] >= 0) if (m_parent->m_pipeout[1] >= 0)
close(m_parent->m_pipeout[1]); 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); pthread_sigmask(SIG_UNBLOCK, &m_parent->m_blkcld, 0);
m_parent->reset(); m_parent->reset();
} }
@ -152,11 +155,10 @@ private:
ExecCmd *m_parent; ExecCmd *m_parent;
bool m_active; bool m_active;
}; };
ExecCmd::~ExecCmd() ExecCmd::~ExecCmd()
{ {
{ ExecCmdRsrc(this);
ExecCmdRsrc(this);
}
} }
int ExecCmd::startExec(const string &cmd, const list<string>& args, 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", LOGDEB(("ExecCmd::startExec: (%d|%d) %s\n",
has_input, has_output, command.c_str())); has_input, has_output, command.c_str()));
} }
// The resource manager ensures resources are freed if we return early
ExecCmdRsrc e(this); ExecCmdRsrc e(this);
if (has_input && pipe(m_pipein) < 0) { if (has_input && pipe(m_pipein) < 0) {
@ -202,128 +206,166 @@ int ExecCmd::startExec(const string &cmd, const list<string>& args,
if (has_input) { if (has_input) {
close(m_pipein[0]); close(m_pipein[0]);
m_pipein[0] = -1; 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) { if (has_output) {
close(m_pipeout[1]); close(m_pipeout[1]);
m_pipeout[1] = -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(); e.inactivate();
return 0; 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, 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; return -1;
} }
// Need something to take note of my own errors (apart from the command's) // Cleanup in case we return early
bool haderror = false;
const char *input = inputstring ? inputstring->data() : 0;
unsigned int inputlen = inputstring ? inputstring->length() : 0;
ExecCmdRsrc e(this); ExecCmdRsrc e(this);
int ret = 0;
if (input || output) { if (input || output) {
unsigned int nwritten = 0; // Setup output
int nfds = MAX(m_pipein[1], m_pipeout[0]) + 1; if (output) {
fd_set readfds, writefds; NetconCli *oclicon = dynamic_cast<NetconCli *>(m_fromcmd.getptr());
struct timeval tv; if (!oclicon) {
tv.tv_sec = m_timeoutMs / 1000; LOGERR(("ExecCmd::doexec: no connection from command\n"));
tv.tv_usec = 1000 * (m_timeoutMs % 1000); return -1;
for(; nfds > 0;) { }
if (m_cancelRequest) oclicon->setcallback(RefCntr<NetconWorker>
break; (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); // Do the actual reading/writing/waiting
FD_ZERO(&readfds); Netcon::setperiodichandler(0, 0, m_timeoutMs);
if (m_pipein[1] >= 0) while ((ret = Netcon::selectloop()) > 0) {
FD_SET(m_pipein[1], &writefds); LOGDEB(("ExecCmd::doexec: selectloop returned %d\n", ret));
if (m_pipeout[0] >= 0) if (m_advise)
FD_SET(m_pipeout[0], &readfds); m_advise->newData(0);
nfds = MAX(m_pipein[1], m_pipeout[0]) + 1; if (m_cancelRequest) {
//struct timeval to; to.tv_sec = 1;to.tv_usec=0; LOGINFO(("ExecCmd::doexec: cancel request\n"));
//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;
break; 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(); e.inactivate();
return wait(haderror);
return ExecCmd::wait(ret);
} }
int ExecCmd::send(const string& data) 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; unsigned int nwritten = 0;
while (nwritten < data.length()) { while (nwritten < data.length()) {
if (m_cancelRequest) if (m_cancelRequest)
break; break;
int n = write(m_pipein[1], data.c_str() + nwritten, int n = con->send(data.c_str() + nwritten, data.length() - nwritten);
data.length() - nwritten);
if (n < 0) { if (n < 0) {
LOGERR(("ExecCmd::doexec: write(2) failed. errno %d\n", errno)); LOGERR(("ExecCmd::doexec: send failed\n"));
return -1; return -1;
} }
nwritten += n; nwritten += n;
@ -333,51 +375,29 @@ int ExecCmd::send(const string& data)
int ExecCmd::receive(string& data) int ExecCmd::receive(string& data)
{ {
if (m_pipeout[0] < 0) { NetconCli *con = dynamic_cast<NetconCli *>(m_fromcmd.getptr());
LOGERR(("ExecCmd::receive: pipe is closed\n")); if (con == 0) {
return -1; LOGERR(("ExecCmd::receive: outpipe is closed\n"));
}
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"));
return -1; return -1;
} }
char buf[8192]; char buf[8192];
int n = read(m_pipeout[0], buf, 8192); int n = con->receive(buf, 8192);
if (n == 0) { if (n < 0) {
return 0; LOGERR(("ExecCmd::receive: error\n"));
} else if (n < 0) { } else if (n > 0) {
LOGERR(("ExecCmd::doexec: read(2) failed. errno %d\n", errno)); data.append(buf, n);
return -1;
} else {
// cerr << "READ: " << n << endl;
data.assign(buf, n);
} }
return n; return n;
} }
// Wait for command status and clean up all resources.
int ExecCmd::wait(bool haderror) int ExecCmd::wait(bool haderror)
{ {
ExecCmdRsrc e(this); ExecCmdRsrc e(this);
int status = -1; int status = -1;
if (!m_cancelRequest) { if (!m_cancelRequest) {
(void)waitpid(m_pid, &status, 0); if (waitpid(m_pid, &status, 0) < 0)
status = -1;
m_pid = -1; m_pid = -1;
} }
LOGDEB(("ExecCmd::wait: got status 0x%x\n", status)); LOGDEB(("ExecCmd::wait: got status 0x%x\n", status));
@ -479,11 +499,23 @@ using namespace std;
#include "execmd.h" #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"; const char *data = "Une ligne de donnees\n";
class MEAdv : public ExecCmdAdvise { class MEAdv : public ExecCmdAdvise {
public: public:
ExecCmd *cmd; ExecCmd *cmd;
void newData(int cnt) { void newData(int cnt) {
if (op_flags & OPT_c) {
static int callcnt;
if (callcnt++ == 3) {
throw CancelExcept();
}
}
cerr << "newData(" << cnt << ")" << endl; cerr << "newData(" << cnt << ")" << endl;
// CancelCheck::instance().setCancel(); // CancelCheck::instance().setCancel();
// CancelCheck::instance().checkCancel(); // CancelCheck::instance().checkCancel();
@ -517,8 +549,9 @@ public:
static char *thisprog; static char *thisprog;
static char usage [] = static char usage [] =
"execmd cmd [arg1 arg2 ...]\n" "trexecmd [-c] cmd [arg1 arg2 ...]\n"
" \n\n" " -c : test cancellation (ie: trexecmd -c sleep 1000)\n"
"trexecmd -w cmd : do the which thing\n"
; ;
static void Usage(void) static void Usage(void)
{ {
@ -526,14 +559,8 @@ static void Usage(void)
exit(1); 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 main(int argc, char **argv)
{ {
int count = 10;
thisprog = argv[0]; thisprog = argv[0];
argc--; argv++; argc--; argv++;
@ -544,13 +571,8 @@ int main(int argc, char **argv)
Usage(); Usage();
while (**argv) while (**argv)
switch (*(*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 'w': op_flags |= OPT_w; break;
case 'c': op_flags |= OPT_c; break;
default: Usage(); break; default: Usage(); break;
} }
b1: argc--; argv++; b1: argc--; argv++;
@ -567,7 +589,7 @@ int main(int argc, char **argv)
DebugLog::getdbl()->setloglevel(DEBDEB1); DebugLog::getdbl()->setloglevel(DEBDEB1);
DebugLog::setfilename("stderr"); DebugLog::setfilename("stderr");
signal(SIGPIPE, SIG_IGN);
if (op_flags & OPT_w) { if (op_flags & OPT_w) {
string path; string path;
if (ExecCmd::which(cmd, path)) { if (ExecCmd::which(cmd, path)) {
@ -580,7 +602,7 @@ int main(int argc, char **argv)
MEAdv adv; MEAdv adv;
adv.cmd = &mexec; adv.cmd = &mexec;
mexec.setAdvise(&adv); mexec.setAdvise(&adv);
mexec.setTimeout(500); mexec.setTimeout(5);
mexec.setStderr("/tmp/trexecStderr"); mexec.setStderr("/tmp/trexecStderr");
mexec.putenv("TESTVARIABLE1=TESTVALUE1"); mexec.putenv("TESTVARIABLE1=TESTVALUE1");
mexec.putenv("TESTVARIABLE2=TESTVALUE2"); mexec.putenv("TESTVARIABLE2=TESTVALUE2");
@ -598,11 +620,11 @@ int main(int argc, char **argv)
try { try {
status = mexec.doexec(cmd, l, ip, &output); status = mexec.doexec(cmd, l, ip, &output);
} catch (CancelExcept) { } catch (CancelExcept) {
cerr << "CANCELED" << endl; cerr << "CANCELLED" << endl;
} }
fprintf(stderr, "Status: 0x%x\n", status); fprintf(stderr, "Status: 0x%x\n", status);
cout << "Output:[" << output << "]" << endl; cout << output;
exit (status >> 8); exit (status >> 8);
} }
#endif // TEST #endif // TEST

View File

@ -27,12 +27,15 @@ using std::string;
using std::vector; using std::vector;
#endif #endif
#include "netcon.h"
/** /**
* Callback function object to advise of new data arrival, or just periodic * Callback function object to advise of new data arrival, or just periodic
* heartbeat if cnt is 0. * heartbeat if cnt is 0.
* *
* The code using ExeCmd should raise an exception inside newData() * To interrupt the command, the code using ExecCmd should either
* (and catch it doexec's caller) to interrupt the command. * raise an exception inside newData() (and catch it in doexec's caller), or
* call ExecCmd::setCancel()
* *
*/ */
class ExecCmdAdvise { class ExecCmdAdvise {
@ -75,7 +78,7 @@ class ExecCmd {
* Add/replace environment variable before executing command. This must * Add/replace environment variable before executing command. This must
* be called before doexec() to have an effect (possibly multiple * be called before doexec() to have an effect (possibly multiple
* times for several variables). * 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); void putenv(const string &envassign);
@ -124,6 +127,10 @@ class ExecCmd {
const string *input = 0, const string *input = 0,
string *output = 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, int startExec(const string &cmd, const list<string>& args,
bool has_input, bool has_output); bool has_input, bool has_output);
int send(const string& data); int send(const string& data);
@ -152,8 +159,7 @@ class ExecCmd {
* @param path exec seach path to use instead of getenv(PATH) * @param path exec seach path to use instead of getenv(PATH)
* @return true if found * @return true if found
*/ */
static bool which(const string& cmd, string& exepath, static bool which(const string& cmd, string& exe, const char* path = 0);
const char* path = 0);
friend class ExecCmdRsrc; friend class ExecCmdRsrc;
private: private:
@ -165,14 +171,17 @@ class ExecCmd {
string m_stderrFile; string m_stderrFile;
// Pipe for data going to the command // Pipe for data going to the command
int m_pipein[2]; int m_pipein[2];
NetconP m_tocmd;
// Pipe for data coming out // Pipe for data coming out
int m_pipeout[2]; int m_pipeout[2];
NetconP m_fromcmd;
// Subprocess id // Subprocess id
pid_t m_pid; pid_t m_pid;
// Saved sigmask // Saved sigmask
sigset_t m_blkcld; sigset_t m_blkcld;
// Reset internal execution state // Reset internal state indicators. Any resources should have been
// previously freed
void reset() { void reset() {
m_cancelRequest = false; m_cancelRequest = false;
m_pipein[0] = m_pipein[1] = m_pipeout[0] = m_pipeout[1] = -1; m_pipein[0] = m_pipein[1] = m_pipeout[0] = m_pipeout[1] = -1;

1
src/utils/netcon.cpp Symbolic link
View File

@ -0,0 +1 @@
../../../../docklib/netcon.cpp

1
src/utils/netcon.h Symbolic link
View File

@ -0,0 +1 @@
../../../../docklib/netcon.h