[KLF Backend][KLF Tools][KLF Home]
KLatexFormula Project
src/klfbackend/klfblockprocess.cpp
00001 /***************************************************************************
00002  *   file klfblockprocess.cpp
00003  *   This file is part of the KLatexFormula Project.
00004  *   Copyright (C) 2011 by Philippe Faist
00005  *   philippe.faist@bluewin.ch
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 /* $Id$ */
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; // assumption by default
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" // general unix
00067                 "/usr/local/opt/*/bin:/opt/local/bin:" // homebrew
00068                 "/opt/local/sbin" // macports
00069                 "/Library/TeX/texbin:/usr/texbin"; // mactex binaries
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"; // general unix paths
00074 const static QString exe_suffix = "";
00075 #endif
00076 
00077 
00078 // static
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   // first, try exact name (python.exe, bash.exe)
00084   QString s = klfSearchPath(interp+exe_suffix, script_extra_paths);
00085   if (!s.isEmpty()) {
00086     return s;
00087   }
00088   // otherwise, try name with some suffix (e.g. python2.exe) -- dont directly try with
00089   // wildcard, because we want the exact name if it exists (and not some other program,
00090   // such as 'bashbug', which happened to be found first)
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; // exited
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   // For scripts, use the interpreter explicitly.  This so that the script doesn't have to
00148   // be executable, and also for an old bug on Ubuntu with epstopdf.
00149   //
00150   // We peek into executable to see if it is script. If it is, use the correct interpreter.
00151 
00152   if (!is_binary_file(cmd[0])) {
00153     // check what script type it is and invoke the corresponding interpreter.
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) { // some error occurred somewhere
00199     klfDbg("some error occurred, _runstatus="<<_runstatus) ;
00200     return false;
00201   }
00202 
00203   return true;
00204 }
00205 

Generated by doxygen 1.7.6.1. The KLatexFormula website is hosted on sourceforge.net