QtPass  1.2.3
Multi-platform GUI for pass, the standard unix password manager.
executor.cpp
Go to the documentation of this file.
1 #include "executor.h"
2 #include <QCoreApplication>
3 #include <QDir>
4 #include <QTextCodec>
5 
6 #ifdef QT_DEBUG
7 #include "debughelper.h"
8 #endif
9 
14 Executor::Executor(QObject *parent) : QObject(parent), running(false) {
15  connect(&m_process,
16  static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(
17  &QProcess::finished),
18  this,
19  static_cast<void (Executor::*)(int, QProcess::ExitStatus)>(
20  &Executor::finished));
21  connect(&m_process, &QProcess::started, this, &Executor::starting);
22 }
23 
27 void Executor::executeNext() {
28  if (!running) {
29  if (!m_execQueue.isEmpty()) {
30  const execQueueItem &i = m_execQueue.head();
31  running = true;
32  if (!i.workingDir.isEmpty())
33  m_process.setWorkingDirectory(i.workingDir);
34  m_process.start(i.app, i.args);
35  if (!i.input.isEmpty()) {
36  m_process.waitForStarted(-1);
37  QByteArray data = i.input.toUtf8();
38  if (m_process.write(data) != data.length()) {
39 #ifdef QT_DEBUG
40  dbg() << "Not all data written to process:" << i.id << " " << i.app;
41 #endif
42  }
43  }
44  m_process.closeWriteChannel();
45  }
46  }
47 }
48 
57 void Executor::execute(int id, const QString &app, const QStringList &args,
58  bool readStdout, bool readStderr) {
59  execute(id, QString(), app, args, QString(), readStdout, readStderr);
60 }
61 
71 void Executor::execute(int id, const QString &workDir, const QString &app,
72  const QStringList &args, bool readStdout,
73  bool readStderr) {
74  execute(id, workDir, app, args, QString(), readStdout, readStderr);
75 }
76 
86 void Executor::execute(int id, const QString &app, const QStringList &args,
87  QString input, bool readStdout, bool readStderr) {
88  execute(id, QString(), app, args, input, readStdout, readStderr);
89 }
90 
102 void Executor::execute(int id, const QString &workDir, const QString &app,
103  const QStringList &args, QString input, bool readStdout,
104  bool readStderr) {
105  // Happens a lot if e.g. git binary is not set.
106  // This will result in bogus "QProcess::FailedToStart" messages,
107  // also hiding legitimate errors from the gpg commands.
108  if (app.isEmpty()) {
109 #ifdef QT_DEBUG
110  dbg() << "Trying to execute nothing...";
111 #endif
112  return;
113  }
114  QString appPath =
115  QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(app);
116  m_execQueue.push_back(
117  {id, appPath, args, input, readStdout, readStderr, workDir});
118  executeNext();
119 }
120 
133 int Executor::executeBlocking(QString app, const QStringList &args,
134  QString input, QString *process_out,
135  QString *process_err) {
136  QProcess internal;
137  internal.start(app, args);
138  if (!input.isEmpty()) {
139  QByteArray data = input.toUtf8();
140  internal.waitForStarted(-1);
141  if (internal.write(data) != data.length()) {
142 #ifdef QT_DEBUG
143  dbg() << "Not all input written:" << app;
144 #endif
145  }
146  internal.closeWriteChannel();
147  }
148  internal.waitForFinished(-1);
149  if (internal.exitStatus() == QProcess::NormalExit) {
150  QTextCodec *codec = QTextCodec::codecForLocale();
151  QString pout = codec->toUnicode(internal.readAllStandardOutput());
152  QString perr = codec->toUnicode(internal.readAllStandardError());
153  if (process_out != Q_NULLPTR)
154  *process_out = pout;
155  if (process_err != Q_NULLPTR)
156  *process_err = perr;
157  return internal.exitCode();
158  } else {
159  // TODO(bezet): emit error() ?
160  return -1; // QProcess error code + qDebug error?
161  }
162 }
163 
172 int Executor::executeBlocking(QString app, const QStringList &args,
173  QString *process_out, QString *process_err) {
174  return executeBlocking(app, args, QString(), process_out, process_err);
175 }
176 
182 void Executor::setEnvironment(const QStringList &env) {
183  m_process.setEnvironment(env);
184 }
185 
193  if (running || m_execQueue.isEmpty())
194  return -1; // TODO(bezet): definitely throw here
195  return m_execQueue.dequeue().id;
196 }
197 
203 void Executor::finished(int exitCode, QProcess::ExitStatus exitStatus) {
204  execQueueItem i = m_execQueue.dequeue();
205  running = false;
206  if (exitStatus == QProcess::NormalExit) {
207  QString output, err;
208  QTextCodec *codec = QTextCodec::codecForLocale();
209  if (i.readStdout)
210  output = codec->toUnicode(m_process.readAllStandardOutput());
211  if (i.readStderr || exitCode != 0) {
212  err = codec->toUnicode(m_process.readAllStandardError());
213  if (exitCode != 0) {
214 #ifdef QT_DEBUG
215  dbg() << exitCode << err;
216 #endif
217  }
218  }
219  emit finished(i.id, exitCode, output, err);
220  }
221  // else: emit crashed with ID, which may give a chance to recover ?
222  executeNext();
223 }
int cancelNext()
Executor::cancelNext cancels execution of first process in queue if it&#39;s not already running...
Definition: executor.cpp:192
#define dbg()
Definition: debughelper.h:7
void setEnvironment(const QStringList &env)
Executor::setEnvironment set environment variables for executor processes.
Definition: executor.cpp:182
Executes external commands for handleing password, git and other data.
Definition: executor.h:12
def data
Definition: avatars.py:87
void execute(int id, const QString &app, const QStringList &args, bool readStdout, bool readStderr=true)
Executor::execute execute an app.
Definition: executor.cpp:57
void starting()
starting signal that is emited when process starts
Executor(QObject *parent=0)
Executor::Executor executes external applications.
Definition: executor.cpp:14
int executeBlocking(QString app, const QStringList &args, QString input=QString(), QString *process_out=Q_NULLPTR, QString *process_err=Q_NULLPTR)
Executor::executeBlocking blocking version of the executor, takes input and presents it as stdin...
Definition: executor.cpp:133