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,970 +1,915 @@
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>
72#endif 59#endif
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;
116} 95}
117 96
118void OProcess::init ( ) 97void OProcess::init ( )
119{ 98{
120 run_mode = NotifyOnExit; 99 run_mode = NotifyOnExit;
121 runs = false; 100 runs = false;
122 pid_ = 0; 101 pid_ = 0;
123 status = 0; 102 status = 0;
124 keepPrivs = false; 103 keepPrivs = false;
125 innot = 0; 104 innot = 0;
126 outnot = 0; 105 outnot = 0;
127 errnot = 0; 106 errnot = 0;
128 communication = NoCommunication; 107 communication = NoCommunication;
129 input_data = 0; 108 input_data = 0;
130 input_sent = 0; 109 input_sent = 0;
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
192 // child process (if it is running) after removing it from the 165 // child process (if it is running) after removing it from the
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();
205 closeStdout(); 178 closeStdout();
206 closeStderr(); 179 closeStderr();
207 180
208 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess 181 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess
209 delete d; 182 delete d;
210} 183}
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;
218 191
219 // Clean up open fd's and socket notifiers. 192 // Clean up open fd's and socket notifiers.
220 closeStdin(); 193 closeStdin();
221 closeStdout(); 194 closeStdout();
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
263void OProcess::clearArguments() 238void OProcess::clearArguments()
264{ 239{
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
278 } 253 }
279 run_mode = runmode; 254 run_mode = runmode;
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;
329 305
330 QApplication::flushX(); 306 QApplication::flushX();
331 307
332 // WABA: Note that we use fork() and not vfork() because 308 // WABA: Note that we use fork() and not vfork() because
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
503 rv = false; 472 rv = false;
504 return rv; 473 return rv;
505} 474}
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
514 do 483 do
515 { 484 {
516 d1 = input_total - input_sent; 485 d1 = input_total - input_sent;
517 slotSendData ( 0 ); 486 slotSendData ( 0 );
518 d2 = input_total - input_sent; 487 d2 = input_total - input_sent;
519 } 488 }
520 while ( d2 <= d1 ); 489 while ( d2 <= d1 );
521} 490}
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
548 rv = false; 517 rv = false;
549 return rv; 518 return rv;
550} 519}
551 520
552bool OProcess::closeStdout() 521bool 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
565 rv = false; 534 rv = false;
566 return rv; 535 return rv;
567} 536}
568 537
569bool OProcess::closeStderr() 538bool 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
582 rv = false; 551 rv = false;
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;
633 585
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 {
787 int null_fd = open( "/dev/null", O_WRONLY ); 730 int null_fd = open( "/dev/null", O_WRONLY );
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 {
798 int null_fd = open( "/dev/null", O_WRONLY ); 741 int null_fd = open( "/dev/null", O_WRONLY );
799 ok &= dup2( null_fd, STDERR_FILENO ) != -1; 742 ok &= dup2( null_fd, STDERR_FILENO ) != -1;
800 close( null_fd ); 743 close( null_fd );
801 } 744 }
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).
821 // Hence we need to use select. 762 // Hence we need to use select.
822 763
823 // Once one or other of the channels has reached EOF (or given an error) go back 764 // Once one or other of the channels has reached EOF (or given an error) go back
824 // to the usual mechanism. 765 // to the usual mechanism.
825 766
826 int fds_ready = 1; 767 int fds_ready = 1;
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)
852 // * If the process has already exited, we only check 793 // * If the process has already exited, we only check
853 // the available data, we don't wait for more. 794 // the available data, we don't wait for more.
854 // (p_timeout = &timeout, timeout immediately) 795 // (p_timeout = &timeout, timeout immediately)
855 struct timeval timeout; 796 struct timeval timeout;
856 timeout.tv_sec = 0; 797 timeout.tv_sec = 0;
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 }
933 877
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,747 +1,747 @@
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;
43 47
44/** 48/**
45 * Child process invocation, monitoring and control. 49 * Child process invocation, monitoring and control.
46 * 50 *
47 * @sect General usage and features 51 * @sect General usage and features
48 * 52 *
49 *This class allows a KDE and OPIE application to start child processes without having 53 *This class allows a KDE and OPIE application to start child processes without having
50 *to worry about UN*X signal handling issues and zombie process reaping. 54 *to worry about UN*X signal handling issues and zombie process reaping.
51 * 55 *
52 *@see KProcIO 56 *@see KProcIO
53 * 57 *
54 *Basically, this class distinguishes three different ways of running 58 *Basically, this class distinguishes three different ways of running
55 *child processes: 59 *child processes:
56 * 60 *
57 *@li OProcess::DontCare -- The child process is invoked and both the child 61 *@li OProcess::DontCare -- The child process is invoked and both the child
58 *process and the parent process continue concurrently. 62 *process and the parent process continue concurrently.
59 * 63 *
60 *Starting a DontCare child process means that the application is 64 *Starting a DontCare child process means that the application is
61 *not interested in any notification to determine whether the 65 *not interested in any notification to determine whether the
62 *child process has already exited or not. 66 *child process has already exited or not.
63 * 67 *
64 *@li OProcess::NotifyOnExit -- The child process is invoked and both the 68 *@li OProcess::NotifyOnExit -- The child process is invoked and both the
65 *child and the parent process run concurrently. 69 *child and the parent process run concurrently.
66 * 70 *
67 *When the child process exits, the OProcess instance 71 *When the child process exits, the OProcess instance
68 *corresponding to it emits the Qt signal @ref processExited(). 72 *corresponding to it emits the Qt signal @ref processExited().
69 * 73 *
70 *Since this signal is @em not emitted from within a UN*X 74 *Since this signal is @em not emitted from within a UN*X
71 *signal handler, arbitrary function calls can be made. 75 *signal handler, arbitrary function calls can be made.
72 * 76 *
73 *Be aware: When the OProcess objects gets destructed, the child 77 *Be aware: When the OProcess objects gets destructed, the child
74 *process will be killed if it is still running! 78 *process will be killed if it is still running!
75 *This means in particular, that you cannot use a OProcess on the stack 79 *This means in particular, that you cannot use a OProcess on the stack
76 *with OProcess::NotifyOnExit. 80 *with OProcess::NotifyOnExit.
77 * 81 *
78 *@li OProcess::Block -- The child process starts and the parent process 82 *@li OProcess::Block -- The child process starts and the parent process
79 *is suspended until the child process exits. (@em Really not recommended 83 *is suspended until the child process exits. (@em Really not recommended
80 *for programs with a GUI.) 84 *for programs with a GUI.)
81 * 85 *
82 *OProcess also provides several functions for determining the exit status 86 *OProcess also provides several functions for determining the exit status
83 *and the pid of the child process it represents. 87 *and the pid of the child process it represents.
84 * 88 *
85 *Furthermore it is possible to supply command-line arguments to the process 89 *Furthermore it is possible to supply command-line arguments to the process
86 *in a clean fashion (no null -- terminated stringlists and such...) 90 *in a clean fashion (no null -- terminated stringlists and such...)
87 * 91 *
88 *A small usage example: 92 *A small usage example:
89 *<pre> 93 *<pre>
90 *OProcess *proc = new OProcess; 94 *OProcess *proc = new OProcess;
91 * 95 *
92 **proc << "my_executable"; 96 **proc << "my_executable";
93 **proc << "These" << "are" << "the" << "command" << "line" << "args"; 97 **proc << "These" << "are" << "the" << "command" << "line" << "args";
94 *QApplication::connect(proc, SIGNAL(processExited(OProcess *)), 98 *QApplication::connect(proc, SIGNAL(processExited(OProcess *)),
95 * pointer_to_my_object, SLOT(my_objects_slot(OProcess *))); 99 * pointer_to_my_object, SLOT(my_objects_slot(OProcess *)));
96 *proc->start(); 100 *proc->start();
97 *</pre> 101 *</pre>
98 * 102 *
99 *This will start "my_executable" with the commandline arguments "These"... 103 *This will start "my_executable" with the commandline arguments "These"...
100 * 104 *
101 *When the child process exits, the respective Qt signal will be emitted. 105 *When the child process exits, the respective Qt signal will be emitted.
102 * 106 *
103 *@sect Communication with the child process 107 *@sect Communication with the child process
104 * 108 *
105 *OProcess supports communication with the child process through 109 *OProcess supports communication with the child process through
106 *stdin/stdout/stderr. 110 *stdin/stdout/stderr.
107 * 111 *
108 *The following functions are provided for getting data from the child 112 *The following functions are provided for getting data from the child
109 *process or sending data to the child's stdin (For more information, 113 *process or sending data to the child's stdin (For more information,
110 *have a look at the documentation of each function): 114 *have a look at the documentation of each function):
111 * 115 *
112 *@li bool @ref writeStdin(char *buffer, int buflen); 116 *@li bool @ref writeStdin(char *buffer, int buflen);
113 *@li -- Transmit data to the child process's stdin. 117 *@li -- Transmit data to the child process's stdin.
114 * 118 *
115 *@li bool @ref closeStdin(); 119 *@li bool @ref closeStdin();
116 *@li -- Closes the child process's stdin (which causes it to see an feof(stdin)). 120 *@li -- Closes the child process's stdin (which causes it to see an feof(stdin)).
117 *Returns false if you try to close stdin for a process that has been started 121 *Returns false if you try to close stdin for a process that has been started
118 *without a communication channel to stdin. 122 *without a communication channel to stdin.
119 * 123 *
120 *@li bool @ref closeStdout(); 124 *@li bool @ref closeStdout();
121 *@li -- Closes the child process's stdout. 125 *@li -- Closes the child process's stdout.
122 *Returns false if you try to close stdout for a process that has been started 126 *Returns false if you try to close stdout for a process that has been started
123 *without a communication channel to stdout. 127 *without a communication channel to stdout.
124 * 128 *
125 *@li bool @ref closeStderr(); 129 *@li bool @ref closeStderr();
126 *@li -- Closes the child process's stderr. 130 *@li -- Closes the child process's stderr.
127 *Returns false if you try to close stderr for a process that has been started 131 *Returns false if you try to close stderr for a process that has been started
128 *without a communication channel to stderr. 132 *without a communication channel to stderr.
129 * 133 *
130 * 134 *
131 *@sect QT signals: 135 *@sect QT signals:
132 * 136 *
133 *@li void @ref receivedStdout(OProcess *proc, char *buffer, int buflen); 137 *@li void @ref receivedStdout(OProcess *proc, char *buffer, int buflen);
134 *@li void @ref receivedStderr(OProcess *proc, char *buffer, int buflen); 138 *@li void @ref receivedStderr(OProcess *proc, char *buffer, int buflen);
135 *@li -- Indicates that new data has arrived from either the 139 *@li -- Indicates that new data has arrived from either the
136 *child process's stdout or stderr. 140 *child process's stdout or stderr.
137 * 141 *
138 *@li void @ref wroteStdin(OProcess *proc); 142 *@li void @ref wroteStdin(OProcess *proc);
139 *@li -- Indicates that all data that has been sent to the child process 143 *@li -- Indicates that all data that has been sent to the child process
140 *by a prior call to @ref writeStdin() has actually been transmitted to the 144 *by a prior call to @ref writeStdin() has actually been transmitted to the
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
148{ 152{
149 Q_OBJECT 153 Q_OBJECT
150 154
151public: 155public:
152 156
153 /** 157 /**
154 * Modes in which the communication channel can be opened. 158 * Modes in which the communication channel can be opened.
155 * 159 *
156 * If communication for more than one channel is required, 160 * If communication for more than one channel is required,
157 * the values have to be or'ed together, for example to get 161 * the values have to be or'ed together, for example to get
158 * communication with stdout as well as with stdin, you would 162 * communication with stdout as well as with stdin, you would
159 * specify @p Stdin @p | @p Stdout 163 * specify @p Stdin @p | @p Stdout
160 * 164 *
161 * If @p NoRead is specified in conjunction with @p Stdout, 165 * If @p NoRead is specified in conjunction with @p Stdout,
162 * no data is actually read from @p Stdout but only 166 * no data is actually read from @p Stdout but only
163 * the signal @ref childOutput(int fd) is emitted. 167 * the signal @ref childOutput(int fd) is emitted.
164 */ 168 */
165 enum Communication { NoCommunication = 0, Stdin = 1, Stdout = 2, Stderr = 4, 169 enum Communication { NoCommunication = 0, Stdin = 1, Stdout = 2, Stderr = 4,
166 AllOutput = 6, All = 7, 170 AllOutput = 6, All = 7,
167 NoRead }; 171 NoRead };
168 172
169 /** 173 /**
170 * Run-modes for a child process. 174 * Run-modes for a child process.
171 */ 175 */
172 enum RunMode { 176 enum RunMode {
173 /** 177 /**
174 * The application does not receive notifications from the subprocess when 178 * The application does not receive notifications from the subprocess when
175 * it is finished or aborted. 179 * it is finished or aborted.
176 */ 180 */
177 DontCare, 181 DontCare,
178 /** 182 /**
179 * The application is notified when the subprocess dies. 183 * The application is notified when the subprocess dies.
180 */ 184 */
181 NotifyOnExit, 185 NotifyOnExit,
182 /** 186 /**
183 * The application is suspended until the started process is finished. 187 * The application is suspended until the started process is finished.
184 */ 188 */
185 Block }; 189 Block };
186 190
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:
202 * 206 *
203 * If the process is running when the destructor for this class 207 * If the process is running when the destructor for this class
204 * is called, the child process is killed with a SIGKILL, but 208 * is called, the child process is killed with a SIGKILL, but
205 * only if the run mode is not of type @p DontCare. 209 * only if the run mode is not of type @p DontCare.
206 * Processes started as @p DontCare keep running anyway. 210 * Processes started as @p DontCare keep running anyway.
207 */ 211 */
208 virtual ~OProcess(); 212 virtual ~OProcess();
209 213
210 /** 214 /**
211 @deprecated 215 @deprecated
212 216
213 The use of this function is now deprecated. -- Please use the 217 The use of this function is now deprecated. -- Please use the
214 "operator<<" instead of "setExecutable". 218 "operator<<" instead of "setExecutable".
215 219
216 Sets the executable to be started with this OProcess object. 220 Sets the executable to be started with this OProcess object.
217 Returns false if the process is currently running (in that 221 Returns false if the process is currently running (in that
218 case the executable remains unchanged.) 222 case the executable remains unchanged.)
219 223
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 /**
227 * Sets the executable and the command line argument list for this process. 231 * Sets the executable and the command line argument list for this process.
228 * 232 *
229 * For example, doing an "ls -l /usr/local/bin" can be achieved by: 233 * For example, doing an "ls -l /usr/local/bin" can be achieved by:
230 * <pre> 234 * <pre>
231 * OProcess p; 235 * OProcess p;
232 * ... 236 * ...
233 * p << "ls" << "-l" << "/usr/local/bin" 237 * p << "ls" << "-l" << "/usr/local/bin"
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
255 * the "operator<<". 259 * the "operator<<".
256 */ 260 */
257 void clearArguments(); 261 void clearArguments();
258 262
259 /** 263 /**
260 * Starts the process. 264 * Starts the process.
261 * For a detailed description of the 265 * For a detailed description of the
262 * various run modes and communication semantics, have a look at the 266 * various run modes and communication semantics, have a look at the
263 * general description of the OProcess class. 267 * general description of the OProcess class.
264 * 268 *
265 * The following problems could cause this function to 269 * The following problems could cause this function to
266 * return false: 270 * return false:
267 * 271 *
268 * @li The process is already running. 272 * @li The process is already running.
269 * @li The command line argument list is empty. 273 * @li The command line argument list is empty.
270 * @li The starting of the process failed (could not fork). 274 * @li The starting of the process failed (could not fork).
271 * @li The executable was not found. 275 * @li The executable was not found.
272 * 276 *
273 * @param comm Specifies which communication links should be 277 * @param comm Specifies which communication links should be
274 * established to the child process (stdin/stdout/stderr). By default, 278 * established to the child process (stdin/stdout/stderr). By default,
275 * no communication takes place and the respective communication 279 * no communication takes place and the respective communication
276 * signals will never get emitted. 280 * signals will never get emitted.
277 * 281 *
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).
286 * 290 *
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
294 */ 298 */
295 bool isRunning() const; 299 bool isRunning() const;
296 300
297 /** Returns the process id of the process. 301 /** Returns the process id of the process.
298 * 302 *
299 * If it is called after 303 * If it is called after
300 * the process has exited, it returns the process id of the last 304 * the process has exited, it returns the process id of the last
301 * child process that was created by this instance of OProcess. 305 * child process that was created by this instance of OProcess.
302 * 306 *
303 * Calling it before any child process has been started by this 307 * Calling it before any child process has been started by this
304 * OProcess instance causes pid() to return 0. 308 * OProcess instance causes pid() to return 0.
305 **/ 309 **/
306 pid_t pid() const; 310 pid_t pid() const;
307 311
308 /** 312 /**
309 * Suspend processing of data from stdout of the child process. 313 * Suspend processing of data from stdout of the child process.
310 */ 314 */
311 void suspend(); 315 void suspend();
312 316
313 /** 317 /**
314 * Resume processing of data from stdout of the child process. 318 * Resume processing of data from stdout of the child process.
315 */ 319 */
316 void resume(); 320 void resume();
317 321
318 /** 322 /**
319 * @return @p true if the process has already finished and has exited 323 * @return @p true if the process has already finished and has exited
320 * "voluntarily", ie: it has not been killed by a signal. 324 * "voluntarily", ie: it has not been killed by a signal.
321 * 325 *
322 * Note that you should check @ref OProcess::exitStatus() to determine 326 * Note that you should check @ref OProcess::exitStatus() to determine
323 * whether the process completed its task successful or not. 327 * whether the process completed its task successful or not.
324 */ 328 */
325 bool normalExit() const; 329 bool normalExit() const;
326 330
327 /** 331 /**
328 * Returns the exit status of the process. 332 * Returns the exit status of the process.
329 * 333 *
330 * Please use 334 * Please use
331 * @ref OProcess::normalExit() to check whether the process has exited 335 * @ref OProcess::normalExit() to check whether the process has exited
332 * cleanly (i.e., @ref OProcess::normalExit() returns @p true) before calling 336 * cleanly (i.e., @ref OProcess::normalExit() returns @p true) before calling
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 /**
340 * Transmit data to the child process's stdin. 344 * Transmit data to the child process's stdin.
341 * 345 *
342 * OProcess::writeStdin may return false in the following cases: 346 * OProcess::writeStdin may return false in the following cases:
343 * 347 *
344 * @li The process is not currently running. 348 * @li The process is not currently running.
345 * 349 *
346 * @li Communication to stdin has not been requested in the @ref start() call. 350 * @li Communication to stdin has not been requested in the @ref start() call.
347 * 351 *
348 * @li Transmission of data to the child process by a previous call to 352 * @li Transmission of data to the child process by a previous call to
349 * @ref writeStdin() is still in progress. 353 * @ref writeStdin() is still in progress.
350 * 354 *
351 * Please note that the data is sent to the client asynchronously, 355 * Please note that the data is sent to the client asynchronously,
352 * so when this function returns, the data might not have been 356 * so when this function returns, the data might not have been
353 * processed by the child process. 357 * processed by the child process.
354 * 358 *
355 * If all the data has been sent to the client, the signal 359 * If all the data has been sent to the client, the signal
356 * @ref wroteStdin() will be emitted. 360 * @ref wroteStdin() will be emitted.
357 * 361 *
358 * Please note that you must not free "buffer" or call @ref writeStdin() 362 * Please note that you must not free "buffer" or call @ref writeStdin()
359 * again until either a @ref wroteStdin() signal indicates that the 363 * again until either a @ref wroteStdin() signal indicates that the
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
367 /** 371 /**
368 * This causes the stdin file descriptor of the child process to be 372 * This causes the stdin file descriptor of the child process to be
369 * closed indicating an "EOF" to the child. 373 * closed indicating an "EOF" to the child.
370 * 374 *
371 * @return @p false if no communication to the process's stdin 375 * @return @p false if no communication to the process's stdin
372 * had been specified in the call to @ref start(). 376 * had been specified in the call to @ref start().
373 */ 377 */
374 bool closeStdin(); 378 bool closeStdin();
375 379
376 /** 380 /**
377 * This causes the stdout file descriptor of the child process to be 381 * This causes the stdout file descriptor of the child process to be
378 * closed. 382 * closed.
379 * 383 *
380 * @return @p false if no communication to the process's stdout 384 * @return @p false if no communication to the process's stdout
381 * had been specified in the call to @ref start(). 385 * had been specified in the call to @ref start().
382 */ 386 */
383 bool closeStdout(); 387 bool closeStdout();
384 388
385 /** 389 /**
386 * This causes the stderr file descriptor of the child process to be 390 * This causes the stderr file descriptor of the child process to be
387 * closed. 391 * closed.
388 * 392 *
389 * @return @p false if no communication to the process's stderr 393 * @return @p false if no communication to the process's stderr
390 * had been specified in the call to @ref start(). 394 * had been specified in the call to @ref start().
391 */ 395 */
392 bool closeStderr(); 396 bool closeStderr();
393 397
394 /** 398 /**
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
402 * setuid/segid privileges or whether it should keep them 409 * setuid/segid privileges or whether it should keep them
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
410 * setuid/segid privileges or whether it will keep them 417 * setuid/segid privileges or whether it will keep them
411 */ 418 */
412 bool runPrivileged() const; 419 bool runPrivileged() const;
413 420
414 /** 421 /**
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.
429 * The default is to start the command directly. 436 * The default is to start the command directly.
430 * If @p useShell is true @p shell will be used as shell, or 437 * If @p useShell is true @p shell will be used as shell, or
431 * if shell is empty, the standard shell is used. 438 * if shell is empty, the standard shell is used.
432 * @p quote A flag indicating whether to quote the arguments. 439 * @p quote A flag indicating whether to quote the arguments.
433 * 440 *
434 * When using a shell, the caller should make sure that all filenames etc. 441 * When using a shell, the caller should make sure that all filenames etc.
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
442 * the shell processes it properly. This is e. g. necessary for 449 * the shell processes it properly. This is e. g. necessary for
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.
450 * No exit notification is emitted any more for the child process. 457 * No exit notification is emitted any more for the child process.
451 * Deleting the OProcess will no longer kill the child process. 458 * Deleting the OProcess will no longer kill the child process.
452 * Note that the current process remains the parent process of the 459 * Note that the current process remains the parent process of the
453 * child process. 460 * child process.
454 */ 461 */
455 void detach(); 462 void detach();
456 463
457
458
459signals: 464signals:
460 465
461 /** 466 /**
462 * Emitted after the process has terminated when 467 * Emitted after the process has terminated when
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 /**
470 * Emitted, when output from the child process has 475 * Emitted, when output from the child process has
471 * been received on stdout. 476 * been received on stdout.
472 * 477 *
473 * To actually get 478 * To actually get
474 * these signals, the respective communication link (stdout/stderr) 479 * these signals, the respective communication link (stdout/stderr)
475 * has to be turned on in @ref start(). 480 * has to be turned on in @ref start().
476 * 481 *
477 * @param buffer The data received. 482 * @param buffer The data received.
478 * @param buflen The number of bytes that are available. 483 * @param buflen The number of bytes that are available.
479 * 484 *
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
487 * been received on stdout. 492 * been received on stdout.
488 * 493 *
489 * To actually get these signals, the respective communications link 494 * To actually get these signals, the respective communications link
490 * (stdout/stderr) has to be turned on in @ref start() and the 495 * (stdout/stderr) has to be turned on in @ref start() and the
491 * @p NoRead flag should have been passed. 496 * @p NoRead flag should have been passed.
492 * 497 *
493 * You will need to explicitly call resume() after your call to start() 498 * You will need to explicitly call resume() after your call to start()
494 * to begin processing data from the child process's stdout. This is 499 * to begin processing data from the child process's stdout. This is
495 * to ensure that this signal is not emitted when no one is connected 500 * to ensure that this signal is not emitted when no one is connected
496 * to it, otherwise this signal will not be emitted. 501 * to it, otherwise this signal will not be emitted.
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 /**
504 * Emitted, when output from the child process has 509 * Emitted, when output from the child process has
505 * been received on stderr. 510 * been received on stderr.
506 * To actually get 511 * To actually get
507 * these signals, the respective communication link (stdout/stderr) 512 * these signals, the respective communication link (stdout/stderr)
508 * has to be turned on in @ref start(). 513 * has to be turned on in @ref start().
509 * 514 *
510 * @param buffer The data received. 515 * @param buffer The data received.
511 * @param buflen The number of bytes that are available. 516 * @param buflen The number of bytes that are available.
512 * 517 *
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
528 /** 532 /**
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 */
542 546
543 /** 547 /**
544 * Called when another bulk of data can be sent to the child's 548 * Called when another bulk of data can be sent to the child's
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
552 /** 556 /**
553 * Sets up the environment according to the data passed via 557 * Sets up the environment according to the data passed via
554 * setEnvironment(...) 558 * setEnvironment(...)
555 */ 559 */
556 void setupEnvironment(); 560 void setupEnvironment();
557 561
558 /** 562 /**
559 * The list of the process' command line arguments. The first entry 563 * The list of the process' command line arguments. The first entry
560 * in this list is the executable itself. 564 * in this list is the executable itself.
561 */ 565 */
562 QValueList<QCString> arguments; 566 QValueList<QCString> arguments;
563 /** 567 /**
564 * How to run the process (Block, NotifyOnExit, DontCare). You should 568 * How to run the process (Block, NotifyOnExit, DontCare). You should
565 * not modify this data member directly from derived classes. 569 * not modify this data member directly from derived classes.
566 */ 570 */
567 RunMode run_mode; 571 RunMode run_mode;
568 /** 572 /**
569 * true if the process is currently running. You should not 573 * true if the process is currently running. You should not
570 * modify this data member directly from derived classes. For 574 * modify this data member directly from derived classes. For
571 * reading the value of this data member, please use "isRunning()" 575 * reading the value of this data member, please use "isRunning()"
572 * since "runs" will probably be made private in later versions 576 * since "runs" will probably be made private in later versions
573 * of OProcess. 577 * of OProcess.
574 */ 578 */
575 bool runs; 579 bool runs;
576 580
577 /** 581 /**
578 * The PID of the currently running process (see "getPid()"). 582 * The PID of the currently running process (see "getPid()").
579 * You should not modify this data member in derived classes. 583 * You should not modify this data member in derived classes.
580 * Please use "getPid()" instead of directly accessing this 584 * Please use "getPid()" instead of directly accessing this
581 * member function since it will probably be made private in 585 * member function since it will probably be made private in
582 * later versions of OProcess. 586 * later versions of OProcess.
583 */ 587 */
584 pid_t pid_; 588 pid_t pid_;
585 589
586 /** 590 /**
587 * The process' exit status as returned by "waitpid". You should not 591 * The process' exit status as returned by "waitpid". You should not
588 * modify the value of this data member from derived classes. You should 592 * modify the value of this data member from derived classes. You should
589 * rather use @ref exitStatus than accessing this data member directly 593 * rather use @ref exitStatus than accessing this data member directly
590 * since it will probably be made private in further versions of 594 * since it will probably be made private in further versions of
591 * OProcess. 595 * OProcess.
592 */ 596 */
593 int status; 597 int status;
594 598
595 599
596 /** 600 /**
597 * See setRunPrivileged() 601 * See setRunPrivileged()
598 */ 602 */
599 bool keepPrivs; 603 bool keepPrivs;
600 604
601 /* 605 /*
602 Functions for setting up the sockets for communication. 606 Functions for setting up the sockets for communication.
603 setupCommunication 607 setupCommunication
604 -- is called from "start" before "fork"ing. 608 -- is called from "start" before "fork"ing.
605 commSetupDoneP 609 commSetupDoneP
606 -- completes communication socket setup in the parent 610 -- completes communication socket setup in the parent
607 commSetupDoneC 611 commSetupDoneC
608 -- completes communication setup in the child process 612 -- completes communication setup in the child process
609 commClose 613 commClose
610 -- frees all allocated communication resources in the parent 614 -- frees all allocated communication resources in the parent
611 after the process has exited 615 after the process has exited
612 */ 616 */
613 617
614 /** 618 /**
615 * This function is called from "OProcess::start" right before a "fork" takes 619 * This function is called from "OProcess::start" right before a "fork" takes
616 * place. According to 620 * place. According to
617 * the "comm" parameter this function has to initialize the "in", "out" and 621 * the "comm" parameter this function has to initialize the "in", "out" and
618 * "err" data member of OProcess. 622 * "err" data member of OProcess.
619 * 623 *
620 * This function should return 0 if setting the needed communication channels 624 * This function should return 0 if setting the needed communication channels
621 * was successful. 625 * was successful.
622 * 626 *
623 * The default implementation is to create UNIX STREAM sockets for the communication, 627 * The default implementation is to create UNIX STREAM sockets for the communication,
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
631 * will usually do some communications cleanup, like closing the reading end 635 * will usually do some communications cleanup, like closing the reading end
632 * of the "stdin" communication channel. 636 * of the "stdin" communication channel.
633 * 637 *
634 * Furthermore, it must also create the QSocketNotifiers "innot", "outnot" and 638 * Furthermore, it must also create the QSocketNotifiers "innot", "outnot" and
635 * "errnot" and connect their Qt slots to the respective OProcess member functions. 639 * "errnot" and connect their Qt slots to the respective OProcess member functions.
636 * 640 *
637 * For a more detailed explanation, it is best to have a look at the default 641 * For a more detailed explanation, it is best to have a look at the default
638 * implementation of "setupCommunication" in kprocess.cpp. 642 * implementation of "setupCommunication" in kprocess.cpp.
639 */ 643 */
640 virtual int commSetupDoneP(); 644 virtual int commSetupDoneP();
641 645
642 /** 646 /**
643 * Called right after a (successful) fork, but before an "exec" on the child 647 * Called right after a (successful) fork, but before an "exec" on the child
644 * process' side. It usually just closes the unused communication ends of 648 * process' side. It usually just closes the unused communication ends of
645 * "in", "out" and "err" (like the writing end of the "in" communication 649 * "in", "out" and "err" (like the writing end of the "in" communication
646 * channel. 650 * channel.
647 */ 651 */
648 virtual int commSetupDoneC(); 652 virtual int commSetupDoneC();
649 653
650 654
651 /** 655 /**
652 * Immediately called after a process has exited. This function normally 656 * Immediately called after a process has exited. This function normally
653 * calls commClose to close all open communication channels to this 657 * calls commClose to close all open communication channels to this
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
661 * exited. Should be called from "processHasExited". 665 * exited. Should be called from "processHasExited".
662 */ 666 */
663 virtual void commClose(); 667 virtual void commClose();
664 668
665 669
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.
675 */ 679 */
676 QSocketNotifier *innot; 680 QSocketNotifier *innot;
677 QSocketNotifier *outnot; 681 QSocketNotifier *outnot;
678 QSocketNotifier *errnot; 682 QSocketNotifier *errnot;
679 683
680 /** 684 /**
681 * Lists the communication links that are activated for the child 685 * Lists the communication links that are activated for the child
682 * process. Should not be modified from derived classes. 686 * process. Should not be modified from derived classes.
683 */ 687 */
684 Communication communication; 688 Communication communication;
685 689
686 /** 690 /**
687 * Called by "slotChildOutput" this function copies data arriving from the 691 * Called by "slotChildOutput" this function copies data arriving from the
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
702 const char *input_data; // the buffer holding the data 706 const char *input_data; // the buffer holding the data
703 int input_sent; // # of bytes already transmitted 707 int input_sent; // # of bytes already transmitted
704 int input_total; // total length of input_data 708 int input_total; // total length of input_data
705 709
706 /** 710 /**
707 * @ref OProcessController is a friend of OProcess because it has to have 711 * @ref OProcessController is a friend of OProcess because it has to have
708 * access to various data members. 712 * access to various data members.
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.
716 * Here is the algorithm used for finding an executable shell: 719 * Here is the algorithm used for finding an executable shell:
717 * 720 *
718 * @li Try the executable pointed to by the "SHELL" environment 721 * @li Try the executable pointed to by the "SHELL" environment
719 * variable with white spaces stripped off 722 * variable with white spaces stripped off
720 * 723 *
721 * @li If your process runs with uid != euid or gid != egid, a shell 724 * @li If your process runs with uid != euid or gid != egid, a shell
722 * not listed in /etc/shells will not used. 725 * not listed in /etc/shells will not used.
723 * 726 *
724 * @li If no valid shell could be found, "/bin/sh" is used as a last resort. 727 * @li If no valid shell could be found, "/bin/sh" is used as a last resort.
725 */ 728 */
726 QCString searchShell(); 729 QCString searchShell();
727 730
728 /** 731 /**
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& );
736 OProcess& operator= ( const OProcess& ); 739 OProcess& operator= ( const OProcess& );
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