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