summaryrefslogtreecommitdiff
path: root/core/launcher/qprocess_unix.cpp
Unidiff
Diffstat (limited to 'core/launcher/qprocess_unix.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/qprocess_unix.cpp646
1 files changed, 323 insertions, 323 deletions
diff --git a/core/launcher/qprocess_unix.cpp b/core/launcher/qprocess_unix.cpp
index 56e1b1d..97c0460 100644
--- a/core/launcher/qprocess_unix.cpp
+++ b/core/launcher/qprocess_unix.cpp
@@ -124,50 +124,50 @@ public:
124 124
125 The helper-class QProc has the semantics that one instance of this class maps 125 The helper-class QProc has the semantics that one instance of this class maps
126 directly to a running child process. 126 directly to a running child process.
127*/ 127*/
128class QProc 128class QProc
129{ 129{
130public: 130public:
131 QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc) 131 QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc)
132 { 132 {
133#if defined(QT_QPROCESS_DEBUG) 133#if defined(QT_QPROCESS_DEBUG)
134 odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl; 134 odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl;
135#endif 135#endif
136 socketStdin = 0; 136 socketStdin = 0;
137 socketStdout = 0; 137 socketStdout = 0;
138 socketStderr = 0; 138 socketStderr = 0;
139 } 139 }
140 ~QProc() 140 ~QProc()
141 { 141 {
142#if defined(QT_QPROCESS_DEBUG) 142#if defined(QT_QPROCESS_DEBUG)
143 odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl; 143 odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl;
144#endif 144#endif
145 if ( process != 0 ) { 145 if ( process != 0 ) {
146 if ( process->d->notifierStdin ) 146 if ( process->d->notifierStdin )
147 process->d->notifierStdin->setEnabled( FALSE ); 147 process->d->notifierStdin->setEnabled( FALSE );
148 if ( process->d->notifierStdout ) 148 if ( process->d->notifierStdout )
149 process->d->notifierStdout->setEnabled( FALSE ); 149 process->d->notifierStdout->setEnabled( FALSE );
150 if ( process->d->notifierStderr ) 150 if ( process->d->notifierStderr )
151 process->d->notifierStderr->setEnabled( FALSE ); 151 process->d->notifierStderr->setEnabled( FALSE );
152 process->d->proc = 0; 152 process->d->proc = 0;
153 } 153 }
154 if( socketStdin != 0 ) 154 if( socketStdin != 0 )
155 ::close( socketStdin ); 155 ::close( socketStdin );
156 // ### close these sockets even on parent exit or is it better only on 156 // ### close these sockets even on parent exit or is it better only on
157 // sigchld (but what do I have to do with them on exit then)? 157 // sigchld (but what do I have to do with them on exit then)?
158 if( socketStdout != 0 ) 158 if( socketStdout != 0 )
159 ::close( socketStdout ); 159 ::close( socketStdout );
160 if( socketStderr != 0 ) 160 if( socketStderr != 0 )
161 ::close( socketStderr ); 161 ::close( socketStderr );
162 } 162 }
163 163
164 pid_t pid; 164 pid_t pid;
165 int socketStdin; 165 int socketStdin;
166 int socketStdout; 166 int socketStdout;
167 int socketStderr; 167 int socketStderr;
168 QProcess *process; 168 QProcess *process;
169}; 169};
170 170
171/*********************************************************************** 171/***********************************************************************
172 * 172 *
173 * QProcessManager 173 * QProcessManager
@@ -199,78 +199,78 @@ public:
199 199
200QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager; 200QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager;
201 201
202QProcessManager::QProcessManager() 202QProcessManager::QProcessManager()
203{ 203{
204 procList = new QList<QProc>; 204 procList = new QList<QProc>;
205 procList->setAutoDelete( TRUE ); 205 procList->setAutoDelete( TRUE );
206 206
207 // The SIGCHLD handler writes to a socket to tell the manager that 207 // The SIGCHLD handler writes to a socket to tell the manager that
208 // something happened. This is done to get the processing in sync with the 208 // something happened. This is done to get the processing in sync with the
209 // event reporting. 209 // event reporting.
210 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) { 210 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
211 sigchldFd[0] = 0; 211 sigchldFd[0] = 0;
212 sigchldFd[1] = 0; 212 sigchldFd[1] = 0;
213 } else { 213 } else {
214#if defined(QT_QPROCESS_DEBUG) 214#if defined(QT_QPROCESS_DEBUG)
215 odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl; 215 odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl;
216#endif 216#endif
217 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1], 217 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1],
218 QSocketNotifier::Read, this ); 218 QSocketNotifier::Read, this );
219 connect( sn, SIGNAL(activated(int)), 219 connect( sn, SIGNAL(activated(int)),
220 this, SLOT(sigchldHnd(int)) ); 220 this, SLOT(sigchldHnd(int)) );
221 sn->setEnabled( TRUE ); 221 sn->setEnabled( TRUE );
222 } 222 }
223 223
224 // install a SIGCHLD handler and ignore SIGPIPE 224 // install a SIGCHLD handler and ignore SIGPIPE
225 struct sigaction act; 225 struct sigaction act;
226 226
227#if defined(QT_QPROCESS_DEBUG) 227#if defined(QT_QPROCESS_DEBUG)
228 odebug << "QProcessManager: install a SIGCHLD handler" << oendl; 228 odebug << "QProcessManager: install a SIGCHLD handler" << oendl;
229#endif 229#endif
230 act.sa_handler = qt_C_sigchldHnd; 230 act.sa_handler = qt_C_sigchldHnd;
231 sigemptyset( &(act.sa_mask) ); 231 sigemptyset( &(act.sa_mask) );
232 sigaddset( &(act.sa_mask), SIGCHLD ); 232 sigaddset( &(act.sa_mask), SIGCHLD );
233 act.sa_flags = SA_NOCLDSTOP; 233 act.sa_flags = SA_NOCLDSTOP;
234#if defined(SA_RESTART) 234#if defined(SA_RESTART)
235 act.sa_flags |= SA_RESTART; 235 act.sa_flags |= SA_RESTART;
236#endif 236#endif
237 if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 ) 237 if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )
238 owarn << "Error installing SIGCHLD handler" << oendl; 238 owarn << "Error installing SIGCHLD handler" << oendl;
239 239
240#if defined(QT_QPROCESS_DEBUG) 240#if defined(QT_QPROCESS_DEBUG)
241 odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl; 241 odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl;
242#endif 242#endif
243 /* 243 /*
244 Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround 244 Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround
245 for a strange problem where GNU tar (called by backuprestore) 245 for a strange problem where GNU tar (called by backuprestore)
246 would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd 246 would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd
247 is never even called, yet this avoids the hang. 247 is never even called, yet this avoids the hang.
248 */ 248 */
249 act.sa_handler = qt_C_sigpipeHnd; 249 act.sa_handler = qt_C_sigpipeHnd;
250 sigemptyset( &(act.sa_mask) ); 250 sigemptyset( &(act.sa_mask) );
251 sigaddset( &(act.sa_mask), SIGPIPE ); 251 sigaddset( &(act.sa_mask), SIGPIPE );
252 act.sa_flags = 0; 252 act.sa_flags = 0;
253 if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 ) 253 if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 )
254 owarn << "Error installing SIGPIPE handler" << oendl; 254 owarn << "Error installing SIGPIPE handler" << oendl;
255} 255}
256 256
257QProcessManager::~QProcessManager() 257QProcessManager::~QProcessManager()
258{ 258{
259 delete procList; 259 delete procList;
260 260
261 if ( sigchldFd[0] != 0 ) 261 if ( sigchldFd[0] != 0 )
262 ::close( sigchldFd[0] ); 262 ::close( sigchldFd[0] );
263 if ( sigchldFd[1] != 0 ) 263 if ( sigchldFd[1] != 0 )
264 ::close( sigchldFd[1] ); 264 ::close( sigchldFd[1] );
265 265
266 // restore SIGCHLD handler 266 // restore SIGCHLD handler
267#if defined(QT_QPROCESS_DEBUG) 267#if defined(QT_QPROCESS_DEBUG)
268 odebug << "QProcessManager: restore old sigchild handler" << oendl; 268 odebug << "QProcessManager: restore old sigchild handler" << oendl;
269#endif 269#endif
270 if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 ) 270 if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )
271 owarn << "Error restoring SIGCHLD handler" << oendl; 271 owarn << "Error restoring SIGCHLD handler" << oendl;
272 272
273#if defined(QT_QPROCESS_DEBUG) 273#if defined(QT_QPROCESS_DEBUG)
274 odebug << "QProcessManager: restore old sigpipe handler" << oendl; 274 odebug << "QProcessManager: restore old sigpipe handler" << oendl;
275#endif 275#endif
276 if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 ) 276 if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )
@@ -288,96 +288,96 @@ void QProcessManager::append( QProc *p )
288void QProcessManager::remove( QProc *p ) 288void QProcessManager::remove( QProc *p )
289{ 289{
290 procList->remove( p ); 290 procList->remove( p );
291#if defined(QT_QPROCESS_DEBUG) 291#if defined(QT_QPROCESS_DEBUG)
292 odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl; 292 odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl;
293#endif 293#endif
294 cleanup(); 294 cleanup();
295} 295}
296 296
297void QProcessManager::cleanup() 297void QProcessManager::cleanup()
298{ 298{
299 if ( procList->count() == 0 ) { 299 if ( procList->count() == 0 ) {
300 QTimer::singleShot( 0, this, SLOT(removeMe()) ); 300 QTimer::singleShot( 0, this, SLOT(removeMe()) );
301 } 301 }
302} 302}
303 303
304void QProcessManager::removeMe() 304void QProcessManager::removeMe()
305{ 305{
306 if ( procList->count() == 0 ) { 306 if ( procList->count() == 0 ) {
307 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager ); 307 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager );
308 QProcessPrivate::procManager = 0; 308 QProcessPrivate::procManager = 0;
309 delete this; 309 delete this;
310 } 310 }
311} 311}
312 312
313void QProcessManager::sigchldHnd( int fd ) 313void QProcessManager::sigchldHnd( int fd )
314{ 314{
315 char tmp; 315 char tmp;
316 ::read( fd, &tmp, sizeof(tmp) ); 316 ::read( fd, &tmp, sizeof(tmp) );
317#if defined(QT_QPROCESS_DEBUG) 317#if defined(QT_QPROCESS_DEBUG)
318 odebug << "QProcessManager::sigchldHnd()" << oendl; 318 odebug << "QProcessManager::sigchldHnd()" << oendl;
319#endif 319#endif
320 QProc *proc; 320 QProc *proc;
321 QProcess *process; 321 QProcess *process;
322 bool removeProc; 322 bool removeProc;
323 proc = procList->first(); 323 proc = procList->first();
324 while ( proc != 0 ) { 324 while ( proc != 0 ) {
325 removeProc = FALSE; 325 removeProc = FALSE;
326 process = proc->process; 326 process = proc->process;
327 QProcess *process_exit_notify=0; 327 QProcess *process_exit_notify=0;
328 if ( process != 0 ) { 328 if ( process != 0 ) {
329 if ( !process->isRunning() ) { 329 if ( !process->isRunning() ) {
330#if defined(QT_QPROCESS_DEBUG) 330#if defined(QT_QPROCESS_DEBUG)
331 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl; 331 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl;
332#endif 332#endif
333 // read pending data 333 // read pending data
334 int nbytes = 0; 334 int nbytes = 0;
335 if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { 335 if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
336#if defined(QT_QPROCESS_DEBUG) 336#if defined(QT_QPROCESS_DEBUG)
337 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl; 337 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl;
338#endif 338#endif
339 process->socketRead( proc->socketStdout ); 339 process->socketRead( proc->socketStdout );
340 } 340 }
341 nbytes = 0; 341 nbytes = 0;
342 if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { 342 if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
343#if defined(QT_QPROCESS_DEBUG) 343#if defined(QT_QPROCESS_DEBUG)
344 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl; 344 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl;
345#endif 345#endif
346 process->socketRead( proc->socketStderr ); 346 process->socketRead( proc->socketStderr );
347 } 347 }
348 348
349 if ( process->notifyOnExit ) 349 if ( process->notifyOnExit )
350 process_exit_notify = process; 350 process_exit_notify = process;
351 351
352 removeProc = TRUE; 352 removeProc = TRUE;
353 } 353 }
354 } else { 354 } else {
355 int status; 355 int status;
356 if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) { 356 if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
357#if defined(QT_QPROCESS_DEBUG) 357#if defined(QT_QPROCESS_DEBUG)
358 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl; 358 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl;
359#endif 359#endif
360 removeProc = TRUE; 360 removeProc = TRUE;
361 } 361 }
362 } 362 }
363 if ( removeProc ) { 363 if ( removeProc ) {
364 QProc *oldproc = proc; 364 QProc *oldproc = proc;
365 proc = procList->next(); 365 proc = procList->next();
366 remove( oldproc ); 366 remove( oldproc );
367 } else { 367 } else {
368 proc = procList->next(); 368 proc = procList->next();
369 } 369 }
370 if ( process_exit_notify ) 370 if ( process_exit_notify )
371 emit process_exit_notify->processExited(); 371 emit process_exit_notify->processExited();
372 } 372 }
373} 373}
374 374
375#include "qprocess_unix.moc" 375#include "qprocess_unix.moc"
376 376
377 377
378/*********************************************************************** 378/***********************************************************************
379 * 379 *
380 * QProcessPrivate 380 * QProcessPrivate
381 * 381 *
382 **********************************************************************/ 382 **********************************************************************/
383QProcessManager *QProcessPrivate::procManager = 0; 383QProcessManager *QProcessPrivate::procManager = 0;
@@ -397,84 +397,84 @@ QProcessPrivate::QProcessPrivate()
397 socketReadCalled = FALSE; 397 socketReadCalled = FALSE;
398 398
399 proc = 0; 399 proc = 0;
400} 400}
401 401
402QProcessPrivate::~QProcessPrivate() 402QProcessPrivate::~QProcessPrivate()
403{ 403{
404#if defined(QT_QPROCESS_DEBUG) 404#if defined(QT_QPROCESS_DEBUG)
405 odebug << "QProcessPrivate: Destructor" << oendl; 405 odebug << "QProcessPrivate: Destructor" << oendl;
406#endif 406#endif
407 407
408 if ( proc != 0 ) { 408 if ( proc != 0 ) {
409 if ( proc->socketStdin != 0 ) { 409 if ( proc->socketStdin != 0 ) {
410 ::close( proc->socketStdin ); 410 ::close( proc->socketStdin );
411 proc->socketStdin = 0; 411 proc->socketStdin = 0;
412 } 412 }
413 proc->process = 0; 413 proc->process = 0;
414 } 414 }
415 415
416 while ( !stdinBuf.isEmpty() ) { 416 while ( !stdinBuf.isEmpty() ) {
417 delete stdinBuf.dequeue(); 417 delete stdinBuf.dequeue();
418 } 418 }
419 delete notifierStdin; 419 delete notifierStdin;
420 delete notifierStdout; 420 delete notifierStdout;
421 delete notifierStderr; 421 delete notifierStderr;
422} 422}
423 423
424/* 424/*
425 Closes all open sockets in the child process that are not needed by the child 425 Closes all open sockets in the child process that are not needed by the child
426 process. Otherwise one child may have an open socket on standard input, etc. 426 process. Otherwise one child may have an open socket on standard input, etc.
427 of another child. 427 of another child.
428*/ 428*/
429void QProcessPrivate::closeOpenSocketsForChild() 429void QProcessPrivate::closeOpenSocketsForChild()
430{ 430{
431 if ( procManager != 0 ) { 431 if ( procManager != 0 ) {
432 if ( procManager->sigchldFd[0] != 0 ) 432 if ( procManager->sigchldFd[0] != 0 )
433 ::close( procManager->sigchldFd[0] ); 433 ::close( procManager->sigchldFd[0] );
434 if ( procManager->sigchldFd[1] != 0 ) 434 if ( procManager->sigchldFd[1] != 0 )
435 ::close( procManager->sigchldFd[1] ); 435 ::close( procManager->sigchldFd[1] );
436 436
437 // close also the sockets from other QProcess instances 437 // close also the sockets from other QProcess instances
438 QProc *proc; 438 QProc *proc;
439 for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) { 439 for ( proc=procManager->procList->first(); proc!=0; proc=procManager->procList->next() ) {
440 ::close( proc->socketStdin ); 440 ::close( proc->socketStdin );
441 ::close( proc->socketStdout ); 441 ::close( proc->socketStdout );
442 ::close( proc->socketStderr ); 442 ::close( proc->socketStderr );
443 } 443 }
444 } 444 }
445} 445}
446 446
447void QProcessPrivate::newProc( pid_t pid, QProcess *process ) 447void QProcessPrivate::newProc( pid_t pid, QProcess *process )
448{ 448{
449 proc = new QProc( pid, process ); 449 proc = new QProc( pid, process );
450 if ( procManager == 0 ) { 450 if ( procManager == 0 ) {
451 procManager = new QProcessManager; 451 procManager = new QProcessManager;
452 qprocess_cleanup_procmanager.add( &procManager ); 452 qprocess_cleanup_procmanager.add( &procManager );
453 } 453 }
454 // the QProcessManager takes care of deleting the QProc instances 454 // the QProcessManager takes care of deleting the QProc instances
455 procManager->append( proc ); 455 procManager->append( proc );
456} 456}
457 457
458/*********************************************************************** 458/***********************************************************************
459 * 459 *
460 * sigchld handler callback 460 * sigchld handler callback
461 * 461 *
462 **********************************************************************/ 462 **********************************************************************/
463QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS ) 463QT_SIGNAL_RETTYPE qt_C_sigchldHnd( QT_SIGNAL_ARGS )
464{ 464{
465 if ( QProcessPrivate::procManager == 0 ) 465 if ( QProcessPrivate::procManager == 0 )
466 return; 466 return;
467 if ( QProcessPrivate::procManager->sigchldFd[0] == 0 ) 467 if ( QProcessPrivate::procManager->sigchldFd[0] == 0 )
468 return; 468 return;
469 469
470 char a = 1; 470 char a = 1;
471 ::write( QProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) ); 471 ::write( QProcessPrivate::procManager->sigchldFd[0], &a, sizeof(a) );
472} 472}
473QT_SIGNAL_RETTYPE qt_C_sigpipeHnd( QT_SIGNAL_ARGS ) 473QT_SIGNAL_RETTYPE qt_C_sigpipeHnd( QT_SIGNAL_ARGS )
474{ 474{
475 // Ignore (but in a way somehow different to SIG_IGN). 475 // Ignore (but in a way somehow different to SIG_IGN).
476} 476}
477 477
478 478
479/*********************************************************************** 479/***********************************************************************
480 * 480 *
@@ -499,62 +499,62 @@ void QProcess::reset()
499{ 499{
500 delete d; 500 delete d;
501 d = new QProcessPrivate(); 501 d = new QProcessPrivate();
502 exitStat = 0; 502 exitStat = 0;
503 exitNormal = FALSE; 503 exitNormal = FALSE;
504 d->bufStdout.resize( 0 ); 504 d->bufStdout.resize( 0 );
505 d->bufStderr.resize( 0 ); 505 d->bufStderr.resize( 0 );
506} 506}
507 507
508QByteArray* QProcess::bufStdout() 508QByteArray* QProcess::bufStdout()
509{ 509{
510 if ( d->proc && d->proc->socketStdout ) { 510 if ( d->proc && d->proc->socketStdout ) {
511 // ### can this cause a blocking behaviour (maybe do a ioctl() to see 511 // ### can this cause a blocking behaviour (maybe do a ioctl() to see
512 // if data is available)? 512 // if data is available)?
513 socketRead( d->proc->socketStdout ); 513 socketRead( d->proc->socketStdout );
514 } 514 }
515 return &d->bufStdout; 515 return &d->bufStdout;
516} 516}
517 517
518QByteArray* QProcess::bufStderr() 518QByteArray* QProcess::bufStderr()
519{ 519{
520 if ( d->proc && d->proc->socketStderr ) { 520 if ( d->proc && d->proc->socketStderr ) {
521 // ### can this cause a blocking behaviour (maybe do a ioctl() to see 521 // ### can this cause a blocking behaviour (maybe do a ioctl() to see
522 // if data is available)? 522 // if data is available)?
523 socketRead( d->proc->socketStderr ); 523 socketRead( d->proc->socketStderr );
524 } 524 }
525 return &d->bufStderr; 525 return &d->bufStderr;
526} 526}
527 527
528void QProcess::consumeBufStdout( int consume ) 528void QProcess::consumeBufStdout( int consume )
529{ 529{
530 uint n = d->bufStdout.size(); 530 uint n = d->bufStdout.size();
531 if ( consume==-1 || (uint)consume >= n ) { 531 if ( consume==-1 || (uint)consume >= n ) {
532 d->bufStdout.resize( 0 ); 532 d->bufStdout.resize( 0 );
533 } else { 533 } else {
534 QByteArray tmp( n - consume ); 534 QByteArray tmp( n - consume );
535 memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume ); 535 memcpy( tmp.data(), d->bufStdout.data()+consume, n-consume );
536 d->bufStdout = tmp; 536 d->bufStdout = tmp;
537 } 537 }
538} 538}
539 539
540void QProcess::consumeBufStderr( int consume ) 540void QProcess::consumeBufStderr( int consume )
541{ 541{
542 uint n = d->bufStderr.size(); 542 uint n = d->bufStderr.size();
543 if ( consume==-1 || (uint)consume >= n ) { 543 if ( consume==-1 || (uint)consume >= n ) {
544 d->bufStderr.resize( 0 ); 544 d->bufStderr.resize( 0 );
545 } else { 545 } else {
546 QByteArray tmp( n - consume ); 546 QByteArray tmp( n - consume );
547 memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume ); 547 memcpy( tmp.data(), d->bufStderr.data()+consume, n-consume );
548 d->bufStderr = tmp; 548 d->bufStderr = tmp;
549 } 549 }
550} 550}
551 551
552/*! 552/*!
553 Destroys the class. 553 Destroys the class.
554 554
555 If the process is running, it is NOT terminated! Standard input, standard 555 If the process is running, it is NOT terminated! Standard input, standard
556 output and standard error of the process are closed. 556 output and standard error of the process are closed.
557 557
558 You can connect the destroyed() signal to the kill() slot, if you want the 558 You can connect the destroyed() signal to the kill() slot, if you want the
559 process to be terminated automatically when the class is destroyed. 559 process to be terminated automatically when the class is destroyed.
560 560
@@ -599,252 +599,252 @@ bool QProcess::start( QStringList *env )
599{ 599{
600#if defined(QT_QPROCESS_DEBUG) 600#if defined(QT_QPROCESS_DEBUG)
601 odebug << "QProcess::start()" << oendl; 601 odebug << "QProcess::start()" << oendl;
602#endif 602#endif
603 reset(); 603 reset();
604 604
605 int sStdin[2]; 605 int sStdin[2];
606 int sStdout[2]; 606 int sStdout[2];
607 int sStderr[2]; 607 int sStderr[2];
608 608
609 // open sockets for piping 609 // open sockets for piping
610 if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) { 610 if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) {
611 return FALSE; 611 return FALSE;
612 } 612 }
613 if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) { 613 if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) {
614 return FALSE; 614 return FALSE;
615 } 615 }
616 if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) { 616 if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) {
617 return FALSE; 617 return FALSE;
618 } 618 }
619 619
620 // the following pipe is only used to determine if the process could be 620 // the following pipe is only used to determine if the process could be
621 // started 621 // started
622 int fd[2]; 622 int fd[2];
623 if ( pipe( fd ) < 0 ) { 623 if ( pipe( fd ) < 0 ) {
624 // non critical error, go on 624 // non critical error, go on
625 fd[0] = 0; 625 fd[0] = 0;
626 fd[1] = 0; 626 fd[1] = 0;
627 } 627 }
628 628
629 // construct the arguments for exec 629 // construct the arguments for exec
630 QCString *arglistQ = new QCString[ _arguments.count() + 1 ]; 630 QCString *arglistQ = new QCString[ _arguments.count() + 1 ];
631 const char** arglist = new const char*[ _arguments.count() + 1 ]; 631 const char** arglist = new const char*[ _arguments.count() + 1 ];
632 int i = 0; 632 int i = 0;
633 for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) { 633 for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) {
634 arglistQ[i] = (*it).local8Bit(); 634 arglistQ[i] = (*it).local8Bit();
635 arglist[i] = arglistQ[i]; 635 arglist[i] = arglistQ[i];
636#if defined(QT_QPROCESS_DEBUG) 636#if defined(QT_QPROCESS_DEBUG)
637 odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl; 637 odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl;
638#endif 638#endif
639 i++; 639 i++;
640 } 640 }
641 arglist[i] = 0; 641 arglist[i] = 0;
642 642
643 // Must make sure signal handlers are installed before exec'ing 643 // Must make sure signal handlers are installed before exec'ing
644 // in case the process exits quickly. 644 // in case the process exits quickly.
645 if ( d->procManager == 0 ) { 645 if ( d->procManager == 0 ) {
646 d->procManager = new QProcessManager; 646 d->procManager = new QProcessManager;
647 qprocess_cleanup_procmanager.add( &d->procManager ); 647 qprocess_cleanup_procmanager.add( &d->procManager );
648 } 648 }
649 649
650 // fork and exec 650 // fork and exec
651 QApplication::flushX(); 651 QApplication::flushX();
652 pid_t pid = fork(); 652 pid_t pid = fork();
653 if ( pid == 0 ) { 653 if ( pid == 0 ) {
654 // child 654 // child
655 d->closeOpenSocketsForChild(); 655 d->closeOpenSocketsForChild();
656 if ( comms & Stdin ) { 656 if ( comms & Stdin ) {
657 ::close( sStdin[1] ); 657 ::close( sStdin[1] );
658 ::dup2( sStdin[0], STDIN_FILENO ); 658 ::dup2( sStdin[0], STDIN_FILENO );
659 } 659 }
660 if ( comms & Stdout ) { 660 if ( comms & Stdout ) {
661 ::close( sStdout[0] ); 661 ::close( sStdout[0] );
662 ::dup2( sStdout[1], STDOUT_FILENO ); 662 ::dup2( sStdout[1], STDOUT_FILENO );
663 } 663 }
664 if ( comms & Stderr ) { 664 if ( comms & Stderr ) {
665 ::close( sStderr[0] ); 665 ::close( sStderr[0] );
666 ::dup2( sStderr[1], STDERR_FILENO ); 666 ::dup2( sStderr[1], STDERR_FILENO );
667 } 667 }
668 if ( comms & DupStderr ) { 668 if ( comms & DupStderr ) {
669 ::dup2( STDOUT_FILENO, STDERR_FILENO ); 669 ::dup2( STDOUT_FILENO, STDERR_FILENO );
670 } 670 }
671#ifndef QT_NO_DIR 671#ifndef QT_NO_DIR
672 ::chdir( workingDir.absPath().latin1() ); 672 ::chdir( workingDir.absPath().latin1() );
673#endif 673#endif
674 if ( fd[0] ) 674 if ( fd[0] )
675 ::close( fd[0] ); 675 ::close( fd[0] );
676 if ( fd[1] ) 676 if ( fd[1] )
677 ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess 677 ::fcntl( fd[1], F_SETFD, FD_CLOEXEC ); // close on exec shows sucess
678 678
679 if ( env == 0 ) { // inherit environment and start process 679 if ( env == 0 ) { // inherit environment and start process
680 ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice 680 ::execvp( arglist[0], (char*const*)arglist ); // ### cast not nice
681 } else { // start process with environment settins as specified in env 681 } else { // start process with environment settins as specified in env
682 // construct the environment for exec 682 // construct the environment for exec
683 int numEntries = env->count(); 683 int numEntries = env->count();
684 bool setLibraryPath = 684 bool setLibraryPath =
685 env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() && 685 env->grep( QRegExp( "^LD_LIBRARY_PATH=" ) ).isEmpty() &&
686 getenv( "LD_LIBRARY_PATH" ) != 0; 686 getenv( "LD_LIBRARY_PATH" ) != 0;
687 if ( setLibraryPath ) 687 if ( setLibraryPath )
688 numEntries++; 688 numEntries++;
689 QCString *envlistQ = new QCString[ numEntries + 1 ]; 689 QCString *envlistQ = new QCString[ numEntries + 1 ];
690 const char** envlist = new const char*[ numEntries + 1 ]; 690 const char** envlist = new const char*[ numEntries + 1 ];
691 int i = 0; 691 int i = 0;
692 if ( setLibraryPath ) { 692 if ( setLibraryPath ) {
693 envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit(); 693 envlistQ[i] = QString( "LD_LIBRARY_PATH=%1" ).arg( getenv( "LD_LIBRARY_PATH" ) ).local8Bit();
694 envlist[i] = envlistQ[i]; 694 envlist[i] = envlistQ[i];
695 i++; 695 i++;
696 } 696 }
697 for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) { 697 for ( QStringList::Iterator it = env->begin(); it != env->end(); ++it ) {
698 envlistQ[i] = (*it).local8Bit(); 698 envlistQ[i] = (*it).local8Bit();
699 envlist[i] = envlistQ[i]; 699 envlist[i] = envlistQ[i];
700 i++; 700 i++;
701 } 701 }
702 envlist[i] = 0; 702 envlist[i] = 0;
703 703
704 // look for the executable in the search path 704 // look for the executable in the search path
705 if ( _arguments.count()>0 && getenv("PATH")!=0 ) { 705 if ( _arguments.count()>0 && getenv("PATH")!=0 ) {
706 QString command = _arguments[0]; 706 QString command = _arguments[0];
707 if ( !command.contains( '/' ) ) { 707 if ( !command.contains( '/' ) ) {
708 QStringList pathList = QStringList::split( ':', getenv( "PATH" ) ); 708 QStringList pathList = QStringList::split( ':', getenv( "PATH" ) );
709 for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) { 709 for (QStringList::Iterator it = pathList.begin(); it != pathList.end(); ++it ) {
710 QString dir = *it; 710 QString dir = *it;
711#ifdef Q_OS_MACX 711#ifdef Q_OS_MACX
712 if(QFile::exists(dir + "/" + command + ".app")) //look in a bundle 712 if(QFile::exists(dir + "/" + command + ".app")) //look in a bundle
713 dir += "/" + command + ".app/Contents/MacOS"; 713 dir += "/" + command + ".app/Contents/MacOS";
714#endif 714#endif
715#ifndef QT_NO_DIR 715#ifndef QT_NO_DIR
716 QFileInfo fileInfo( dir, command ); 716 QFileInfo fileInfo( dir, command );
717#else 717#else
718 QFileInfo fileInfo( dir + "/" + command ); 718 QFileInfo fileInfo( dir + "/" + command );
719#endif 719#endif
720 if ( fileInfo.isExecutable() ) { 720 if ( fileInfo.isExecutable() ) {
721 arglistQ[0] = fileInfo.filePath().local8Bit(); 721 arglistQ[0] = fileInfo.filePath().local8Bit();
722 arglist[0] = arglistQ[0]; 722 arglist[0] = arglistQ[0];
723 break; 723 break;
724 } 724 }
725 } 725 }
726 } 726 }
727 } 727 }
728 ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice 728 ::execve( arglist[0], (char*const*)arglist, (char*const*)envlist ); // ### casts not nice
729 } 729 }
730 if ( fd[1] ) { 730 if ( fd[1] ) {
731 char buf = 0; 731 char buf = 0;
732 ::write( fd[1], &buf, 1 ); 732 ::write( fd[1], &buf, 1 );
733 ::close( fd[1] ); 733 ::close( fd[1] );
734 } 734 }
735 ::exit( -1 ); 735 ::exit( -1 );
736 } else if ( pid == -1 ) { 736 } else if ( pid == -1 ) {
737 // error forking 737 // error forking
738 goto error; 738 goto error;
739 } 739 }
740 740
741 // test if exec was successful 741 // test if exec was successful
742 if ( fd[1] ) 742 if ( fd[1] )
743 ::close( fd[1] ); 743 ::close( fd[1] );
744 if ( fd[0] ) { 744 if ( fd[0] ) {
745 char buf; 745 char buf;
746 for ( ;; ) { 746 for ( ;; ) {
747 int n = ::read( fd[0], &buf, 1 ); 747 int n = ::read( fd[0], &buf, 1 );
748 if ( n==1 ) { 748 if ( n==1 ) {
749 // socket was not closed => error 749 // socket was not closed => error
750 d->proc = 0; 750 d->proc = 0;
751 goto error; 751 goto error;
752 } else if ( n==-1 ) { 752 } else if ( n==-1 ) {
753 if ( errno==EAGAIN || errno==EINTR ) 753 if ( errno==EAGAIN || errno==EINTR )
754 // try it again 754 // try it again
755 continue; 755 continue;
756 } 756 }
757 break; 757 break;
758 } 758 }
759 ::close( fd[0] ); 759 ::close( fd[0] );
760 } 760 }
761 761
762 d->newProc( pid, this ); 762 d->newProc( pid, this );
763 763
764 if ( comms & Stdin ) { 764 if ( comms & Stdin ) {
765 ::close( sStdin[0] ); 765 ::close( sStdin[0] );
766 d->proc->socketStdin = sStdin[1]; 766 d->proc->socketStdin = sStdin[1];
767 d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write ); 767 d->notifierStdin = new QSocketNotifier( sStdin[1], QSocketNotifier::Write );
768 connect( d->notifierStdin, SIGNAL(activated(int)), 768 connect( d->notifierStdin, SIGNAL(activated(int)),
769 this, SLOT(socketWrite(int)) ); 769 this, SLOT(socketWrite(int)) );
770 // setup notifiers for the sockets 770 // setup notifiers for the sockets
771 if ( !d->stdinBuf.isEmpty() ) { 771 if ( !d->stdinBuf.isEmpty() ) {
772 d->notifierStdin->setEnabled( TRUE ); 772 d->notifierStdin->setEnabled( TRUE );
773 } 773 }
774 } 774 }
775 if ( comms & Stdout ) { 775 if ( comms & Stdout ) {
776 ::close( sStdout[1] ); 776 ::close( sStdout[1] );
777 d->proc->socketStdout = sStdout[0]; 777 d->proc->socketStdout = sStdout[0];
778 d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read ); 778 d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read );
779 connect( d->notifierStdout, SIGNAL(activated(int)), 779 connect( d->notifierStdout, SIGNAL(activated(int)),
780 this, SLOT(socketRead(int)) ); 780 this, SLOT(socketRead(int)) );
781 if ( ioRedirection ) 781 if ( ioRedirection )
782 d->notifierStdout->setEnabled( TRUE ); 782 d->notifierStdout->setEnabled( TRUE );
783 } 783 }
784 if ( comms & Stderr ) { 784 if ( comms & Stderr ) {
785 ::close( sStderr[1] ); 785 ::close( sStderr[1] );
786 d->proc->socketStderr = sStderr[0]; 786 d->proc->socketStderr = sStderr[0];
787 d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read ); 787 d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read );
788 connect( d->notifierStderr, SIGNAL(activated(int)), 788 connect( d->notifierStderr, SIGNAL(activated(int)),
789 this, SLOT(socketRead(int)) ); 789 this, SLOT(socketRead(int)) );
790 if ( ioRedirection ) 790 if ( ioRedirection )
791 d->notifierStderr->setEnabled( TRUE ); 791 d->notifierStderr->setEnabled( TRUE );
792 } 792 }
793 793
794 // cleanup and return 794 // cleanup and return
795 delete[] arglistQ; 795 delete[] arglistQ;
796 delete[] arglist; 796 delete[] arglist;
797 return TRUE; 797 return TRUE;
798 798
799error: 799error:
800#if defined(QT_QPROCESS_DEBUG) 800#if defined(QT_QPROCESS_DEBUG)
801 odebug << "QProcess::start(): error starting process" << oendl; 801 odebug << "QProcess::start(): error starting process" << oendl;
802#endif 802#endif
803 if ( d->procManager ) 803 if ( d->procManager )
804 d->procManager->cleanup(); 804 d->procManager->cleanup();
805 if ( comms & Stdin ) { 805 if ( comms & Stdin ) {
806 ::close( sStdin[1] ); 806 ::close( sStdin[1] );
807 ::close( sStdin[0] ); 807 ::close( sStdin[0] );
808 } 808 }
809 if ( comms & Stdout ) { 809 if ( comms & Stdout ) {
810 ::close( sStdout[0] ); 810 ::close( sStdout[0] );
811 ::close( sStdout[1] ); 811 ::close( sStdout[1] );
812 } 812 }
813 if ( comms & Stderr ) { 813 if ( comms & Stderr ) {
814 ::close( sStderr[0] ); 814 ::close( sStderr[0] );
815 ::close( sStderr[1] ); 815 ::close( sStderr[1] );
816 } 816 }
817 ::close( fd[0] ); 817 ::close( fd[0] );
818 ::close( fd[1] ); 818 ::close( fd[1] );
819 delete[] arglistQ; 819 delete[] arglistQ;
820 delete[] arglist; 820 delete[] arglist;
821 return FALSE; 821 return FALSE;
822} 822}
823 823
824 824
825/*! 825/*!
826 Asks the process to terminate. Processes can ignore this wish. If you want to 826 Asks the process to terminate. Processes can ignore this wish. If you want to
827 be sure that the process really terminates, you must use kill() instead. 827 be sure that the process really terminates, you must use kill() instead.
828 828
829 The slot returns immediately: it does not wait until the process has 829 The slot returns immediately: it does not wait until the process has
830 finished. When the process really exited, the signal processExited() is 830 finished. When the process really exited, the signal processExited() is
831 emitted. 831 emitted.
832 832
833 \sa kill() processExited() 833 \sa kill() processExited()
834*/ 834*/
835void QProcess::tryTerminate() const 835void QProcess::tryTerminate() const
836{ 836{
837 if ( d->proc != 0 ) 837 if ( d->proc != 0 )
838 ::kill( d->proc->pid, SIGTERM ); 838 ::kill( d->proc->pid, SIGTERM );
839} 839}
840 840
841/*! 841/*!
842 Terminates the process. This is not a safe way to end a process since the 842 Terminates the process. This is not a safe way to end a process since the
843 process will not be able to do cleanup. tryTerminate() is a safer way to do 843 process will not be able to do cleanup. tryTerminate() is a safer way to do
844 it, but processes might ignore a tryTerminate(). 844 it, but processes might ignore a tryTerminate().
845 845
846 The nice way to end a process and to be sure that it is finished, is doing 846 The nice way to end a process and to be sure that it is finished, is doing
847 something like this: 847 something like this:
848 \code 848 \code
849 process->tryTerminate(); 849 process->tryTerminate();
850 QTimer::singleShot( 5000, process, SLOT( kill() ) ); 850 QTimer::singleShot( 5000, process, SLOT( kill() ) );
@@ -856,56 +856,56 @@ void QProcess::tryTerminate() const
856 cleanup: use a higher value if the process is likely to do heavy computation 856 cleanup: use a higher value if the process is likely to do heavy computation
857 on cleanup. 857 on cleanup.
858 858
859 The slot returns immediately: it does not wait until the process has 859 The slot returns immediately: it does not wait until the process has
860 finished. When the process really exited, the signal processExited() is 860 finished. When the process really exited, the signal processExited() is
861 emitted. 861 emitted.
862 862
863 \sa tryTerminate() processExited() 863 \sa tryTerminate() processExited()
864*/ 864*/
865void QProcess::kill() const 865void QProcess::kill() const
866{ 866{
867 if ( d->proc != 0 ) 867 if ( d->proc != 0 )
868 ::kill( d->proc->pid, SIGKILL ); 868 ::kill( d->proc->pid, SIGKILL );
869} 869}
870 870
871/*! 871/*!
872 Returns TRUE if the process is running, otherwise FALSE. 872 Returns TRUE if the process is running, otherwise FALSE.
873 873
874 \sa normalExit() exitStatus() processExited() 874 \sa normalExit() exitStatus() processExited()
875*/ 875*/
876bool QProcess::isRunning() const 876bool QProcess::isRunning() const
877{ 877{
878 if ( d->exitValuesCalculated ) { 878 if ( d->exitValuesCalculated ) {
879#if defined(QT_QPROCESS_DEBUG) 879#if defined(QT_QPROCESS_DEBUG)
880 odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl; 880 odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl;
881#endif 881#endif
882 return FALSE; 882 return FALSE;
883 } 883 }
884 if ( d->proc == 0 ) 884 if ( d->proc == 0 )
885 return FALSE; 885 return FALSE;
886 int status; 886 int status;
887 if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid ) 887 if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid )
888 { 888 {
889 // compute the exit values 889 // compute the exit values
890 QProcess *that = (QProcess*)this; // mutable 890 QProcess *that = (QProcess*)this; // mutable
891 that->exitNormal = WIFEXITED( status ) != 0; 891 that->exitNormal = WIFEXITED( status ) != 0;
892 if ( exitNormal ) { 892 if ( exitNormal ) {
893 that->exitStat = (char)WEXITSTATUS( status ); 893 that->exitStat = (char)WEXITSTATUS( status );
894 } 894 }
895 d->exitValuesCalculated = TRUE; 895 d->exitValuesCalculated = TRUE;
896#if defined(QT_QPROCESS_DEBUG) 896#if defined(QT_QPROCESS_DEBUG)
897 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl; 897 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl;
898#endif 898#endif
899 return FALSE; 899 return FALSE;
900 } 900 }
901#if defined(QT_QPROCESS_DEBUG) 901#if defined(QT_QPROCESS_DEBUG)
902 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): TRUE" << oendl; 902 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): TRUE" << oendl;
903#endif 903#endif
904 return TRUE; 904 return TRUE;
905} 905}
906 906
907/*! 907/*!
908 Writes the data \a buf to the standard input of the process. The process may 908 Writes the data \a buf to the standard input of the process. The process may
909 or may not read this data. 909 or may not read this data.
910 910
911 This function returns immediately; the QProcess class might write the data at 911 This function returns immediately; the QProcess class might write the data at
@@ -914,174 +914,174 @@ bool QProcess::isRunning() const
914 not mean that the process really read the data, since this class only detects 914 not mean that the process really read the data, since this class only detects
915 when it was able to write the data to the operating system. 915 when it was able to write the data to the operating system.
916 916
917 \sa wroteToStdin() closeStdin() readStdout() readStderr() 917 \sa wroteToStdin() closeStdin() readStdout() readStderr()
918*/ 918*/
919void QProcess::writeToStdin( const QByteArray& buf ) 919void QProcess::writeToStdin( const QByteArray& buf )
920{ 920{
921#if defined(QT_QPROCESS_DEBUG) 921#if defined(QT_QPROCESS_DEBUG)
922// odebug << "QProcess::writeToStdin(): write to stdin (" << d->socketStdin << ")" << oendl; 922// odebug << "QProcess::writeToStdin(): write to stdin (" << d->socketStdin << ")" << oendl;
923#endif 923#endif
924 d->stdinBuf.enqueue( new QByteArray(buf) ); 924 d->stdinBuf.enqueue( new QByteArray(buf) );
925 if ( d->notifierStdin != 0 ) 925 if ( d->notifierStdin != 0 )
926 d->notifierStdin->setEnabled( TRUE ); 926 d->notifierStdin->setEnabled( TRUE );
927} 927}
928 928
929 929
930/*! 930/*!
931 Closes standard input of the process. 931 Closes standard input of the process.
932 932
933 This function also deletes pending data that is not written to standard input 933 This function also deletes pending data that is not written to standard input
934 yet. 934 yet.
935 935
936 \sa wroteToStdin() 936 \sa wroteToStdin()
937*/ 937*/
938void QProcess::closeStdin() 938void QProcess::closeStdin()
939{ 939{
940 if ( d->proc == 0 ) 940 if ( d->proc == 0 )
941 return; 941 return;
942 if ( d->proc->socketStdin !=0 ) { 942 if ( d->proc->socketStdin !=0 ) {
943 while ( !d->stdinBuf.isEmpty() ) { 943 while ( !d->stdinBuf.isEmpty() ) {
944 delete d->stdinBuf.dequeue(); 944 delete d->stdinBuf.dequeue();
945 } 945 }
946 delete d->notifierStdin; 946 delete d->notifierStdin;
947 d->notifierStdin = 0; 947 d->notifierStdin = 0;
948 if ( ::close( d->proc->socketStdin ) != 0 ) { 948 if ( ::close( d->proc->socketStdin ) != 0 ) {
949 owarn << "Could not close stdin of child process" << oendl; 949 owarn << "Could not close stdin of child process" << oendl;
950 } 950 }
951#if defined(QT_QPROCESS_DEBUG) 951#if defined(QT_QPROCESS_DEBUG)
952 odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl; 952 odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl;
953#endif 953#endif
954 d->proc->socketStdin = 0; 954 d->proc->socketStdin = 0;
955 } 955 }
956} 956}
957 957
958 958
959/* 959/*
960 This private slot is called when the process has outputted data to either 960 This private slot is called when the process has outputted data to either
961 standard output or standard error. 961 standard output or standard error.
962*/ 962*/
963void QProcess::socketRead( int fd ) 963void QProcess::socketRead( int fd )
964{ 964{
965 if ( d->socketReadCalled ) { 965 if ( d->socketReadCalled ) {
966 // the slots that are connected to the readyRead...() signals might 966 // the slots that are connected to the readyRead...() signals might
967 // trigger a recursive call of socketRead(). Avoid this since you get a 967 // trigger a recursive call of socketRead(). Avoid this since you get a
968 // blocking read otherwise. 968 // blocking read otherwise.
969 return; 969 return;
970 } 970 }
971#if defined(QT_QPROCESS_DEBUG) 971#if defined(QT_QPROCESS_DEBUG)
972 odebug << "QProcess::socketRead(): " << fd << "" << oendl; 972 odebug << "QProcess::socketRead(): " << fd << "" << oendl;
973#endif 973#endif
974 if ( fd == 0 ) 974 if ( fd == 0 )
975 return; 975 return;
976 const int bufsize = 4096; 976 const int bufsize = 4096;
977 QByteArray *buffer = 0; 977 QByteArray *buffer = 0;
978 uint oldSize; 978 uint oldSize;
979 int n; 979 int n;
980 if ( fd == d->proc->socketStdout ) { 980 if ( fd == d->proc->socketStdout ) {
981 buffer = &d->bufStdout; 981 buffer = &d->bufStdout;
982 } else if ( fd == d->proc->socketStderr ) { 982 } else if ( fd == d->proc->socketStderr ) {
983 buffer = &d->bufStderr; 983 buffer = &d->bufStderr;
984 } else { 984 } else {
985 // this case should never happen, but just to be safe 985 // this case should never happen, but just to be safe
986 return; 986 return;
987 } 987 }
988 988
989 // read data 989 // read data
990 oldSize = buffer->size(); 990 oldSize = buffer->size();
991 buffer->resize( oldSize + bufsize ); 991 buffer->resize( oldSize + bufsize );
992 n = ::read( fd, buffer->data()+oldSize, bufsize ); 992 n = ::read( fd, buffer->data()+oldSize, bufsize );
993 if ( n > 0 ) 993 if ( n > 0 )
994 buffer->resize( oldSize + n ); 994 buffer->resize( oldSize + n );
995 else 995 else
996 buffer->resize( oldSize ); 996 buffer->resize( oldSize );
997 // eof or error? 997 // eof or error?
998 if ( n == 0 || n == -1 ) { 998 if ( n == 0 || n == -1 ) {
999 if ( fd == d->proc->socketStdout ) { 999 if ( fd == d->proc->socketStdout ) {
1000#if defined(QT_QPROCESS_DEBUG) 1000#if defined(QT_QPROCESS_DEBUG)
1001 odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl; 1001 odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl;
1002#endif 1002#endif
1003 d->notifierStdout->setEnabled( FALSE ); 1003 d->notifierStdout->setEnabled( FALSE );
1004 delete d->notifierStdout; 1004 delete d->notifierStdout;
1005 d->notifierStdout = 0; 1005 d->notifierStdout = 0;
1006 ::close( d->proc->socketStdout ); 1006 ::close( d->proc->socketStdout );
1007 d->proc->socketStdout = 0; 1007 d->proc->socketStdout = 0;
1008 return; 1008 return;
1009 } else if ( fd == d->proc->socketStderr ) { 1009 } else if ( fd == d->proc->socketStderr ) {
1010#if defined(QT_QPROCESS_DEBUG) 1010#if defined(QT_QPROCESS_DEBUG)
1011 odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl; 1011 odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl;
1012#endif 1012#endif
1013 d->notifierStderr->setEnabled( FALSE ); 1013 d->notifierStderr->setEnabled( FALSE );
1014 delete d->notifierStderr; 1014 delete d->notifierStderr;
1015 d->notifierStderr = 0; 1015 d->notifierStderr = 0;
1016 ::close( d->proc->socketStderr ); 1016 ::close( d->proc->socketStderr );
1017 d->proc->socketStderr = 0; 1017 d->proc->socketStderr = 0;
1018 return; 1018 return;
1019 } 1019 }
1020 } 1020 }
1021 // read all data that is available 1021 // read all data that is available
1022 while ( n == bufsize ) { 1022 while ( n == bufsize ) {
1023 oldSize = buffer->size(); 1023 oldSize = buffer->size();
1024 buffer->resize( oldSize + bufsize ); 1024 buffer->resize( oldSize + bufsize );
1025 n = ::read( fd, buffer->data()+oldSize, bufsize ); 1025 n = ::read( fd, buffer->data()+oldSize, bufsize );
1026 if ( n > 0 ) 1026 if ( n > 0 )
1027 buffer->resize( oldSize + n ); 1027 buffer->resize( oldSize + n );
1028 else 1028 else
1029 buffer->resize( oldSize ); 1029 buffer->resize( oldSize );
1030 } 1030 }
1031 1031
1032 d->socketReadCalled = TRUE; 1032 d->socketReadCalled = TRUE;
1033 if ( fd == d->proc->socketStdout ) { 1033 if ( fd == d->proc->socketStdout ) {
1034#if defined(QT_QPROCESS_DEBUG) 1034#if defined(QT_QPROCESS_DEBUG)
1035 qDebug( "QProcess::socketRead(): %d bytes read from stdout (%d)", 1035 odebug << "QProcess::socketRead(): " << buffer->size()-oldSize << "bytes read from stdout ("
1036 buffer->size()-oldSize, fd ); 1036 << fd << ")" << oendl;
1037#endif 1037#endif
1038 emit readyReadStdout(); 1038 emit readyReadStdout();
1039 } else if ( fd == d->proc->socketStderr ) { 1039 } else if ( fd == d->proc->socketStderr ) {
1040#if defined(QT_QPROCESS_DEBUG) 1040#if defined(QT_QPROCESS_DEBUG)
1041 qDebug( "QProcess::socketRead(): %d bytes read from stderr (%d)", 1041 odebug << "QProcess::socketRead(): " << buffer->size()-oldSize << " bytes read from stderr ("
1042 buffer->size()-oldSize, fd ); 1042 << fd << ")" << oendl;
1043#endif 1043#endif
1044 emit readyReadStderr(); 1044 emit readyReadStderr();
1045 } 1045 }
1046 d->socketReadCalled = FALSE; 1046 d->socketReadCalled = FALSE;
1047} 1047}
1048 1048
1049 1049
1050/* 1050/*
1051 This private slot is called when the process tries to read data from standard 1051 This private slot is called when the process tries to read data from standard
1052 input. 1052 input.
1053*/ 1053*/
1054void QProcess::socketWrite( int fd ) 1054void QProcess::socketWrite( int fd )
1055{ 1055{
1056 if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 ) 1056 if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 )
1057 return; 1057 return;
1058 if ( d->stdinBuf.isEmpty() ) { 1058 if ( d->stdinBuf.isEmpty() ) {
1059 d->notifierStdin->setEnabled( FALSE ); 1059 d->notifierStdin->setEnabled( FALSE );
1060 return; 1060 return;
1061 } 1061 }
1062#if defined(QT_QPROCESS_DEBUG) 1062#if defined(QT_QPROCESS_DEBUG)
1063 odebug << "QProcess::socketWrite(): write to stdin (" << fd << ")" << oendl; 1063 odebug << "QProcess::socketWrite(): write to stdin (" << fd << ")" << oendl;
1064#endif 1064#endif
1065 ssize_t ret = ::write( fd, 1065 ssize_t ret = ::write( fd,
1066 d->stdinBuf.head()->data() + d->stdinBufRead, 1066 d->stdinBuf.head()->data() + d->stdinBufRead,
1067 d->stdinBuf.head()->size() - d->stdinBufRead ); 1067 d->stdinBuf.head()->size() - d->stdinBufRead );
1068 if ( ret > 0 ) 1068 if ( ret > 0 )
1069 d->stdinBufRead += ret; 1069 d->stdinBufRead += ret;
1070 if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) { 1070 if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) {
1071 d->stdinBufRead = 0; 1071 d->stdinBufRead = 0;
1072 delete d->stdinBuf.dequeue(); 1072 delete d->stdinBuf.dequeue();
1073 if ( wroteToStdinConnected && d->stdinBuf.isEmpty() ) 1073 if ( wroteToStdinConnected && d->stdinBuf.isEmpty() )
1074 emit wroteToStdin(); 1074 emit wroteToStdin();
1075 socketWrite( fd ); 1075 socketWrite( fd );
1076 } 1076 }
1077} 1077}
1078 1078
1079/*! 1079/*!
1080 \internal 1080 \internal
1081 Flushes standard input. This is useful if you want to use QProcess in a 1081 Flushes standard input. This is useful if you want to use QProcess in a
1082 synchronous manner. 1082 synchronous manner.
1083 1083
1084 This function should probably go into the public API. 1084 This function should probably go into the public API.
1085*/ 1085*/
1086void QProcess::flushStdin() 1086void QProcess::flushStdin()
1087{ 1087{
@@ -1096,33 +1096,33 @@ void QProcess::timeout()
1096{ 1096{
1097} 1097}
1098 1098
1099 1099
1100/* 1100/*
1101 This private function is used by connectNotify() and disconnectNotify() to 1101 This private function is used by connectNotify() and disconnectNotify() to
1102 change the value of ioRedirection (and related behaviour) 1102 change the value of ioRedirection (and related behaviour)
1103*/ 1103*/
1104void QProcess::setIoRedirection( bool value ) 1104void QProcess::setIoRedirection( bool value )
1105{ 1105{
1106 ioRedirection = value; 1106 ioRedirection = value;
1107 if ( ioRedirection ) { 1107 if ( ioRedirection ) {
1108 if ( d->notifierStdout ) 1108 if ( d->notifierStdout )
1109 d->notifierStdout->setEnabled( TRUE ); 1109 d->notifierStdout->setEnabled( TRUE );
1110 if ( d->notifierStderr ) 1110 if ( d->notifierStderr )
1111 d->notifierStderr->setEnabled( TRUE ); 1111 d->notifierStderr->setEnabled( TRUE );
1112 } else { 1112 } else {
1113 if ( d->notifierStdout ) 1113 if ( d->notifierStdout )
1114 d->notifierStdout->setEnabled( FALSE ); 1114 d->notifierStdout->setEnabled( FALSE );
1115 if ( d->notifierStderr ) 1115 if ( d->notifierStderr )
1116 d->notifierStderr->setEnabled( FALSE ); 1116 d->notifierStderr->setEnabled( FALSE );
1117 } 1117 }
1118} 1118}
1119 1119
1120/* 1120/*
1121 This private function is used by connectNotify() and 1121 This private function is used by connectNotify() and
1122 disconnectNotify() to change the value of notifyOnExit (and related 1122 disconnectNotify() to change the value of notifyOnExit (and related
1123 behaviour) 1123 behaviour)
1124*/ 1124*/
1125void QProcess::setNotifyOnExit( bool value ) 1125void QProcess::setNotifyOnExit( bool value )
1126{ 1126{
1127 notifyOnExit = value; 1127 notifyOnExit = value;
1128} 1128}
@@ -1143,31 +1143,31 @@ void QProcess::setWroteStdinConnected( bool value )
1143 Returns platform dependent information about the process. This can be used 1143 Returns platform dependent information about the process. This can be used
1144 together with platform specific system calls. 1144 together with platform specific system calls.
1145 1145
1146 Under Unix the return value is the PID of the process, or -1 if no process is 1146 Under Unix the return value is the PID of the process, or -1 if no process is
1147 belonging to this object. 1147 belonging to this object.
1148 1148
1149 Under Windows it is a pointer to the \c PROCESS_INFORMATION struct, or 0 if 1149 Under Windows it is a pointer to the \c PROCESS_INFORMATION struct, or 0 if
1150 no process is belonging to this object. 1150 no process is belonging to this object.
1151*/ 1151*/
1152QProcess::PID QProcess::processIdentifier() 1152QProcess::PID QProcess::processIdentifier()
1153{ 1153{
1154 if ( d->proc == 0 ) 1154 if ( d->proc == 0 )
1155 return -1; 1155 return -1;
1156 return d->proc->pid; 1156 return d->proc->pid;
1157} 1157}
1158 1158
1159int QProcess::priority() const 1159int QProcess::priority() const
1160{ 1160{
1161 if ( d->proc ) 1161 if ( d->proc )
1162 return getpriority(PRIO_PROCESS,d->proc->pid); 1162 return getpriority(PRIO_PROCESS,d->proc->pid);
1163 return 0; 1163 return 0;
1164} 1164}
1165 1165
1166void QProcess::setPriority(int p) 1166void QProcess::setPriority(int p)
1167{ 1167{
1168 if ( d->proc ) 1168 if ( d->proc )
1169 setpriority(PRIO_PROCESS,d->proc->pid,p); 1169 setpriority(PRIO_PROCESS,d->proc->pid,p);
1170} 1170}
1171 1171
1172 1172
1173#endif // QT_NO_PROCESS 1173#endif // QT_NO_PROCESS