summaryrefslogtreecommitdiff
path: root/libopie/oprocess.cpp
Unidiff
Diffstat (limited to 'libopie/oprocess.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/oprocess.cpp1
1 files changed, 0 insertions, 1 deletions
diff --git a/libopie/oprocess.cpp b/libopie/oprocess.cpp
index 5db2b6c..c19881a 100644
--- a/libopie/oprocess.cpp
+++ b/libopie/oprocess.cpp
@@ -1,312 +1,311 @@
1/* 1/*
2 2
3 $Id$ 3 $Id$
4 4
5 This file is part of the KDE libraries 5 This file is part of the KDE libraries
6 Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at) 6 Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
7 7
8 This library is free software; you can redistribute it and/or 8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public 9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either 10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version. 11 version 2 of the License, or (at your option) any later version.
12 12
13 This library is distributed in the hope that it will be useful, 13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details. 16 Library General Public License for more details.
17 17
18 You should have received a copy of the GNU Library General Public License 18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to 19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. 21 Boston, MA 02111-1307, USA.
22 22
23*/ 23*/
24 24
25 25
26// 26//
27// KPROCESS -- A class for handling child processes in KDE without 27// KPROCESS -- A class for handling child processes in KDE without
28// having to take care of Un*x specific implementation details 28// having to take care of Un*x specific implementation details
29// 29//
30// version 0.3.1, Jan 8th 1998 30// version 0.3.1, Jan 8th 1998
31// 31//
32// (C) Christian Czezatke 32// (C) Christian Czezatke
33// e9025461@student.tuwien.ac.at 33// e9025461@student.tuwien.ac.at
34// 34//
35// Changes: 35// Changes:
36// 36//
37// March 2nd, 1998: Changed parameter list for KShellProcess: 37// March 2nd, 1998: Changed parameter list for KShellProcess:
38// Arguments are now placed in a single string so that 38// Arguments are now placed in a single string so that
39// <shell> -c <commandstring> is passed to the shell 39// <shell> -c <commandstring> is passed to the shell
40// to make the use of "operator<<" consistent with KProcess 40// to make the use of "operator<<" consistent with KProcess
41// 41//
42// 42//
43// Ported by Holger Freyther 43// Ported by Holger Freyther
44// <zekce> Harlekin: oprocess and say it was ported to Qt by the Opie developers an Qt 2 44// <zekce> Harlekin: oprocess and say it was ported to Qt by the Opie developers an Qt 2
45 45
46 46
47 47
48#include "oprocess.h" 48#include "oprocess.h"
49#define _MAY_INCLUDE_KPROCESSCONTROLLER_ 49#define _MAY_INCLUDE_KPROCESSCONTROLLER_
50#include "oprocctrl.h" 50#include "oprocctrl.h"
51 51
52//#include <config.h> 52//#include <config.h>
53 53
54#include <qfile.h> 54#include <qfile.h>
55#include <qsocketnotifier.h> 55#include <qsocketnotifier.h>
56#include <qregexp.h>
57 56
58#include <sys/time.h> 57#include <sys/time.h>
59#include <sys/types.h> 58#include <sys/types.h>
60#include <sys/stat.h> 59#include <sys/stat.h>
61#include <sys/socket.h> 60#include <sys/socket.h>
62 61
63#include <errno.h> 62#include <errno.h>
64#include <fcntl.h> 63#include <fcntl.h>
65#include <stdlib.h> 64#include <stdlib.h>
66#include <signal.h> 65#include <signal.h>
67#include <stdio.h> 66#include <stdio.h>
68#include <string.h> 67#include <string.h>
69#include <unistd.h> 68#include <unistd.h>
70#ifdef HAVE_SYS_SELECT_H 69#ifdef HAVE_SYS_SELECT_H
71#include <sys/select.h> 70#include <sys/select.h>
72#endif 71#endif
73#ifdef HAVE_INITGROUPS 72#ifdef HAVE_INITGROUPS
74#include <grp.h> 73#include <grp.h>
75#endif 74#endif
76#include <pwd.h> 75#include <pwd.h>
77 76
78#include <qapplication.h> 77#include <qapplication.h>
79#include <qmap.h> 78#include <qmap.h>
80//#include <kdebug.h> 79//#include <kdebug.h>
81 80
82///////////////////////////// 81/////////////////////////////
83// public member functions // 82// public member functions //
84///////////////////////////// 83/////////////////////////////
85 84
86class OProcessPrivate { 85class OProcessPrivate {
87public: 86public:
88 OProcessPrivate() : useShell(false) { } 87 OProcessPrivate() : useShell(false) { }
89 88
90 bool useShell; 89 bool useShell;
91 QMap<QString,QString> env; 90 QMap<QString,QString> env;
92 QString wd; 91 QString wd;
93 QCString shell; 92 QCString shell;
94}; 93};
95 94
96 95
97OProcess::OProcess(QObject *parent, const char *name) 96OProcess::OProcess(QObject *parent, const char *name)
98 : QObject(parent, name) 97 : QObject(parent, name)
99{ 98{
100 init ( ); 99 init ( );
101} 100}
102 101
103OProcess::OProcess(const QString &arg0, QObject *parent, const char *name) 102OProcess::OProcess(const QString &arg0, QObject *parent, const char *name)
104 : QObject(parent, name) 103 : QObject(parent, name)
105{ 104{
106 init ( ); 105 init ( );
107 *this << arg0; 106 *this << arg0;
108} 107}
109 108
110OProcess::OProcess(const QStringList &args, QObject *parent, const char *name) 109OProcess::OProcess(const QStringList &args, QObject *parent, const char *name)
111 : QObject(parent, name) 110 : QObject(parent, name)
112{ 111{
113 init ( ); 112 init ( );
114 *this << args; 113 *this << args;
115} 114}
116 115
117void OProcess::init ( ) 116void OProcess::init ( )
118{ 117{
119 run_mode = NotifyOnExit; 118 run_mode = NotifyOnExit;
120 runs = false; 119 runs = false;
121 pid_ = 0; 120 pid_ = 0;
122 status = 0; 121 status = 0;
123 keepPrivs = false; 122 keepPrivs = false;
124 innot = 0; 123 innot = 0;
125 outnot = 0; 124 outnot = 0;
126 errnot = 0; 125 errnot = 0;
127 communication = NoCommunication; 126 communication = NoCommunication;
128 input_data = 0; 127 input_data = 0;
129 input_sent = 0; 128 input_sent = 0;
130 input_total = 0; 129 input_total = 0;
131 d = 0; 130 d = 0;
132 131
133 if (0 == OProcessController::theOProcessController) { 132 if (0 == OProcessController::theOProcessController) {
134 (void) new OProcessController(); 133 (void) new OProcessController();
135 CHECK_PTR(OProcessController::theOProcessController); 134 CHECK_PTR(OProcessController::theOProcessController);
136 } 135 }
137 136
138 OProcessController::theOProcessController->addOProcess(this); 137 OProcessController::theOProcessController->addOProcess(this);
139 out[0] = out[1] = -1; 138 out[0] = out[1] = -1;
140 in[0] = in[1] = -1; 139 in[0] = in[1] = -1;
141 err[0] = err[1] = -1; 140 err[0] = err[1] = -1;
142} 141}
143 142
144void 143void
145OProcess::setEnvironment(const QString &name, const QString &value) 144OProcess::setEnvironment(const QString &name, const QString &value)
146{ 145{
147 if (!d) 146 if (!d)
148 d = new OProcessPrivate; 147 d = new OProcessPrivate;
149 d->env.insert(name, value); 148 d->env.insert(name, value);
150} 149}
151 150
152void 151void
153OProcess::setWorkingDirectory(const QString &dir) 152OProcess::setWorkingDirectory(const QString &dir)
154{ 153{
155 if (!d) 154 if (!d)
156 d = new OProcessPrivate; 155 d = new OProcessPrivate;
157 d->wd = dir; 156 d->wd = dir;
158} 157}
159 158
160void 159void
161OProcess::setupEnvironment() 160OProcess::setupEnvironment()
162{ 161{
163 if (d) 162 if (d)
164 { 163 {
165 QMap<QString,QString>::Iterator it; 164 QMap<QString,QString>::Iterator it;
166 for(it = d->env.begin(); it != d->env.end(); ++it) 165 for(it = d->env.begin(); it != d->env.end(); ++it)
167 setenv(QFile::encodeName(it.key()).data(), 166 setenv(QFile::encodeName(it.key()).data(),
168 QFile::encodeName(it.data()).data(), 1); 167 QFile::encodeName(it.data()).data(), 1);
169 if (!d->wd.isEmpty()) 168 if (!d->wd.isEmpty())
170 chdir(QFile::encodeName(d->wd).data()); 169 chdir(QFile::encodeName(d->wd).data());
171 } 170 }
172} 171}
173 172
174void 173void
175OProcess::setRunPrivileged(bool keepPrivileges) 174OProcess::setRunPrivileged(bool keepPrivileges)
176{ 175{
177 keepPrivs = keepPrivileges; 176 keepPrivs = keepPrivileges;
178} 177}
179 178
180bool 179bool
181OProcess::runPrivileged() const 180OProcess::runPrivileged() const
182{ 181{
183 return keepPrivs; 182 return keepPrivs;
184} 183}
185 184
186 185
187OProcess::~OProcess() 186OProcess::~OProcess()
188{ 187{
189 // destroying the OProcess instance sends a SIGKILL to the 188 // destroying the OProcess instance sends a SIGKILL to the
190 // child process (if it is running) after removing it from the 189 // child process (if it is running) after removing it from the
191 // list of valid processes (if the process is not started as 190 // list of valid processes (if the process is not started as
192 // "DontCare") 191 // "DontCare")
193 192
194 OProcessController::theOProcessController->removeOProcess(this); 193 OProcessController::theOProcessController->removeOProcess(this);
195 // this must happen before we kill the child 194 // this must happen before we kill the child
196 // TODO: block the signal while removing the current process from the process list 195 // TODO: block the signal while removing the current process from the process list
197 196
198 if (runs && (run_mode != DontCare)) 197 if (runs && (run_mode != DontCare))
199 kill(SIGKILL); 198 kill(SIGKILL);
200 199
201 // Clean up open fd's and socket notifiers. 200 // Clean up open fd's and socket notifiers.
202 closeStdin(); 201 closeStdin();
203 closeStdout(); 202 closeStdout();
204 closeStderr(); 203 closeStderr();
205 204
206 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess 205 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess
207 delete d; 206 delete d;
208} 207}
209 208
210void OProcess::detach() 209void OProcess::detach()
211{ 210{
212 OProcessController::theOProcessController->removeOProcess(this); 211 OProcessController::theOProcessController->removeOProcess(this);
213 212
214 runs = false; 213 runs = false;
215 pid_ = 0; 214 pid_ = 0;
216 215
217 // Clean up open fd's and socket notifiers. 216 // Clean up open fd's and socket notifiers.
218 closeStdin(); 217 closeStdin();
219 closeStdout(); 218 closeStdout();
220 closeStderr(); 219 closeStderr();
221} 220}
222 221
223bool OProcess::setExecutable(const QString& proc) 222bool OProcess::setExecutable(const QString& proc)
224{ 223{
225 if (runs) return false; 224 if (runs) return false;
226 225
227 if (proc.isEmpty()) return false; 226 if (proc.isEmpty()) return false;
228 227
229 if (!arguments.isEmpty()) 228 if (!arguments.isEmpty())
230 arguments.remove(arguments.begin()); 229 arguments.remove(arguments.begin());
231 arguments.prepend(QFile::encodeName(proc)); 230 arguments.prepend(QFile::encodeName(proc));
232 231
233 return true; 232 return true;
234} 233}
235 234
236OProcess &OProcess::operator<<(const QStringList& args) 235OProcess &OProcess::operator<<(const QStringList& args)
237{ 236{
238 QStringList::ConstIterator it = args.begin(); 237 QStringList::ConstIterator it = args.begin();
239 for ( ; it != args.end() ; ++it ) 238 for ( ; it != args.end() ; ++it )
240 arguments.append(QFile::encodeName(*it)); 239 arguments.append(QFile::encodeName(*it));
241 return *this; 240 return *this;
242} 241}
243 242
244OProcess &OProcess::operator<<(const QCString& arg) 243OProcess &OProcess::operator<<(const QCString& arg)
245{ 244{
246 return operator<< (arg.data()); 245 return operator<< (arg.data());
247} 246}
248 247
249OProcess &OProcess::operator<<(const char* arg) 248OProcess &OProcess::operator<<(const char* arg)
250{ 249{
251 arguments.append(arg); 250 arguments.append(arg);
252 return *this; 251 return *this;
253} 252}
254 253
255OProcess &OProcess::operator<<(const QString& arg) 254OProcess &OProcess::operator<<(const QString& arg)
256{ 255{
257 arguments.append(QFile::encodeName(arg)); 256 arguments.append(QFile::encodeName(arg));
258 return *this; 257 return *this;
259} 258}
260 259
261void OProcess::clearArguments() 260void OProcess::clearArguments()
262{ 261{
263 arguments.clear(); 262 arguments.clear();
264} 263}
265 264
266bool OProcess::start(RunMode runmode, Communication comm) 265bool OProcess::start(RunMode runmode, Communication comm)
267{ 266{
268 uint i; 267 uint i;
269 uint n = arguments.count(); 268 uint n = arguments.count();
270 char **arglist; 269 char **arglist;
271 270
272 if (runs || (0 == n)) { 271 if (runs || (0 == n)) {
273 return false; // cannot start a process that is already running 272 return false; // cannot start a process that is already running
274 // or if no executable has been assigned 273 // or if no executable has been assigned
275 } 274 }
276 run_mode = runmode; 275 run_mode = runmode;
277 status = 0; 276 status = 0;
278 277
279 QCString shellCmd; 278 QCString shellCmd;
280 if (d && d->useShell) 279 if (d && d->useShell)
281 { 280 {
282 if (d->shell.isEmpty()) 281 if (d->shell.isEmpty())
283 { 282 {
284 qWarning( "Could not find a valid shell" ); 283 qWarning( "Could not find a valid shell" );
285 return false; 284 return false;
286 } 285 }
287 286
288 arglist = static_cast<char **>(malloc( (4)*sizeof(char *))); 287 arglist = static_cast<char **>(malloc( (4)*sizeof(char *)));
289 for (i=0; i < n; i++) { 288 for (i=0; i < n; i++) {
290 shellCmd += arguments[i]; 289 shellCmd += arguments[i];
291 shellCmd += " "; // CC: to separate the arguments 290 shellCmd += " "; // CC: to separate the arguments
292 } 291 }
293 292
294 arglist[0] = d->shell.data(); 293 arglist[0] = d->shell.data();
295 arglist[1] = (char *) "-c"; 294 arglist[1] = (char *) "-c";
296 arglist[2] = shellCmd.data(); 295 arglist[2] = shellCmd.data();
297 arglist[3] = 0; 296 arglist[3] = 0;
298 } 297 }
299 else 298 else
300 { 299 {
301 arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *))); 300 arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *)));
302 for (i=0; i < n; i++) 301 for (i=0; i < n; i++)
303 arglist[i] = arguments[i].data(); 302 arglist[i] = arguments[i].data();
304 arglist[n]= 0; 303 arglist[n]= 0;
305 } 304 }
306 305
307 if (!setupCommunication(comm)) 306 if (!setupCommunication(comm))
308 qWarning( "Could not setup Communication!"); 307 qWarning( "Could not setup Communication!");
309 308
310 // We do this in the parent because if we do it in the child process 309 // We do this in the parent because if we do it in the child process
311 // gdb gets confused when the application runs from gdb. 310 // gdb gets confused when the application runs from gdb.
312 uid_t uid = getuid(); 311 uid_t uid = getuid();