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,552 +1,553 @@
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();
297 gid_t gid = getgid(); 298 gid_t gid = getgid();
298#ifdef HAVE_INITGROUPS 299#ifdef HAVE_INITGROUPS
299 300
300 struct passwd *pw = getpwuid( uid ); 301 struct passwd *pw = getpwuid( uid );
301#endif 302#endif
302 303
303 int fd[ 2 ]; 304 int fd[ 2 ];
304 if ( 0 > pipe( fd ) ) 305 if ( 0 > pipe( fd ) )
305 { 306 {
306 fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue 307 fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue
307 } 308 }
308 309
309 runs = true; 310 runs = true;
310 311
311 QApplication::flushX(); 312 QApplication::flushX();
312 313
313 // WABA: Note that we use fork() and not vfork() because 314 // WABA: Note that we use fork() and not vfork() because
314 // vfork() has unclear semantics and is not standardized. 315 // vfork() has unclear semantics and is not standardized.
315 pid_ = fork(); 316 pid_ = fork();
316 317
317 if ( 0 == pid_ ) 318 if ( 0 == pid_ )
318 { 319 {
319 if ( fd[ 0 ] ) 320 if ( fd[ 0 ] )
320 close( fd[ 0 ] ); 321 close( fd[ 0 ] );
321 if ( !runPrivileged() ) 322 if ( !runPrivileged() )
322 { 323 {
323 setgid( gid ); 324 setgid( gid );
324#if defined( HAVE_INITGROUPS) 325#if defined( HAVE_INITGROUPS)
325 326
326 if ( pw ) 327 if ( pw )
327 initgroups( pw->pw_name, pw->pw_gid ); 328 initgroups( pw->pw_name, pw->pw_gid );
328#endif 329#endif
329 330
330 setuid( uid ); 331 setuid( uid );
331 } 332 }
332 // The child process 333 // The child process
333 if ( !commSetupDoneC() ) 334 if ( !commSetupDoneC() )
334 qWarning( "Could not finish comm setup in child!" ); 335 qWarning( "Could not finish comm setup in child!" );
335 336
336 setupEnvironment(); 337 setupEnvironment();
337 338
338 // Matthias 339 // Matthias
339 if ( run_mode == DontCare ) 340 if ( run_mode == DontCare )
340 setpgid( 0, 0 ); 341 setpgid( 0, 0 );
341 // restore default SIGPIPE handler (Harri) 342 // restore default SIGPIPE handler (Harri)
342 struct sigaction act; 343 struct sigaction act;
343 sigemptyset( &( act.sa_mask ) ); 344 sigemptyset( &( act.sa_mask ) );
344 sigaddset( &( act.sa_mask ), SIGPIPE ); 345 sigaddset( &( act.sa_mask ), SIGPIPE );
345 act.sa_handler = SIG_DFL; 346 act.sa_handler = SIG_DFL;
346 act.sa_flags = 0; 347 act.sa_flags = 0;
347 sigaction( SIGPIPE, &act, 0L ); 348 sigaction( SIGPIPE, &act, 0L );
348 349
349 // We set the close on exec flag. 350 // We set the close on exec flag.
350 // Closing of fd[1] indicates that the execvp succeeded! 351 // Closing of fd[1] indicates that the execvp succeeded!
351 if ( fd[ 1 ] ) 352 if ( fd[ 1 ] )
352 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC ); 353 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC );
353 execvp( arglist[ 0 ], arglist ); 354 execvp( arglist[ 0 ], arglist );
354 char resultByte = 1; 355 char resultByte = 1;
355 if ( fd[ 1 ] ) 356 if ( fd[ 1 ] )
356 write( fd[ 1 ], &resultByte, 1 ); 357 write( fd[ 1 ], &resultByte, 1 );
357 _exit( -1 ); 358 _exit( -1 );
358 } 359 }
359 else if ( -1 == pid_ ) 360 else if ( -1 == pid_ )
360 { 361 {
361 // forking failed 362 // forking failed
362 363
363 runs = false; 364 runs = false;
364 free( arglist ); 365 free( arglist );
365 return false; 366 return false;
366 } 367 }
367 else 368 else
368 { 369 {
369 if ( fd[ 1 ] ) 370 if ( fd[ 1 ] )
370 close( fd[ 1 ] ); 371 close( fd[ 1 ] );
371 // the parent continues here 372 // the parent continues here
372 373
373 // Discard any data for stdin that might still be there 374 // Discard any data for stdin that might still be there
374 input_data = 0; 375 input_data = 0;
375 376
376 // Check whether client could be started. 377 // Check whether client could be started.
377 if ( fd[ 0 ] ) 378 if ( fd[ 0 ] )
378 for ( ;; ) 379 for ( ;; )
379 { 380 {
380 char resultByte; 381 char resultByte;
381 int n = ::read( fd[ 0 ], &resultByte, 1 ); 382 int n = ::read( fd[ 0 ], &resultByte, 1 );
382 if ( n == 1 ) 383 if ( n == 1 )
383 { 384 {
384 // Error 385 // Error
385 runs = false; 386 runs = false;
386 close( fd[ 0 ] ); 387 close( fd[ 0 ] );
387 free( arglist ); 388 free( arglist );
388 pid_ = 0; 389 pid_ = 0;
389 return false; 390 return false;
390 } 391 }
391 if ( n == -1 ) 392 if ( n == -1 )
392 { 393 {
393 if ( ( errno == ECHILD ) || ( errno == EINTR ) ) 394 if ( ( errno == ECHILD ) || ( errno == EINTR ) )
394 continue; // Ignore 395 continue; // Ignore
395 } 396 }
396 break; // success 397 break; // success
397 } 398 }
398 if ( fd[ 0 ] ) 399 if ( fd[ 0 ] )
399 close( fd[ 0 ] ); 400 close( fd[ 0 ] );
400 401
401 if ( !commSetupDoneP() ) // finish communication socket setup for the parent 402 if ( !commSetupDoneP() ) // finish communication socket setup for the parent
402 qWarning( "Could not finish comm setup in parent!" ); 403 qWarning( "Could not finish comm setup in parent!" );
403 404
404 if ( run_mode == Block ) 405 if ( run_mode == Block )
405 { 406 {
406 commClose(); 407 commClose();
407 408
408 // The SIGCHLD handler of the process controller will catch 409 // The SIGCHLD handler of the process controller will catch
409 // the exit and set the status 410 // the exit and set the status
410 while ( runs ) 411 while ( runs )
411 { 412 {
412 OProcessController::theOProcessController-> 413 OProcessController::theOProcessController->
413 slotDoHousekeeping( 0 ); 414 slotDoHousekeeping( 0 );
414 } 415 }
415 runs = FALSE; 416 runs = FALSE;
416 emit processExited( this ); 417 emit processExited( this );
417 } 418 }
418 } 419 }
419 free( arglist ); 420 free( arglist );
420 return true; 421 return true;
421} 422}
422 423
423 424
424 425
425bool OProcess::kill( int signo ) 426bool OProcess::kill( int signo )
426{ 427{
427 bool rv = false; 428 bool rv = false;
428 429
429 if ( 0 != pid_ ) 430 if ( 0 != pid_ )
430 rv = ( -1 != ::kill( pid_, signo ) ); 431 rv = ( -1 != ::kill( pid_, signo ) );
431 // probably store errno somewhere... 432 // probably store errno somewhere...
432 return rv; 433 return rv;
433} 434}
434 435
435bool OProcess::isRunning() const 436bool OProcess::isRunning() const
436{ 437{
437 return runs; 438 return runs;
438} 439}
439 440
440pid_t OProcess::pid() const 441pid_t OProcess::pid() const
441{ 442{
442 return pid_; 443 return pid_;
443} 444}
444 445
445bool OProcess::normalExit() const 446bool OProcess::normalExit() const
446{ 447{
447 int _status = status; 448 int _status = status;
448 return ( pid_ != 0 ) && ( !runs ) && ( WIFEXITED( ( _status ) ) ); 449 return ( pid_ != 0 ) && ( !runs ) && ( WIFEXITED( ( _status ) ) );
449} 450}
450 451
451int OProcess::exitStatus() const 452int OProcess::exitStatus() const
452{ 453{
453 int _status = status; 454 int _status = status;
454 return WEXITSTATUS( ( _status ) ); 455 return WEXITSTATUS( ( _status ) );
455} 456}
456 457
457bool OProcess::writeStdin( const char *buffer, int buflen ) 458bool OProcess::writeStdin( const char *buffer, int buflen )
458{ 459{
459 bool rv; 460 bool rv;
460 461
461 // if there is still data pending, writing new data 462 // if there is still data pending, writing new data
462 // to stdout is not allowed (since it could also confuse 463 // to stdout is not allowed (since it could also confuse
463 // kprocess... 464 // kprocess...
464 if ( 0 != input_data ) 465 if ( 0 != input_data )
465 return false; 466 return false;
466 467
467 if ( runs && ( communication & Stdin ) ) 468 if ( runs && ( communication & Stdin ) )
468 { 469 {
469 input_data = buffer; 470 input_data = buffer;
470 input_sent = 0; 471 input_sent = 0;
471 input_total = buflen; 472 input_total = buflen;
472 slotSendData( 0 ); 473 slotSendData( 0 );
473 innot->setEnabled( true ); 474 innot->setEnabled( true );
474 rv = true; 475 rv = true;
475 } 476 }
476 else 477 else
477 rv = false; 478 rv = false;
478 return rv; 479 return rv;
479} 480}
480 481
481void OProcess::flushStdin ( ) 482void OProcess::flushStdin ( )
482{ 483{
483 if ( !input_data || ( input_sent == input_total ) ) 484 if ( !input_data || ( input_sent == input_total ) )
484 return ; 485 return ;
485 486
486 int d1, d2; 487 int d1, d2;
487 488
488 do 489 do
489 { 490 {
490 d1 = input_total - input_sent; 491 d1 = input_total - input_sent;
491 slotSendData ( 0 ); 492 slotSendData ( 0 );
492 d2 = input_total - input_sent; 493 d2 = input_total - input_sent;
493 } 494 }
494 while ( d2 <= d1 ); 495 while ( d2 <= d1 );
495} 496}
496 497
497void OProcess::suspend() 498void OProcess::suspend()
498{ 499{
499 if ( ( communication & Stdout ) && outnot ) 500 if ( ( communication & Stdout ) && outnot )
500 outnot->setEnabled( false ); 501 outnot->setEnabled( false );
501} 502}
502 503
503void OProcess::resume() 504void OProcess::resume()
504{ 505{
505 if ( ( communication & Stdout ) && outnot ) 506 if ( ( communication & Stdout ) && outnot )
506 outnot->setEnabled( true ); 507 outnot->setEnabled( true );
507} 508}
508 509
509bool OProcess::closeStdin() 510bool OProcess::closeStdin()
510{ 511{
511 bool rv; 512 bool rv;
512 513
513 if ( communication & Stdin ) 514 if ( communication & Stdin )
514 { 515 {
515 communication = ( Communication ) ( communication & ~Stdin ); 516 communication = ( Communication ) ( communication & ~Stdin );
516 delete innot; 517 delete innot;
517 innot = 0; 518 innot = 0;
518 close( in[ 1 ] ); 519 close( in[ 1 ] );
519 rv = true; 520 rv = true;
520 } 521 }
521 else 522 else
522 rv = false; 523 rv = false;
523 return rv; 524 return rv;
524} 525}
525 526
526bool OProcess::closeStdout() 527bool OProcess::closeStdout()
527{ 528{
528 bool rv; 529 bool rv;
529 530
530 if ( communication & Stdout ) 531 if ( communication & Stdout )
531 { 532 {
532 communication = ( Communication ) ( communication & ~Stdout ); 533 communication = ( Communication ) ( communication & ~Stdout );
533 delete outnot; 534 delete outnot;
534 outnot = 0; 535 outnot = 0;
535 close( out[ 0 ] ); 536 close( out[ 0 ] );
536 rv = true; 537 rv = true;
537 } 538 }
538 else 539 else
539 rv = false; 540 rv = false;
540 return rv; 541 return rv;
541} 542}
542 543
543bool OProcess::closeStderr() 544bool OProcess::closeStderr()
544{ 545{
545 bool rv; 546 bool rv;
546 547
547 if ( communication & Stderr ) 548 if ( communication & Stderr )
548 { 549 {
549 communication = static_cast<Communication>( communication & ~Stderr ); 550 communication = static_cast<Communication>( communication & ~Stderr );
550 delete errnot; 551 delete errnot;
551 errnot = 0; 552 errnot = 0;
552 close( err[ 0 ] ); 553 close( err[ 0 ] );