summaryrefslogtreecommitdiff
path: root/libopie/oprocess.cpp
Unidiff
Diffstat (limited to 'libopie/oprocess.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/oprocess.cpp1
1 files changed, 0 insertions, 1 deletions
diff --git a/libopie/oprocess.cpp b/libopie/oprocess.cpp
index 5db2b6c..c19881a 100644
--- a/libopie/oprocess.cpp
+++ b/libopie/oprocess.cpp
@@ -1,568 +1,567 @@
1/* 1/*
2 2
3 $Id$ 3 $Id$
4 4
5 This file is part of the KDE libraries 5 This file is part of the KDE libraries
6 Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at) 6 Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
7 7
8 This library is free software; you can redistribute it and/or 8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public 9 modify it under the terms of the GNU Library General Public
10 License as published by the Free Software Foundation; either 10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version. 11 version 2 of the License, or (at your option) any later version.
12 12
13 This library is distributed in the hope that it will be useful, 13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details. 16 Library General Public License for more details.
17 17
18 You should have received a copy of the GNU Library General Public License 18 You should have received a copy of the GNU Library General Public License
19 along with this library; see the file COPYING.LIB. If not, write to 19 along with this library; see the file COPYING.LIB. If not, write to
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. 21 Boston, MA 02111-1307, USA.
22 22
23*/ 23*/
24 24
25 25
26// 26//
27// KPROCESS -- A class for handling child processes in KDE without 27// KPROCESS -- A class for handling child processes in KDE without
28// having to take care of Un*x specific implementation details 28// having to take care of Un*x specific implementation details
29// 29//
30// version 0.3.1, Jan 8th 1998 30// version 0.3.1, Jan 8th 1998
31// 31//
32// (C) Christian Czezatke 32// (C) Christian Czezatke
33// e9025461@student.tuwien.ac.at 33// e9025461@student.tuwien.ac.at
34// 34//
35// Changes: 35// Changes:
36// 36//
37// March 2nd, 1998: Changed parameter list for KShellProcess: 37// March 2nd, 1998: Changed parameter list for KShellProcess:
38// Arguments are now placed in a single string so that 38// Arguments are now placed in a single string so that
39// <shell> -c <commandstring> is passed to the shell 39// <shell> -c <commandstring> is passed to the shell
40// to make the use of "operator<<" consistent with KProcess 40// to make the use of "operator<<" consistent with KProcess
41// 41//
42// 42//
43// Ported by Holger Freyther 43// Ported by Holger Freyther
44// <zekce> Harlekin: oprocess and say it was ported to Qt by the Opie developers an Qt 2 44// <zekce> Harlekin: oprocess and say it was ported to Qt by the Opie developers an Qt 2
45 45
46 46
47 47
48#include "oprocess.h" 48#include "oprocess.h"
49#define _MAY_INCLUDE_KPROCESSCONTROLLER_ 49#define _MAY_INCLUDE_KPROCESSCONTROLLER_
50#include "oprocctrl.h" 50#include "oprocctrl.h"
51 51
52//#include <config.h> 52//#include <config.h>
53 53
54#include <qfile.h> 54#include <qfile.h>
55#include <qsocketnotifier.h> 55#include <qsocketnotifier.h>
56#include <qregexp.h>
57 56
58#include <sys/time.h> 57#include <sys/time.h>
59#include <sys/types.h> 58#include <sys/types.h>
60#include <sys/stat.h> 59#include <sys/stat.h>
61#include <sys/socket.h> 60#include <sys/socket.h>
62 61
63#include <errno.h> 62#include <errno.h>
64#include <fcntl.h> 63#include <fcntl.h>
65#include <stdlib.h> 64#include <stdlib.h>
66#include <signal.h> 65#include <signal.h>
67#include <stdio.h> 66#include <stdio.h>
68#include <string.h> 67#include <string.h>
69#include <unistd.h> 68#include <unistd.h>
70#ifdef HAVE_SYS_SELECT_H 69#ifdef HAVE_SYS_SELECT_H
71#include <sys/select.h> 70#include <sys/select.h>
72#endif 71#endif
73#ifdef HAVE_INITGROUPS 72#ifdef HAVE_INITGROUPS
74#include <grp.h> 73#include <grp.h>
75#endif 74#endif
76#include <pwd.h> 75#include <pwd.h>
77 76
78#include <qapplication.h> 77#include <qapplication.h>
79#include <qmap.h> 78#include <qmap.h>
80//#include <kdebug.h> 79//#include <kdebug.h>
81 80
82///////////////////////////// 81/////////////////////////////
83// public member functions // 82// public member functions //
84///////////////////////////// 83/////////////////////////////
85 84
86class OProcessPrivate { 85class OProcessPrivate {
87public: 86public:
88 OProcessPrivate() : useShell(false) { } 87 OProcessPrivate() : useShell(false) { }
89 88
90 bool useShell; 89 bool useShell;
91 QMap<QString,QString> env; 90 QMap<QString,QString> env;
92 QString wd; 91 QString wd;
93 QCString shell; 92 QCString shell;
94}; 93};
95 94
96 95
97OProcess::OProcess(QObject *parent, const char *name) 96OProcess::OProcess(QObject *parent, const char *name)
98 : QObject(parent, name) 97 : QObject(parent, name)
99{ 98{
100 init ( ); 99 init ( );
101} 100}
102 101
103OProcess::OProcess(const QString &arg0, QObject *parent, const char *name) 102OProcess::OProcess(const QString &arg0, QObject *parent, const char *name)
104 : QObject(parent, name) 103 : QObject(parent, name)
105{ 104{
106 init ( ); 105 init ( );
107 *this << arg0; 106 *this << arg0;
108} 107}
109 108
110OProcess::OProcess(const QStringList &args, QObject *parent, const char *name) 109OProcess::OProcess(const QStringList &args, QObject *parent, const char *name)
111 : QObject(parent, name) 110 : QObject(parent, name)
112{ 111{
113 init ( ); 112 init ( );
114 *this << args; 113 *this << args;
115} 114}
116 115
117void OProcess::init ( ) 116void OProcess::init ( )
118{ 117{
119 run_mode = NotifyOnExit; 118 run_mode = NotifyOnExit;
120 runs = false; 119 runs = false;
121 pid_ = 0; 120 pid_ = 0;
122 status = 0; 121 status = 0;
123 keepPrivs = false; 122 keepPrivs = false;
124 innot = 0; 123 innot = 0;
125 outnot = 0; 124 outnot = 0;
126 errnot = 0; 125 errnot = 0;
127 communication = NoCommunication; 126 communication = NoCommunication;
128 input_data = 0; 127 input_data = 0;
129 input_sent = 0; 128 input_sent = 0;
130 input_total = 0; 129 input_total = 0;
131 d = 0; 130 d = 0;
132 131
133 if (0 == OProcessController::theOProcessController) { 132 if (0 == OProcessController::theOProcessController) {
134 (void) new OProcessController(); 133 (void) new OProcessController();
135 CHECK_PTR(OProcessController::theOProcessController); 134 CHECK_PTR(OProcessController::theOProcessController);
136 } 135 }
137 136
138 OProcessController::theOProcessController->addOProcess(this); 137 OProcessController::theOProcessController->addOProcess(this);
139 out[0] = out[1] = -1; 138 out[0] = out[1] = -1;
140 in[0] = in[1] = -1; 139 in[0] = in[1] = -1;
141 err[0] = err[1] = -1; 140 err[0] = err[1] = -1;
142} 141}
143 142
144void 143void
145OProcess::setEnvironment(const QString &name, const QString &value) 144OProcess::setEnvironment(const QString &name, const QString &value)
146{ 145{
147 if (!d) 146 if (!d)
148 d = new OProcessPrivate; 147 d = new OProcessPrivate;
149 d->env.insert(name, value); 148 d->env.insert(name, value);
150} 149}
151 150
152void 151void
153OProcess::setWorkingDirectory(const QString &dir) 152OProcess::setWorkingDirectory(const QString &dir)
154{ 153{
155 if (!d) 154 if (!d)
156 d = new OProcessPrivate; 155 d = new OProcessPrivate;
157 d->wd = dir; 156 d->wd = dir;
158} 157}
159 158
160void 159void
161OProcess::setupEnvironment() 160OProcess::setupEnvironment()
162{ 161{
163 if (d) 162 if (d)
164 { 163 {
165 QMap<QString,QString>::Iterator it; 164 QMap<QString,QString>::Iterator it;
166 for(it = d->env.begin(); it != d->env.end(); ++it) 165 for(it = d->env.begin(); it != d->env.end(); ++it)
167 setenv(QFile::encodeName(it.key()).data(), 166 setenv(QFile::encodeName(it.key()).data(),
168 QFile::encodeName(it.data()).data(), 1); 167 QFile::encodeName(it.data()).data(), 1);
169 if (!d->wd.isEmpty()) 168 if (!d->wd.isEmpty())
170 chdir(QFile::encodeName(d->wd).data()); 169 chdir(QFile::encodeName(d->wd).data());
171 } 170 }
172} 171}
173 172
174void 173void
175OProcess::setRunPrivileged(bool keepPrivileges) 174OProcess::setRunPrivileged(bool keepPrivileges)
176{ 175{
177 keepPrivs = keepPrivileges; 176 keepPrivs = keepPrivileges;
178} 177}
179 178
180bool 179bool
181OProcess::runPrivileged() const 180OProcess::runPrivileged() const
182{ 181{
183 return keepPrivs; 182 return keepPrivs;
184} 183}
185 184
186 185
187OProcess::~OProcess() 186OProcess::~OProcess()
188{ 187{
189 // destroying the OProcess instance sends a SIGKILL to the 188 // destroying the OProcess instance sends a SIGKILL to the
190 // child process (if it is running) after removing it from the 189 // child process (if it is running) after removing it from the
191 // list of valid processes (if the process is not started as 190 // list of valid processes (if the process is not started as
192 // "DontCare") 191 // "DontCare")
193 192
194 OProcessController::theOProcessController->removeOProcess(this); 193 OProcessController::theOProcessController->removeOProcess(this);
195 // this must happen before we kill the child 194 // this must happen before we kill the child
196 // TODO: block the signal while removing the current process from the process list 195 // TODO: block the signal while removing the current process from the process list
197 196
198 if (runs && (run_mode != DontCare)) 197 if (runs && (run_mode != DontCare))
199 kill(SIGKILL); 198 kill(SIGKILL);
200 199
201 // Clean up open fd's and socket notifiers. 200 // Clean up open fd's and socket notifiers.
202 closeStdin(); 201 closeStdin();
203 closeStdout(); 202 closeStdout();
204 closeStderr(); 203 closeStderr();
205 204
206 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess 205 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess
207 delete d; 206 delete d;
208} 207}
209 208
210void OProcess::detach() 209void OProcess::detach()
211{ 210{
212 OProcessController::theOProcessController->removeOProcess(this); 211 OProcessController::theOProcessController->removeOProcess(this);
213 212
214 runs = false; 213 runs = false;
215 pid_ = 0; 214 pid_ = 0;
216 215
217 // Clean up open fd's and socket notifiers. 216 // Clean up open fd's and socket notifiers.
218 closeStdin(); 217 closeStdin();
219 closeStdout(); 218 closeStdout();
220 closeStderr(); 219 closeStderr();
221} 220}
222 221
223bool OProcess::setExecutable(const QString& proc) 222bool OProcess::setExecutable(const QString& proc)
224{ 223{
225 if (runs) return false; 224 if (runs) return false;
226 225
227 if (proc.isEmpty()) return false; 226 if (proc.isEmpty()) return false;
228 227
229 if (!arguments.isEmpty()) 228 if (!arguments.isEmpty())
230 arguments.remove(arguments.begin()); 229 arguments.remove(arguments.begin());
231 arguments.prepend(QFile::encodeName(proc)); 230 arguments.prepend(QFile::encodeName(proc));
232 231
233 return true; 232 return true;
234} 233}
235 234
236OProcess &OProcess::operator<<(const QStringList& args) 235OProcess &OProcess::operator<<(const QStringList& args)
237{ 236{
238 QStringList::ConstIterator it = args.begin(); 237 QStringList::ConstIterator it = args.begin();
239 for ( ; it != args.end() ; ++it ) 238 for ( ; it != args.end() ; ++it )
240 arguments.append(QFile::encodeName(*it)); 239 arguments.append(QFile::encodeName(*it));
241 return *this; 240 return *this;
242} 241}
243 242
244OProcess &OProcess::operator<<(const QCString& arg) 243OProcess &OProcess::operator<<(const QCString& arg)
245{ 244{
246 return operator<< (arg.data()); 245 return operator<< (arg.data());
247} 246}
248 247
249OProcess &OProcess::operator<<(const char* arg) 248OProcess &OProcess::operator<<(const char* arg)
250{ 249{
251 arguments.append(arg); 250 arguments.append(arg);
252 return *this; 251 return *this;
253} 252}
254 253
255OProcess &OProcess::operator<<(const QString& arg) 254OProcess &OProcess::operator<<(const QString& arg)
256{ 255{
257 arguments.append(QFile::encodeName(arg)); 256 arguments.append(QFile::encodeName(arg));
258 return *this; 257 return *this;
259} 258}
260 259
261void OProcess::clearArguments() 260void OProcess::clearArguments()
262{ 261{
263 arguments.clear(); 262 arguments.clear();
264} 263}
265 264
266bool OProcess::start(RunMode runmode, Communication comm) 265bool OProcess::start(RunMode runmode, Communication comm)
267{ 266{
268 uint i; 267 uint i;
269 uint n = arguments.count(); 268 uint n = arguments.count();
270 char **arglist; 269 char **arglist;
271 270
272 if (runs || (0 == n)) { 271 if (runs || (0 == n)) {
273 return false; // cannot start a process that is already running 272 return false; // cannot start a process that is already running
274 // or if no executable has been assigned 273 // or if no executable has been assigned
275 } 274 }
276 run_mode = runmode; 275 run_mode = runmode;
277 status = 0; 276 status = 0;
278 277
279 QCString shellCmd; 278 QCString shellCmd;
280 if (d && d->useShell) 279 if (d && d->useShell)
281 { 280 {
282 if (d->shell.isEmpty()) 281 if (d->shell.isEmpty())
283 { 282 {
284 qWarning( "Could not find a valid shell" ); 283 qWarning( "Could not find a valid shell" );
285 return false; 284 return false;
286 } 285 }
287 286
288 arglist = static_cast<char **>(malloc( (4)*sizeof(char *))); 287 arglist = static_cast<char **>(malloc( (4)*sizeof(char *)));
289 for (i=0; i < n; i++) { 288 for (i=0; i < n; i++) {
290 shellCmd += arguments[i]; 289 shellCmd += arguments[i];
291 shellCmd += " "; // CC: to separate the arguments 290 shellCmd += " "; // CC: to separate the arguments
292 } 291 }
293 292
294 arglist[0] = d->shell.data(); 293 arglist[0] = d->shell.data();
295 arglist[1] = (char *) "-c"; 294 arglist[1] = (char *) "-c";
296 arglist[2] = shellCmd.data(); 295 arglist[2] = shellCmd.data();
297 arglist[3] = 0; 296 arglist[3] = 0;
298 } 297 }
299 else 298 else
300 { 299 {
301 arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *))); 300 arglist = static_cast<char **>(malloc( (n+1)*sizeof(char *)));
302 for (i=0; i < n; i++) 301 for (i=0; i < n; i++)
303 arglist[i] = arguments[i].data(); 302 arglist[i] = arguments[i].data();
304 arglist[n]= 0; 303 arglist[n]= 0;
305 } 304 }
306 305
307 if (!setupCommunication(comm)) 306 if (!setupCommunication(comm))
308 qWarning( "Could not setup Communication!"); 307 qWarning( "Could not setup Communication!");
309 308
310 // We do this in the parent because if we do it in the child process 309 // We do this in the parent because if we do it in the child process
311 // gdb gets confused when the application runs from gdb. 310 // gdb gets confused when the application runs from gdb.
312 uid_t uid = getuid(); 311 uid_t uid = getuid();
313 gid_t gid = getgid(); 312 gid_t gid = getgid();
314#ifdef HAVE_INITGROUPS 313#ifdef HAVE_INITGROUPS
315 struct passwd *pw = getpwuid(uid); 314 struct passwd *pw = getpwuid(uid);
316#endif 315#endif
317 316
318 int fd[2]; 317 int fd[2];
319 if (0 > pipe(fd)) 318 if (0 > pipe(fd))
320 { 319 {
321 fd[0] = fd[1] = 0; // Pipe failed.. continue 320 fd[0] = fd[1] = 0; // Pipe failed.. continue
322 } 321 }
323 322
324 runs = true; 323 runs = true;
325 324
326 QApplication::flushX(); 325 QApplication::flushX();
327 326
328 // WABA: Note that we use fork() and not vfork() because 327 // WABA: Note that we use fork() and not vfork() because
329 // vfork() has unclear semantics and is not standardized. 328 // vfork() has unclear semantics and is not standardized.
330 pid_ = fork(); 329 pid_ = fork();
331 330
332 if (0 == pid_) { 331 if (0 == pid_) {
333 if (fd[0]) 332 if (fd[0])
334 close(fd[0]); 333 close(fd[0]);
335 if (!runPrivileged()) 334 if (!runPrivileged())
336 { 335 {
337 setgid(gid); 336 setgid(gid);
338#if defined( HAVE_INITGROUPS) 337#if defined( HAVE_INITGROUPS)
339 if(pw) 338 if(pw)
340 initgroups(pw->pw_name, pw->pw_gid); 339 initgroups(pw->pw_name, pw->pw_gid);
341#endif 340#endif
342 setuid(uid); 341 setuid(uid);
343 } 342 }
344 // The child process 343 // The child process
345 if(!commSetupDoneC()) 344 if(!commSetupDoneC())
346 qWarning( "Could not finish comm setup in child!" ); 345 qWarning( "Could not finish comm setup in child!" );
347 346
348 setupEnvironment(); 347 setupEnvironment();
349 348
350 // Matthias 349 // Matthias
351 if (run_mode == DontCare) 350 if (run_mode == DontCare)
352 setpgid(0,0); 351 setpgid(0,0);
353 // restore default SIGPIPE handler (Harri) 352 // restore default SIGPIPE handler (Harri)
354 struct sigaction act; 353 struct sigaction act;
355 sigemptyset(&(act.sa_mask)); 354 sigemptyset(&(act.sa_mask));
356 sigaddset(&(act.sa_mask), SIGPIPE); 355 sigaddset(&(act.sa_mask), SIGPIPE);
357 act.sa_handler = SIG_DFL; 356 act.sa_handler = SIG_DFL;
358 act.sa_flags = 0; 357 act.sa_flags = 0;
359 sigaction(SIGPIPE, &act, 0L); 358 sigaction(SIGPIPE, &act, 0L);
360 359
361 // We set the close on exec flag. 360 // We set the close on exec flag.
362 // Closing of fd[1] indicates that the execvp succeeded! 361 // Closing of fd[1] indicates that the execvp succeeded!
363 if (fd[1]) 362 if (fd[1])
364 fcntl(fd[1], F_SETFD, FD_CLOEXEC); 363 fcntl(fd[1], F_SETFD, FD_CLOEXEC);
365 execvp(arglist[0], arglist); 364 execvp(arglist[0], arglist);
366 char resultByte = 1; 365 char resultByte = 1;
367 if (fd[1]) 366 if (fd[1])
368 write(fd[1], &resultByte, 1); 367 write(fd[1], &resultByte, 1);
369 _exit(-1); 368 _exit(-1);
370 } else if (-1 == pid_) { 369 } else if (-1 == pid_) {
371 // forking failed 370 // forking failed
372 371
373 runs = false; 372 runs = false;
374 free(arglist); 373 free(arglist);
375 return false; 374 return false;
376 } else { 375 } else {
377 if (fd[1]) 376 if (fd[1])
378 close(fd[1]); 377 close(fd[1]);
379 // the parent continues here 378 // the parent continues here
380 379
381 // Discard any data for stdin that might still be there 380 // Discard any data for stdin that might still be there
382 input_data = 0; 381 input_data = 0;
383 382
384 // Check whether client could be started. 383 // Check whether client could be started.
385 if (fd[0]) for(;;) 384 if (fd[0]) for(;;)
386 { 385 {
387 char resultByte; 386 char resultByte;
388 int n = ::read(fd[0], &resultByte, 1); 387 int n = ::read(fd[0], &resultByte, 1);
389 if (n == 1) 388 if (n == 1)
390 { 389 {
391 // Error 390 // Error
392 runs = false; 391 runs = false;
393 close(fd[0]); 392 close(fd[0]);
394 free(arglist); 393 free(arglist);
395 pid_ = 0; 394 pid_ = 0;
396 return false; 395 return false;
397 } 396 }
398 if (n == -1) 397 if (n == -1)
399 { 398 {
400 if ((errno == ECHILD) || (errno == EINTR)) 399 if ((errno == ECHILD) || (errno == EINTR))
401 continue; // Ignore 400 continue; // Ignore
402 } 401 }
403 break; // success 402 break; // success
404 } 403 }
405 if (fd[0]) 404 if (fd[0])
406 close(fd[0]); 405 close(fd[0]);
407 406
408 if (!commSetupDoneP()) // finish communication socket setup for the parent 407 if (!commSetupDoneP()) // finish communication socket setup for the parent
409 qWarning( "Could not finish comm setup in parent!" ); 408 qWarning( "Could not finish comm setup in parent!" );
410 409
411 if (run_mode == Block) { 410 if (run_mode == Block) {
412 commClose(); 411 commClose();
413 412
414 // The SIGCHLD handler of the process controller will catch 413 // The SIGCHLD handler of the process controller will catch
415 // the exit and set the status 414 // the exit and set the status
416 while(runs) 415 while(runs)
417 { 416 {
418 OProcessController::theOProcessController-> 417 OProcessController::theOProcessController->
419 slotDoHousekeeping(0); 418 slotDoHousekeeping(0);
420 } 419 }
421 runs = FALSE; 420 runs = FALSE;
422 emit processExited(this); 421 emit processExited(this);
423 } 422 }
424 } 423 }
425 free(arglist); 424 free(arglist);
426 return true; 425 return true;
427} 426}
428 427
429 428
430 429
431bool OProcess::kill(int signo) 430bool OProcess::kill(int signo)
432{ 431{
433 bool rv=false; 432 bool rv=false;
434 433
435 if (0 != pid_) 434 if (0 != pid_)
436 rv= (-1 != ::kill(pid_, signo)); 435 rv= (-1 != ::kill(pid_, signo));
437 // probably store errno somewhere... 436 // probably store errno somewhere...
438 return rv; 437 return rv;
439} 438}
440 439
441 440
442 441
443bool OProcess::isRunning() const 442bool OProcess::isRunning() const
444{ 443{
445 return runs; 444 return runs;
446} 445}
447 446
448 447
449 448
450pid_t OProcess::pid() const 449pid_t OProcess::pid() const
451{ 450{
452 return pid_; 451 return pid_;
453} 452}
454 453
455 454
456 455
457bool OProcess::normalExit() const 456bool OProcess::normalExit() const
458{ 457{
459 int _status = status; 458 int _status = status;
460 return (pid_ != 0) && (!runs) && (WIFEXITED((_status))); 459 return (pid_ != 0) && (!runs) && (WIFEXITED((_status)));
461} 460}
462 461
463 462
464 463
465int OProcess::exitStatus() const 464int OProcess::exitStatus() const
466{ 465{
467 int _status = status; 466 int _status = status;
468 return WEXITSTATUS((_status)); 467 return WEXITSTATUS((_status));
469} 468}
470 469
471 470
472 471
473bool OProcess::writeStdin(const char *buffer, int buflen) 472bool OProcess::writeStdin(const char *buffer, int buflen)
474{ 473{
475 bool rv; 474 bool rv;
476 475
477 // if there is still data pending, writing new data 476 // if there is still data pending, writing new data
478 // to stdout is not allowed (since it could also confuse 477 // to stdout is not allowed (since it could also confuse
479 // kprocess... 478 // kprocess...
480 if (0 != input_data) 479 if (0 != input_data)
481 return false; 480 return false;
482 481
483 if (runs && (communication & Stdin)) { 482 if (runs && (communication & Stdin)) {
484 input_data = buffer; 483 input_data = buffer;
485 input_sent = 0; 484 input_sent = 0;
486 input_total = buflen; 485 input_total = buflen;
487 slotSendData(0); 486 slotSendData(0);
488 innot->setEnabled(true); 487 innot->setEnabled(true);
489 rv = true; 488 rv = true;
490 } else 489 } else
491 rv = false; 490 rv = false;
492 return rv; 491 return rv;
493} 492}
494 493
495void OProcess::flushStdin ( ) 494void OProcess::flushStdin ( )
496{ 495{
497 if ( !input_data || ( input_sent == input_total )) 496 if ( !input_data || ( input_sent == input_total ))
498 return; 497 return;
499 498
500 int d1, d2; 499 int d1, d2;
501 500
502 do { 501 do {
503 d1 = input_total - input_sent; 502 d1 = input_total - input_sent;
504 slotSendData ( 0 ); 503 slotSendData ( 0 );
505 d2 = input_total - input_sent; 504 d2 = input_total - input_sent;
506 } while ( d2 <= d1 ); 505 } while ( d2 <= d1 );
507} 506}
508 507
509void OProcess::suspend() 508void OProcess::suspend()
510{ 509{
511 if ((communication & Stdout) && outnot) 510 if ((communication & Stdout) && outnot)
512 outnot->setEnabled(false); 511 outnot->setEnabled(false);
513} 512}
514 513
515void OProcess::resume() 514void OProcess::resume()
516{ 515{
517 if ((communication & Stdout) && outnot) 516 if ((communication & Stdout) && outnot)
518 outnot->setEnabled(true); 517 outnot->setEnabled(true);
519} 518}
520 519
521bool OProcess::closeStdin() 520bool OProcess::closeStdin()
522{ 521{
523 bool rv; 522 bool rv;
524 523
525 if (communication & Stdin) { 524 if (communication & Stdin) {
526 communication = (Communication) (communication & ~Stdin); 525 communication = (Communication) (communication & ~Stdin);
527 delete innot; 526 delete innot;
528 innot = 0; 527 innot = 0;
529 close(in[1]); 528 close(in[1]);
530 rv = true; 529 rv = true;
531 } else 530 } else
532 rv = false; 531 rv = false;
533 return rv; 532 return rv;
534} 533}
535 534
536bool OProcess::closeStdout() 535bool OProcess::closeStdout()
537{ 536{
538 bool rv; 537 bool rv;
539 538
540 if (communication & Stdout) { 539 if (communication & Stdout) {
541 communication = (Communication) (communication & ~Stdout); 540 communication = (Communication) (communication & ~Stdout);
542 delete outnot; 541 delete outnot;
543 outnot = 0; 542 outnot = 0;
544 close(out[0]); 543 close(out[0]);
545 rv = true; 544 rv = true;
546 } else 545 } else
547 rv = false; 546 rv = false;
548 return rv; 547 return rv;
549} 548}
550 549
551bool OProcess::closeStderr() 550bool OProcess::closeStderr()
552{ 551{
553 bool rv; 552 bool rv;
554 553
555 if (communication & Stderr) { 554 if (communication & Stderr) {
556 communication = static_cast<Communication>(communication & ~Stderr); 555 communication = static_cast<Communication>(communication & ~Stderr);
557 delete errnot; 556 delete errnot;
558 errnot = 0; 557 errnot = 0;
559 close(err[0]); 558 close(err[0]);
560 rv = true; 559 rv = true;
561 } else 560 } else
562 rv = false; 561 rv = false;
563 return rv; 562 return rv;
564} 563}
565 564
566 565
567///////////////////////////// 566/////////////////////////////
568// protected slots // 567// protected slots //