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.cpp93
1 files changed, 46 insertions, 47 deletions
diff --git a/core/launcher/qprocess_unix.cpp b/core/launcher/qprocess_unix.cpp
index 19a8c93..d62e4e6 100644
--- a/core/launcher/qprocess_unix.cpp
+++ b/core/launcher/qprocess_unix.cpp
@@ -1,80 +1,79 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21//#include "qplatformdefs.h"
22
23// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. 21// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED.
24#if defined(connect) 22#if defined(connect)
25#undef connect 23#undef connect
26#endif 24#endif
27 25
28#include "qprocess.h" 26#include "qprocess.h"
29 27
30#ifndef QT_NO_PROCESS 28/* OPIE */
29#include <opie2/odebug.h>
30using namespace Opie::Core;
31 31
32#include "qapplication.h" 32/* QT */
33#include "qqueue.h" 33#ifndef QT_NO_PROCESS
34#include "qlist.h" 34#include <qapplication.h>
35#include "qsocketnotifier.h" 35#include <qqueue.h>
36#include "qtimer.h" 36#include <qlist.h>
37#include "qregexp.h" 37#include <qsocketnotifier.h>
38#include <qtimer.h>
39#include <qregexp.h>
38 40
39#include "qcleanuphandler_p.h" 41#include "qcleanuphandler_p.h"
40 42
43/* STD */
41#include <stdlib.h> 44#include <stdlib.h>
42
43// ### FOR Qt 2.3 compat
44#include <unistd.h> 45#include <unistd.h>
45#include <signal.h> 46#include <signal.h>
46#include <sys/socket.h> 47#include <sys/socket.h>
47#include <sys/ioctl.h> 48#include <sys/ioctl.h>
48#include <sys/wait.h> 49#include <sys/wait.h>
49#include <sys/fcntl.h> 50#include <sys/fcntl.h>
50 51#include <sys/resource.h>
51#include <errno.h> 52#include <errno.h>
52
53#ifdef Q_OS_MACX 53#ifdef Q_OS_MACX
54#include <sys/time.h> 54#include <sys/time.h>
55#endif 55#endif
56#include <sys/resource.h>
57 56
58#ifdef __MIPSEL__ 57#ifdef __MIPSEL__
59# ifndef SOCK_DGRAM 58# ifndef SOCK_DGRAM
60# define SOCK_DGRAM 1 59# define SOCK_DGRAM 1
61# endif 60# endif
62# ifndef SOCK_STREAM 61# ifndef SOCK_STREAM
63# define SOCK_STREAM 2 62# define SOCK_STREAM 2
64# endif 63# endif
65#endif 64#endif
66 65
67//#define QT_QPROCESS_DEBUG 66//#define QT_QPROCESS_DEBUG
68 67
69 68
70#ifdef Q_C_CALLBACKS 69#ifdef Q_C_CALLBACKS
71extern "C" { 70extern "C" {
72#endif // Q_C_CALLBACKS 71#endif // Q_C_CALLBACKS
73 72
74#define QT_SIGNAL_RETTYPE void 73#define QT_SIGNAL_RETTYPE void
75#define QT_SIGNAL_ARGS int 74#define QT_SIGNAL_ARGS int
76#define QT_SIGNAL_IGNORE SIG_IGN 75#define QT_SIGNAL_IGNORE SIG_IGN
77 76
78 QT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS); 77 QT_SIGNAL_RETTYPE qt_C_sigchldHnd(QT_SIGNAL_ARGS);
79 QT_SIGNAL_RETTYPE qt_C_sigpipeHnd(QT_SIGNAL_ARGS); 78 QT_SIGNAL_RETTYPE qt_C_sigpipeHnd(QT_SIGNAL_ARGS);
80 79
@@ -111,58 +110,58 @@ public:
111 110
112 static QProcessManager *procManager; 111 static QProcessManager *procManager;
113}; 112};
114 113
115 114
116/*********************************************************************** 115/***********************************************************************
117 * 116 *
118 * QProc 117 * QProc
119 * 118 *
120 **********************************************************************/ 119 **********************************************************************/
121/* 120/*
122 The class QProcess does not necessarily map exactly to the running 121 The class QProcess does not necessarily map exactly to the running
123 child processes: if the process is finished, the QProcess class may still be 122 child processes: if the process is finished, the QProcess class may still be
124 there; furthermore a user can use QProcess to start more than one process. 123 there; furthermore a user can use QProcess to start more than one process.
125 124
126 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
127 directly to a running child process. 126 directly to a running child process.
128*/ 127*/
129class QProc 128class QProc
130{ 129{
131public: 130public:
132 QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc) 131 QProc( pid_t p, QProcess *proc=0 ) : pid(p), process(proc)
133 { 132 {
134#if defined(QT_QPROCESS_DEBUG) 133#if defined(QT_QPROCESS_DEBUG)
135 qDebug( "QProc: Constructor for pid %d and QProcess %p", pid, process ); 134 odebug << "QProc: Constructor for pid " << pid << " and QProcess " << process << "" << oendl;
136#endif 135#endif
137 socketStdin = 0; 136 socketStdin = 0;
138 socketStdout = 0; 137 socketStdout = 0;
139 socketStderr = 0; 138 socketStderr = 0;
140 } 139 }
141 ~QProc() 140 ~QProc()
142 { 141 {
143#if defined(QT_QPROCESS_DEBUG) 142#if defined(QT_QPROCESS_DEBUG)
144 qDebug( "QProc: Destructor for pid %d and QProcess %p", pid, process ); 143 odebug << "QProc: Destructor for pid " << pid << " and QProcess " << process << "" << oendl;
145#endif 144#endif
146 if ( process != 0 ) { 145 if ( process != 0 ) {
147 if ( process->d->notifierStdin ) 146 if ( process->d->notifierStdin )
148 process->d->notifierStdin->setEnabled( FALSE ); 147 process->d->notifierStdin->setEnabled( FALSE );
149 if ( process->d->notifierStdout ) 148 if ( process->d->notifierStdout )
150 process->d->notifierStdout->setEnabled( FALSE ); 149 process->d->notifierStdout->setEnabled( FALSE );
151 if ( process->d->notifierStderr ) 150 if ( process->d->notifierStderr )
152 process->d->notifierStderr->setEnabled( FALSE ); 151 process->d->notifierStderr->setEnabled( FALSE );
153 process->d->proc = 0; 152 process->d->proc = 0;
154 } 153 }
155 if( socketStdin != 0 ) 154 if( socketStdin != 0 )
156 ::close( socketStdin ); 155 ::close( socketStdin );
157 // ### 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
158 // 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)?
159 if( socketStdout != 0 ) 158 if( socketStdout != 0 )
160 ::close( socketStdout ); 159 ::close( socketStdout );
161 if( socketStderr != 0 ) 160 if( socketStderr != 0 )
162 ::close( socketStderr ); 161 ::close( socketStderr );
163 } 162 }
164 163
165 pid_t pid; 164 pid_t pid;
166 int socketStdin; 165 int socketStdin;
167 int socketStdout; 166 int socketStdout;
168 int socketStderr; 167 int socketStderr;
@@ -192,239 +191,239 @@ public slots:
192 void sigchldHnd( int ); 191 void sigchldHnd( int );
193 192
194public: 193public:
195 struct sigaction oldactChld; 194 struct sigaction oldactChld;
196 struct sigaction oldactPipe; 195 struct sigaction oldactPipe;
197 QList<QProc> *procList; 196 QList<QProc> *procList;
198 int sigchldFd[2]; 197 int sigchldFd[2];
199}; 198};
200 199
201QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager; 200QCleanupHandler<QProcessManager> qprocess_cleanup_procmanager;
202 201
203QProcessManager::QProcessManager() 202QProcessManager::QProcessManager()
204{ 203{
205 procList = new QList<QProc>; 204 procList = new QList<QProc>;
206 procList->setAutoDelete( TRUE ); 205 procList->setAutoDelete( TRUE );
207 206
208 // 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
209 // 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
210 // event reporting. 209 // event reporting.
211 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) { 210 if ( ::socketpair( AF_UNIX, SOCK_STREAM, 0, sigchldFd ) ) {
212 sigchldFd[0] = 0; 211 sigchldFd[0] = 0;
213 sigchldFd[1] = 0; 212 sigchldFd[1] = 0;
214 } else { 213 } else {
215#if defined(QT_QPROCESS_DEBUG) 214#if defined(QT_QPROCESS_DEBUG)
216 qDebug( "QProcessManager: install socket notifier (%d)", sigchldFd[1] ); 215 odebug << "QProcessManager: install socket notifier (" << sigchldFd[1] << ")" << oendl;
217#endif 216#endif
218 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1], 217 QSocketNotifier *sn = new QSocketNotifier( sigchldFd[1],
219 QSocketNotifier::Read, this ); 218 QSocketNotifier::Read, this );
220 connect( sn, SIGNAL(activated(int)), 219 connect( sn, SIGNAL(activated(int)),
221 this, SLOT(sigchldHnd(int)) ); 220 this, SLOT(sigchldHnd(int)) );
222 sn->setEnabled( TRUE ); 221 sn->setEnabled( TRUE );
223 } 222 }
224 223
225 // install a SIGCHLD handler and ignore SIGPIPE 224 // install a SIGCHLD handler and ignore SIGPIPE
226 struct sigaction act; 225 struct sigaction act;
227 226
228#if defined(QT_QPROCESS_DEBUG) 227#if defined(QT_QPROCESS_DEBUG)
229 qDebug( "QProcessManager: install a SIGCHLD handler" ); 228 odebug << "QProcessManager: install a SIGCHLD handler" << oendl;
230#endif 229#endif
231 act.sa_handler = qt_C_sigchldHnd; 230 act.sa_handler = qt_C_sigchldHnd;
232 sigemptyset( &(act.sa_mask) ); 231 sigemptyset( &(act.sa_mask) );
233 sigaddset( &(act.sa_mask), SIGCHLD ); 232 sigaddset( &(act.sa_mask), SIGCHLD );
234 act.sa_flags = SA_NOCLDSTOP; 233 act.sa_flags = SA_NOCLDSTOP;
235#if defined(SA_RESTART) 234#if defined(SA_RESTART)
236 act.sa_flags |= SA_RESTART; 235 act.sa_flags |= SA_RESTART;
237#endif 236#endif
238 if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 ) 237 if ( sigaction( SIGCHLD, &act, &oldactChld ) != 0 )
239 qWarning( "Error installing SIGCHLD handler" ); 238 owarn << "Error installing SIGCHLD handler" << oendl;
240 239
241#if defined(QT_QPROCESS_DEBUG) 240#if defined(QT_QPROCESS_DEBUG)
242 qDebug( "QProcessManager: install a SIGPIPE handler (SIG_IGN)" ); 241 odebug << "QProcessManager: install a SIGPIPE handler (SIG_IGN)" << oendl;
243#endif 242#endif
244 /* 243 /*
245 Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround 244 Using qt_C_sigpipeHnd rather than SIG_IGN is a workaround
246 for a strange problem where GNU tar (called by backuprestore) 245 for a strange problem where GNU tar (called by backuprestore)
247 would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd 246 would hang on filesystem-full. Strangely, the qt_C_sigpipeHnd
248 is never even called, yet this avoids the hang. 247 is never even called, yet this avoids the hang.
249 */ 248 */
250 act.sa_handler = qt_C_sigpipeHnd; 249 act.sa_handler = qt_C_sigpipeHnd;
251 sigemptyset( &(act.sa_mask) ); 250 sigemptyset( &(act.sa_mask) );
252 sigaddset( &(act.sa_mask), SIGPIPE ); 251 sigaddset( &(act.sa_mask), SIGPIPE );
253 act.sa_flags = 0; 252 act.sa_flags = 0;
254 if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 ) 253 if ( sigaction( SIGPIPE, &act, &oldactPipe ) != 0 )
255 qWarning( "Error installing SIGPIPE handler" ); 254 owarn << "Error installing SIGPIPE handler" << oendl;
256} 255}
257 256
258QProcessManager::~QProcessManager() 257QProcessManager::~QProcessManager()
259{ 258{
260 delete procList; 259 delete procList;
261 260
262 if ( sigchldFd[0] != 0 ) 261 if ( sigchldFd[0] != 0 )
263 ::close( sigchldFd[0] ); 262 ::close( sigchldFd[0] );
264 if ( sigchldFd[1] != 0 ) 263 if ( sigchldFd[1] != 0 )
265 ::close( sigchldFd[1] ); 264 ::close( sigchldFd[1] );
266 265
267 // restore SIGCHLD handler 266 // restore SIGCHLD handler
268#if defined(QT_QPROCESS_DEBUG) 267#if defined(QT_QPROCESS_DEBUG)
269 qDebug( "QProcessManager: restore old sigchild handler" ); 268 odebug << "QProcessManager: restore old sigchild handler" << oendl;
270#endif 269#endif
271 if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 ) 270 if ( sigaction( SIGCHLD, &oldactChld, 0 ) != 0 )
272 qWarning( "Error restoring SIGCHLD handler" ); 271 owarn << "Error restoring SIGCHLD handler" << oendl;
273 272
274#if defined(QT_QPROCESS_DEBUG) 273#if defined(QT_QPROCESS_DEBUG)
275 qDebug( "QProcessManager: restore old sigpipe handler" ); 274 odebug << "QProcessManager: restore old sigpipe handler" << oendl;
276#endif 275#endif
277 if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 ) 276 if ( sigaction( SIGPIPE, &oldactPipe, 0 ) != 0 )
278 qWarning( "Error restoring SIGPIPE handler" ); 277 owarn << "Error restoring SIGPIPE handler" << oendl;
279} 278}
280 279
281void QProcessManager::append( QProc *p ) 280void QProcessManager::append( QProc *p )
282{ 281{
283 procList->append( p ); 282 procList->append( p );
284#if defined(QT_QPROCESS_DEBUG) 283#if defined(QT_QPROCESS_DEBUG)
285 qDebug( "QProcessManager: append process (procList.count(): %d)", procList->count() ); 284 odebug << "QProcessManager: append process (procList.count(): " << procList->count() << ")" << oendl;
286#endif 285#endif
287} 286}
288 287
289void QProcessManager::remove( QProc *p ) 288void QProcessManager::remove( QProc *p )
290{ 289{
291 procList->remove( p ); 290 procList->remove( p );
292#if defined(QT_QPROCESS_DEBUG) 291#if defined(QT_QPROCESS_DEBUG)
293 qDebug( "QProcessManager: remove process (procList.count(): %d)", procList->count() ); 292 odebug << "QProcessManager: remove process (procList.count(): " << procList->count() << ")" << oendl;
294#endif 293#endif
295 cleanup(); 294 cleanup();
296} 295}
297 296
298void QProcessManager::cleanup() 297void QProcessManager::cleanup()
299{ 298{
300 if ( procList->count() == 0 ) { 299 if ( procList->count() == 0 ) {
301 QTimer::singleShot( 0, this, SLOT(removeMe()) ); 300 QTimer::singleShot( 0, this, SLOT(removeMe()) );
302 } 301 }
303} 302}
304 303
305void QProcessManager::removeMe() 304void QProcessManager::removeMe()
306{ 305{
307 if ( procList->count() == 0 ) { 306 if ( procList->count() == 0 ) {
308 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager ); 307 qprocess_cleanup_procmanager.remove( &QProcessPrivate::procManager );
309 QProcessPrivate::procManager = 0; 308 QProcessPrivate::procManager = 0;
310 delete this; 309 delete this;
311 } 310 }
312} 311}
313 312
314void QProcessManager::sigchldHnd( int fd ) 313void QProcessManager::sigchldHnd( int fd )
315{ 314{
316 char tmp; 315 char tmp;
317 ::read( fd, &tmp, sizeof(tmp) ); 316 ::read( fd, &tmp, sizeof(tmp) );
318#if defined(QT_QPROCESS_DEBUG) 317#if defined(QT_QPROCESS_DEBUG)
319 qDebug( "QProcessManager::sigchldHnd()" ); 318 odebug << "QProcessManager::sigchldHnd()" << oendl;
320#endif 319#endif
321 QProc *proc; 320 QProc *proc;
322 QProcess *process; 321 QProcess *process;
323 bool removeProc; 322 bool removeProc;
324 proc = procList->first(); 323 proc = procList->first();
325 while ( proc != 0 ) { 324 while ( proc != 0 ) {
326 removeProc = FALSE; 325 removeProc = FALSE;
327 process = proc->process; 326 process = proc->process;
328 QProcess *process_exit_notify=0; 327 QProcess *process_exit_notify=0;
329 if ( process != 0 ) { 328 if ( process != 0 ) {
330 if ( !process->isRunning() ) { 329 if ( !process->isRunning() ) {
331#if defined(QT_QPROCESS_DEBUG) 330#if defined(QT_QPROCESS_DEBUG)
332 qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess available)", proc->pid ); 331 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess available)" << oendl;
333#endif 332#endif
334 // read pending data 333 // read pending data
335 int nbytes = 0; 334 int nbytes = 0;
336 if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { 335 if ( ::ioctl(proc->socketStdout, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
337#if defined(QT_QPROCESS_DEBUG) 336#if defined(QT_QPROCESS_DEBUG)
338 qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stdout", proc->pid, nbytes ); 337 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stdout" << oendl;
339#endif 338#endif
340 process->socketRead( proc->socketStdout ); 339 process->socketRead( proc->socketStdout );
341 } 340 }
342 nbytes = 0; 341 nbytes = 0;
343 if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) { 342 if ( ::ioctl(proc->socketStderr, FIONREAD, (char*)&nbytes)==0 && nbytes>0 ) {
344#if defined(QT_QPROCESS_DEBUG) 343#if defined(QT_QPROCESS_DEBUG)
345 qDebug( "QProcessManager::sigchldHnd() (PID: %d): reading %d bytes of pending data on stderr", proc->pid, nbytes ); 344 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): reading " << nbytes << " bytes of pending data on stderr" << oendl;
346#endif 345#endif
347 process->socketRead( proc->socketStderr ); 346 process->socketRead( proc->socketStderr );
348 } 347 }
349 348
350 if ( process->notifyOnExit ) 349 if ( process->notifyOnExit )
351 process_exit_notify = process; 350 process_exit_notify = process;
352 351
353 removeProc = TRUE; 352 removeProc = TRUE;
354 } 353 }
355 } else { 354 } else {
356 int status; 355 int status;
357 if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) { 356 if ( ::waitpid( proc->pid, &status, WNOHANG ) == proc->pid ) {
358#if defined(QT_QPROCESS_DEBUG) 357#if defined(QT_QPROCESS_DEBUG)
359 qDebug( "QProcessManager::sigchldHnd() (PID: %d): process exited (QProcess not available)", proc->pid ); 358 odebug << "QProcessManager::sigchldHnd() (PID: " << proc->pid << "): process exited (QProcess not available)" << oendl;
360#endif 359#endif
361 removeProc = TRUE; 360 removeProc = TRUE;
362 } 361 }
363 } 362 }
364 if ( removeProc ) { 363 if ( removeProc ) {
365 QProc *oldproc = proc; 364 QProc *oldproc = proc;
366 proc = procList->next(); 365 proc = procList->next();
367 remove( oldproc ); 366 remove( oldproc );
368 } else { 367 } else {
369 proc = procList->next(); 368 proc = procList->next();
370 } 369 }
371 if ( process_exit_notify ) 370 if ( process_exit_notify )
372 emit process_exit_notify->processExited(); 371 emit process_exit_notify->processExited();
373 } 372 }
374} 373}
375 374
376#include "qprocess_unix.moc" 375#include "qprocess_unix.moc"
377 376
378 377
379/*********************************************************************** 378/***********************************************************************
380 * 379 *
381 * QProcessPrivate 380 * QProcessPrivate
382 * 381 *
383 **********************************************************************/ 382 **********************************************************************/
384QProcessManager *QProcessPrivate::procManager = 0; 383QProcessManager *QProcessPrivate::procManager = 0;
385 384
386QProcessPrivate::QProcessPrivate() 385QProcessPrivate::QProcessPrivate()
387{ 386{
388#if defined(QT_QPROCESS_DEBUG) 387#if defined(QT_QPROCESS_DEBUG)
389 qDebug( "QProcessPrivate: Constructor" ); 388 odebug << "QProcessPrivate: Constructor" << oendl;
390#endif 389#endif
391 stdinBufRead = 0; 390 stdinBufRead = 0;
392 391
393 notifierStdin = 0; 392 notifierStdin = 0;
394 notifierStdout = 0; 393 notifierStdout = 0;
395 notifierStderr = 0; 394 notifierStderr = 0;
396 395
397 exitValuesCalculated = FALSE; 396 exitValuesCalculated = FALSE;
398 socketReadCalled = FALSE; 397 socketReadCalled = FALSE;
399 398
400 proc = 0; 399 proc = 0;
401} 400}
402 401
403QProcessPrivate::~QProcessPrivate() 402QProcessPrivate::~QProcessPrivate()
404{ 403{
405#if defined(QT_QPROCESS_DEBUG) 404#if defined(QT_QPROCESS_DEBUG)
406 qDebug( "QProcessPrivate: Destructor" ); 405 odebug << "QProcessPrivate: Destructor" << oendl;
407#endif 406#endif
408 407
409 if ( proc != 0 ) { 408 if ( proc != 0 ) {
410 if ( proc->socketStdin != 0 ) { 409 if ( proc->socketStdin != 0 ) {
411 ::close( proc->socketStdin ); 410 ::close( proc->socketStdin );
412 proc->socketStdin = 0; 411 proc->socketStdin = 0;
413 } 412 }
414 proc->process = 0; 413 proc->process = 0;
415 } 414 }
416 415
417 while ( !stdinBuf.isEmpty() ) { 416 while ( !stdinBuf.isEmpty() ) {
418 delete stdinBuf.dequeue(); 417 delete stdinBuf.dequeue();
419 } 418 }
420 delete notifierStdin; 419 delete notifierStdin;
421 delete notifierStdout; 420 delete notifierStdout;
422 delete notifierStderr; 421 delete notifierStderr;
423} 422}
424 423
425/* 424/*
426 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
427 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.
428 of another child. 427 of another child.
429*/ 428*/
430void QProcessPrivate::closeOpenSocketsForChild() 429void QProcessPrivate::closeOpenSocketsForChild()
@@ -578,85 +577,85 @@ QProcess::~QProcess()
578 {key=value} and the process is started in these environment settings. For 577 {key=value} and the process is started in these environment settings. For
579 convenience, there is a small exception to this rule: under Unix, if \a env 578 convenience, there is a small exception to this rule: under Unix, if \a env
580 does not contain any settings for the environment variable \c 579 does not contain any settings for the environment variable \c
581 LD_LIBRARY_PATH, then this variable is inherited from the starting process; 580 LD_LIBRARY_PATH, then this variable is inherited from the starting process;
582 under Windows the same applies for the enverionment varialbe \c PATH. 581 under Windows the same applies for the enverionment varialbe \c PATH.
583 582
584 Returns TRUE if the process could be started, otherwise FALSE. 583 Returns TRUE if the process could be started, otherwise FALSE.
585 584
586 You can write data to standard input of the process with 585 You can write data to standard input of the process with
587 writeToStdin(), you can close standard input with closeStdin() and you can 586 writeToStdin(), you can close standard input with closeStdin() and you can
588 terminate the process tryTerminate() resp. kill(). 587 terminate the process tryTerminate() resp. kill().
589 588
590 You can call this function even when there already is a running 589 You can call this function even when there already is a running
591 process in this object. In this case, QProcess closes standard input 590 process in this object. In this case, QProcess closes standard input
592 of the old process and deletes pending data, i.e., you loose all 591 of the old process and deletes pending data, i.e., you loose all
593 control over that process, but the process is not terminated. This applies 592 control over that process, but the process is not terminated. This applies
594 also if the process could not be started. (On operating systems that have 593 also if the process could not be started. (On operating systems that have
595 zombie processes, Qt will also wait() on the old process.) 594 zombie processes, Qt will also wait() on the old process.)
596 595
597 \sa launch() closeStdin() 596 \sa launch() closeStdin()
598*/ 597*/
599bool QProcess::start( QStringList *env ) 598bool QProcess::start( QStringList *env )
600{ 599{
601#if defined(QT_QPROCESS_DEBUG) 600#if defined(QT_QPROCESS_DEBUG)
602 qDebug( "QProcess::start()" ); 601 odebug << "QProcess::start()" << oendl;
603#endif 602#endif
604 reset(); 603 reset();
605 604
606 int sStdin[2]; 605 int sStdin[2];
607 int sStdout[2]; 606 int sStdout[2];
608 int sStderr[2]; 607 int sStderr[2];
609 608
610 // open sockets for piping 609 // open sockets for piping
611 if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) { 610 if ( (comms & Stdin) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdin ) == -1 ) {
612 return FALSE; 611 return FALSE;
613 } 612 }
614 if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) { 613 if ( (comms & Stderr) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStderr ) == -1 ) {
615 return FALSE; 614 return FALSE;
616 } 615 }
617 if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) { 616 if ( (comms & Stdout) && ::socketpair( AF_UNIX, SOCK_STREAM, 0, sStdout ) == -1 ) {
618 return FALSE; 617 return FALSE;
619 } 618 }
620 619
621 // 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
622 // started 621 // started
623 int fd[2]; 622 int fd[2];
624 if ( pipe( fd ) < 0 ) { 623 if ( pipe( fd ) < 0 ) {
625 // non critical error, go on 624 // non critical error, go on
626 fd[0] = 0; 625 fd[0] = 0;
627 fd[1] = 0; 626 fd[1] = 0;
628 } 627 }
629 628
630 // construct the arguments for exec 629 // construct the arguments for exec
631 QCString *arglistQ = new QCString[ _arguments.count() + 1 ]; 630 QCString *arglistQ = new QCString[ _arguments.count() + 1 ];
632 const char** arglist = new const char*[ _arguments.count() + 1 ]; 631 const char** arglist = new const char*[ _arguments.count() + 1 ];
633 int i = 0; 632 int i = 0;
634 for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) { 633 for ( QStringList::Iterator it = _arguments.begin(); it != _arguments.end(); ++it ) {
635 arglistQ[i] = (*it).local8Bit(); 634 arglistQ[i] = (*it).local8Bit();
636 arglist[i] = arglistQ[i]; 635 arglist[i] = arglistQ[i];
637#if defined(QT_QPROCESS_DEBUG) 636#if defined(QT_QPROCESS_DEBUG)
638 qDebug( "QProcess::start(): arg %d = %s", i, arglist[i] ); 637 odebug << "QProcess::start(): arg " << i << " = " << arglist[i] << "" << oendl;
639#endif 638#endif
640 i++; 639 i++;
641 } 640 }
642 arglist[i] = 0; 641 arglist[i] = 0;
643 642
644 // Must make sure signal handlers are installed before exec'ing 643 // Must make sure signal handlers are installed before exec'ing
645 // in case the process exits quickly. 644 // in case the process exits quickly.
646 if ( d->procManager == 0 ) { 645 if ( d->procManager == 0 ) {
647 d->procManager = new QProcessManager; 646 d->procManager = new QProcessManager;
648 qprocess_cleanup_procmanager.add( &d->procManager ); 647 qprocess_cleanup_procmanager.add( &d->procManager );
649 } 648 }
650 649
651 // fork and exec 650 // fork and exec
652 QApplication::flushX(); 651 QApplication::flushX();
653 pid_t pid = fork(); 652 pid_t pid = fork();
654 if ( pid == 0 ) { 653 if ( pid == 0 ) {
655 // child 654 // child
656 d->closeOpenSocketsForChild(); 655 d->closeOpenSocketsForChild();
657 if ( comms & Stdin ) { 656 if ( comms & Stdin ) {
658 ::close( sStdin[1] ); 657 ::close( sStdin[1] );
659 ::dup2( sStdin[0], STDIN_FILENO ); 658 ::dup2( sStdin[0], STDIN_FILENO );
660 } 659 }
661 if ( comms & Stdout ) { 660 if ( comms & Stdout ) {
662 ::close( sStdout[0] ); 661 ::close( sStdout[0] );
@@ -778,49 +777,49 @@ bool QProcess::start( QStringList *env )
778 d->proc->socketStdout = sStdout[0]; 777 d->proc->socketStdout = sStdout[0];
779 d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read ); 778 d->notifierStdout = new QSocketNotifier( sStdout[0], QSocketNotifier::Read );
780 connect( d->notifierStdout, SIGNAL(activated(int)), 779 connect( d->notifierStdout, SIGNAL(activated(int)),
781 this, SLOT(socketRead(int)) ); 780 this, SLOT(socketRead(int)) );
782 if ( ioRedirection ) 781 if ( ioRedirection )
783 d->notifierStdout->setEnabled( TRUE ); 782 d->notifierStdout->setEnabled( TRUE );
784 } 783 }
785 if ( comms & Stderr ) { 784 if ( comms & Stderr ) {
786 ::close( sStderr[1] ); 785 ::close( sStderr[1] );
787 d->proc->socketStderr = sStderr[0]; 786 d->proc->socketStderr = sStderr[0];
788 d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read ); 787 d->notifierStderr = new QSocketNotifier( sStderr[0], QSocketNotifier::Read );
789 connect( d->notifierStderr, SIGNAL(activated(int)), 788 connect( d->notifierStderr, SIGNAL(activated(int)),
790 this, SLOT(socketRead(int)) ); 789 this, SLOT(socketRead(int)) );
791 if ( ioRedirection ) 790 if ( ioRedirection )
792 d->notifierStderr->setEnabled( TRUE ); 791 d->notifierStderr->setEnabled( TRUE );
793 } 792 }
794 793
795 // cleanup and return 794 // cleanup and return
796 delete[] arglistQ; 795 delete[] arglistQ;
797 delete[] arglist; 796 delete[] arglist;
798 return TRUE; 797 return TRUE;
799 798
800error: 799error:
801#if defined(QT_QPROCESS_DEBUG) 800#if defined(QT_QPROCESS_DEBUG)
802 qDebug( "QProcess::start(): error starting process" ); 801 odebug << "QProcess::start(): error starting process" << oendl;
803#endif 802#endif
804 if ( d->procManager ) 803 if ( d->procManager )
805 d->procManager->cleanup(); 804 d->procManager->cleanup();
806 if ( comms & Stdin ) { 805 if ( comms & Stdin ) {
807 ::close( sStdin[1] ); 806 ::close( sStdin[1] );
808 ::close( sStdin[0] ); 807 ::close( sStdin[0] );
809 } 808 }
810 if ( comms & Stdout ) { 809 if ( comms & Stdout ) {
811 ::close( sStdout[0] ); 810 ::close( sStdout[0] );
812 ::close( sStdout[1] ); 811 ::close( sStdout[1] );
813 } 812 }
814 if ( comms & Stderr ) { 813 if ( comms & Stderr ) {
815 ::close( sStderr[0] ); 814 ::close( sStderr[0] );
816 ::close( sStderr[1] ); 815 ::close( sStderr[1] );
817 } 816 }
818 ::close( fd[0] ); 817 ::close( fd[0] );
819 ::close( fd[1] ); 818 ::close( fd[1] );
820 delete[] arglistQ; 819 delete[] arglistQ;
821 delete[] arglist; 820 delete[] arglist;
822 return FALSE; 821 return FALSE;
823} 822}
824 823
825 824
826/*! 825/*!
@@ -857,180 +856,180 @@ void QProcess::tryTerminate() const
857 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
858 on cleanup. 857 on cleanup.
859 858
860 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
861 finished. When the process really exited, the signal processExited() is 860 finished. When the process really exited, the signal processExited() is
862 emitted. 861 emitted.
863 862
864 \sa tryTerminate() processExited() 863 \sa tryTerminate() processExited()
865*/ 864*/
866void QProcess::kill() const 865void QProcess::kill() const
867{ 866{
868 if ( d->proc != 0 ) 867 if ( d->proc != 0 )
869 ::kill( d->proc->pid, SIGKILL ); 868 ::kill( d->proc->pid, SIGKILL );
870} 869}
871 870
872/*! 871/*!
873 Returns TRUE if the process is running, otherwise FALSE. 872 Returns TRUE if the process is running, otherwise FALSE.
874 873
875 \sa normalExit() exitStatus() processExited() 874 \sa normalExit() exitStatus() processExited()
876*/ 875*/
877bool QProcess::isRunning() const 876bool QProcess::isRunning() const
878{ 877{
879 if ( d->exitValuesCalculated ) { 878 if ( d->exitValuesCalculated ) {
880#if defined(QT_QPROCESS_DEBUG) 879#if defined(QT_QPROCESS_DEBUG)
881 qDebug( "QProcess::isRunning(): FALSE (already computed)" ); 880 odebug << "QProcess::isRunning(): FALSE (already computed)" << oendl;
882#endif 881#endif
883 return FALSE; 882 return FALSE;
884 } 883 }
885 if ( d->proc == 0 ) 884 if ( d->proc == 0 )
886 return FALSE; 885 return FALSE;
887 int status; 886 int status;
888 if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid ) 887 if ( ::waitpid( d->proc->pid, &status, WNOHANG ) == d->proc->pid )
889 { 888 {
890 // compute the exit values 889 // compute the exit values
891 QProcess *that = (QProcess*)this; // mutable 890 QProcess *that = (QProcess*)this; // mutable
892 that->exitNormal = WIFEXITED( status ) != 0; 891 that->exitNormal = WIFEXITED( status ) != 0;
893 if ( exitNormal ) { 892 if ( exitNormal ) {
894 that->exitStat = (char)WEXITSTATUS( status ); 893 that->exitStat = (char)WEXITSTATUS( status );
895 } 894 }
896 d->exitValuesCalculated = TRUE; 895 d->exitValuesCalculated = TRUE;
897#if defined(QT_QPROCESS_DEBUG) 896#if defined(QT_QPROCESS_DEBUG)
898 qDebug( "QProcess::isRunning() (PID: %d): FALSE", d->proc->pid ); 897 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): FALSE" << oendl;
899#endif 898#endif
900 return FALSE; 899 return FALSE;
901 } 900 }
902#if defined(QT_QPROCESS_DEBUG) 901#if defined(QT_QPROCESS_DEBUG)
903 qDebug( "QProcess::isRunning() (PID: %d): TRUE", d->proc->pid ); 902 odebug << "QProcess::isRunning() (PID: " << d->proc->pid << "): TRUE" << oendl;
904#endif 903#endif
905 return TRUE; 904 return TRUE;
906} 905}
907 906
908/*! 907/*!
909 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
910 or may not read this data. 909 or may not read this data.
911 910
912 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
913 a later point (you have to enter the event loop for that). When all the data 912 a later point (you have to enter the event loop for that). When all the data
914 is written to the process, the signal wroteToStdin() is emitted. This does 913 is written to the process, the signal wroteToStdin() is emitted. This does
915 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
916 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.
917 916
918 \sa wroteToStdin() closeStdin() readStdout() readStderr() 917 \sa wroteToStdin() closeStdin() readStdout() readStderr()
919*/ 918*/
920void QProcess::writeToStdin( const QByteArray& buf ) 919void QProcess::writeToStdin( const QByteArray& buf )
921{ 920{
922#if defined(QT_QPROCESS_DEBUG) 921#if defined(QT_QPROCESS_DEBUG)
923// qDebug( "QProcess::writeToStdin(): write to stdin (%d)", d->socketStdin ); 922// odebug << "QProcess::writeToStdin(): write to stdin (" << d->socketStdin << ")" << oendl;
924#endif 923#endif
925 d->stdinBuf.enqueue( new QByteArray(buf) ); 924 d->stdinBuf.enqueue( new QByteArray(buf) );
926 if ( d->notifierStdin != 0 ) 925 if ( d->notifierStdin != 0 )
927 d->notifierStdin->setEnabled( TRUE ); 926 d->notifierStdin->setEnabled( TRUE );
928} 927}
929 928
930 929
931/*! 930/*!
932 Closes standard input of the process. 931 Closes standard input of the process.
933 932
934 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
935 yet. 934 yet.
936 935
937 \sa wroteToStdin() 936 \sa wroteToStdin()
938*/ 937*/
939void QProcess::closeStdin() 938void QProcess::closeStdin()
940{ 939{
941 if ( d->proc == 0 ) 940 if ( d->proc == 0 )
942 return; 941 return;
943 if ( d->proc->socketStdin !=0 ) { 942 if ( d->proc->socketStdin !=0 ) {
944 while ( !d->stdinBuf.isEmpty() ) { 943 while ( !d->stdinBuf.isEmpty() ) {
945 delete d->stdinBuf.dequeue(); 944 delete d->stdinBuf.dequeue();
946 } 945 }
947 delete d->notifierStdin; 946 delete d->notifierStdin;
948 d->notifierStdin = 0; 947 d->notifierStdin = 0;
949 if ( ::close( d->proc->socketStdin ) != 0 ) { 948 if ( ::close( d->proc->socketStdin ) != 0 ) {
950 qWarning( "Could not close stdin of child process" ); 949 owarn << "Could not close stdin of child process" << oendl;
951 } 950 }
952#if defined(QT_QPROCESS_DEBUG) 951#if defined(QT_QPROCESS_DEBUG)
953 qDebug( "QProcess::closeStdin(): stdin (%d) closed", d->proc->socketStdin ); 952 odebug << "QProcess::closeStdin(): stdin (" << d->proc->socketStdin << ") closed" << oendl;
954#endif 953#endif
955 d->proc->socketStdin = 0; 954 d->proc->socketStdin = 0;
956 } 955 }
957} 956}
958 957
959 958
960/* 959/*
961 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
962 standard output or standard error. 961 standard output or standard error.
963*/ 962*/
964void QProcess::socketRead( int fd ) 963void QProcess::socketRead( int fd )
965{ 964{
966 if ( d->socketReadCalled ) { 965 if ( d->socketReadCalled ) {
967 // the slots that are connected to the readyRead...() signals might 966 // the slots that are connected to the readyRead...() signals might
968 // 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
969 // blocking read otherwise. 968 // blocking read otherwise.
970 return; 969 return;
971 } 970 }
972#if defined(QT_QPROCESS_DEBUG) 971#if defined(QT_QPROCESS_DEBUG)
973 qDebug( "QProcess::socketRead(): %d", fd ); 972 odebug << "QProcess::socketRead(): " << fd << "" << oendl;
974#endif 973#endif
975 if ( fd == 0 ) 974 if ( fd == 0 )
976 return; 975 return;
977 const int bufsize = 4096; 976 const int bufsize = 4096;
978 QByteArray *buffer = 0; 977 QByteArray *buffer = 0;
979 uint oldSize; 978 uint oldSize;
980 int n; 979 int n;
981 if ( fd == d->proc->socketStdout ) { 980 if ( fd == d->proc->socketStdout ) {
982 buffer = &d->bufStdout; 981 buffer = &d->bufStdout;
983 } else if ( fd == d->proc->socketStderr ) { 982 } else if ( fd == d->proc->socketStderr ) {
984 buffer = &d->bufStderr; 983 buffer = &d->bufStderr;
985 } else { 984 } else {
986 // this case should never happen, but just to be safe 985 // this case should never happen, but just to be safe
987 return; 986 return;
988 } 987 }
989 988
990 // read data 989 // read data
991 oldSize = buffer->size(); 990 oldSize = buffer->size();
992 buffer->resize( oldSize + bufsize ); 991 buffer->resize( oldSize + bufsize );
993 n = ::read( fd, buffer->data()+oldSize, bufsize ); 992 n = ::read( fd, buffer->data()+oldSize, bufsize );
994 if ( n > 0 ) 993 if ( n > 0 )
995 buffer->resize( oldSize + n ); 994 buffer->resize( oldSize + n );
996 else 995 else
997 buffer->resize( oldSize ); 996 buffer->resize( oldSize );
998 // eof or error? 997 // eof or error?
999 if ( n == 0 || n == -1 ) { 998 if ( n == 0 || n == -1 ) {
1000 if ( fd == d->proc->socketStdout ) { 999 if ( fd == d->proc->socketStdout ) {
1001#if defined(QT_QPROCESS_DEBUG) 1000#if defined(QT_QPROCESS_DEBUG)
1002 qDebug( "QProcess::socketRead(): stdout (%d) closed", fd ); 1001 odebug << "QProcess::socketRead(): stdout (" << fd << ") closed" << oendl;
1003#endif 1002#endif
1004 d->notifierStdout->setEnabled( FALSE ); 1003 d->notifierStdout->setEnabled( FALSE );
1005 delete d->notifierStdout; 1004 delete d->notifierStdout;
1006 d->notifierStdout = 0; 1005 d->notifierStdout = 0;
1007 ::close( d->proc->socketStdout ); 1006 ::close( d->proc->socketStdout );
1008 d->proc->socketStdout = 0; 1007 d->proc->socketStdout = 0;
1009 return; 1008 return;
1010 } else if ( fd == d->proc->socketStderr ) { 1009 } else if ( fd == d->proc->socketStderr ) {
1011#if defined(QT_QPROCESS_DEBUG) 1010#if defined(QT_QPROCESS_DEBUG)
1012 qDebug( "QProcess::socketRead(): stderr (%d) closed", fd ); 1011 odebug << "QProcess::socketRead(): stderr (" << fd << ") closed" << oendl;
1013#endif 1012#endif
1014 d->notifierStderr->setEnabled( FALSE ); 1013 d->notifierStderr->setEnabled( FALSE );
1015 delete d->notifierStderr; 1014 delete d->notifierStderr;
1016 d->notifierStderr = 0; 1015 d->notifierStderr = 0;
1017 ::close( d->proc->socketStderr ); 1016 ::close( d->proc->socketStderr );
1018 d->proc->socketStderr = 0; 1017 d->proc->socketStderr = 0;
1019 return; 1018 return;
1020 } 1019 }
1021 } 1020 }
1022 // read all data that is available 1021 // read all data that is available
1023 while ( n == bufsize ) { 1022 while ( n == bufsize ) {
1024 oldSize = buffer->size(); 1023 oldSize = buffer->size();
1025 buffer->resize( oldSize + bufsize ); 1024 buffer->resize( oldSize + bufsize );
1026 n = ::read( fd, buffer->data()+oldSize, bufsize ); 1025 n = ::read( fd, buffer->data()+oldSize, bufsize );
1027 if ( n > 0 ) 1026 if ( n > 0 )
1028 buffer->resize( oldSize + n ); 1027 buffer->resize( oldSize + n );
1029 else 1028 else
1030 buffer->resize( oldSize ); 1029 buffer->resize( oldSize );
1031 } 1030 }
1032 1031
1033 d->socketReadCalled = TRUE; 1032 d->socketReadCalled = TRUE;
1034 if ( fd == d->proc->socketStdout ) { 1033 if ( fd == d->proc->socketStdout ) {
1035#if defined(QT_QPROCESS_DEBUG) 1034#if defined(QT_QPROCESS_DEBUG)
1036 qDebug( "QProcess::socketRead(): %d bytes read from stdout (%d)", 1035 qDebug( "QProcess::socketRead(): %d bytes read from stdout (%d)",
@@ -1040,49 +1039,49 @@ void QProcess::socketRead( int fd )
1040 } else if ( fd == d->proc->socketStderr ) { 1039 } else if ( fd == d->proc->socketStderr ) {
1041#if defined(QT_QPROCESS_DEBUG) 1040#if defined(QT_QPROCESS_DEBUG)
1042 qDebug( "QProcess::socketRead(): %d bytes read from stderr (%d)", 1041 qDebug( "QProcess::socketRead(): %d bytes read from stderr (%d)",
1043 buffer->size()-oldSize, fd ); 1042 buffer->size()-oldSize, fd );
1044#endif 1043#endif
1045 emit readyReadStderr(); 1044 emit readyReadStderr();
1046 } 1045 }
1047 d->socketReadCalled = FALSE; 1046 d->socketReadCalled = FALSE;
1048} 1047}
1049 1048
1050 1049
1051/* 1050/*
1052 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
1053 input. 1052 input.
1054*/ 1053*/
1055void QProcess::socketWrite( int fd ) 1054void QProcess::socketWrite( int fd )
1056{ 1055{
1057 if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 ) 1056 if ( fd != d->proc->socketStdin || d->proc->socketStdin == 0 )
1058 return; 1057 return;
1059 if ( d->stdinBuf.isEmpty() ) { 1058 if ( d->stdinBuf.isEmpty() ) {
1060 d->notifierStdin->setEnabled( FALSE ); 1059 d->notifierStdin->setEnabled( FALSE );
1061 return; 1060 return;
1062 } 1061 }
1063#if defined(QT_QPROCESS_DEBUG) 1062#if defined(QT_QPROCESS_DEBUG)
1064 qDebug( "QProcess::socketWrite(): write to stdin (%d)", fd ); 1063 odebug << "QProcess::socketWrite(): write to stdin (" << fd << ")" << oendl;
1065#endif 1064#endif
1066 ssize_t ret = ::write( fd, 1065 ssize_t ret = ::write( fd,
1067 d->stdinBuf.head()->data() + d->stdinBufRead, 1066 d->stdinBuf.head()->data() + d->stdinBufRead,
1068 d->stdinBuf.head()->size() - d->stdinBufRead ); 1067 d->stdinBuf.head()->size() - d->stdinBufRead );
1069 if ( ret > 0 ) 1068 if ( ret > 0 )
1070 d->stdinBufRead += ret; 1069 d->stdinBufRead += ret;
1071 if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) { 1070 if ( d->stdinBufRead == (ssize_t)d->stdinBuf.head()->size() ) {
1072 d->stdinBufRead = 0; 1071 d->stdinBufRead = 0;
1073 delete d->stdinBuf.dequeue(); 1072 delete d->stdinBuf.dequeue();
1074 if ( wroteToStdinConnected && d->stdinBuf.isEmpty() ) 1073 if ( wroteToStdinConnected && d->stdinBuf.isEmpty() )
1075 emit wroteToStdin(); 1074 emit wroteToStdin();
1076 socketWrite( fd ); 1075 socketWrite( fd );
1077 } 1076 }
1078} 1077}
1079 1078
1080/*! 1079/*!
1081 \internal 1080 \internal
1082 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
1083 synchronous manner. 1082 synchronous manner.
1084 1083
1085 This function should probably go into the public API. 1084 This function should probably go into the public API.
1086*/ 1085*/
1087void QProcess::flushStdin() 1086void QProcess::flushStdin()
1088{ 1087{