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