00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <QProcess>
00025 #include <QCoreApplication>
00026 #include <QEventLoop>
00027 #include <QFile>
00028 #include <QThread>
00029
00030 #include <klfutil.h>
00031 #include <klfsysinfo.h>
00032 #include "klfblockprocess.h"
00033
00034 static bool is_binary_file(QString fn)
00035 {
00036 klfDbg("is_binary_file("<<fn<<")") ;
00037 if (!QFile::exists(fn)) {
00038 fn = klfSearchPath(fn);
00039 klfDbg("is_binary_file: file doesn't exist directly, path search gave "<<fn) ;
00040 }
00041 QFile fpeek(fn);
00042 if (!fpeek.open(QIODevice::ReadOnly)) {
00043 klfDbg("fn="<<fn<<", Can't peek into file "<<fn<<"!") ;
00044 return true;
00045 }
00046 QByteArray line;
00047 int n = 0, j;
00048 while (n++ < 5 && (line = fpeek.readLine(1024)).size()) {
00049 for (j = 0; j < line.size(); ++j) {
00050 if ((int)line[j] >= 127 || (int)line[j] <= 0) {
00051 klfDbg("fn="<<fn<<" found binary char '"<<(char)line[j]<<"'=="<<(int)line[j]
00052 <<" on line "<<n<<", column "<< j) ;
00053 return true;
00054 }
00055 }
00056 }
00057 klfDbg("fn="<<fn<<", file seems to be ascii based on the first few lines") ;
00058 return false;
00059 }
00060
00061 #if defined(Q_OS_WIN)
00062 const static QString script_extra_paths = QString("C:\\Python27;C:\\Python*");
00063 const static QString exe_suffix = ".exe";
00064 #elif defined(Q_OS_MAC)
00065 const static QString script_extra_paths =
00066 "/usr/bin:/bin:/usr/local/bin:/usr/sbin:/sbin:/usr/local/sbin"
00067 "/usr/local/opt/*/bin:/opt/local/bin:"
00068 "/opt/local/sbin"
00069 "/Library/TeX/texbin:/usr/texbin";
00070 const static QString exe_suffix = "";
00071 #else
00072 const static QString script_extra_paths =
00073 "/usr/bin:/bin:/usr/local/bin:/usr/sbin:/sbin:/usr/local/sbin";
00074 const static QString exe_suffix = "";
00075 #endif
00076
00077
00078
00079 QString KLFBlockProcess::detectInterpreterPath(const QString& interp, const QStringList & addpaths)
00080 {
00081 QString search_paths = script_extra_paths;
00082 search_paths += addpaths.join(KLF_PATH_SEP);
00083
00084 QString s = klfSearchPath(interp+exe_suffix, script_extra_paths);
00085 if (!s.isEmpty()) {
00086 return s;
00087 }
00088
00089
00090
00091 return klfSearchPath(interp+"*"+exe_suffix, script_extra_paths);
00092 }
00093
00094
00095
00096
00097 KLFBlockProcess::KLFBlockProcess(QObject *p)
00098 : QProcess(p)
00099 {
00100 mProcessAppEvents = true;
00101 connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(ourProcExited()));
00102 }
00103
00104
00105 KLFBlockProcess::~KLFBlockProcess()
00106 {
00107 }
00108
00109 void KLFBlockProcess::ourProcGotOurStdinData()
00110 {
00111 }
00112
00113 void KLFBlockProcess::ourProcExited()
00114 {
00115 _runstatus = 1;
00116 }
00117
00118 QString KLFBlockProcess::getInterpreterPath(const QString & ext)
00119 {
00120 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00121 klfDbg("ext = " << ext) ;
00122 if (ext == "py") {
00123 return detectInterpreterPath("python");
00124 } else if (ext == "sh") {
00125 return detectInterpreterPath("bash");
00126 } else if (ext == "rb") {
00127 return detectInterpreterPath("ruby");
00128 }
00129 return QString();
00130 }
00131
00132 bool KLFBlockProcess::startProcess(QStringList cmd, QStringList env)
00133 {
00134 return startProcess(cmd, QByteArray(), env);
00135 }
00136
00137 bool KLFBlockProcess::startProcess(QStringList cmd, QByteArray stdindata, QStringList env)
00138 {
00139 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00140
00141 klfDbg("Running: "<<cmd<<", stdindata/size="<<stdindata.size());
00142
00143 _runstatus = 0;
00144
00145 KLF_ASSERT_CONDITION(cmd.size(), "Empty command list given.", return false;) ;
00146
00147
00148
00149
00150
00151
00152 if (!is_binary_file(cmd[0])) {
00153
00154 QString ext = cmd[0].split('.').last();
00155 QByteArray exec_proc = getInterpreterPath(ext).toLocal8Bit();
00156 if (exec_proc.size()) {
00157 cmd.prepend(exec_proc);
00158 }
00159 }
00160
00161 QString program = cmd[0];
00162
00163 klfDbg("Running cmd="<<cmd);
00164 klfDbg("env="<<env<<", curenv="<<environment());
00165
00166 if (env.size() > 0) {
00167 setEnvironment(env);
00168 }
00169
00170 QStringList args = cmd;
00171 args.erase(args.begin());
00172 klfDbg("Starting "<<program<<", "<<args) ;
00173 start(program, args);
00174 if ( ! waitForStarted() ) {
00175 klfDbg("Can't wait for started! Error="<<error()) ;
00176 return false;
00177 }
00178
00179 write(stdindata.constData(), stdindata.size());
00180 closeWriteChannel();
00181
00182 klfDbg("wrote input data (size="<<stdindata.size()<<")") ;
00183
00184 if (mProcessAppEvents) {
00185 klfDbg("letting current thread (="<<QThread::currentThread()<<") process events ...") ;
00186 while (_runstatus == 0) {
00187 QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1000);
00188 klfDbg("events processed, maybe more?") ;
00189 }
00190 } else {
00191 if (!waitForFinished()) {
00192 klfDbg("Can't wait for finished!");
00193 return false;
00194 }
00195 }
00196 klfDbg("Process should have finished now.");
00197
00198 if (_runstatus < 0) {
00199 klfDbg("some error occurred, _runstatus="<<_runstatus) ;
00200 return false;
00201 }
00202
00203 return true;
00204 }
00205