aspell checkpoint

This commit is contained in:
dockes 2006-10-09 16:37:08 +00:00
parent 57b468f58a
commit 8283ca3bfc
12 changed files with 264 additions and 119 deletions

View File

@ -1 +1 @@
1.5.4
1.6.0

View File

@ -1,6 +1,6 @@
#ifndef TEST_RCLASPELL
#ifndef lint
static char rcsid[] = "@(#$Id: rclaspell.cpp,v 1.1 2006-10-09 14:05:35 dockes Exp $ (C) 2006 J.F.Dockes";
static char rcsid[] = "@(#$Id: rclaspell.cpp,v 1.2 2006-10-09 16:37:08 dockes Exp $ (C) 2006 J.F.Dockes";
#endif
#include <unistd.h>
#include <dlfcn.h>
@ -173,7 +173,7 @@ bool Aspell::buildDict(Rcl::Db &db, string &reason)
bool Aspell::suggest(Rcl::Db &db,
string &term, list<string>suggestions, string &reason)
string &term, list<string> &suggestions, string &reason)
{
AspellCanHaveError *ret;
AspellSpeller *speller;
@ -184,6 +184,8 @@ bool Aspell::suggest(Rcl::Db &db,
aapi.aspell_config_replace(config, "lang", m_lang.c_str());
aapi.aspell_config_replace(config, "encoding", "utf-8");
aapi.aspell_config_replace(config, "master", dicPath().c_str());
aapi.aspell_config_replace(config, "sug-mode", "fast");
// aapi.aspell_config_replace(config, "sug-edit-dist", "2");
ret = aapi.new_aspell_speller(config);
aapi.delete_aspell_config(config);
@ -203,7 +205,15 @@ bool Aspell::suggest(Rcl::Db &db,
AspellStringEnumeration *els = aapi.aspell_word_list_elements(wl);
const char *word;
while ((word = aapi.aspell_string_enumeration_next(els)) != 0) {
suggestions.push_back(word);
// stemDiffers checks that the word exists (we don't want
// aspell computed stuff, only exact terms from the dictionary),
// and that it stems differently to the base word (else it's not
// useful to expand the search). Or is it ?
// ******** This should depend if
// stemming is turned on or not for querying *******
string sw(word);
if (db.termExists(sw) && db.stemDiffers("english", sw, term))
suggestions.push_back(word);
}
aapi.delete_aspell_string_enumeration(els);
aapi.delete_aspell_speller(speller);
@ -233,7 +243,9 @@ RclConfig *rclconfig;
Rcl::Db rcldb;
static char usage [] =
" \n\n"
" -b : build dictionary\n"
" -s <term>: suggestions for term\n"
"\n\n"
;
static void
Usage(void)
@ -249,75 +261,75 @@ static int op_flags;
int main(int argc, char **argv)
{
int count = 10;
string word;
thisprog = argv[0];
argc--; argv++;
thisprog = argv[0];
argc--; argv++;
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
Usage();
while (**argv)
switch (*(*argv)++) {
case 's': op_flags |= OPT_s; break;
case 'b': op_flags |= OPT_b; if (argc < 2) Usage();
if ((sscanf(*(++argv), "%d", &count)) != 1)
Usage();
argc--;
goto b1;
default: Usage(); break;
}
b1: argc--; argv++;
}
if (argc != 0)
Usage();
string reason;
rclconfig = recollinit(0, 0, reason);
if (!rclconfig || !rclconfig->ok()) {
fprintf(stderr, "Configuration problem: %s\n", reason.c_str());
exit(1);
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
Usage();
while (**argv)
switch (*(*argv)++) {
case 'b': op_flags |= OPT_b; break;
case 's': op_flags |= OPT_s; if (argc < 2) Usage();
word = *(++argv);
argc--;
goto b1;
default: Usage(); break;
}
b1: argc--; argv++;
}
string dbdir = rclconfig->getDbDir();
if (dbdir.empty()) {
fprintf(stderr, "No db directory in configuration");
exit(1);
}
if (argc != 0 || op_flags == 0)
Usage();
if (!rcldb.open(dbdir, Rcl::Db::DbRO, 0)) {
fprintf(stderr, "Could not open database in %s\n", dbdir.c_str());
exit(1);
}
string reason;
rclconfig = recollinit(0, 0, reason);
if (!rclconfig || !rclconfig->ok()) {
fprintf(stderr, "Configuration problem: %s\n", reason.c_str());
exit(1);
}
string lang = "en";
string dbdir = rclconfig->getDbDir();
if (dbdir.empty()) {
fprintf(stderr, "No db directory in configuration");
exit(1);
}
Aspell aspell(rclconfig, lang);
if (!rcldb.open(dbdir, Rcl::Db::DbRO, 0)) {
fprintf(stderr, "Could not open database in %s\n", dbdir.c_str());
exit(1);
}
if (!aspell.init("/usr/local", reason)) {
cerr << "Init failed: " << reason << endl;
exit(1);
}
#if 0
if (!aspell.buildDict(rcldb, reason)) {
cerr << "buildDict failed: " << reason << endl;
exit(1);
}
#endif
list<string> sug;
string word = "practice";
if (!aspell.suggest(rcldb, word, sug, reason)) {
cerr << "suggest failed: " << reason << endl;
exit(1);
}
for (list<string>::iterator it = sug.begin(); it != sug.end(); it++) {
cout << *it << endl;
}
string lang = "en";
exit(0);
Aspell aspell(rclconfig, lang);
if (!aspell.init("/usr/local", reason)) {
cerr << "Init failed: " << reason << endl;
exit(1);
}
if (op_flags & OPT_b) {
if (!aspell.buildDict(rcldb, reason)) {
cerr << "buildDict failed: " << reason << endl;
exit(1);
}
} else {
list<string> suggs;
if (!aspell.suggest(rcldb, word, suggs, reason)) {
cerr << "suggest failed: " << reason << endl;
exit(1);
}
cout << "Suggestions for " << word << ":" << endl;
for (list<string>::iterator it = suggs.begin();
it != suggs.end(); it++) {
cout << *it << endl;
}
}
exit(0);
}
#endif // TEST_RCLASPELL test driver

View File

@ -1,8 +1,17 @@
#ifndef _RCLASPELL_H_INCLUDED_
#define _RCLASPELL_H_INCLUDED_
/* @(#$Id: rclaspell.h,v 1.1 2006-10-09 14:05:35 dockes Exp $ (C) 2006 J.F.Dockes */
/* @(#$Id: rclaspell.h,v 1.2 2006-10-09 16:37:08 dockes Exp $ (C) 2006 J.F.Dockes */
/// Class to interface an aspell speller.
/**
* Aspell speller interface class.
*
* Aspell is used to let the user find about spelling variations that may
* exist in the document set for a given word.
* A specific aspell dictionary is created out of all the terms in the
* xapian index, and we then use it to expand a term to spelling neighbours.
* We use the aspell C api for term expansion, but have
* to execute the program to create dictionaries.
*/
#include <string>
#include <list>
@ -22,19 +31,23 @@ class Aspell {
Aspell(RclConfig *cnf, const string &lang)
: m_conf(cnf), m_lang(lang), m_data(0) {};
~Aspell();
/** Check health */
bool ok();
/** Get hold of the aspell command and shared library */
/** Find the aspell command and shared library, init function pointers */
bool init(const string &basedir, string &reason);
/** Build dictionary out of index term list. This is done at the end
* of an indexing pass. */
bool buildDict(Rcl::Db &db, string &reason);
/** Return a list of possible expansions for user term */
bool suggest(Rcl::Db &db, string &term, list<string>suggestions,
/** Return a list of possible expansions for a given word */
bool suggest(Rcl::Db &db, string &term, list<string> &suggestions,
string &reason);
string dicPath();
private:
string dicPath();
RclConfig *m_conf;
string m_lang;
AspellData *m_data;

View File

@ -4,7 +4,7 @@ include $(depth)/mk/sysconf
PROGS = recollindex csguess mimetype
SRCS = recollindex.cpp
all: depend $(PROGS)
all: depend $(PROGS) $(BIGLIB)
RECOLLINDEX_OBJS= recollindex.o $(BIGLIB) $(MIMELIB)
recollindex : $(RECOLLINDEX_OBJS)
@ -29,8 +29,10 @@ trmimetype.o : mimetype.cpp
$(CXX) $(ALL_CXXFLAGS) -DTEST_MIMETYPE -c -o trmimetype.o \
mimetype.cpp
$(BIGLIB):
$(BIGLIB): force
cd $(depth)/lib;$(MAKE)
force:
$(MIMELIB):
cd $(depth)/bincimapmime;$(MAKE)

View File

@ -8,8 +8,8 @@ LIBS = librcl.a
all: $(LIBS)
OBJS = conftree.o csguess.o debuglog.o execmd.o idfile.o md5.o wipedir.o fstreewalk.o mh_html.o mh_mail.o mh_exec.o mh_text.o htmlparse.o indexer.o internfile.o mimehandler.o mimeparse.o mimetype.o myhtmlparse.o pathhash.o pathut.o rclconfig.o rcldb.o rclinit.o stemdb.o base64.o readfile.o smallut.o textsplit.o transcode.o unacpp.o history.o docseq.o sortseq.o copyfile.o
DEPS = conftree.dep.stamp csguess.dep.stamp debuglog.dep.stamp execmd.dep.stamp idfile.dep.stamp md5.dep.stamp wipedir.dep.stamp fstreewalk.dep.stamp mh_html.dep.stamp mh_mail.dep.stamp mh_exec.dep.stamp mh_text.dep.stamp htmlparse.dep.stamp indexer.dep.stamp internfile.dep.stamp mimehandler.dep.stamp mimeparse.dep.stamp mimetype.dep.stamp myhtmlparse.dep.stamp pathhash.dep.stamp pathut.dep.stamp rclconfig.dep.stamp rcldb.dep.stamp rclinit.dep.stamp stemdb.dep.stamp base64.dep.stamp readfile.dep.stamp smallut.dep.stamp textsplit.dep.stamp transcode.dep.stamp unacpp.dep.stamp history.dep.stamp docseq.dep.stamp sortseq.dep.stamp copyfile.dep.stamp
OBJS = conftree.o csguess.o debuglog.o execmd.o idfile.o md5.o wipedir.o fstreewalk.o mh_html.o mh_mail.o mh_exec.o mh_text.o htmlparse.o indexer.o internfile.o mimehandler.o mimeparse.o mimetype.o myhtmlparse.o pathhash.o pathut.o rclconfig.o rcldb.o rclinit.o stemdb.o base64.o readfile.o smallut.o textsplit.o transcode.o unacpp.o history.o docseq.o sortseq.o copyfile.o rclaspell.o
DEPS = conftree.dep.stamp csguess.dep.stamp debuglog.dep.stamp execmd.dep.stamp idfile.dep.stamp md5.dep.stamp wipedir.dep.stamp fstreewalk.dep.stamp mh_html.dep.stamp mh_mail.dep.stamp mh_exec.dep.stamp mh_text.dep.stamp htmlparse.dep.stamp indexer.dep.stamp internfile.dep.stamp mimehandler.dep.stamp mimeparse.dep.stamp mimetype.dep.stamp myhtmlparse.dep.stamp pathhash.dep.stamp pathut.dep.stamp rclconfig.dep.stamp rcldb.dep.stamp rclinit.dep.stamp stemdb.dep.stamp base64.dep.stamp readfile.dep.stamp smallut.dep.stamp textsplit.dep.stamp transcode.dep.stamp unacpp.dep.stamp history.dep.stamp docseq.dep.stamp sortseq.dep.stamp copyfile.dep.stamp rclaspell.dep.stamp
librcl.a : $(DEPS) $(OBJS) unac.o
ar ru librcl.a $(OBJS) unac.o
@ -87,6 +87,8 @@ sortseq.o : ../query/sortseq.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../query/sortseq.cpp
copyfile.o : ../utils/copyfile.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../utils/copyfile.cpp
rclaspell.o : ../aspell/rclaspell.cpp
$(CXX) $(ALL_CXXFLAGS) -c ../aspell/rclaspell.cpp
depend: $(DEPS)
clean:
rm -f $(OBJS) $(LIBS) $(DEPS) unac.o
@ -198,6 +200,9 @@ sortseq.dep.stamp : ../query/sortseq.cpp
copyfile.dep.stamp : ../utils/copyfile.cpp
$(CXX) -M $(ALL_CXXFLAGS) ../utils/copyfile.cpp > copyfile.dep
touch copyfile.dep.stamp
rclaspell.dep.stamp : ../aspell/rclaspell.cpp
$(CXX) -M $(ALL_CXXFLAGS) ../aspell/rclaspell.cpp > rclaspell.dep
touch rclaspell.dep.stamp
include conftree.dep
include csguess.dep
include debuglog.dep
@ -233,3 +238,4 @@ include history.dep
include docseq.dep
include sortseq.dep
include copyfile.dep
include rclaspell.dep

View File

@ -21,7 +21,7 @@ SRCS="${depth}/utils/conftree.cpp ${depth}/index/csguess.cpp \
${depth}/utils/transcode.cpp ${depth}/common/unacpp.cpp \
${depth}/query/history.cpp \
${depth}/query/docseq.cpp ${depth}/query/sortseq.cpp \
${depth}/utils/copyfile.cpp"
${depth}/utils/copyfile.cpp ${depth}/aspell/rclaspell.cpp"
for c in $SRCS;do

View File

@ -1,5 +1,5 @@
#!/bin/sh
# @(#$Id: makesrcdist.sh,v 1.10 2006-09-23 13:13:49 dockes Exp $ (C) 2005 J.F.Dockes
# @(#$Id: makesrcdist.sh,v 1.11 2006-10-09 16:37:08 dockes Exp $ (C) 2005 J.F.Dockes
# A shell-script to make a recoll source distribution
#set -x
@ -71,7 +71,7 @@ diff $topdir/doc/user/u1.html $topdir/doc/user/usermanual.html
mv -f $topdir/doc/user/u1.html $topdir/doc/user/usermanual.html
# We tag .. as there is the 'packaging/' directory in there
CVSTAG="RECOLL-$versionforcvs"
CVSTAG="RECOLL_$versionforcvs"
[ $dotag = "yes" ] && (cd ..;cvs tag -F $CVSTAG .)
out=recoll-$version.tar.gz

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.79 2006-09-29 08:26:02 dockes Exp $ (C) 2004 J.F.Dockes";
static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.80 2006-10-09 16:37:08 dockes Exp $ (C) 2004 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -890,7 +890,7 @@ static void stringToXapianQueries(const string &iq,
dumb_string(term, term1);
// Possibly perform stem compression/expansion
if (!nostemexp && (opts & Db::QO_STEM)) {
exp = m_ndb->stemExpand(stemlang,term1);
exp = m_ndb->stemExpand(stemlang, term1);
} else {
exp.push_back(term1);
}
@ -1117,6 +1117,60 @@ list<string> Db::completions(const string &root, const string &lang, int max)
return res;
}
/** Term list walking. */
class TermIter {
public:
Xapian::TermIterator it;
Xapian::Database db;
};
TermIter *Db::termWalkOpen()
{
if (!m_ndb || !m_ndb->m_isopen)
return 0;
TermIter *tit = new TermIter;
if (tit) {
tit->db = m_ndb->m_iswritable ? m_ndb->wdb: m_ndb->db;
tit->it = tit->db.allterms_begin();
}
return tit;
}
bool Db::termWalkNext(TermIter *tit, string &term)
{
if (tit && tit->it != tit->db.allterms_end()) {
term = *(tit->it)++;
return true;
}
return false;
}
void Db::termWalkClose(TermIter *tit)
{
delete tit;
}
bool Db::termExists(const string& word)
{
if (!m_ndb || !m_ndb->m_isopen)
return 0;
Xapian::Database db = m_ndb->m_iswritable ? m_ndb->wdb: m_ndb->db;
if (!db.term_exists(word))
return false;
return true;
}
bool Db::stemDiffers(const string& lang, const string& word,
const string& base)
{
Xapian::Stem stemmer(lang);
if (!stemmer.stem_word(word).compare(stemmer.stem_word(base))) {
LOGDEB2(("Rcl::Db::stemDiffers: same for %s and %s\n",
word.c_str(), base.c_str()));
return false;
}
return true;
}
bool Db::getQueryTerms(list<string>& terms)
{
if (!m_ndb)

View File

@ -16,7 +16,7 @@
*/
#ifndef _DB_H_INCLUDED_
#define _DB_H_INCLUDED_
/* @(#$Id: rcldb.h,v 1.36 2006-09-13 13:53:35 dockes Exp $ (C) 2004 J.F.Dockes */
/* @(#$Id: rcldb.h,v 1.37 2006-10-09 16:37:08 dockes Exp $ (C) 2004 J.F.Dockes */
#include <string>
#include <list>
@ -105,6 +105,7 @@ class Doc {
class AdvSearchData;
class Native;
class TermIter;
/**
* Wrapper class for the native database.
@ -170,9 +171,22 @@ class Db {
/** Get a list of existing stemming databases */
std::list<std::string> getStemLangs();
/** Retrieve main database directory */
string getDbDir();
/** Set parameters for synthetic abstract generation */
void setAbstractParams(int idxTrunc, int synthLen, int syntCtxLen);
/** Whole term list walking. */
TermIter *termWalkOpen();
bool termWalkNext(TermIter *, string &term);
void termWalkClose(TermIter *);
/** Test term existence */
bool termExists(const string& term);
/** Test if terms stem to different roots. */
bool stemDiffers(const string& lang, const string& term,
const string& base);
private:
string m_filterTopDir; // Current query filter on subtree top directory

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: stemdb.cpp,v 1.4 2006-09-20 06:21:43 dockes Exp $ (C) 2005 J.F.Dockes";
static char rcsid[] = "@(#$Id: stemdb.cpp,v 1.5 2006-10-09 16:37:08 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
/**
@ -254,7 +254,8 @@ list<string> stemExpand(const string& dbdir, const string& lang,
LOGDEB(("stemExpand: %s -> %s\n", stem.c_str(),
stringlistdisp(explist).c_str()));
} catch (...) {
LOGERR(("stemExpand: error accessing stem db\n"));
LOGERR(("stemExpand: error accessing stem db. dbdir [%s] lang [%s]\n",
dbdir.c_str(), lang.c_str()));
explist.push_back(term);
return explist;
}

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: execmd.cpp,v 1.17 2006-04-03 09:42:47 dockes Exp $ (C) 2004 J.F.Dockes";
static char rcsid[] = "@(#$Id: execmd.cpp,v 1.18 2006-10-09 16:37:08 dockes Exp $ (C) 2004 J.F.Dockes";
#endif
/*
* This program is free software; you can redistribute it and/or modify
@ -53,7 +53,9 @@ void ExecCmd::putenv(const string &ea)
* raised in the callback */
class ExecCmdRsrc {
public:
// Pipe for data going to the command
int pipein[2];
// Pipe for data coming out
int pipeout[2];
pid_t pid;
ExecCmdRsrc() {
@ -124,26 +126,25 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
}
if (e.pid) {
// Father process
if (input) {
close(e.pipein[0]);
e.pipein[0] = -1;
fcntl(e.pipein[1], F_SETFL, O_NONBLOCK);
}
if (output) {
close(e.pipeout[1]);
e.pipeout[1] = -1;
fcntl(e.pipeout[0], F_SETFL, O_NONBLOCK);
}
fd_set readfds, writefds;
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
if (input || output) {
if (input)
fcntl(e.pipein[1], F_SETFL, O_NONBLOCK);
if (output)
fcntl(e.pipeout[0], F_SETFL, O_NONBLOCK);
unsigned int nwritten = 0;
int nfds = MAX(e.pipein[1], e.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;
@ -240,7 +241,22 @@ int ExecCmd::doexec(const string &cmd, const list<string>& args,
e.pipeout[1] = -1;
}
}
// Do we need to redirect stderr ?
if (!m_stderrFile.empty()) {
int fd = open(m_stderrFile.c_str(), O_WRONLY|O_CREAT
#ifdef O_APPEND
|O_APPEND
#endif
, 0600);
if (fd < 0) {
close(2);
} else {
if (fd != 2) {
dup2(fd, 2);
}
lseek(2, 0, 2);
}
}
e.reset();
// Allocate arg vector (2 more for arg0 + final 0)
@ -300,10 +316,10 @@ const char *data = "Une ligne de donnees\n";
class MEAdv : public ExecCmdAdvise {
public:
ExecCmd *cmd;
void newData(int) {
cerr << "New Data!" << endl;
CancelCheck::instance().setCancel();
CancelCheck::instance().checkCancel();
void newData(int cnt) {
cerr << "newData(" << cnt << ")" << endl;
// CancelCheck::instance().setCancel();
// CancelCheck::instance().checkCancel();
// cmd->setCancel();
}
};
@ -325,10 +341,13 @@ int main(int argc, const char **argv)
MEAdv adv;
adv.cmd = &mexec;
mexec.setAdvise(&adv);
mexec.setTimeout(500);
mexec.setStderr("/tmp/trexecStderr");
string input, output;
input = data;
string *ip = 0;
//ip = &input;
ip = &input;
mexec.putenv("TESTVARIABLE1=TESTVALUE1");
mexec.putenv("TESTVARIABLE2=TESTVALUE2");
mexec.putenv("TESTVARIABLE3=TESTVALUE3");

View File

@ -16,10 +16,14 @@
*/
#ifndef _EXECMD_H_INCLUDED_
#define _EXECMD_H_INCLUDED_
/* @(#$Id: execmd.h,v 1.8 2006-01-30 11:15:28 dockes Exp $ (C) 2004 J.F.Dockes */
/* @(#$Id: execmd.h,v 1.9 2006-10-09 16:37:08 dockes Exp $ (C) 2004 J.F.Dockes */
#include <string>
#include <list>
#ifndef NO_NAMESPACES
using std::list;
using std::string;
#endif
/** Callback function object to advise of new data arrival (or just heartbeat) * if cnt is 0 */
class ExecCmdAdvise {
@ -37,46 +41,66 @@ class ExecCmd {
/**
* Execute command.
*
* Both input and output can be specified, and
* asynchronous io is used to prevent blocking. This wont work if
* input and output need to be synchronized (ie: Q/A), but ok for
* filtering.
* Both input and output can be specified, and asynchronous
* io (select-based) is used to prevent blocking. This will not
* work if input and output need to be synchronized (ie: Q/A), but
* works ok for filtering.
* The function is exception-safe. In case an exception occurs in the
* advise callback, fds and pids will be cleaned-up properly.
*
* @param cmd the program to execute. This must be an absolute file name
* or exist in the PATH.
* @param args the argument list (NOT including argv[0]).
* @param input Input to send to the command.
* @param output Output from the command.
* @param input Input to send TO the command.
* @param output Output FROM the command.
* @return the exec ouput status (0 if ok).
*/
int doexec(const std::string &cmd, const std::list<std::string>& args,
const std::string *input = 0,
std::string *output = 0);
int doexec(const string &cmd, const list<string>& args,
const string *input = 0,
string *output = 0);
/**
* Add/replace environment variable before executing command. This should
* be called before doexec of course (possibly multiple times for several
* variables).
* 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)
*/
void putenv(const std::string &envassign);
void putenv(const string &envassign);
/** Set function object to call whenever new data is available */
/**
* Set function object to call whenever new data is available or on
* select timeout.
*/
void setAdvise(ExecCmdAdvise *adv) {m_advise = adv;}
/** Cancel exec. This can be called from another thread or from the
* advise callback, which could also raise an exception to accomplish
* the same thing
/**
* Set select timeout in milliseconds. The default is 1 S.
*/
void setTimeout(int mS) {if (mS > 30) m_timeoutMs = mS;}
/**
* Set destination for stderr data. The default is to let it alone (will
* usually go to the terminal or to wherever the desktop messages go).
* There is currently no option to put stderr data into a program variable
* If the parameter can't be opened for writing, the command's
* stderr will be closed.
*/
void setStderr(const string &stderrFile) {m_stderrFile = stderrFile;}
/**
* Cancel/kill command. This can be called from another thread or
* from the advise callback, which could also raise an exception to
* accomplish the same thing
*/
void setCancel() {m_cancelRequest = true;}
ExecCmd() : m_advise(0), m_cancelRequest(false) {}
ExecCmd() : m_advise(0), m_cancelRequest(false), m_timeoutMs(1000) {}
private:
std::list<std::string> m_env;
list<string> m_env;
ExecCmdAdvise *m_advise;
bool m_cancelRequest;
bool m_cancelRequest;
int m_timeoutMs;
string m_stderrFile;
};