QtPass  1.2.0
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 "debughelper.h"
3 #include <QCoreApplication>
4 #include <QDir>
5 #include <QTextCodec>
6 
11 Executor::Executor(QObject *parent) : QObject(parent), running(false) {
12  connect(&m_process,
13  static_cast<void (QProcess::*)(int, QProcess::ExitStatus)>(
14  &QProcess::finished),
15  this, static_cast<void (Executor::*)(int, QProcess::ExitStatus)>(
16  &Executor::finished));
17  connect(&m_process, &QProcess::started, this, &Executor::starting);
18 }
19 
23 void Executor::executeNext() {
24  if (!running) {
25  if (!m_execQueue.isEmpty()) {
26  const execQueueItem &i = m_execQueue.head();
27  running = true;
28  if (!i.workingDir.isEmpty())
29  m_process.setWorkingDirectory(i.workingDir);
30  m_process.start(i.app, i.args);
31  if (!i.input.isEmpty()) {
32  m_process.waitForStarted(-1);
33  QByteArray data = i.input.toUtf8();
34  if (m_process.write(data) != data.length())
35  dbg() << "Not all data written to process:" << i.id << " " << i.app;
36  }
37  m_process.closeWriteChannel();
38  }
39  }
40 }
41 
50 void Executor::execute(int id, const QString &app, const QStringList &args,
51  bool readStdout, bool readStderr) {
52  execute(id, QString(), app, args, QString(), readStdout, readStderr);
53 }
54 
64 void Executor::execute(int id, const QString &workDir, const QString &app,
65  const QStringList &args, bool readStdout,
66  bool readStderr) {
67  execute(id, workDir, app, args, QString(), readStdout, readStderr);
68 }
69 
79 void Executor::execute(int id, const QString &app, const QStringList &args,
80  QString input, bool readStdout, bool readStderr) {
81  execute(id, QString(), app, args, input, readStdout, readStderr);
82 }
83 
95 void Executor::execute(int id, const QString &workDir, const QString &app,
96  const QStringList &args, QString input, bool readStdout,
97  bool readStderr) {
98  // Happens a lot if e.g. git binary is not set.
99  // This will result in bogus "QProcess::FailedToStart" messages,
100  // also hiding legitimate errors from the gpg commands.
101  if (app.isEmpty()) {
102  dbg() << "Trying to execute nothing...";
103  return;
104  }
105  QString appPath =
106  QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(app);
107  m_execQueue.push_back(
108  {id, appPath, args, input, readStdout, readStderr, workDir});
109  executeNext();
110 }
111 
124 int Executor::executeBlocking(QString app, const QStringList &args,
125  QString input, QString *process_out,
126  QString *process_err) {
127  QProcess internal;
128  internal.start(app, args);
129  if (!input.isEmpty()) {
130  QByteArray data = input.toUtf8();
131  internal.waitForStarted(-1);
132  if (internal.write(data) != data.length()) {
133  dbg() << "Not all input written:" << app;
134  }
135  internal.closeWriteChannel();
136  }
137  internal.waitForFinished(-1);
138  if (internal.exitStatus() == QProcess::NormalExit) {
139  QTextCodec *codec = QTextCodec::codecForLocale();
140  QString pout = codec->toUnicode(internal.readAllStandardOutput());
141  QString perr = codec->toUnicode(internal.readAllStandardError());
142  if (process_out != Q_NULLPTR)
143  *process_out = pout;
144  if (process_err != Q_NULLPTR)
145  *process_err = perr;
146  return internal.exitCode();
147  } else {
148  // TODO(bezet): emit error() ?
149  return -1; // QProcess error code + qDebug error?
150  }
151 }
152 
161 int Executor::executeBlocking(QString app, const QStringList &args,
162  QString *process_out, QString *process_err) {
163  return executeBlocking(app, args, QString(), process_out, process_err);
164 }
165 
171 void Executor::setEnvironment(const QStringList &env) {
172  m_process.setEnvironment(env);
173 }
174 
182  if (running || m_execQueue.isEmpty())
183  return -1; // TODO(bezet): definitely throw here
184  return m_execQueue.dequeue().id;
185 }
186 
192 void Executor::finished(int exitCode, QProcess::ExitStatus exitStatus) {
193  execQueueItem i = m_execQueue.dequeue();
194  running = false;
195  if (exitStatus == QProcess::NormalExit) {
196  QString output, err;
197  QTextCodec *codec = QTextCodec::codecForLocale();
198  if (i.readStdout)
199  output = codec->toUnicode(m_process.readAllStandardOutput());
200  if (i.readStderr or exitCode != 0) {
201  err = codec->toUnicode(m_process.readAllStandardError());
202  if (exitCode != 0)
203  dbg() << exitCode << err;
204  }
205  emit finished(i.id, exitCode, output, err);
206  }
207  // else: emit crashed with ID, which may give a chance to recover ?
208  executeNext();
209 }
int cancelNext()
Executor::cancelNext cancels execution of first process in queue if it&#39;s not already running...
Definition: executor.cpp:181
#define dbg()
Definition: debughelper.h:7
void setEnvironment(const QStringList &env)
Executor::setEnvironment set environment variables for executor processes.
Definition: executor.cpp:171
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:50
void starting()
starting signal that is emited when process starts
Executor(QObject *parent=0)
Executor::Executor executes external applications.
Definition: executor.cpp:11
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:124