summaryrefslogtreecommitdiff
path: root/libopie/oprocess.cpp
authorsandman <sandman>2002-12-17 19:12:05 (UTC)
committer sandman <sandman>2002-12-17 19:12:05 (UTC)
commitb6a03145553d7f536b04fc3355718cfdd72c590d (patch) (unidiff)
treecfadab49e69801a2000001f80d57ec081b2c5ea4 /libopie/oprocess.cpp
parent6bbe59222c6b439f2016d0a36a111f17d338d120 (diff)
downloadopie-b6a03145553d7f536b04fc3355718cfdd72c590d.zip
opie-b6a03145553d7f536b04fc3355718cfdd72c590d.tar.gz
opie-b6a03145553d7f536b04fc3355718cfdd72c590d.tar.bz2
- removed a the obsolete KShellProcess class
- added a few methods to OProcess to make it easier to port programs using QProcess
Diffstat (limited to 'libopie/oprocess.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/oprocess.cpp94
1 files changed, 49 insertions, 45 deletions
diff --git a/libopie/oprocess.cpp b/libopie/oprocess.cpp
index f3e52bd..5db2b6c 100644
--- a/libopie/oprocess.cpp
+++ b/libopie/oprocess.cpp
@@ -33,144 +33,164 @@
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> 56#include <qregexp.h>
57 57
58#include <sys/time.h> 58#include <sys/time.h>
59#include <sys/types.h> 59#include <sys/types.h>
60#include <sys/stat.h> 60#include <sys/stat.h>
61#include <sys/socket.h> 61#include <sys/socket.h>
62 62
63#include <errno.h> 63#include <errno.h>
64#include <fcntl.h> 64#include <fcntl.h>
65#include <stdlib.h> 65#include <stdlib.h>
66#include <signal.h> 66#include <signal.h>
67#include <stdio.h> 67#include <stdio.h>
68#include <string.h> 68#include <string.h>
69#include <unistd.h> 69#include <unistd.h>
70#ifdef HAVE_SYS_SELECT_H 70#ifdef HAVE_SYS_SELECT_H
71#include <sys/select.h> 71#include <sys/select.h>
72#endif 72#endif
73#ifdef HAVE_INITGROUPS 73#ifdef HAVE_INITGROUPS
74#include <grp.h> 74#include <grp.h>
75#endif 75#endif
76#include <pwd.h> 76#include <pwd.h>
77 77
78#include <qapplication.h> 78#include <qapplication.h>
79#include <qmap.h> 79#include <qmap.h>
80//#include <kdebug.h> 80//#include <kdebug.h>
81 81
82///////////////////////////// 82/////////////////////////////
83// public member functions // 83// public member functions //
84///////////////////////////// 84/////////////////////////////
85 85
86class OProcessPrivate { 86class OProcessPrivate {
87public: 87public:
88 OProcessPrivate() : useShell(false) { } 88 OProcessPrivate() : useShell(false) { }
89 89
90 bool useShell; 90 bool useShell;
91 QMap<QString,QString> env; 91 QMap<QString,QString> env;
92 QString wd; 92 QString wd;
93 QCString shell; 93 QCString shell;
94}; 94};
95 95
96 96
97OProcess::OProcess() 97OProcess::OProcess(QObject *parent, const char *name)
98 : QObject(), 98 : QObject(parent, name)
99 run_mode(NotifyOnExit),
100 runs(false),
101 pid_(0),
102 status(0),
103 keepPrivs(false),
104 innot(0),
105 outnot(0),
106 errnot(0),
107 communication(NoCommunication),
108 input_data(0),
109 input_sent(0),
110 input_total(0),
111 d(0)
112{ 99{
100 init ( );
101}
102
103OProcess::OProcess(const QString &arg0, QObject *parent, const char *name)
104 : QObject(parent, name)
105{
106 init ( );
107 *this << arg0;
108}
109
110OProcess::OProcess(const QStringList &args, QObject *parent, const char *name)
111 : QObject(parent, name)
112{
113 init ( );
114 *this << args;
115}
116
117void OProcess::init ( )
118{
119 run_mode = NotifyOnExit;
120 runs = false;
121 pid_ = 0;
122 status = 0;
123 keepPrivs = false;
124 innot = 0;
125 outnot = 0;
126 errnot = 0;
127 communication = NoCommunication;
128 input_data = 0;
129 input_sent = 0;
130 input_total = 0;
131 d = 0;
132
113 if (0 == OProcessController::theOProcessController) { 133 if (0 == OProcessController::theOProcessController) {
114 (void) new OProcessController(); 134 (void) new OProcessController();
115 CHECK_PTR(OProcessController::theOProcessController); 135 CHECK_PTR(OProcessController::theOProcessController);
116 } 136 }
117 137
118 OProcessController::theOProcessController->addOProcess(this); 138 OProcessController::theOProcessController->addOProcess(this);
119 out[0] = out[1] = -1; 139 out[0] = out[1] = -1;
120 in[0] = in[1] = -1; 140 in[0] = in[1] = -1;
121 err[0] = err[1] = -1; 141 err[0] = err[1] = -1;
122} 142}
123 143
124void 144void
125OProcess::setEnvironment(const QString &name, const QString &value) 145OProcess::setEnvironment(const QString &name, const QString &value)
126{ 146{
127 if (!d) 147 if (!d)
128 d = new OProcessPrivate; 148 d = new OProcessPrivate;
129 d->env.insert(name, value); 149 d->env.insert(name, value);
130} 150}
131 151
132void 152void
133OProcess::setWorkingDirectory(const QString &dir) 153OProcess::setWorkingDirectory(const QString &dir)
134{ 154{
135 if (!d) 155 if (!d)
136 d = new OProcessPrivate; 156 d = new OProcessPrivate;
137 d->wd = dir; 157 d->wd = dir;
138} 158}
139 159
140void 160void
141OProcess::setupEnvironment() 161OProcess::setupEnvironment()
142{ 162{
143 if (d) 163 if (d)
144 { 164 {
145 QMap<QString,QString>::Iterator it; 165 QMap<QString,QString>::Iterator it;
146 for(it = d->env.begin(); it != d->env.end(); ++it) 166 for(it = d->env.begin(); it != d->env.end(); ++it)
147 setenv(QFile::encodeName(it.key()).data(), 167 setenv(QFile::encodeName(it.key()).data(),
148 QFile::encodeName(it.data()).data(), 1); 168 QFile::encodeName(it.data()).data(), 1);
149 if (!d->wd.isEmpty()) 169 if (!d->wd.isEmpty())
150 chdir(QFile::encodeName(d->wd).data()); 170 chdir(QFile::encodeName(d->wd).data());
151 } 171 }
152} 172}
153 173
154void 174void
155OProcess::setRunPrivileged(bool keepPrivileges) 175OProcess::setRunPrivileged(bool keepPrivileges)
156{ 176{
157 keepPrivs = keepPrivileges; 177 keepPrivs = keepPrivileges;
158} 178}
159 179
160bool 180bool
161OProcess::runPrivileged() const 181OProcess::runPrivileged() const
162{ 182{
163 return keepPrivs; 183 return keepPrivs;
164} 184}
165 185
166 186
167OProcess::~OProcess() 187OProcess::~OProcess()
168{ 188{
169 // destroying the OProcess instance sends a SIGKILL to the 189 // destroying the OProcess instance sends a SIGKILL to the
170 // child process (if it is running) after removing it from the 190 // child process (if it is running) after removing it from the
171 // list of valid processes (if the process is not started as 191 // list of valid processes (if the process is not started as
172 // "DontCare") 192 // "DontCare")
173 193
174 OProcessController::theOProcessController->removeOProcess(this); 194 OProcessController::theOProcessController->removeOProcess(this);
175 // this must happen before we kill the child 195 // this must happen before we kill the child
176 // TODO: block the signal while removing the current process from the process list 196 // TODO: block the signal while removing the current process from the process list
@@ -411,128 +431,142 @@ bool OProcess::start(RunMode runmode, Communication comm)
411bool OProcess::kill(int signo) 431bool OProcess::kill(int signo)
412{ 432{
413 bool rv=false; 433 bool rv=false;
414 434
415 if (0 != pid_) 435 if (0 != pid_)
416 rv= (-1 != ::kill(pid_, signo)); 436 rv= (-1 != ::kill(pid_, signo));
417 // probably store errno somewhere... 437 // probably store errno somewhere...
418 return rv; 438 return rv;
419} 439}
420 440
421 441
422 442
423bool OProcess::isRunning() const 443bool OProcess::isRunning() const
424{ 444{
425 return runs; 445 return runs;
426} 446}
427 447
428 448
429 449
430pid_t OProcess::pid() const 450pid_t OProcess::pid() const
431{ 451{
432 return pid_; 452 return pid_;
433} 453}
434 454
435 455
436 456
437bool OProcess::normalExit() const 457bool OProcess::normalExit() const
438{ 458{
439 int _status = status; 459 int _status = status;
440 return (pid_ != 0) && (!runs) && (WIFEXITED((_status))); 460 return (pid_ != 0) && (!runs) && (WIFEXITED((_status)));
441} 461}
442 462
443 463
444 464
445int OProcess::exitStatus() const 465int OProcess::exitStatus() const
446{ 466{
447 int _status = status; 467 int _status = status;
448 return WEXITSTATUS((_status)); 468 return WEXITSTATUS((_status));
449} 469}
450 470
451 471
452 472
453bool OProcess::writeStdin(const char *buffer, int buflen) 473bool OProcess::writeStdin(const char *buffer, int buflen)
454{ 474{
455 bool rv; 475 bool rv;
456 476
457 // if there is still data pending, writing new data 477 // if there is still data pending, writing new data
458 // to stdout is not allowed (since it could also confuse 478 // to stdout is not allowed (since it could also confuse
459 // kprocess... 479 // kprocess...
460 if (0 != input_data) 480 if (0 != input_data)
461 return false; 481 return false;
462 482
463 if (runs && (communication & Stdin)) { 483 if (runs && (communication & Stdin)) {
464 input_data = buffer; 484 input_data = buffer;
465 input_sent = 0; 485 input_sent = 0;
466 input_total = buflen; 486 input_total = buflen;
467 slotSendData(0); 487 slotSendData(0);
468 innot->setEnabled(true); 488 innot->setEnabled(true);
469 rv = true; 489 rv = true;
470 } else 490 } else
471 rv = false; 491 rv = false;
472 return rv; 492 return rv;
473} 493}
474 494
495void OProcess::flushStdin ( )
496{
497 if ( !input_data || ( input_sent == input_total ))
498 return;
499
500 int d1, d2;
501
502 do {
503 d1 = input_total - input_sent;
504 slotSendData ( 0 );
505 d2 = input_total - input_sent;
506 } while ( d2 <= d1 );
507}
508
475void OProcess::suspend() 509void OProcess::suspend()
476{ 510{
477 if ((communication & Stdout) && outnot) 511 if ((communication & Stdout) && outnot)
478 outnot->setEnabled(false); 512 outnot->setEnabled(false);
479} 513}
480 514
481void OProcess::resume() 515void OProcess::resume()
482{ 516{
483 if ((communication & Stdout) && outnot) 517 if ((communication & Stdout) && outnot)
484 outnot->setEnabled(true); 518 outnot->setEnabled(true);
485} 519}
486 520
487bool OProcess::closeStdin() 521bool OProcess::closeStdin()
488{ 522{
489 bool rv; 523 bool rv;
490 524
491 if (communication & Stdin) { 525 if (communication & Stdin) {
492 communication = (Communication) (communication & ~Stdin); 526 communication = (Communication) (communication & ~Stdin);
493 delete innot; 527 delete innot;
494 innot = 0; 528 innot = 0;
495 close(in[1]); 529 close(in[1]);
496 rv = true; 530 rv = true;
497 } else 531 } else
498 rv = false; 532 rv = false;
499 return rv; 533 return rv;
500} 534}
501 535
502bool OProcess::closeStdout() 536bool OProcess::closeStdout()
503{ 537{
504 bool rv; 538 bool rv;
505 539
506 if (communication & Stdout) { 540 if (communication & Stdout) {
507 communication = (Communication) (communication & ~Stdout); 541 communication = (Communication) (communication & ~Stdout);
508 delete outnot; 542 delete outnot;
509 outnot = 0; 543 outnot = 0;
510 close(out[0]); 544 close(out[0]);
511 rv = true; 545 rv = true;
512 } else 546 } else
513 rv = false; 547 rv = false;
514 return rv; 548 return rv;
515} 549}
516 550
517bool OProcess::closeStderr() 551bool OProcess::closeStderr()
518{ 552{
519 bool rv; 553 bool rv;
520 554
521 if (communication & Stderr) { 555 if (communication & Stderr) {
522 communication = static_cast<Communication>(communication & ~Stderr); 556 communication = static_cast<Communication>(communication & ~Stderr);
523 delete errnot; 557 delete errnot;
524 errnot = 0; 558 errnot = 0;
525 close(err[0]); 559 close(err[0]);
526 rv = true; 560 rv = true;
527 } else 561 } else
528 rv = false; 562 rv = false;
529 return rv; 563 return rv;
530} 564}
531 565
532 566
533///////////////////////////// 567/////////////////////////////
534// protected slots // 568// protected slots //
535///////////////////////////// 569/////////////////////////////
536 570
537 571
538 572
@@ -827,96 +861,66 @@ void OProcess::commClose()
827} 861}
828 862
829void OProcess::setUseShell(bool useShell, const char *shell) 863void OProcess::setUseShell(bool useShell, const char *shell)
830{ 864{
831 if (!d) 865 if (!d)
832 d = new OProcessPrivate; 866 d = new OProcessPrivate;
833 d->useShell = useShell; 867 d->useShell = useShell;
834 d->shell = shell; 868 d->shell = shell;
835 if (d->shell.isEmpty()) 869 if (d->shell.isEmpty())
836 d->shell = searchShell(); 870 d->shell = searchShell();
837} 871}
838 872
839QString OProcess::quote(const QString &arg) 873QString OProcess::quote(const QString &arg)
840{ 874{
841 QString res = arg; 875 QString res = arg;
842 res.replace(QRegExp(QString::fromLatin1("\'")), 876 res.replace(QRegExp(QString::fromLatin1("\'")),
843 QString::fromLatin1("'\"'\"'")); 877 QString::fromLatin1("'\"'\"'"));
844 res.prepend('\''); 878 res.prepend('\'');
845 res.append('\''); 879 res.append('\'');
846 return res; 880 return res;
847} 881}
848 882
849QCString OProcess::searchShell() 883QCString OProcess::searchShell()
850{ 884{
851 QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace(); 885 QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace();
852 if (!isExecutable(tmpShell)) 886 if (!isExecutable(tmpShell))
853 { 887 {
854 tmpShell = "/bin/sh"; 888 tmpShell = "/bin/sh";
855 } 889 }
856 890
857 return tmpShell; 891 return tmpShell;
858} 892}
859 893
860bool OProcess::isExecutable(const QCString &filename) 894bool OProcess::isExecutable(const QCString &filename)
861{ 895{
862 struct stat fileinfo; 896 struct stat fileinfo;
863 897
864 if (filename.isEmpty()) return false; 898 if (filename.isEmpty()) return false;
865 899
866 // CC: we've got a valid filename, now let's see whether we can execute that file 900 // CC: we've got a valid filename, now let's see whether we can execute that file
867 901
868 if (-1 == stat(filename.data(), &fileinfo)) return false; 902 if (-1 == stat(filename.data(), &fileinfo)) return false;
869 // CC: return false if the file does not exist 903 // CC: return false if the file does not exist
870 904
871 // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets 905 // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets
872 if ( (S_ISDIR(fileinfo.st_mode)) || 906 if ( (S_ISDIR(fileinfo.st_mode)) ||
873 (S_ISCHR(fileinfo.st_mode)) || 907 (S_ISCHR(fileinfo.st_mode)) ||
874 (S_ISBLK(fileinfo.st_mode)) || 908 (S_ISBLK(fileinfo.st_mode)) ||
875#ifdef S_ISSOCK 909#ifdef S_ISSOCK
876 // CC: SYSVR4 systems don't have that macro 910 // CC: SYSVR4 systems don't have that macro
877 (S_ISSOCK(fileinfo.st_mode)) || 911 (S_ISSOCK(fileinfo.st_mode)) ||
878#endif 912#endif
879 (S_ISFIFO(fileinfo.st_mode)) || 913 (S_ISFIFO(fileinfo.st_mode)) ||
880 (S_ISDIR(fileinfo.st_mode)) ) { 914 (S_ISDIR(fileinfo.st_mode)) ) {
881 return false; 915 return false;
882 } 916 }
883 917
884 // CC: now check for permission to execute the file 918 // CC: now check for permission to execute the file
885 if (access(filename.data(), X_OK) != 0) return false; 919 if (access(filename.data(), X_OK) != 0) return false;
886 920
887 // CC: we've passed all the tests... 921 // CC: we've passed all the tests...
888 return true; 922 return true;
889} 923}
890 924
891void OProcess::virtual_hook( int, void* )
892{ /*BASE::virtual_hook( id, data );*/ }
893
894
895///////////////////////////
896// CC: Class KShellProcess
897///////////////////////////
898
899KShellProcess::KShellProcess(const char *shellname):
900 OProcess()
901{
902 setUseShell(true, shellname);
903}
904
905
906KShellProcess::~KShellProcess() {
907}
908
909QString KShellProcess::quote(const QString &arg)
910{
911 return OProcess::quote(arg);
912}
913
914bool KShellProcess::start(RunMode runmode, Communication comm)
915{
916 return OProcess::start(runmode, comm);
917}
918 925
919void KShellProcess::virtual_hook( int id, void* data )
920{ OProcess::virtual_hook( id, data ); }
921 926
922//#include "kprocess.moc"