--- a/src/utils/execmd.cpp
+++ b/src/utils/execmd.cpp
@@ -37,6 +37,7 @@
#include <vector>
#include <string>
+#include <stdexcept>
#ifdef HAVE_SPAWN_H
#ifndef __USE_GNU
#define __USE_GNU
@@ -52,6 +53,7 @@
#include "netcon.h"
#include "closefrom.h"
+#include "smallut.h"
using namespace std;
@@ -59,7 +61,6 @@
#ifdef BUILDING_RECOLL
#include "debuglog.h"
-#include "smallut.h"
#else
// If compiling outside of recoll, make the file as standalone as reasonable.
@@ -74,42 +75,6 @@
#define LOGDEB3(X)
#define LOGDEB4(X)
-#ifndef MIN
-#define MIN(A,B) ((A) < (B) ? (A) : (B))
-#endif
-
-static void stringToTokens(const string &s, vector<string> &tokens,
- const string &delims = " \t", bool skipinit=true);
-
-static void stringToTokens(const string& str, vector<string>& tokens,
- const string& delims, bool skipinit)
-{
- string::size_type startPos = 0, pos;
-
- // Skip initial delims, return empty if this eats all.
- if (skipinit &&
- (startPos = str.find_first_not_of(delims, 0)) == string::npos) {
- return;
- }
- while (startPos < str.size()) {
- // Find next delimiter or end of string (end of token)
- pos = str.find_first_of(delims, startPos);
-
- // Add token to the vector and adjust start
- if (pos == string::npos) {
- tokens.push_back(str.substr(startPos));
- break;
- } else if (pos == startPos) {
- // Dont' push empty tokens after first
- if (tokens.empty())
- tokens.push_back(string());
- startPos = ++pos;
- } else {
- tokens.push_back(str.substr(startPos, pos - startPos));
- startPos = ++pos;
- }
- }
-}
#endif // BUILDING_RECOLL
class ExecCmd::Internal {
@@ -932,6 +897,30 @@
return n;
}
+class GetlineWatchdog : public ExecCmdAdvise {
+public:
+ GetlineWatchdog(int secs) : m_secs(secs), tstart(time(0)) {}
+ void newData(int cnt) {
+ if (time(0) - tstart >= m_secs) {
+ throw std::runtime_error("getline timeout");
+ }
+ }
+ int m_secs;
+ time_t tstart;
+};
+
+int ExecCmd::getline(string& data, int timeosecs)
+{
+ GetlineWatchdog gwd(timeosecs);
+ setAdvise(&gwd);
+ try {
+ return getline(data);
+ } catch (...) {
+ return -1;
+ }
+}
+
+
// Wait for command status and clean up all resources.
// We would like to avoid blocking here too, but there is no simple
// way to do this. The 2 possible approaches would be to:
@@ -1250,6 +1239,7 @@
" <filter> should be the path to an execm filter\n"
" <mimetype> the type of the file parameters\n"
"trexecmd -w cmd : do the 'which' thing\n"
+"trexecmd -l cmd test getline\n"
;
static void Usage(void)
@@ -1266,6 +1256,7 @@
#define OPT_r 0x20
#define OPT_m 0x40
#define OPT_o 0x80
+#define OPT_l 0x100
// Data sink for data coming out of the command. We also use it to set
// a cancellation after a moment.
@@ -1347,6 +1338,7 @@
case 'm': op_flags |= OPT_m; break;
#endif
case 'i': op_flags |= OPT_i; break;
+ case 'l': op_flags |= OPT_l; break;
case 'o': op_flags |= OPT_o; break;
default: Usage(); break;
}
@@ -1362,8 +1354,10 @@
l.push_back(*argv++); argc--;
}
+#ifdef BUILDING_RECOLL
DebugLog::getdbl()->setloglevel(DEBDEB1);
DebugLog::setfilename("stderr");
+#endif
signal(SIGPIPE, SIG_IGN);
if (op_flags & OPT_r) {
@@ -1396,6 +1390,20 @@
l.erase(l.begin());
return exercise_mhexecm(arg1, mimetype, l) ? 0 : 1;
#endif
+ } else if (op_flags & OPT_l) {
+ ExecCmd mexec;
+
+ if (mexec.startExec(arg1, l, false, true) < 0) {
+ cerr << "Startexec failed\n";
+ exit(1);
+ }
+ string output;
+ int ret = mexec.getline(output, 2);
+ cerr << "Got ret " << ret << " output " << output << endl;
+ cerr << "Waiting\n";
+ int status = mexec.wait();
+ cerr << "Got status " << status << endl;
+ exit (status);
} else {
// Default: execute command line arguments
ExecCmd mexec;