summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiecore/oprocess.cpp689
-rw-r--r--libopie2/opiecore/oprocess.h152
2 files changed, 393 insertions, 448 deletions
diff --git a/libopie2/opiecore/oprocess.cpp b/libopie2/opiecore/oprocess.cpp
index fb51bf9..f1a5f3b 100644
--- a/libopie2/opiecore/oprocess.cpp
+++ b/libopie2/opiecore/oprocess.cpp
@@ -1,71 +1,58 @@
1/* 1/*
2 2                This file is part of the Opie Project
3 $Id$ 3             Copyright (C) 2002-2004 Holger Freyther <zecke@handhelds.org>
4 4 and The Opie Team <opie-devel@handhelds.org>
5 This file is part of the KDE libraries 5 =. Based on KProcess (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
6 Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at) 6 .=l.
7 7          .>+-=
8 This library is free software; you can redistribute it and/or 8_;:,     .>    :=|. This program is free software; you can
9 modify it under the terms of the GNU Library General Public 9.> <`_,   >  .   <= redistribute it and/or modify it under
10 License as published by the Free Software Foundation; either 10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11 version 2 of the License, or (at your option) any later version. 11.="- .-=="i,     .._ License as published by the Free Software
12 12- .   .-<_>     .<> Foundation; either version 2 of the License,
13 This library is distributed in the hope that it will be useful, 13    ._= =}       : or (at your option) any later version.
14 but WITHOUT ANY WARRANTY; without even the implied warranty of 14   .%`+i>       _;_.
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15   .i_,=:_.      -<s. This program is distributed in the hope that
16 Library General Public License for more details. 16    +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17 17   : ..    .:,     . . . without even the implied warranty of
18 You should have received a copy of the GNU Library General Public License 18   =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19 along with this library; see the file COPYING.LIB. If not, write to 19 _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20..}^=.=       =       ; Library General Public License for more
21 Boston, MA 02111-1307, USA. 21++=   -.     .`     .: details.
22 22:     =  ...= . :.=-
23-.   .:....=;==+<; You should have received a copy of the GNU
24 -_. . .   )=.  = Library General Public License along with
25   --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
23*/ 29*/
24 30
25
26//
27// KPROCESS -- A class for handling child processes in KDE without
28// having to take care of Un*x specific implementation details
29//
30// version 0.3.1, Jan 8th 1998
31//
32// (C) Christian Czezatke
33// e9025461@student.tuwien.ac.at
34//
35// Changes:
36//
37// March 2nd, 1998: Changed parameter list for KShellProcess:
38// Arguments are now placed in a single string so that
39// <shell> -c <commandstring> is passed to the shell
40// to make the use of "operator<<" consistent with KProcess
41//
42//
43// Ported by Holger Freyther
44// <zekce> Harlekin: oprocess and say it was ported to Qt by the Opie developers an Qt 2
45
46
47
48#include "oprocess.h"
49#define _MAY_INCLUDE_KPROCESSCONTROLLER_
50#include "oprocctrl.h" 31#include "oprocctrl.h"
51 32
52//#include <config.h> 33/* OPIE */
34#include <opie2/oprocess.h>
35
36/* QT */
53 37
38#include <qapplication.h>
54#include <qfile.h> 39#include <qfile.h>
55#include <qsocketnotifier.h> 40#include <qmap.h>
56#include <qregexp.h> 41#include <qregexp.h>
42#include <qsocketnotifier.h>
57 43
58#include <sys/time.h> 44/* STD */
59#include <sys/types.h>
60#include <sys/stat.h>
61#include <sys/socket.h>
62
63#include <errno.h> 45#include <errno.h>
64#include <fcntl.h> 46#include <fcntl.h>
47#include <pwd.h>
65#include <stdlib.h> 48#include <stdlib.h>
66#include <signal.h> 49#include <signal.h>
67#include <stdio.h> 50#include <stdio.h>
68#include <string.h> 51#include <string.h>
52#include <sys/time.h>
53#include <sys/types.h>
54#include <sys/stat.h>
55#include <sys/socket.h>
69#include <unistd.h> 56#include <unistd.h>
70#ifdef HAVE_SYS_SELECT_H 57#ifdef HAVE_SYS_SELECT_H
71#include <sys/select.h> 58#include <sys/select.h>
@@ -73,43 +60,35 @@
73#ifdef HAVE_INITGROUPS 60#ifdef HAVE_INITGROUPS
74#include <grp.h> 61#include <grp.h>
75#endif 62#endif
76#include <pwd.h>
77
78#include <qapplication.h>
79#include <qmap.h>
80//#include <kdebug.h>
81
82/////////////////////////////
83// public member functions //
84/////////////////////////////
85 63
86class OProcessPrivate 64class OProcessPrivate
87{ 65{
88public: 66public:
89 OProcessPrivate() : useShell(false) { } 67 OProcessPrivate() : useShell( false )
68 { }
90 69
91 bool useShell; 70 bool useShell;
92 QMap<QString,QString> env; 71 QMap<QString, QString> env;
93 QString wd; 72 QString wd;
94 QCString shell; 73 QCString shell;
95}; 74};
96 75
97 76
98OProcess::OProcess(QObject *parent, const char *name) 77OProcess::OProcess( QObject *parent, const char *name )
99 : QObject(parent, name) 78 : QObject( parent, name )
100{ 79{
101 init ( ); 80 init ( );
102} 81}
103 82
104OProcess::OProcess(const QString &arg0, QObject *parent, const char *name) 83OProcess::OProcess( const QString &arg0, QObject *parent, const char *name )
105 : QObject(parent, name) 84 : QObject( parent, name )
106{ 85{
107 init ( ); 86 init ( );
108 *this << arg0; 87 *this << arg0;
109} 88}
110 89
111OProcess::OProcess(const QStringList &args, QObject *parent, const char *name) 90OProcess::OProcess( const QStringList &args, QObject *parent, const char *name )
112 : QObject(parent, name) 91 : QObject( parent, name )
113{ 92{
114 init ( ); 93 init ( );
115 *this << args; 94 *this << args;
@@ -131,61 +110,55 @@ void OProcess::init ( )
131 input_total = 0; 110 input_total = 0;
132 d = 0; 111 d = 0;
133 112
134 if (0 == OProcessController::theOProcessController) 113 if ( 0 == OProcessController::theOProcessController )
135 { 114 {
136 (void) new OProcessController(); 115 ( void ) new OProcessController();
137 CHECK_PTR(OProcessController::theOProcessController); 116 CHECK_PTR( OProcessController::theOProcessController );
138 } 117 }
139 118
140 OProcessController::theOProcessController->addOProcess(this); 119 OProcessController::theOProcessController->addOProcess( this );
141 out[0] = out[1] = -1; 120 out[ 0 ] = out[ 1 ] = -1;
142 in[0] = in[1] = -1; 121 in[ 0 ] = in[ 1 ] = -1;
143 err[0] = err[1] = -1; 122 err[ 0 ] = err[ 1 ] = -1;
144} 123}
145 124
146void 125void OProcess::setEnvironment( const QString &name, const QString &value )
147OProcess::setEnvironment(const QString &name, const QString &value)
148{ 126{
149 if (!d) 127 if ( !d )
150 d = new OProcessPrivate; 128 d = new OProcessPrivate;
151 d->env.insert(name, value); 129 d->env.insert( name, value );
152} 130}
153 131
154void 132void OProcess::setWorkingDirectory( const QString &dir )
155OProcess::setWorkingDirectory(const QString &dir)
156{ 133{
157 if (!d) 134 if ( !d )
158 d = new OProcessPrivate; 135 d = new OProcessPrivate;
159 d->wd = dir; 136 d->wd = dir;
160} 137}
161 138
162void 139void OProcess::setupEnvironment()
163OProcess::setupEnvironment()
164{ 140{
165 if (d) 141 if ( d )
166 { 142 {
167 QMap<QString,QString>::Iterator it; 143 QMap<QString, QString>::Iterator it;
168 for(it = d->env.begin(); it != d->env.end(); ++it) 144 for ( it = d->env.begin(); it != d->env.end(); ++it )
169 setenv(QFile::encodeName(it.key()).data(), 145 setenv( QFile::encodeName( it.key() ).data(),
170 QFile::encodeName(it.data()).data(), 1); 146 QFile::encodeName( it.data() ).data(), 1 );
171 if (!d->wd.isEmpty()) 147 if ( !d->wd.isEmpty() )
172 chdir(QFile::encodeName(d->wd).data()); 148 chdir( QFile::encodeName( d->wd ).data() );
173 } 149 }
174} 150}
175 151
176void 152void OProcess::setRunPrivileged( bool keepPrivileges )
177OProcess::setRunPrivileged(bool keepPrivileges)
178{ 153{
179 keepPrivs = keepPrivileges; 154 keepPrivs = keepPrivileges;
180} 155}
181 156
182bool 157bool OProcess::runPrivileged() const
183OProcess::runPrivileged() const
184{ 158{
185 return keepPrivs; 159 return keepPrivs;
186} 160}
187 161
188
189OProcess::~OProcess() 162OProcess::~OProcess()
190{ 163{
191 // destroying the OProcess instance sends a SIGKILL to the 164 // destroying the OProcess instance sends a SIGKILL to the
@@ -193,12 +166,12 @@ OProcess::~OProcess()
193 // list of valid processes (if the process is not started as 166 // list of valid processes (if the process is not started as
194 // "DontCare") 167 // "DontCare")
195 168
196 OProcessController::theOProcessController->removeOProcess(this); 169 OProcessController::theOProcessController->removeOProcess( this );
197 // this must happen before we kill the child 170 // this must happen before we kill the child
198 // TODO: block the signal while removing the current process from the process list 171 // TODO: block the signal while removing the current process from the process list
199 172
200 if (runs && (run_mode != DontCare)) 173 if ( runs && ( run_mode != DontCare ) )
201 kill(SIGKILL); 174 kill( SIGKILL );
202 175
203 // Clean up open fd's and socket notifiers. 176 // Clean up open fd's and socket notifiers.
204 closeStdin(); 177 closeStdin();
@@ -211,7 +184,7 @@ OProcess::~OProcess()
211 184
212void OProcess::detach() 185void OProcess::detach()
213{ 186{
214 OProcessController::theOProcessController->removeOProcess(this); 187 OProcessController::theOProcessController->removeOProcess( this );
215 188
216 runs = false; 189 runs = false;
217 pid_ = 0; 190 pid_ = 0;
@@ -222,41 +195,43 @@ void OProcess::detach()
222 closeStderr(); 195 closeStderr();
223} 196}
224 197
225bool OProcess::setExecutable(const QString& proc) 198bool OProcess::setExecutable( const QString& proc )
226{ 199{
227 if (runs) return false; 200 if ( runs )
201 return false;
228 202
229 if (proc.isEmpty()) return false; 203 if ( proc.isEmpty() )
204 return false;
230 205
231 if (!arguments.isEmpty()) 206 if ( !arguments.isEmpty() )
232 arguments.remove(arguments.begin()); 207 arguments.remove( arguments.begin() );
233 arguments.prepend(QFile::encodeName(proc)); 208 arguments.prepend( QFile::encodeName( proc ) );
234 209
235 return true; 210 return true;
236} 211}
237 212
238OProcess &OProcess::operator<<(const QStringList& args) 213OProcess &OProcess::operator<<( const QStringList& args )
239{ 214{
240 QStringList::ConstIterator it = args.begin(); 215 QStringList::ConstIterator it = args.begin();
241 for ( ; it != args.end() ; ++it ) 216 for ( ; it != args.end() ; ++it )
242 arguments.append(QFile::encodeName(*it)); 217 arguments.append( QFile::encodeName( *it ) );
243 return *this; 218 return *this;
244} 219}
245 220
246OProcess &OProcess::operator<<(const QCString& arg) 221OProcess &OProcess::operator<<( const QCString& arg )
247{ 222{
248 return operator<< (arg.data()); 223 return operator<< ( arg.data() );
249} 224}
250 225
251OProcess &OProcess::operator<<(const char* arg) 226OProcess &OProcess::operator<<( const char* arg )
252{ 227{
253 arguments.append(arg); 228 arguments.append( arg );
254 return *this; 229 return *this;
255} 230}
256 231
257OProcess &OProcess::operator<<(const QString& arg) 232OProcess &OProcess::operator<<( const QString& arg )
258{ 233{
259 arguments.append(QFile::encodeName(arg)); 234 arguments.append( QFile::encodeName( arg ) );
260 return *this; 235 return *this;
261} 236}
262 237
@@ -265,13 +240,13 @@ void OProcess::clearArguments()
265 arguments.clear(); 240 arguments.clear();
266} 241}
267 242
268bool OProcess::start(RunMode runmode, Communication comm) 243bool OProcess::start( RunMode runmode, Communication comm )
269{ 244{
270 uint i; 245 uint i;
271 uint n = arguments.count(); 246 uint n = arguments.count();
272 char **arglist; 247 char **arglist;
273 248
274 if (runs || (0 == n)) 249 if ( runs || ( 0 == n ) )
275 { 250 {
276 return false; // cannot start a process that is already running 251 return false; // cannot start a process that is already running
277 // or if no executable has been assigned 252 // or if no executable has been assigned
@@ -280,49 +255,50 @@ bool OProcess::start(RunMode runmode, Communication comm)
280 status = 0; 255 status = 0;
281 256
282 QCString shellCmd; 257 QCString shellCmd;
283 if (d && d->useShell) 258 if ( d && d->useShell )
284 { 259 {
285 if (d->shell.isEmpty()) 260 if ( d->shell.isEmpty() )
286 { 261 {
287 qWarning( "Could not find a valid shell" ); 262 qWarning( "Could not find a valid shell" );
288 return false; 263 return false;
289 } 264 }
290 265
291 arglist = static_cast<char **>(malloc( (4)*sizeof(char *))); 266 arglist = static_cast<char **>( malloc( ( 4 ) * sizeof( char * ) ) );
292 for (i=0; i < n; i++) 267 for ( i = 0; i < n; i++ )
293 { 268 {
294 shellCmd += arguments[i]; 269 shellCmd += arguments[ i ];
295 shellCmd += " "; // CC: to separate the arguments 270 shellCmd += " "; // CC: to separate the arguments
296 } 271 }
297 272
298 arglist[0] = d->shell.data(); 273 arglist[ 0 ] = d->shell.data();
299 arglist[1] = (char *) "-c"; 274 arglist[ 1 ] = ( char * ) "-c";
300 arglist[2] = shellCmd.data(); 275 arglist[ 2 ] = shellCmd.data();
301 arglist[3] = 0; 276 arglist[ 3 ] = 0;
302 } 277 }
303 else 278 else
304 { 279 {
305 arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *))); 280 arglist = static_cast<char **>( malloc( ( n + 1 ) * sizeof( char * ) ) );
306 for (i=0; i < n; i++) 281 for ( i = 0; i < n; i++ )
307 arglist[i] = arguments[i].data(); 282 arglist[ i ] = arguments[ i ].data();
308 arglist[n]= 0; 283 arglist[ n ] = 0;
309 } 284 }
310 285
311 if (!setupCommunication(comm)) 286 if ( !setupCommunication( comm ) )
312 qWarning( "Could not setup Communication!"); 287 qWarning( "Could not setup Communication!" );
313 288
314 // We do this in the parent because if we do it in the child process 289 // We do this in the parent because if we do it in the child process
315 // gdb gets confused when the application runs from gdb. 290 // gdb gets confused when the application runs from gdb.
316 uid_t uid = getuid(); 291 uid_t uid = getuid();
317 gid_t gid = getgid(); 292 gid_t gid = getgid();
318#ifdef HAVE_INITGROUPS 293#ifdef HAVE_INITGROUPS
319 struct passwd *pw = getpwuid(uid); 294
295 struct passwd *pw = getpwuid( uid );
320#endif 296#endif
321 297
322 int fd[2]; 298 int fd[ 2 ];
323 if (0 > pipe(fd)) 299 if ( 0 > pipe( fd ) )
324 { 300 {
325 fd[0] = fd[1] = 0; // Pipe failed.. continue 301 fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue
326 } 302 }
327 303
328 runs = true; 304 runs = true;
@@ -333,170 +309,163 @@ bool OProcess::start(RunMode runmode, Communication comm)
333 // vfork() has unclear semantics and is not standardized. 309 // vfork() has unclear semantics and is not standardized.
334 pid_ = fork(); 310 pid_ = fork();
335 311
336 if (0 == pid_) 312 if ( 0 == pid_ )
337 { 313 {
338 if (fd[0]) 314 if ( fd[ 0 ] )
339 close(fd[0]); 315 close( fd[ 0 ] );
340 if (!runPrivileged()) 316 if ( !runPrivileged() )
341 { 317 {
342 setgid(gid); 318 setgid( gid );
343#if defined( HAVE_INITGROUPS) 319#if defined( HAVE_INITGROUPS)
344 if(pw) 320
345 initgroups(pw->pw_name, pw->pw_gid); 321 if ( pw )
322 initgroups( pw->pw_name, pw->pw_gid );
346#endif 323#endif
347 setuid(uid); 324
325 setuid( uid );
348 } 326 }
349 // The child process 327 // The child process
350 if(!commSetupDoneC()) 328 if ( !commSetupDoneC() )
351 qWarning( "Could not finish comm setup in child!" ); 329 qWarning( "Could not finish comm setup in child!" );
352 330
353 setupEnvironment(); 331 setupEnvironment();
354 332
355 // Matthias 333 // Matthias
356 if (run_mode == DontCare) 334 if ( run_mode == DontCare )
357 setpgid(0,0); 335 setpgid( 0, 0 );
358 // restore default SIGPIPE handler (Harri) 336 // restore default SIGPIPE handler (Harri)
359 struct sigaction act; 337 struct sigaction act;
360 sigemptyset(&(act.sa_mask)); 338 sigemptyset( &( act.sa_mask ) );
361 sigaddset(&(act.sa_mask), SIGPIPE); 339 sigaddset( &( act.sa_mask ), SIGPIPE );
362 act.sa_handler = SIG_DFL; 340 act.sa_handler = SIG_DFL;
363 act.sa_flags = 0; 341 act.sa_flags = 0;
364 sigaction(SIGPIPE, &act, 0L); 342 sigaction( SIGPIPE, &act, 0L );
365 343
366 // We set the close on exec flag. 344 // We set the close on exec flag.
367 // Closing of fd[1] indicates that the execvp succeeded! 345 // Closing of fd[1] indicates that the execvp succeeded!
368 if (fd[1]) 346 if ( fd[ 1 ] )
369 fcntl(fd[1], F_SETFD, FD_CLOEXEC); 347 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC );
370 execvp(arglist[0], arglist); 348 execvp( arglist[ 0 ], arglist );
371 char resultByte = 1; 349 char resultByte = 1;
372 if (fd[1]) 350 if ( fd[ 1 ] )
373 write(fd[1], &resultByte, 1); 351 write( fd[ 1 ], &resultByte, 1 );
374 _exit(-1); 352 _exit( -1 );
375 } 353 }
376 else if (-1 == pid_) 354 else if ( -1 == pid_ )
377 { 355 {
378 // forking failed 356 // forking failed
379 357
380 runs = false; 358 runs = false;
381 free(arglist); 359 free( arglist );
382 return false; 360 return false;
383 } 361 }
384 else 362 else
385 { 363 {
386 if (fd[1]) 364 if ( fd[ 1 ] )
387 close(fd[1]); 365 close( fd[ 1 ] );
388 // the parent continues here 366 // the parent continues here
389 367
390 // Discard any data for stdin that might still be there 368 // Discard any data for stdin that might still be there
391 input_data = 0; 369 input_data = 0;
392 370
393 // Check whether client could be started. 371 // Check whether client could be started.
394 if (fd[0]) for(;;) 372 if ( fd[ 0 ] )
373 for ( ;; )
395 { 374 {
396 char resultByte; 375 char resultByte;
397 int n = ::read(fd[0], &resultByte, 1); 376 int n = ::read( fd[ 0 ], &resultByte, 1 );
398 if (n == 1) 377 if ( n == 1 )
399 { 378 {
400 // Error 379 // Error
401 runs = false; 380 runs = false;
402 close(fd[0]); 381 close( fd[ 0 ] );
403 free(arglist); 382 free( arglist );
404 pid_ = 0; 383 pid_ = 0;
405 return false; 384 return false;
406 } 385 }
407 if (n == -1) 386 if ( n == -1 )
408 { 387 {
409 if ((errno == ECHILD) || (errno == EINTR)) 388 if ( ( errno == ECHILD ) || ( errno == EINTR ) )
410 continue; // Ignore 389 continue; // Ignore
411 } 390 }
412 break; // success 391 break; // success
413 } 392 }
414 if (fd[0]) 393 if ( fd[ 0 ] )
415 close(fd[0]); 394 close( fd[ 0 ] );
416 395
417 if (!commSetupDoneP()) // finish communication socket setup for the parent 396 if ( !commSetupDoneP() ) // finish communication socket setup for the parent
418 qWarning( "Could not finish comm setup in parent!" ); 397 qWarning( "Could not finish comm setup in parent!" );
419 398
420 if (run_mode == Block) 399 if ( run_mode == Block )
421 { 400 {
422 commClose(); 401 commClose();
423 402
424 // The SIGCHLD handler of the process controller will catch 403 // The SIGCHLD handler of the process controller will catch
425 // the exit and set the status 404 // the exit and set the status
426 while(runs) 405 while ( runs )
427 { 406 {
428 OProcessController::theOProcessController-> 407 OProcessController::theOProcessController->
429 slotDoHousekeeping(0); 408 slotDoHousekeeping( 0 );
430 } 409 }
431 runs = FALSE; 410 runs = FALSE;
432 emit processExited(this); 411 emit processExited( this );
433 } 412 }
434 } 413 }
435 free(arglist); 414 free( arglist );
436 return true; 415 return true;
437} 416}
438 417
439 418
440 419
441bool OProcess::kill(int signo) 420bool OProcess::kill( int signo )
442{ 421{
443 bool rv=false; 422 bool rv = false;
444 423
445 if (0 != pid_) 424 if ( 0 != pid_ )
446 rv= (-1 != ::kill(pid_, signo)); 425 rv = ( -1 != ::kill( pid_, signo ) );
447 // probably store errno somewhere... 426 // probably store errno somewhere...
448 return rv; 427 return rv;
449} 428}
450 429
451
452
453bool OProcess::isRunning() const 430bool OProcess::isRunning() const
454{ 431{
455 return runs; 432 return runs;
456} 433}
457 434
458
459
460pid_t OProcess::pid() const 435pid_t OProcess::pid() const
461{ 436{
462 return pid_; 437 return pid_;
463} 438}
464 439
465
466
467bool OProcess::normalExit() const 440bool OProcess::normalExit() const
468{ 441{
469 int _status = status; 442 int _status = status;
470 return (pid_ != 0) && (!runs) && (WIFEXITED((_status))); 443 return ( pid_ != 0 ) && ( !runs ) && ( WIFEXITED( ( _status ) ) );
471} 444}
472 445
473
474
475int OProcess::exitStatus() const 446int OProcess::exitStatus() const
476{ 447{
477 int _status = status; 448 int _status = status;
478 return WEXITSTATUS((_status)); 449 return WEXITSTATUS( ( _status ) );
479} 450}
480 451
481 452bool OProcess::writeStdin( const char *buffer, int buflen )
482
483bool OProcess::writeStdin(const char *buffer, int buflen)
484{ 453{
485 bool rv; 454 bool rv;
486 455
487 // if there is still data pending, writing new data 456 // if there is still data pending, writing new data
488 // to stdout is not allowed (since it could also confuse 457 // to stdout is not allowed (since it could also confuse
489 // kprocess... 458 // kprocess...
490 if (0 != input_data) 459 if ( 0 != input_data )
491 return false; 460 return false;
492 461
493 if (runs && (communication & Stdin)) 462 if ( runs && ( communication & Stdin ) )
494 { 463 {
495 input_data = buffer; 464 input_data = buffer;
496 input_sent = 0; 465 input_sent = 0;
497 input_total = buflen; 466 input_total = buflen;
498 slotSendData(0); 467 slotSendData( 0 );
499 innot->setEnabled(true); 468 innot->setEnabled( true );
500 rv = true; 469 rv = true;
501 } 470 }
502 else 471 else
@@ -506,8 +475,8 @@ bool OProcess::writeStdin(const char *buffer, int buflen)
506 475
507void OProcess::flushStdin ( ) 476void OProcess::flushStdin ( )
508{ 477{
509 if ( !input_data || ( input_sent == input_total )) 478 if ( !input_data || ( input_sent == input_total ) )
510 return; 479 return ;
511 480
512 int d1, d2; 481 int d1, d2;
513 482
@@ -522,26 +491,26 @@ void OProcess::flushStdin ( )
522 491
523void OProcess::suspend() 492void OProcess::suspend()
524{ 493{
525 if ((communication & Stdout) && outnot) 494 if ( ( communication & Stdout ) && outnot )
526 outnot->setEnabled(false); 495 outnot->setEnabled( false );
527} 496}
528 497
529void OProcess::resume() 498void OProcess::resume()
530{ 499{
531 if ((communication & Stdout) && outnot) 500 if ( ( communication & Stdout ) && outnot )
532 outnot->setEnabled(true); 501 outnot->setEnabled( true );
533} 502}
534 503
535bool OProcess::closeStdin() 504bool OProcess::closeStdin()
536{ 505{
537 bool rv; 506 bool rv;
538 507
539 if (communication & Stdin) 508 if ( communication & Stdin )
540 { 509 {
541 communication = (Communication) (communication & ~Stdin); 510 communication = ( Communication ) ( communication & ~Stdin );
542 delete innot; 511 delete innot;
543 innot = 0; 512 innot = 0;
544 close(in[1]); 513 close( in[ 1 ] );
545 rv = true; 514 rv = true;
546 } 515 }
547 else 516 else
@@ -553,12 +522,12 @@ bool OProcess::closeStdout()
553{ 522{
554 bool rv; 523 bool rv;
555 524
556 if (communication & Stdout) 525 if ( communication & Stdout )
557 { 526 {
558 communication = (Communication) (communication & ~Stdout); 527 communication = ( Communication ) ( communication & ~Stdout );
559 delete outnot; 528 delete outnot;
560 outnot = 0; 529 outnot = 0;
561 close(out[0]); 530 close( out[ 0 ] );
562 rv = true; 531 rv = true;
563 } 532 }
564 else 533 else
@@ -570,12 +539,12 @@ bool OProcess::closeStderr()
570{ 539{
571 bool rv; 540 bool rv;
572 541
573 if (communication & Stderr) 542 if ( communication & Stderr )
574 { 543 {
575 communication = static_cast<Communication>(communication & ~Stderr); 544 communication = static_cast<Communication>( communication & ~Stderr );
576 delete errnot; 545 delete errnot;
577 errnot = 0; 546 errnot = 0;
578 close(err[0]); 547 close( err[ 0 ] );
579 rv = true; 548 rv = true;
580 } 549 }
581 else 550 else
@@ -583,50 +552,33 @@ bool OProcess::closeStderr()
583 return rv; 552 return rv;
584} 553}
585 554
586 555void OProcess::slotChildOutput( int fdno )
587/////////////////////////////
588// protected slots //
589/////////////////////////////
590
591
592
593void OProcess::slotChildOutput(int fdno)
594{ 556{
595 if (!childOutput(fdno)) 557 if ( !childOutput( fdno ) )
596 closeStdout(); 558 closeStdout();
597} 559}
598 560
599 561void OProcess::slotChildError( int fdno )
600void OProcess::slotChildError(int fdno)
601{ 562{
602 if (!childError(fdno)) 563 if ( !childError( fdno ) )
603 closeStderr(); 564 closeStderr();
604} 565}
605 566
606 567void OProcess::slotSendData( int )
607void OProcess::slotSendData(int)
608{ 568{
609 if (input_sent == input_total) 569 if ( input_sent == input_total )
610 { 570 {
611 innot->setEnabled(false); 571 innot->setEnabled( false );
612 input_data = 0; 572 input_data = 0;
613 emit wroteStdin(this); 573 emit wroteStdin( this );
614 } 574 }
615 else 575 else
616 input_sent += ::write(in[1], input_data+input_sent, input_total-input_sent); 576 input_sent += ::write( in[ 1 ], input_data + input_sent, input_total - input_sent );
617} 577}
618 578
619 579void OProcess::processHasExited( int state )
620
621//////////////////////////////
622// private member functions //
623//////////////////////////////
624
625
626
627void OProcess::processHasExited(int state)
628{ 580{
629 if (runs) 581 if ( runs )
630 { 582 {
631 runs = false; 583 runs = false;
632 status = state; 584 status = state;
@@ -634,153 +586,144 @@ void OProcess::processHasExited(int state)
634 commClose(); // cleanup communication sockets 586 commClose(); // cleanup communication sockets
635 587
636 // also emit a signal if the process was run Blocking 588 // also emit a signal if the process was run Blocking
637 if (DontCare != run_mode) 589 if ( DontCare != run_mode )
638 { 590 {
639 emit processExited(this); 591 emit processExited( this );
640 } 592 }
641 } 593 }
642} 594}
643 595
644 596int OProcess::childOutput( int fdno )
645
646int OProcess::childOutput(int fdno)
647{ 597{
648 if (communication & NoRead) 598 if ( communication & NoRead )
649 { 599 {
650 int len = -1; 600 int len = -1;
651 emit receivedStdout(fdno, len); 601 emit receivedStdout( fdno, len );
652 errno = 0; // Make sure errno doesn't read "EAGAIN" 602 errno = 0; // Make sure errno doesn't read "EAGAIN"
653 return len; 603 return len;
654 } 604 }
655 else 605 else
656 { 606 {
657 char buffer[1024]; 607 char buffer[ 1024 ];
658 int len; 608 int len;
659 609
660 len = ::read(fdno, buffer, 1024); 610 len = ::read( fdno, buffer, 1024 );
661 611
662 if ( 0 < len) 612 if ( 0 < len )
663 { 613 {
664 emit receivedStdout(this, buffer, len); 614 emit receivedStdout( this, buffer, len );
665 } 615 }
666 return len; 616 return len;
667 } 617 }
668} 618}
669 619
670 620int OProcess::childError( int fdno )
671
672int OProcess::childError(int fdno)
673{ 621{
674 char buffer[1024]; 622 char buffer[ 1024 ];
675 int len; 623 int len;
676 624
677 len = ::read(fdno, buffer, 1024); 625 len = ::read( fdno, buffer, 1024 );
678 626
679 if ( 0 < len) 627 if ( 0 < len )
680 emit receivedStderr(this, buffer, len); 628 emit receivedStderr( this, buffer, len );
681 return len; 629 return len;
682} 630}
683 631
684 632int OProcess::setupCommunication( Communication comm )
685
686int OProcess::setupCommunication(Communication comm)
687{ 633{
688 int ok; 634 int ok;
689 635
690 communication = comm; 636 communication = comm;
691 637
692 ok = 1; 638 ok = 1;
693 if (comm & Stdin) 639 if ( comm & Stdin )
694 ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, in) >= 0; 640 ok &= socketpair( AF_UNIX, SOCK_STREAM, 0, in ) >= 0;
695 641
696 if (comm & Stdout) 642 if ( comm & Stdout )
697 ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, out) >= 0; 643 ok &= socketpair( AF_UNIX, SOCK_STREAM, 0, out ) >= 0;
698 644
699 if (comm & Stderr) 645 if ( comm & Stderr )
700 ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err) >= 0; 646 ok &= socketpair( AF_UNIX, SOCK_STREAM, 0, err ) >= 0;
701 647
702 return ok; 648 return ok;
703} 649}
704 650
705
706
707int OProcess::commSetupDoneP() 651int OProcess::commSetupDoneP()
708{ 652{
709 int ok = 1; 653 int ok = 1;
710 654
711 if (communication != NoCommunication) 655 if ( communication != NoCommunication )
712 { 656 {
713 if (communication & Stdin) 657 if ( communication & Stdin )
714 close(in[0]); 658 close( in[ 0 ] );
715 if (communication & Stdout) 659 if ( communication & Stdout )
716 close(out[1]); 660 close( out[ 1 ] );
717 if (communication & Stderr) 661 if ( communication & Stderr )
718 close(err[1]); 662 close( err[ 1 ] );
719 663
720 // Don't create socket notifiers and set the sockets non-blocking if 664 // Don't create socket notifiers and set the sockets non-blocking if
721 // blocking is requested. 665 // blocking is requested.
722 if (run_mode == Block) return ok; 666 if ( run_mode == Block )
667 return ok;
723 668
724 if (communication & Stdin) 669 if ( communication & Stdin )
725 { 670 {
726 // ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK)); 671 // ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK));
727 innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this); 672 innot = new QSocketNotifier( in[ 1 ], QSocketNotifier::Write, this );
728 CHECK_PTR(innot); 673 CHECK_PTR( innot );
729 innot->setEnabled(false); // will be enabled when data has to be sent 674 innot->setEnabled( false ); // will be enabled when data has to be sent
730 QObject::connect(innot, SIGNAL(activated(int)), 675 QObject::connect( innot, SIGNAL( activated( int ) ),
731 this, SLOT(slotSendData(int))); 676 this, SLOT( slotSendData( int ) ) );
732 } 677 }
733 678
734 if (communication & Stdout) 679 if ( communication & Stdout )
735 { 680 {
736 // ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK)); 681 // ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK));
737 outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this); 682 outnot = new QSocketNotifier( out[ 0 ], QSocketNotifier::Read, this );
738 CHECK_PTR(outnot); 683 CHECK_PTR( outnot );
739 QObject::connect(outnot, SIGNAL(activated(int)), 684 QObject::connect( outnot, SIGNAL( activated( int ) ),
740 this, SLOT(slotChildOutput(int))); 685 this, SLOT( slotChildOutput( int ) ) );
741 if (communication & NoRead) 686 if ( communication & NoRead )
742 suspend(); 687 suspend();
743 } 688 }
744 689
745 if (communication & Stderr) 690 if ( communication & Stderr )
746 { 691 {
747 // ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK)); 692 // ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK));
748 errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this ); 693 errnot = new QSocketNotifier( err[ 0 ], QSocketNotifier::Read, this );
749 CHECK_PTR(errnot); 694 CHECK_PTR( errnot );
750 QObject::connect(errnot, SIGNAL(activated(int)), 695 QObject::connect( errnot, SIGNAL( activated( int ) ),
751 this, SLOT(slotChildError(int))); 696 this, SLOT( slotChildError( int ) ) );
752 } 697 }
753 } 698 }
754 return ok; 699 return ok;
755} 700}
756 701
757
758
759int OProcess::commSetupDoneC() 702int OProcess::commSetupDoneC()
760{ 703{
761 int ok = 1; 704 int ok = 1;
762 struct linger so; 705 struct linger so;
763 memset(&so, 0, sizeof(so)); 706 memset( &so, 0, sizeof( so ) );
764 707
765 if (communication & Stdin) 708 if ( communication & Stdin )
766 close(in[1]); 709 close( in[ 1 ] );
767 if (communication & Stdout) 710 if ( communication & Stdout )
768 close(out[0]); 711 close( out[ 0 ] );
769 if (communication & Stderr) 712 if ( communication & Stderr )
770 close(err[0]); 713 close( err[ 0 ] );
771 714
772 if (communication & Stdin) 715 if ( communication & Stdin )
773 ok &= dup2(in[0], STDIN_FILENO) != -1; 716 ok &= dup2( in[ 0 ], STDIN_FILENO ) != -1;
774 else 717 else
775 { 718 {
776 int null_fd = open( "/dev/null", O_RDONLY ); 719 int null_fd = open( "/dev/null", O_RDONLY );
777 ok &= dup2( null_fd, STDIN_FILENO ) != -1; 720 ok &= dup2( null_fd, STDIN_FILENO ) != -1;
778 close( null_fd ); 721 close( null_fd );
779 } 722 }
780 if (communication & Stdout) 723 if ( communication & Stdout )
781 { 724 {
782 ok &= dup2(out[1], STDOUT_FILENO) != -1; 725 ok &= dup2( out[ 1 ], STDOUT_FILENO ) != -1;
783 ok &= !setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so)); 726 ok &= !setsockopt( out[ 1 ], SOL_SOCKET, SO_LINGER, ( char* ) & so, sizeof( so ) );
784 } 727 }
785 else 728 else
786 { 729 {
@@ -788,10 +731,10 @@ int OProcess::commSetupDoneC()
788 ok &= dup2( null_fd, STDOUT_FILENO ) != -1; 731 ok &= dup2( null_fd, STDOUT_FILENO ) != -1;
789 close( null_fd ); 732 close( null_fd );
790 } 733 }
791 if (communication & Stderr) 734 if ( communication & Stderr )
792 { 735 {
793 ok &= dup2(err[1], STDERR_FILENO) != -1; 736 ok &= dup2( err[ 1 ], STDERR_FILENO ) != -1;
794 ok &= !setsockopt(err[1], SOL_SOCKET, SO_LINGER, reinterpret_cast<char *>(&so), sizeof(so)); 737 ok &= !setsockopt( err[ 1 ], SOL_SOCKET, SO_LINGER, reinterpret_cast<char *>( &so ), sizeof( so ) );
795 } 738 }
796 else 739 else
797 { 740 {
@@ -802,19 +745,17 @@ int OProcess::commSetupDoneC()
802 return ok; 745 return ok;
803} 746}
804 747
805
806
807void OProcess::commClose() 748void OProcess::commClose()
808{ 749{
809 if (NoCommunication != communication) 750 if ( NoCommunication != communication )
810 { 751 {
811 bool b_in = (communication & Stdin); 752 bool b_in = ( communication & Stdin );
812 bool b_out = (communication & Stdout); 753 bool b_out = ( communication & Stdout );
813 bool b_err = (communication & Stderr); 754 bool b_err = ( communication & Stderr );
814 if (b_in) 755 if ( b_in )
815 delete innot; 756 delete innot;
816 757
817 if (b_out || b_err) 758 if ( b_out || b_err )
818 { 759 {
819 // If both channels are being read we need to make sure that one socket buffer 760 // If both channels are being read we need to make sure that one socket buffer
820 // doesn't fill up whilst we are waiting for data on the other (causing a deadlock). 761 // doesn't fill up whilst we are waiting for data on the other (causing a deadlock).
@@ -827,25 +768,25 @@ void OProcess::commClose()
827 fd_set rfds; 768 fd_set rfds;
828 769
829 int max_fd = 0; 770 int max_fd = 0;
830 if (b_out) 771 if ( b_out )
831 { 772 {
832 fcntl(out[0], F_SETFL, O_NONBLOCK); 773 fcntl( out[ 0 ], F_SETFL, O_NONBLOCK );
833 if (out[0] > max_fd) 774 if ( out[ 0 ] > max_fd )
834 max_fd = out[0]; 775 max_fd = out[ 0 ];
835 delete outnot; 776 delete outnot;
836 outnot = 0; 777 outnot = 0;
837 } 778 }
838 if (b_err) 779 if ( b_err )
839 { 780 {
840 fcntl(err[0], F_SETFL, O_NONBLOCK); 781 fcntl( err[ 0 ], F_SETFL, O_NONBLOCK );
841 if (err[0] > max_fd) 782 if ( err[ 0 ] > max_fd )
842 max_fd = err[0]; 783 max_fd = err[ 0 ];
843 delete errnot; 784 delete errnot;
844 errnot = 0; 785 errnot = 0;
845 } 786 }
846 787
847 788
848 while (b_out || b_err) 789 while ( b_out || b_err )
849 { 790 {
850 // * If the process is still running we block until we 791 // * If the process is still running we block until we
851 // receive data. (p_timeout = 0, no timeout) 792 // receive data. (p_timeout = 0, no timeout)
@@ -857,76 +798,79 @@ void OProcess::commClose()
857 timeout.tv_usec = 0; 798 timeout.tv_usec = 0;
858 struct timeval *p_timeout = runs ? 0 : &timeout; 799 struct timeval *p_timeout = runs ? 0 : &timeout;
859 800
860 FD_ZERO(&rfds); 801 FD_ZERO( &rfds );
861 if (b_out) 802 if ( b_out )
862 FD_SET(out[0], &rfds); 803 FD_SET( out[ 0 ], &rfds );
863 804
864 if (b_err) 805 if ( b_err )
865 FD_SET(err[0], &rfds); 806 FD_SET( err[ 0 ], &rfds );
866 807
867 fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout); 808 fds_ready = select( max_fd + 1, &rfds, 0, 0, p_timeout );
868 if (fds_ready <= 0) break; 809 if ( fds_ready <= 0 )
810 break;
869 811
870 if (b_out && FD_ISSET(out[0], &rfds)) 812 if ( b_out && FD_ISSET( out[ 0 ], &rfds ) )
871 { 813 {
872 int ret = 1; 814 int ret = 1;
873 while (ret > 0) ret = childOutput(out[0]); 815 while ( ret > 0 )
874 if ((ret == -1 && errno != EAGAIN) || ret == 0) 816 ret = childOutput( out[ 0 ] );
817 if ( ( ret == -1 && errno != EAGAIN ) || ret == 0 )
875 b_out = false; 818 b_out = false;
876 } 819 }
877 820
878 if (b_err && FD_ISSET(err[0], &rfds)) 821 if ( b_err && FD_ISSET( err[ 0 ], &rfds ) )
879 { 822 {
880 int ret = 1; 823 int ret = 1;
881 while (ret > 0) ret = childError(err[0]); 824 while ( ret > 0 )
882 if ((ret == -1 && errno != EAGAIN) || ret == 0) 825 ret = childError( err[ 0 ] );
826 if ( ( ret == -1 && errno != EAGAIN ) || ret == 0 )
883 b_err = false; 827 b_err = false;
884 } 828 }
885 } 829 }
886 } 830 }
887 831
888 if (b_in) 832 if ( b_in )
889 { 833 {
890 communication = (Communication) (communication & ~Stdin); 834 communication = ( Communication ) ( communication & ~Stdin );
891 close(in[1]); 835 close( in[ 1 ] );
892 } 836 }
893 if (b_out) 837 if ( b_out )
894 { 838 {
895 communication = (Communication) (communication & ~Stdout); 839 communication = ( Communication ) ( communication & ~Stdout );
896 close(out[0]); 840 close( out[ 0 ] );
897 } 841 }
898 if (b_err) 842 if ( b_err )
899 { 843 {
900 communication = (Communication) (communication & ~Stderr); 844 communication = ( Communication ) ( communication & ~Stderr );
901 close(err[0]); 845 close( err[ 0 ] );
902 } 846 }
903 } 847 }
904} 848}
905 849
906void OProcess::setUseShell(bool useShell, const char *shell) 850void OProcess::setUseShell( bool useShell, const char *shell )
907{ 851{
908 if (!d) 852 if ( !d )
909 d = new OProcessPrivate; 853 d = new OProcessPrivate;
910 d->useShell = useShell; 854 d->useShell = useShell;
911 d->shell = shell; 855 d->shell = shell;
912 if (d->shell.isEmpty()) 856 if ( d->shell.isEmpty() )
913 d->shell = searchShell(); 857 d->shell = searchShell();
914} 858}
915 859
916QString OProcess::quote(const QString &arg) 860QString OProcess::quote( const QString &arg )
917{ 861{
918 QString res = arg; 862 QString res = arg;
919 res.replace(QRegExp(QString::fromLatin1("\'")), 863 res.replace( QRegExp( QString::fromLatin1( "\'" ) ),
920 QString::fromLatin1("'\"'\"'")); 864 QString::fromLatin1( "'\"'\"'" ) );
921 res.prepend('\''); 865 res.prepend( '\'' );
922 res.append('\''); 866 res.append( '\'' );
923 return res; 867 return res;
924} 868}
925 869
926QCString OProcess::searchShell() 870QCString OProcess::searchShell()
927{ 871{
928 QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace(); 872 QCString tmpShell = QCString( getenv( "SHELL" ) ).stripWhiteSpace();
929 if (!isExecutable(tmpShell)) 873 if ( !isExecutable( tmpShell ) )
930 { 874 {
931 tmpShell = "/bin/sh"; 875 tmpShell = "/bin/sh";
932 } 876 }
@@ -934,37 +878,38 @@ QCString OProcess::searchShell()
934 return tmpShell; 878 return tmpShell;
935} 879}
936 880
937bool OProcess::isExecutable(const QCString &filename) 881bool OProcess::isExecutable( const QCString &filename )
938{ 882{
939 struct stat fileinfo; 883 struct stat fileinfo;
940 884
941 if (filename.isEmpty()) return false; 885 if ( filename.isEmpty() )
886 return false;
942 887
943 // CC: we've got a valid filename, now let's see whether we can execute that file 888 // CC: we've got a valid filename, now let's see whether we can execute that file
944 889
945 if (-1 == stat(filename.data(), &fileinfo)) return false; 890 if ( -1 == stat( filename.data(), &fileinfo ) )
891 return false;
946 // CC: return false if the file does not exist 892 // CC: return false if the file does not exist
947 893
948 // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets 894 // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets
949 if ( (S_ISDIR(fileinfo.st_mode)) || 895 if ( ( S_ISDIR( fileinfo.st_mode ) ) ||
950 (S_ISCHR(fileinfo.st_mode)) || 896 ( S_ISCHR( fileinfo.st_mode ) ) ||
951 (S_ISBLK(fileinfo.st_mode)) || 897 ( S_ISBLK( fileinfo.st_mode ) ) ||
952#ifdef S_ISSOCK 898#ifdef S_ISSOCK
953 // CC: SYSVR4 systems don't have that macro 899 // CC: SYSVR4 systems don't have that macro
954 (S_ISSOCK(fileinfo.st_mode)) || 900 ( S_ISSOCK( fileinfo.st_mode ) ) ||
955#endif 901#endif
956 (S_ISFIFO(fileinfo.st_mode)) || 902 ( S_ISFIFO( fileinfo.st_mode ) ) ||
957 (S_ISDIR(fileinfo.st_mode)) ) 903 ( S_ISDIR( fileinfo.st_mode ) ) )
958 { 904 {
959 return false; 905 return false;
960 } 906 }
961 907
962 // CC: now check for permission to execute the file 908 // CC: now check for permission to execute the file
963 if (access(filename.data(), X_OK) != 0) return false; 909 if ( access( filename.data(), X_OK ) != 0 )
910 return false;
964 911
965 // CC: we've passed all the tests... 912 // CC: we've passed all the tests...
966 return true; 913 return true;
967} 914}
968 915
969
970
diff --git a/libopie2/opiecore/oprocess.h b/libopie2/opiecore/oprocess.h
index 8dd19b5..352485b 100644
--- a/libopie2/opiecore/oprocess.h
+++ b/libopie2/opiecore/oprocess.h
@@ -1,42 +1,46 @@
1/* This file is part of the KDE libraries 1/*
2 Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at) 2                This file is part of the Opie Project
3 3             Copyright (C) 2003-2004 Holger Freyther <zecke@handhelds.org>
4 This library is free software; you can redistribute it and/or 4 Copyright (C) The Opie Team <opie-devel@handhelds.org>
5 modify it under the terms of the GNU Library General Public 5 =. Based on KProcess (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
6 License as published by the Free Software Foundation; either 6 .=l.
7 version 2 of the License, or (at your option) any later version. 7          .>+-=
8 8_;:,     .>    :=|. This program is free software; you can
9 This library is distributed in the hope that it will be useful, 9.> <`_,   >  .   <= redistribute it and/or modify it under
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11.="- .-=="i,     .._ License as published by the Free Software
12 Library General Public License for more details. 12- .   .-<_>     .<> Foundation; either version 2 of the License,
13 13    ._= =}       : or (at your option) any later version.
14 You should have received a copy of the GNU Library General Public License 14   .%`+i>       _;_.
15 along with this library; see the file COPYING.LIB. If not, write to 15   .i_,=:_.      -<s. This program is distributed in the hope that
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16    +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17 Boston, MA 02111-1307, USA. 17   : ..    .:,     . . . without even the implied warranty of
18   =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19 _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details.
22:     =  ...= . :.=-
23-.   .:....=;==+<; You should have received a copy of the GNU
24 -_. . .   )=.  = Library General Public License along with
25   --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA.
18*/ 29*/
19//
20// KPROCESS -- A class for handling child processes in KDE without
21// having to take care of Un*x specific implementation details
22//
23// version 0.3.1, Jan 8th 1998
24//
25// (C) Christian Czezatke
26// e9025461@student.tuwien.ac.at
27// Ported by Holger Freyther to the Open Palmtop Integrated Environment
28//
29
30#ifndef __kprocess_h__
31#define __kprocess_h__
32 30
31#ifndef OPROCESS_H
32#define OPROCESS_H
33
34/* QT */
35#include <qcstring.h>
36#include <qobject.h>
37#include <qvaluelist.h>
38
39/* STD */
33#include <sys/types.h> // for pid_t 40#include <sys/types.h> // for pid_t
34#include <sys/wait.h> 41#include <sys/wait.h>
35#include <signal.h> 42#include <signal.h>
36#include <unistd.h> 43#include <unistd.h>
37#include <qvaluelist.h>
38#include <qcstring.h>
39#include <qobject.h>
40 44
41class QSocketNotifier; 45class QSocketNotifier;
42class OProcessPrivate; 46class OProcessPrivate;
@@ -141,7 +145,7 @@ class OProcessPrivate;
141 *client . 145 *client .
142 * 146 *
143 *@author Christian Czezakte e9025461@student.tuwien.ac.at 147 *@author Christian Czezakte e9025461@student.tuwien.ac.at
144 * 148 *@author Holger Freyther (Opie Port)
145 * 149 *
146 **/ 150 **/
147class OProcess : public QObject 151class OProcess : public QObject
@@ -187,15 +191,15 @@ public:
187 /** 191 /**
188 * Constructor 192 * Constructor
189 */ 193 */
190 OProcess(QObject *parent = 0, const char *name = 0); 194 OProcess( QObject *parent = 0, const char *name = 0 );
191 /** 195 /**
192 * Constructor 196 * Constructor
193 */ 197 */
194 OProcess(const QString &arg0, QObject *parent = 0, const char *name = 0); 198 OProcess( const QString &arg0, QObject *parent = 0, const char *name = 0 );
195 /** 199 /**
196 * Constructor 200 * Constructor
197 */ 201 */
198 OProcess(const QStringList &args, QObject *parent = 0, const char *name = 0); 202 OProcess( const QStringList &args, QObject *parent = 0, const char *name = 0 );
199 203
200 /** 204 /**
201 *Destructor: 205 *Destructor:
@@ -220,7 +224,7 @@ public:
220 @see operator<< 224 @see operator<<
221 225
222 */ 226 */
223 bool setExecutable(const QString& proc); 227 bool setExecutable( const QString& proc );
224 228
225 229
226 /** 230 /**
@@ -234,21 +238,21 @@ public:
234 * </pre> 238 * </pre>
235 * 239 *
236 **/ 240 **/
237 OProcess &operator<<(const QString& arg); 241 OProcess &operator<<( const QString& arg );
238 /** 242 /**
239 * Similar to previous method, takes a char *, supposed to be in locale 8 bit already. 243 * Similar to previous method, takes a char *, supposed to be in locale 8 bit already.
240 */ 244 */
241 OProcess &operator<<(const char * arg); 245 OProcess &operator<<( const char * arg );
242 /** 246 /**
243 * Similar to previous method, takes a QCString, supposed to be in locale 8 bit already. 247 * Similar to previous method, takes a QCString, supposed to be in locale 8 bit already.
244 */ 248 */
245 OProcess &operator<<(const QCString & arg); 249 OProcess &operator<<( const QCString & arg );
246 250
247 /** 251 /**
248 * Sets the executable and the command line argument list for this process, 252 * Sets the executable and the command line argument list for this process,
249 * in a single method call, or add a list of arguments. 253 * in a single method call, or add a list of arguments.
250 **/ 254 **/
251 OProcess &operator<<(const QStringList& args); 255 OProcess &operator<<( const QStringList& args );
252 256
253 /** 257 /**
254 * Clear a command line argument list that has been set by using 258 * Clear a command line argument list that has been set by using
@@ -278,8 +282,8 @@ public:
278 * @return true on success, false on error 282 * @return true on success, false on error
279 * (see above for error conditions) 283 * (see above for error conditions)
280 **/ 284 **/
281 virtual bool start(RunMode runmode = NotifyOnExit, 285 virtual bool start( RunMode runmode = NotifyOnExit,
282 Communication comm = NoCommunication); 286 Communication comm = NoCommunication );
283 287
284 /** 288 /**
285 * Stop the process (by sending it a signal). 289 * Stop the process (by sending it a signal).
@@ -287,7 +291,7 @@ public:
287 * @param signoThe signal to send. The default is SIGTERM. 291 * @param signoThe signal to send. The default is SIGTERM.
288 * @return @p true if the signal was delivered successfully. 292 * @return @p true if the signal was delivered successfully.
289 */ 293 */
290 virtual bool kill(int signo = SIGTERM); 294 virtual bool kill( int signo = SIGTERM );
291 295
292 /** 296 /**
293 @return @p true if the process is (still) considered to be running 297 @return @p true if the process is (still) considered to be running
@@ -333,7 +337,7 @@ public:
333 * this function because if the process did not exit normally, 337 * this function because if the process did not exit normally,
334 * it does not have a valid exit status. 338 * it does not have a valid exit status.
335 */ 339 */
336 int exitStatus() const; 340 int exitStatus() const;
337 341
338 342
339 /** 343 /**
@@ -360,7 +364,7 @@ public:
360 * data has been sent or a @ref processHasExited() signal shows that 364 * data has been sent or a @ref processHasExited() signal shows that
361 * the child process is no longer alive... 365 * the child process is no longer alive...
362 **/ 366 **/
363 bool writeStdin(const char *buffer, int buflen); 367 bool writeStdin( const char *buffer, int buflen );
364 368
365 void flushStdin(); 369 void flushStdin();
366 370
@@ -395,7 +399,10 @@ public:
395 * Lets you see what your arguments are for debugging. 399 * Lets you see what your arguments are for debugging.
396 */ 400 */
397 401
398 const QValueList<QCString> &args() { return arguments; } 402 const QValueList<QCString> &args()
403 {
404 return arguments;
405 }
399 406
400 /** 407 /**
401 * Controls whether the started process should drop any 408 * Controls whether the started process should drop any
@@ -403,7 +410,7 @@ public:
403 * 410 *
404 * The default is @p false : drop privileges 411 * The default is @p false : drop privileges
405 */ 412 */
406 void setRunPrivileged(bool keepPrivileges); 413 void setRunPrivileged( bool keepPrivileges );
407 414
408 /** 415 /**
409 * Returns whether the started process will drop any 416 * Returns whether the started process will drop any
@@ -415,14 +422,14 @@ public:
415 * Modifies the environment of the process to be started. 422 * Modifies the environment of the process to be started.
416 * This function must be called before starting the process. 423 * This function must be called before starting the process.
417 */ 424 */
418 void setEnvironment(const QString &name, const QString &value); 425 void setEnvironment( const QString &name, const QString &value );
419 426
420 /** 427 /**
421 * Changes the current working directory (CWD) of the process 428 * Changes the current working directory (CWD) of the process
422 * to be started. 429 * to be started.
423 * This function must be called before starting the process. 430 * This function must be called before starting the process.
424 */ 431 */
425 void setWorkingDirectory(const QString &dir); 432 void setWorkingDirectory( const QString &dir );
426 433
427 /** 434 /**
428 * Specify whether to start the command via a shell or directly. 435 * Specify whether to start the command via a shell or directly.
@@ -435,7 +442,7 @@ public:
435 * are properly quoted when passed as argument. 442 * are properly quoted when passed as argument.
436 * @see quote() 443 * @see quote()
437 */ 444 */
438 void setUseShell(bool useShell, const char *shell = 0); 445 void setUseShell( bool useShell, const char *shell = 0 );
439 446
440 /** 447 /**
441 * This function can be used to quote an argument string such that 448 * This function can be used to quote an argument string such that
@@ -443,7 +450,7 @@ public:
443 * user-provided file names which may contain spaces or quotes. 450 * user-provided file names which may contain spaces or quotes.
444 * It also prevents expansion of wild cards and environment variables. 451 * It also prevents expansion of wild cards and environment variables.
445 */ 452 */
446 static QString quote(const QString &arg); 453 static QString quote( const QString &arg );
447 454
448 /** 455 /**
449 * Detaches OProcess from child process. All communication is closed. 456 * Detaches OProcess from child process. All communication is closed.
@@ -454,8 +461,6 @@ public:
454 */ 461 */
455 void detach(); 462 void detach();
456 463
457
458
459signals: 464signals:
460 465
461 /** 466 /**
@@ -463,7 +468,7 @@ signals:
463 * the process was run in the @p NotifyOnExit (==default option to 468 * the process was run in the @p NotifyOnExit (==default option to
464 * @ref start()) or the @ref Block mode. 469 * @ref start()) or the @ref Block mode.
465 **/ 470 **/
466 void processExited(OProcess *proc); 471 void processExited( OProcess *proc );
467 472
468 473
469 /** 474 /**
@@ -480,7 +485,7 @@ signals:
480 * You should copy the information contained in @p buffer to your private 485 * You should copy the information contained in @p buffer to your private
481 * data structures before returning from this slot. 486 * data structures before returning from this slot.
482 **/ 487 **/
483 void receivedStdout(OProcess *proc, char *buffer, int buflen); 488 void receivedStdout( OProcess *proc, char *buffer, int buflen );
484 489
485 /** 490 /**
486 * Emitted when output from the child process has 491 * Emitted when output from the child process has
@@ -497,7 +502,7 @@ signals:
497 * 502 *
498 * The data still has to be read from file descriptor @p fd. 503 * The data still has to be read from file descriptor @p fd.
499 **/ 504 **/
500 void receivedStdout(int fd, int &len); 505 void receivedStdout( int fd, int &len );
501 506
502 507
503 /** 508 /**
@@ -513,15 +518,14 @@ signals:
513 * You should copy the information contained in @p buffer to your private 518 * You should copy the information contained in @p buffer to your private
514 * data structures before returning from this slot. 519 * data structures before returning from this slot.
515 */ 520 */
516 void receivedStderr(OProcess *proc, char *buffer, int buflen); 521 void receivedStderr( OProcess *proc, char *buffer, int buflen );
517 522
518 /** 523 /**
519 * Emitted after all the data that has been 524 * Emitted after all the data that has been
520 * specified by a prior call to @ref writeStdin() has actually been 525 * specified by a prior call to @ref writeStdin() has actually been
521 * written to the child process. 526 * written to the child process.
522 **/ 527 **/
523 void wroteStdin(OProcess *proc); 528 void wroteStdin( OProcess *proc );
524
525 529
526protected slots: 530protected slots:
527 531
@@ -529,13 +533,13 @@ protected slots:
529 * This slot gets activated when data from the child's stdout arrives. 533 * This slot gets activated when data from the child's stdout arrives.
530 * It usually calls "childOutput" 534 * It usually calls "childOutput"
531 */ 535 */
532 void slotChildOutput(int fdno); 536 void slotChildOutput( int fdno );
533 537
534 /** 538 /**
535 * This slot gets activated when data from the child's stderr arrives. 539 * This slot gets activated when data from the child's stderr arrives.
536 * It usually calls "childError" 540 * It usually calls "childError"
537 */ 541 */
538 void slotChildError(int fdno); 542 void slotChildError( int fdno );
539 /* 543 /*
540 Slot functions for capturing stdout and stderr of the child 544 Slot functions for capturing stdout and stderr of the child
541 */ 545 */
@@ -545,7 +549,7 @@ protected slots:
545 * stdin. If there is no more data to be sent to stdin currently 549 * stdin. If there is no more data to be sent to stdin currently
546 * available, this function must disable the QSocketNotifier "innot". 550 * available, this function must disable the QSocketNotifier "innot".
547 */ 551 */
548 void slotSendData(int dummy); 552 void slotSendData( int dummy );
549 553
550protected: 554protected:
551 555
@@ -624,7 +628,7 @@ protected:
624 * but you could overload this function and establish a TCP/IP communication for 628 * but you could overload this function and establish a TCP/IP communication for
625 * network communication, for example. 629 * network communication, for example.
626 */ 630 */
627 virtual int setupCommunication(Communication comm); 631 virtual int setupCommunication( Communication comm );
628 632
629 /** 633 /**
630 * Called right after a (successful) fork on the parent side. This function 634 * Called right after a (successful) fork on the parent side. This function
@@ -654,7 +658,7 @@ protected:
654 * process and emits the "processExited" signal (if the process was 658 * process and emits the "processExited" signal (if the process was
655 * not running in the "DontCare" mode). 659 * not running in the "DontCare" mode).
656 */ 660 */
657 virtual void processHasExited(int state); 661 virtual void processHasExited( int state );
658 662
659 /** 663 /**
660 * Should clean up the communication links to the child after it has 664 * Should clean up the communication links to the child after it has
@@ -666,9 +670,9 @@ protected:
666 /** 670 /**
667 * the socket descriptors for stdin/stdout/stderr. 671 * the socket descriptors for stdin/stdout/stderr.
668 */ 672 */
669 int out[2]; 673 int out[ 2 ];
670 int in[2]; 674 int in[ 2 ];
671 int err[2]; 675 int err[ 2 ];
672 676
673 /** 677 /**
674 * The socket notifiers for the above socket descriptors. 678 * The socket notifiers for the above socket descriptors.
@@ -688,14 +692,14 @@ protected:
688 * child process's stdout to the respective buffer and emits the signal 692 * child process's stdout to the respective buffer and emits the signal
689 * "@ref receivedStderr". 693 * "@ref receivedStderr".
690 */ 694 */
691 int childOutput(int fdno); 695 int childOutput( int fdno );
692 696
693 /** 697 /**
694 * Called by "slotChildOutput" this function copies data arriving from the 698 * Called by "slotChildOutput" this function copies data arriving from the
695 * child process's stdout to the respective buffer and emits the signal 699 * child process's stdout to the respective buffer and emits the signal
696 * "@ref receivedStderr" 700 * "@ref receivedStderr"
697 */ 701 */
698 int childError(int fdno); 702 int childError( int fdno );
699 703
700 // information about the data that has to be sent to the child: 704 // information about the data that has to be sent to the child:
701 705
@@ -709,7 +713,6 @@ protected:
709 */ 713 */
710 friend class OProcessController; 714 friend class OProcessController;
711 715
712
713private: 716private:
714 /** 717 /**
715 * Searches for a valid shell. 718 * Searches for a valid shell.
@@ -729,7 +732,7 @@ private:
729 * Used by @ref searchShell in order to find out whether the shell found 732 * Used by @ref searchShell in order to find out whether the shell found
730 * is actually executable at all. 733 * is actually executable at all.
731 */ 734 */
732 bool isExecutable(const QCString &filename); 735 bool isExecutable( const QCString &filename );
733 736
734 // Disallow assignment and copy-construction 737 // Disallow assignment and copy-construction
735 OProcess( const OProcess& ); 738 OProcess( const OProcess& );
@@ -737,11 +740,8 @@ private:
737 740
738private: 741private:
739 void init ( ); 742 void init ( );
740
741 OProcessPrivate *d; 743 OProcessPrivate *d;
742}; 744};
743 745
744
745
746#endif 746#endif
747 747