Official websites use .gov
A .gov website belongs to an official government organization in the United States.

Secure .gov websites use HTTPS
A lock ( ) or https:// means you’ve safely connected to the .gov website. Share sensitive information only on official, secure websites.

Isis 3 Programmer Reference
ProgramLauncher.cpp
1
5
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "ProgramLauncher.h"
8
9#include <iostream>
10#include <sstream>
11#include <sys/wait.h>
12
13#include <QLocalServer>
14#include <QLocalSocket>
15#include <QProcess>
16
17#include "Application.h"
18#include "FileName.h"
19#include "IException.h"
20#include "IString.h"
21#include "Preference.h"
22
23using namespace std;
24namespace Isis {
37 void ProgramLauncher::RunIsisProgram(QString programName,
38 QString parameters) {
39 FileName program(programName);
40 FileName isisExecutableFileName("$ISISROOT/bin/" + program.name());
41 bool isIsisProgram = false;
42
43 if(isisExecutableFileName.fileExists()) {
44 isIsisProgram = true;
45 program = isisExecutableFileName;
46 }
47
48 PvlGroup &dataDir = Preference::Preferences().findGroup("DataDirectory");
49 QString tempDir = dataDir["Temporary"];
50
51 QString command = program.expanded() + " " + parameters +
52 " -pid=" + toString(getpid());
53 QStringList split = QProcess::splitCommand(command);
54 QString app = split.takeFirst();
55 QStringList paramList = split;
56
57 if(!isIsisProgram) {
58 QString msg = "Program [" + programName + "] does not appear to be a "
59 "valid Isis program";
60 throw IException(IException::Unknown, msg, _FILEINFO_);
61 }
62
63 QString serverName = "isis_" + Application::UserName() +
64 "_" + toString(getpid());
65
66 QLocalServer server;
67 server.listen(serverName);
68
69 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
70 env.insert("TEMPORARY", tempDir);
71
72 QProcess childProcess;
73 childProcess.setProcessEnvironment(env);
74 childProcess.setProcessChannelMode(QProcess::ForwardedChannels);
75 childProcess.start(app, paramList);
76 childProcess.waitForStarted();
77
78 bool connected = false;
79
80 while(!connected && childProcess.state() != QProcess::NotRunning) {
81 // Give time for the process to connect to us or for it to finish
82 // wait 30s for the new connection....
83 connected = server.waitForNewConnection(30000);
84 childProcess.waitForFinished(100);
85 }
86
87 if(!connected) {
88 QString msg = "Isis child process failed to communicate with parent";
89 throw IException(IException::Programmer, msg, _FILEINFO_);
90 }
91
92 QLocalSocket *childSocket = server.nextPendingConnection();
93 IException errors;
94
95 // Don't return until we're done running this program
96 while(childSocket->state() != QLocalSocket::UnconnectedState) {
97 bool insideCode = true;
98 bool messageDone = false;
99
100 QString code;
101 QString message;
102 QByteArray lineData;
103
104 if(childSocket->waitForReadyRead(1000)) {
105 lineData = childSocket->read(childSocket->bytesAvailable());
106
107 for(int i = 0; i < lineData.size(); i++) {
108 if(insideCode) {
109 if(lineData[i] != (char)27) {
110 code += lineData[i];
111 }
112 else {
113 insideCode = false;
114 }
115 }
116 else {
117 if(lineData[i] != (char)27) {
118 message += lineData[i];
119 }
120 else {
121 messageDone = true;
122 insideCode = true;
123 i ++; // skip \n that should always exist here
124 }
125 }
126
127 if(messageDone) {
128 errors.append(
129 ProcessIsisMessageFromChild(code, message));
130 code = "";
131 message = "";
132 messageDone = false;
133 }
134 }
135 }
136 }
137
138 childProcess.waitForFinished();
139
140 if(childProcess.exitCode() != 0) {
141 QString msg = "Running Isis program [" + programName + "] failed with "
142 "return status [" + toString(childProcess.exitCode()) + "]";
143 throw IException(errors, IException::Unknown, msg, _FILEINFO_);
144 }
145 }
146
147
158 IException
160 IException errors;
161
162 if(code == "PROGRESSTEXT" && iApp) {
163 iApp->UpdateProgress(msg, true);
164 }
165 else if(code == "PROGRESS" && iApp) {
166 iApp->UpdateProgress(toInt(msg), true);
167 }
168 else if(code == "LOG" && iApp) {
169 stringstream msgStream;
170 msgStream << msg;
171 Pvl logPvl;
172 msgStream >> logPvl;
173
174 if(logPvl.groups() == 1 &&
175 logPvl.keywords() == 0 &&
176 logPvl.objects() == 0) {
177 iApp->Log(logPvl.group(0));
178 }
179 }
180 else if(code == "GUILOG" && iApp) {
181 iApp->GuiLog(msg);
182 }
183 else if(code == "ERROR") {
184 stringstream msgStream;
185 msgStream << msg;
186 Pvl errorPvl;
187 msgStream >> errorPvl;
188
189 for(int i = 0; i < errorPvl.groups(); i++) {
190 PvlGroup &g = errorPvl.group(i);
191 QString emsg = g["Message"];
192 int ecode = g["Code"];
193 QString efile = g["File"];
194 int eline = g["Line"];
195
196 errors.append(
197 IException((IException::ErrorType)ecode, emsg, efile.toLatin1().data(), eline));
198 }
199 }
200
201 return errors;
202 }
203
204
216 void ProgramLauncher::RunSystemCommand(QString fullCommand) {
217 int status = system(fullCommand.toLatin1().data());
218
219 if(status != 0) {
220 QString msg = "Executing command [" + fullCommand +
221 "] failed with return status [" + toString(status) + "]";
222 throw IException(IException::Programmer, msg, _FILEINFO_);
223 }
224 }
225} //end namespace isis
static QString UserName()
Returns the user name.
static void RunIsisProgram(QString isisProgramName, QString arguments)
Executes the Isis program with the given arguments.
static void RunSystemCommand(QString commandLine)
This runs arbitrary system commands.
static IException ProcessIsisMessageFromChild(QString code, QString msg)
This interprets a message sent along the pipe from a child process to us (the parent).
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(const LinearAlgebra::Vector &vector, int precision)
A global function to format LinearAlgebra::Vector as a QString with the given precision.
Namespace for the standard library.