diff --git a/src/internfile/mh_exec.cpp b/src/internfile/mh_exec.cpp index d408ac81..43ebeb4f 100644 --- a/src/internfile/mh_exec.cpp +++ b/src/internfile/mh_exec.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: mh_exec.cpp,v 1.12 2008-10-04 14:26:59 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: mh_exec.cpp,v 1.13 2008-10-06 06:22:46 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -23,6 +23,10 @@ static char rcsid[] = "@(#$Id: mh_exec.cpp,v 1.12 2008-10-04 14:26:59 dockes Exp #include "mh_html.h" #include "debuglog.h" #include "cancelcheck.h" +#include "smallut.h" + +#include +#include #ifndef NO_NAMESPACES using namespace std; @@ -42,6 +46,10 @@ bool MimeHandlerExec::next_document() if (m_havedoc == false) return false; m_havedoc = false; + if (missingHelper) { + LOGDEB(("MimeHandlerExec::next_document(): helper known missing\n")); + return false; + } if (params.empty()) { // Hu ho LOGERR(("MimeHandlerExec::mkDoc: empty params\n")); @@ -59,7 +67,7 @@ bool MimeHandlerExec::next_document() if (!m_ipath.empty()) myparams.push_back(m_ipath); - // Execute command and store the result text + // Execute command, store the output string& output = m_metaData["content"]; output.erase(); ExecCmd mexec; @@ -68,15 +76,37 @@ bool MimeHandlerExec::next_document() mexec.putenv(m_forPreview ? "RECOLL_FILTER_FORPREVIEW=yes" : "RECOLL_FILTER_FORPREVIEW=no"); int status = mexec.doexec(cmd, myparams, 0, &output); + if (status) { - LOGERR(("MimeHandlerExec: command status 0x%x: %s\n", + LOGERR(("MimeHandlerExec: command status 0x%x for %s\n", status, cmd.c_str())); - // If the output string begins with RECFILTERROR, then it's - // interpretable error information - if (output.find("RECFILTERROR") == 0) + if (WIFEXITED(status) && WEXITSTATUS(status) == 127) { + // That's how execmd signals a failed exec (most probably + // a missing command). Let'hope no filter uses the same value as + // an exit status... Disable myself permanently and signal the + // missing cmd. + missingHelper = true; + m_reason = string("RECFILTERROR HELPERNOTFOUND ") + cmd; + } else if (output.find("RECFILTERROR") == 0) { + // If the output string begins with RECFILTERROR, then it's + // interpretable error information out from a recoll script m_reason = output; + list lerr; + stringToStrings(output, lerr); + if (lerr.size() > 2) { + list::iterator it = lerr.begin(); + it++; + if (*it == "HELPERNOTFOUND") { + // No use trying again and again to execute this filter, + // it won't work. + missingHelper = true; + } + } + } return false; } + + // Success. Store some external metadata m_metaData["origcharset"] = m_defcharset; // Default charset: all recoll filters output utf-8, but this // could still be overridden by the content-type meta tag. diff --git a/src/internfile/mh_exec.h b/src/internfile/mh_exec.h index 6263f563..d6d2f1b4 100644 --- a/src/internfile/mh_exec.h +++ b/src/internfile/mh_exec.h @@ -16,7 +16,7 @@ */ #ifndef _MH_EXEC_H_INCLUDED_ #define _MH_EXEC_H_INCLUDED_ -/* @(#$Id: mh_exec.h,v 1.7 2008-10-04 14:26:59 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: mh_exec.h,v 1.8 2008-10-06 06:22:46 dockes Exp $ (C) 2004 J.F.Dockes */ #include #include @@ -33,8 +33,10 @@ using std::string; */ class MimeHandlerExec : public RecollFilter { public: - // params, cfgMtype and chgCharset do not get reset by - // clear(). They define what I am + // Members not reset by clear(). params, cfgMtype and chgCharset + // actually define what I am. missingHelper is a permanent error + // (no use to try and execute over and over something that's not + // here). list params; // The defaults for external filters is to output html except if defined // otherwise in the config. @@ -42,8 +44,10 @@ class MimeHandlerExec : public RecollFilter { // For ext programs which don't output html, the output charset // has to be known: ie they have a --charset utf-8 like option. string cfgCharset; + bool missingHelper; - MimeHandlerExec(const string& mt) : RecollFilter(mt) {} + MimeHandlerExec(const string& mt) : RecollFilter(mt), missingHelper(false) + {} virtual ~MimeHandlerExec() {} virtual bool set_document_file(const string &file_path) { m_fn = file_path; diff --git a/src/internfile/mimehandler.cpp b/src/internfile/mimehandler.cpp index 5fa22ad9..26068ef7 100644 --- a/src/internfile/mimehandler.cpp +++ b/src/internfile/mimehandler.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: mimehandler.cpp,v 1.23 2008-10-04 14:26:59 dockes Exp $ (C) 2004 J.F.Dockes"; +static char rcsid[] = "@(#$Id: mimehandler.cpp,v 1.24 2008-10-06 06:22:46 dockes Exp $ (C) 2004 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -35,8 +35,9 @@ using namespace std; #include "mh_text.h" #include "mh_unknown.h" -// Pool of already known and created handlers -static map o_handlers; +// Pool of already known and created handlers. There can be several instance +// for a given mime type (think email attachment in email message) +static multimap o_handlers; /** Create internal handler object appropriate for given mime type */ static Dijon::Filter *mhFactory(const string &mime) @@ -127,9 +128,10 @@ MimeHandlerExec *mhExecFactory(RclConfig *cfg, const string& mtype, string& hs) /* Return mime handler to pool */ void returnMimeHandler(Dijon::Filter *handler) { + typedef multimap::value_type value_type; if (handler) { handler->clear(); - o_handlers[handler->get_mime_type()] = handler; + o_handlers.insert(value_type(handler->get_mime_type(), handler)); } } diff --git a/src/utils/execmd.cpp b/src/utils/execmd.cpp index 91336763..dd889053 100644 --- a/src/utils/execmd.cpp +++ b/src/utils/execmd.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: execmd.cpp,v 1.26 2007-11-08 09:34:40 dockes Exp $ (C) 2004 J.F.Dockes"; +static char rcsid[] = "@(#$Id: execmd.cpp,v 1.27 2008-10-06 06:22:47 dockes Exp $ (C) 2004 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -374,7 +374,7 @@ int ExecCmd::doexec(const string &cmd, const list& args, // Hu ho LOGERR(("ExecCmd::doexec: execvp(%s) failed. errno %d\n", cmd.c_str(), errno)); - _exit(128); + _exit(127); } /* This cant be reached: to make cc happy */ return -1;