summaryrefslogtreecommitdiffabout
path: root/microkde
Unidiff
Diffstat (limited to 'microkde') (more/less context) (ignore whitespace changes)
-rw-r--r--microkde/microkde.pro7
-rw-r--r--microkde/oprocess.cpp1
2 files changed, 7 insertions, 1 deletions
diff --git a/microkde/microkde.pro b/microkde/microkde.pro
index 21da158..6e75442 100644
--- a/microkde/microkde.pro
+++ b/microkde/microkde.pro
@@ -1,174 +1,179 @@
1 TEMPLATE= lib 1 TEMPLATE= lib
2 CONFIG += qt warn_on 2 CONFIG += qt warn_on
3#INCLUDEPATH += $(QTDIR)/include . 3#INCLUDEPATH += $(QTDIR)/include .
4#DEPENDPATH += $(QTDIR)/include 4#DEPENDPATH += $(QTDIR)/include
5INCLUDEPATH += . ../ ../kabc ./kdecore ./kdeui ./kio/kfile ./kio/kio 5INCLUDEPATH += . ../ ../kabc ./kdecore ./kdeui ./kio/kfile ./kio/kio
6#LIBS += -lqtcompat 6#LIBS += -lqtcompat
7 7
8 TARGET = microkde 8 TARGET = microkde
9DESTDIR= ../bin 9DESTDIR= ../bin
10DEFINES += DESKTOP_VERSION KDE_QT_ONLY 10DEFINES += DESKTOP_VERSION KDE_QT_ONLY
11unix : { 11unix : {
12OBJECTS_DIR = obj/unix 12OBJECTS_DIR = obj/unix
13MOC_DIR = moc/unix 13MOC_DIR = moc/unix
14} 14}
15win32: { 15win32: {
16DEFINES += _WIN32_ 16DEFINES += _WIN32_
17OBJECTS_DIR = obj/win 17OBJECTS_DIR = obj/win
18MOC_DIR = moc/win 18MOC_DIR = moc/win
19} 19}
20include( ../variables.pri ) 20include( ../variables.pri )
21 21
22 22
23 23
24HEADERS = \ 24HEADERS = \
25qlayoutengine_p.h \ 25qlayoutengine_p.h \
26KDGanttMinimizeSplitter.h \ 26KDGanttMinimizeSplitter.h \
27 kapplication.h \ 27 kapplication.h \
28 kaudioplayer.h \ 28 kaudioplayer.h \
29 kcalendarsystem.h \ 29 kcalendarsystem.h \
30 kcalendarsystemgregorian.h \ 30 kcalendarsystemgregorian.h \
31 kcolorbutton.h \ 31 kcolorbutton.h \
32 kcolordialog.h \ 32 kcolordialog.h \
33 kcombobox.h \ 33 kcombobox.h \
34 kconfig.h \ 34 kconfig.h \
35 kdatetbl.h \ 35 kdatetbl.h \
36 kdebug.h \ 36 kdebug.h \
37 kdialog.h \ 37 kdialog.h \
38 kdialogbase.h \ 38 kdialogbase.h \
39 keditlistbox.h \ 39 keditlistbox.h \
40 kemailsettings.h \ 40 kemailsettings.h \
41 kfiledialog.h \ 41 kfiledialog.h \
42 kfontdialog.h \ 42 kfontdialog.h \
43 kglobal.h \ 43 kglobal.h \
44 kglobalsettings.h \ 44 kglobalsettings.h \
45 kiconloader.h \ 45 kiconloader.h \
46 klineedit.h \ 46 klineedit.h \
47 klineeditdlg.h \ 47 klineeditdlg.h \
48 kmessagebox.h \ 48 kmessagebox.h \
49 knotifyclient.h \ 49 knotifyclient.h \
50 kprinter.h \ 50 kprinter.h \
51 kprocess.h \ 51 kprocess.h \
52 krestrictedline.h \ 52 krestrictedline.h \
53 krun.h \ 53 krun.h \
54 ksimpleconfig.h \ 54 ksimpleconfig.h \
55 kstaticdeleter.h \ 55 kstaticdeleter.h \
56 ksystemtray.h \ 56 ksystemtray.h \
57 ktempfile.h \ 57 ktempfile.h \
58 ktextedit.h \ 58 ktextedit.h \
59 kunload.h \ 59 kunload.h \
60 kurl.h \ 60 kurl.h \
61oprocctrl.h \
62oprocess.h \
63osmartpointer.h \
61 kdeui/kguiitem.h \ 64 kdeui/kguiitem.h \
62 kdeui/kcmodule.h \ 65 kdeui/kcmodule.h \
63 kdeui/kbuttonbox.h \ 66 kdeui/kbuttonbox.h \
64 kdeui/klistbox.h \ 67 kdeui/klistbox.h \
65 kdeui/klistview.h \ 68 kdeui/klistview.h \
66 kdeui/kjanuswidget.h \ 69 kdeui/kjanuswidget.h \
67 kdeui/kseparator.h \ 70 kdeui/kseparator.h \
68 kdeui/knuminput.h \ 71 kdeui/knuminput.h \
69 kdeui/knumvalidator.h \ 72 kdeui/knumvalidator.h \
70 kdeui/ksqueezedtextlabel.h \ 73 kdeui/ksqueezedtextlabel.h \
71 kio/job.h \ 74 kio/job.h \
72 kio/kio/kdirwatch.h \ 75 kio/kio/kdirwatch.h \
73 kio/kio/kdirwatch_p.h \ 76 kio/kio/kdirwatch_p.h \
74 kio/kfile/kurlrequester.h \ 77 kio/kfile/kurlrequester.h \
75 kresources/resource.h \ 78 kresources/resource.h \
76 kresources/factory.h \ 79 kresources/factory.h \
77 kresources/managerimpl.h \ 80 kresources/managerimpl.h \
78 kresources/manager.h \ 81 kresources/manager.h \
79 kresources/selectdialog.h \ 82 kresources/selectdialog.h \
80 kresources/configpage.h \ 83 kresources/configpage.h \
81 kresources/configwidget.h \ 84 kresources/configwidget.h \
82 kresources/configdialog.h \ 85 kresources/configdialog.h \
83 kresources/kcmkresources.h \ 86 kresources/kcmkresources.h \
84 kdecore/kmdcodec.h \ 87 kdecore/kmdcodec.h \
85 kdecore/kconfigbase.h \ 88 kdecore/kconfigbase.h \
86 kdecore/klocale.h \ 89 kdecore/klocale.h \
87 kdecore/kcatalogue.h \ 90 kdecore/kcatalogue.h \
88 kdecore/ksharedptr.h \ 91 kdecore/ksharedptr.h \
89 kdecore/kshell.h \ 92 kdecore/kshell.h \
90 kdecore/kstandarddirs.h \ 93 kdecore/kstandarddirs.h \
91 kdecore/kstringhandler.h \ 94 kdecore/kstringhandler.h \
92 kdecore/kshortcut.h \ 95 kdecore/kshortcut.h \
93 kutils/kcmultidialog.h \ 96 kutils/kcmultidialog.h \
94 kdeui/kxmlguiclient.h \ 97 kdeui/kxmlguiclient.h \
95 kdeui/kstdaction.h \ 98 kdeui/kstdaction.h \
96 kdeui/kmainwindow.h \ 99 kdeui/kmainwindow.h \
97 kdeui/ktoolbar.h \ 100 kdeui/ktoolbar.h \
98 kdeui/ktoolbarbutton.h \ 101 kdeui/ktoolbarbutton.h \
99 kdeui/ktoolbarhandler.h \ 102 kdeui/ktoolbarhandler.h \
100 kdeui/kaction.h \ 103 kdeui/kaction.h \
101 kdeui/kactionclasses.h \ 104 kdeui/kactionclasses.h \
102 kdeui/kactioncollection.h \ 105 kdeui/kactioncollection.h \
103 kdecore/kprefs.h \ 106 kdecore/kprefs.h \
104 kdecore/klibloader.h \ 107 kdecore/klibloader.h \
105 kidmanager.h 108 kidmanager.h
106 109
107 110
108# kdecore/klibloader.h \ 111# kdecore/klibloader.h \
109 112
110 113
111SOURCES = \ 114SOURCES = \
112KDGanttMinimizeSplitter.cpp \ 115KDGanttMinimizeSplitter.cpp \
113 kapplication.cpp \ 116 kapplication.cpp \
114 kcalendarsystem.cpp \ 117 kcalendarsystem.cpp \
115 kcalendarsystemgregorian.cpp \ 118 kcalendarsystemgregorian.cpp \
116 kcolorbutton.cpp \ 119 kcolorbutton.cpp \
117 kcolordialog.cpp \ 120 kcolordialog.cpp \
118 kconfig.cpp \ 121 kconfig.cpp \
119 kdatetbl.cpp \ 122 kdatetbl.cpp \
120 kdialog.cpp \ 123 kdialog.cpp \
121 kdialogbase.cpp \ 124 kdialogbase.cpp \
122 keditlistbox.cpp \ 125 keditlistbox.cpp \
123 kemailsettings.cpp \ 126 kemailsettings.cpp \
124 kfontdialog.cpp \ 127 kfontdialog.cpp \
125 kfiledialog.cpp \ 128 kfiledialog.cpp \
126 kglobal.cpp \ 129 kglobal.cpp \
127 kglobalsettings.cpp \ 130 kglobalsettings.cpp \
128 kiconloader.cpp \ 131 kiconloader.cpp \
129 kmessagebox.cpp \ 132 kmessagebox.cpp \
130 ktextedit.cpp \ 133 ktextedit.cpp \
131 kprocess.cpp \ 134 kprocess.cpp \
132 krun.cpp \ 135 krun.cpp \
133 ksystemtray.cpp \ 136 ksystemtray.cpp \
134 ktempfile.cpp \ 137 ktempfile.cpp \
135 kurl.cpp \ 138 kurl.cpp \
136 kdecore/kcatalogue.cpp \ 139 kdecore/kcatalogue.cpp \
137 kdecore/klocale.cpp \ 140 kdecore/klocale.cpp \
138 kdecore/kmdcodec.cpp \ 141 kdecore/kmdcodec.cpp \
139 kdecore/kshell.cpp \ 142 kdecore/kshell.cpp \
140 kdecore/kstandarddirs.cpp \ 143 kdecore/kstandarddirs.cpp \
141 kdecore/kstringhandler.cpp \ 144 kdecore/kstringhandler.cpp \
142 kdeui/kbuttonbox.cpp \ 145 kdeui/kbuttonbox.cpp \
143 kdeui/kcmodule.cpp \ 146 kdeui/kcmodule.cpp \
144 kdeui/kguiitem.cpp \ 147 kdeui/kguiitem.cpp \
145 kdeui/kjanuswidget.cpp \ 148 kdeui/kjanuswidget.cpp \
146 kdeui/klistbox.cpp \ 149 kdeui/klistbox.cpp \
147 kdeui/klistview.cpp \ 150 kdeui/klistview.cpp \
148 kdeui/knuminput.cpp \ 151 kdeui/knuminput.cpp \
149 kdeui/knumvalidator.cpp \ 152 kdeui/knumvalidator.cpp \
150 kdeui/kseparator.cpp \ 153 kdeui/kseparator.cpp \
151 kdeui/ksqueezedtextlabel.cpp \ 154 kdeui/ksqueezedtextlabel.cpp \
152 kio/kio/kdirwatch.cpp \ 155 kio/kio/kdirwatch.cpp \
153 kio/kfile/kurlrequester.cpp \ 156 kio/kfile/kurlrequester.cpp \
154 kresources/configpage.cpp \ 157 kresources/configpage.cpp \
155 kresources/configdialog.cpp \ 158 kresources/configdialog.cpp \
156 kresources/configwidget.cpp \ 159 kresources/configwidget.cpp \
157 kresources/factory.cpp \ 160 kresources/factory.cpp \
158 kresources/kcmkresources.cpp \ 161 kresources/kcmkresources.cpp \
159 kresources/managerimpl.cpp \ 162 kresources/managerimpl.cpp \
160 kresources/resource.cpp \ 163 kresources/resource.cpp \
161 kresources/selectdialog.cpp \ 164 kresources/selectdialog.cpp \
162 kutils/kcmultidialog.cpp \ 165 kutils/kcmultidialog.cpp \
163 kdeui/kaction.cpp \ 166 kdeui/kaction.cpp \
164 kdeui/kactionclasses.cpp \ 167 kdeui/kactionclasses.cpp \
165 kdeui/kactioncollection.cpp \ 168 kdeui/kactioncollection.cpp \
166 kdeui/kmainwindow.cpp \ 169 kdeui/kmainwindow.cpp \
167 kdeui/ktoolbar.cpp \ 170 kdeui/ktoolbar.cpp \
168 kdeui/ktoolbarbutton.cpp \ 171 kdeui/ktoolbarbutton.cpp \
169 kdeui/ktoolbarhandler.cpp \ 172 kdeui/ktoolbarhandler.cpp \
170 kdeui/kstdaction.cpp \ 173 kdeui/kstdaction.cpp \
171 kdeui/kxmlguiclient.cpp \ 174 kdeui/kxmlguiclient.cpp \
172 kdecore/kprefs.cpp \ 175 kdecore/kprefs.cpp \
173 kdecore/klibloader.cpp \ 176 kdecore/klibloader.cpp \
174 kidmanager.cpp 177 kidmanager.cpp \
178oprocctrl.cpp \
179oprocess.cpp
diff --git a/microkde/oprocess.cpp b/microkde/oprocess.cpp
index 95e3e4b..a935792 100644
--- a/microkde/oprocess.cpp
+++ b/microkde/oprocess.cpp
@@ -1,424 +1,425 @@
1/* 1/*
2                This file is part of the Opie Project 2                This file is part of the Opie Project
3             Copyright (C) 2002-2004 Holger Freyther <zecke@handhelds.org> 3             Copyright (C) 2002-2004 Holger Freyther <zecke@handhelds.org>
4 and The Opie Team <opie-devel@handhelds.org> 4 and The Opie Team <opie-devel@handhelds.org>
5 =. Based on KProcess (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at) 5 =. Based on KProcess (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at)
6 .=l. 6 .=l.
7          .>+-= 7          .>+-=
8_;:,     .>    :=|. This program is free software; you can 8_;:,     .>    :=|. This program is free software; you can
9.> <`_,   >  .   <= redistribute it and/or modify it under 9.> <`_,   >  .   <= redistribute it and/or modify it under
10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public 10:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
11.="- .-=="i,     .._ License as published by the Free Software 11.="- .-=="i,     .._ License as published by the Free Software
12- .   .-<_>     .<> Foundation; either version 2 of the License, 12- .   .-<_>     .<> Foundation; either version 2 of the License,
13    ._= =}       : or (at your option) any later version. 13    ._= =}       : or (at your option) any later version.
14   .%`+i>       _;_. 14   .%`+i>       _;_.
15   .i_,=:_.      -<s. This program is distributed in the hope that 15   .i_,=:_.      -<s. This program is distributed in the hope that
16    +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY; 16    +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
17   : ..    .:,     . . . without even the implied warranty of 17   : ..    .:,     . . . without even the implied warranty of
18   =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A 18   =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
19 _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU 19 _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
20..}^=.=       =       ; Library General Public License for more 20..}^=.=       =       ; Library General Public License for more
21++=   -.     .`     .: details. 21++=   -.     .`     .: details.
22:     =  ...= . :.=- 22:     =  ...= . :.=-
23-.   .:....=;==+<; You should have received a copy of the GNU 23-.   .:....=;==+<; You should have received a copy of the GNU
24 -_. . .   )=.  = Library General Public License along with 24 -_. . .   )=.  = Library General Public License along with
25   --        :-=` this library; see the file COPYING.LIB. 25   --        :-=` this library; see the file COPYING.LIB.
26 If not, write to the Free Software Foundation, 26 If not, write to the Free Software Foundation,
27 Inc., 59 Temple Place - Suite 330, 27 Inc., 59 Temple Place - Suite 330,
28 Boston, MA 02111-1307, USA. 28 Boston, MA 02111-1307, USA.
29*/ 29*/
30 30
31#include "oprocctrl.h" 31#include "oprocctrl.h"
32 32
33/* OPIE */ 33/* OPIE */
34#include <oprocess.h> 34#include <oprocess.h>
35 35
36/* QT */ 36/* QT */
37 37
38#include <qapplication.h> 38#include <qapplication.h>
39#include <qdir.h> 39#include <qdir.h>
40#include <qmap.h> 40#include <qmap.h>
41#include <qregexp.h>
41#include <qsocketnotifier.h> 42#include <qsocketnotifier.h>
42#include <qtextstream.h> 43#include <qtextstream.h>
43 44
44/* STD */ 45/* STD */
45#include <errno.h> 46#include <errno.h>
46#include <fcntl.h> 47#include <fcntl.h>
47#include <pwd.h> 48#include <pwd.h>
48#include <stdlib.h> 49#include <stdlib.h>
49#include <signal.h> 50#include <signal.h>
50#include <stdio.h> 51#include <stdio.h>
51#include <string.h> 52#include <string.h>
52#include <sys/time.h> 53#include <sys/time.h>
53#include <sys/types.h> 54#include <sys/types.h>
54#include <sys/stat.h> 55#include <sys/stat.h>
55#include <sys/socket.h> 56#include <sys/socket.h>
56#include <unistd.h> 57#include <unistd.h>
57#ifdef HAVE_SYS_SELECT_H 58#ifdef HAVE_SYS_SELECT_H
58#include <sys/select.h> 59#include <sys/select.h>
59#endif 60#endif
60#ifdef HAVE_INITGROUPS 61#ifdef HAVE_INITGROUPS
61#include <grp.h> 62#include <grp.h>
62#endif 63#endif
63 64
64using namespace Opie::Core::Internal; 65using namespace Opie::Core::Internal;
65 66
66namespace Opie { 67namespace Opie {
67namespace Core { 68namespace Core {
68namespace Internal { 69namespace Internal {
69class OProcessPrivate 70class OProcessPrivate
70{ 71{
71public: 72public:
72 OProcessPrivate() : useShell( false ) 73 OProcessPrivate() : useShell( false )
73 { } 74 { }
74 75
75 bool useShell; 76 bool useShell;
76 QMap<QString, QString> env; 77 QMap<QString, QString> env;
77 QString wd; 78 QString wd;
78 QCString shell; 79 QCString shell;
79}; 80};
80} 81}
81 82
82OProcess::OProcess( QObject *parent, const char *name ) 83OProcess::OProcess( QObject *parent, const char *name )
83 : QObject( parent, name ) 84 : QObject( parent, name )
84{ 85{
85 init ( ); 86 init ( );
86} 87}
87 88
88OProcess::OProcess( const QString &arg0, QObject *parent, const char *name ) 89OProcess::OProcess( const QString &arg0, QObject *parent, const char *name )
89 : QObject( parent, name ) 90 : QObject( parent, name )
90{ 91{
91 init ( ); 92 init ( );
92 *this << arg0; 93 *this << arg0;
93} 94}
94 95
95OProcess::OProcess( const QStringList &args, QObject *parent, const char *name ) 96OProcess::OProcess( const QStringList &args, QObject *parent, const char *name )
96 : QObject( parent, name ) 97 : QObject( parent, name )
97{ 98{
98 init ( ); 99 init ( );
99 *this << args; 100 *this << args;
100} 101}
101 102
102void OProcess::init ( ) 103void OProcess::init ( )
103{ 104{
104 run_mode = NotifyOnExit; 105 run_mode = NotifyOnExit;
105 runs = false; 106 runs = false;
106 pid_ = 0; 107 pid_ = 0;
107 status = 0; 108 status = 0;
108 keepPrivs = false; 109 keepPrivs = false;
109 innot = 0; 110 innot = 0;
110 outnot = 0; 111 outnot = 0;
111 errnot = 0; 112 errnot = 0;
112 communication = NoCommunication; 113 communication = NoCommunication;
113 input_data = 0; 114 input_data = 0;
114 input_sent = 0; 115 input_sent = 0;
115 input_total = 0; 116 input_total = 0;
116 d = 0; 117 d = 0;
117 118
118 if ( 0 == OProcessController::theOProcessController ) 119 if ( 0 == OProcessController::theOProcessController )
119 { 120 {
120 ( void ) new OProcessController(); 121 ( void ) new OProcessController();
121 CHECK_PTR( OProcessController::theOProcessController ); 122 CHECK_PTR( OProcessController::theOProcessController );
122 } 123 }
123 124
124 OProcessController::theOProcessController->addOProcess( this ); 125 OProcessController::theOProcessController->addOProcess( this );
125 out[ 0 ] = out[ 1 ] = -1; 126 out[ 0 ] = out[ 1 ] = -1;
126 in[ 0 ] = in[ 1 ] = -1; 127 in[ 0 ] = in[ 1 ] = -1;
127 err[ 0 ] = err[ 1 ] = -1; 128 err[ 0 ] = err[ 1 ] = -1;
128} 129}
129 130
130void OProcess::setEnvironment( const QString &name, const QString &value ) 131void OProcess::setEnvironment( const QString &name, const QString &value )
131{ 132{
132 if ( !d ) 133 if ( !d )
133 d = new OProcessPrivate; 134 d = new OProcessPrivate;
134 d->env.insert( name, value ); 135 d->env.insert( name, value );
135} 136}
136 137
137void OProcess::setWorkingDirectory( const QString &dir ) 138void OProcess::setWorkingDirectory( const QString &dir )
138{ 139{
139 if ( !d ) 140 if ( !d )
140 d = new OProcessPrivate; 141 d = new OProcessPrivate;
141 d->wd = dir; 142 d->wd = dir;
142} 143}
143 144
144void OProcess::setupEnvironment() 145void OProcess::setupEnvironment()
145{ 146{
146 if ( d ) 147 if ( d )
147 { 148 {
148 QMap<QString, QString>::Iterator it; 149 QMap<QString, QString>::Iterator it;
149 for ( it = d->env.begin(); it != d->env.end(); ++it ) 150 for ( it = d->env.begin(); it != d->env.end(); ++it )
150 setenv( QFile::encodeName( it.key() ).data(), 151 setenv( QFile::encodeName( it.key() ).data(),
151 QFile::encodeName( it.data() ).data(), 1 ); 152 QFile::encodeName( it.data() ).data(), 1 );
152 if ( !d->wd.isEmpty() ) 153 if ( !d->wd.isEmpty() )
153 chdir( QFile::encodeName( d->wd ).data() ); 154 chdir( QFile::encodeName( d->wd ).data() );
154 } 155 }
155} 156}
156 157
157void OProcess::setRunPrivileged( bool keepPrivileges ) 158void OProcess::setRunPrivileged( bool keepPrivileges )
158{ 159{
159 keepPrivs = keepPrivileges; 160 keepPrivs = keepPrivileges;
160} 161}
161 162
162bool OProcess::runPrivileged() const 163bool OProcess::runPrivileged() const
163{ 164{
164 return keepPrivs; 165 return keepPrivs;
165} 166}
166 167
167OProcess::~OProcess() 168OProcess::~OProcess()
168{ 169{
169 // destroying the OProcess instance sends a SIGKILL to the 170 // destroying the OProcess instance sends a SIGKILL to the
170 // child process (if it is running) after removing it from the 171 // child process (if it is running) after removing it from the
171 // list of valid processes (if the process is not started as 172 // list of valid processes (if the process is not started as
172 // "DontCare") 173 // "DontCare")
173 174
174 OProcessController::theOProcessController->removeOProcess( this ); 175 OProcessController::theOProcessController->removeOProcess( this );
175 // this must happen before we kill the child 176 // this must happen before we kill the child
176 // TODO: block the signal while removing the current process from the process list 177 // TODO: block the signal while removing the current process from the process list
177 178
178 if ( runs && ( run_mode != DontCare ) ) 179 if ( runs && ( run_mode != DontCare ) )
179 kill( SIGKILL ); 180 kill( SIGKILL );
180 181
181 // Clean up open fd's and socket notifiers. 182 // Clean up open fd's and socket notifiers.
182 closeStdin(); 183 closeStdin();
183 closeStdout(); 184 closeStdout();
184 closeStderr(); 185 closeStderr();
185 186
186 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess 187 // TODO: restore SIGCHLD and SIGPIPE handler if this is the last OProcess
187 delete d; 188 delete d;
188} 189}
189 190
190void OProcess::detach() 191void OProcess::detach()
191{ 192{
192 OProcessController::theOProcessController->removeOProcess( this ); 193 OProcessController::theOProcessController->removeOProcess( this );
193 194
194 runs = false; 195 runs = false;
195 pid_ = 0; 196 pid_ = 0;
196 197
197 // Clean up open fd's and socket notifiers. 198 // Clean up open fd's and socket notifiers.
198 closeStdin(); 199 closeStdin();
199 closeStdout(); 200 closeStdout();
200 closeStderr(); 201 closeStderr();
201} 202}
202 203
203bool OProcess::setExecutable( const QString& proc ) 204bool OProcess::setExecutable( const QString& proc )
204{ 205{
205 if ( runs ) 206 if ( runs )
206 return false; 207 return false;
207 208
208 if ( proc.isEmpty() ) 209 if ( proc.isEmpty() )
209 return false; 210 return false;
210 211
211 if ( !arguments.isEmpty() ) 212 if ( !arguments.isEmpty() )
212 arguments.remove( arguments.begin() ); 213 arguments.remove( arguments.begin() );
213 arguments.prepend( QFile::encodeName( proc ) ); 214 arguments.prepend( QFile::encodeName( proc ) );
214 215
215 return true; 216 return true;
216} 217}
217 218
218OProcess &OProcess::operator<<( const QStringList& args ) 219OProcess &OProcess::operator<<( const QStringList& args )
219{ 220{
220 QStringList::ConstIterator it = args.begin(); 221 QStringList::ConstIterator it = args.begin();
221 for ( ; it != args.end() ; ++it ) 222 for ( ; it != args.end() ; ++it )
222 arguments.append( QFile::encodeName( *it ) ); 223 arguments.append( QFile::encodeName( *it ) );
223 return *this; 224 return *this;
224} 225}
225 226
226OProcess &OProcess::operator<<( const QCString& arg ) 227OProcess &OProcess::operator<<( const QCString& arg )
227{ 228{
228 return operator<< ( arg.data() ); 229 return operator<< ( arg.data() );
229} 230}
230 231
231OProcess &OProcess::operator<<( const char* arg ) 232OProcess &OProcess::operator<<( const char* arg )
232{ 233{
233 arguments.append( arg ); 234 arguments.append( arg );
234 return *this; 235 return *this;
235} 236}
236 237
237OProcess &OProcess::operator<<( const QString& arg ) 238OProcess &OProcess::operator<<( const QString& arg )
238{ 239{
239 arguments.append( QFile::encodeName( arg ) ); 240 arguments.append( QFile::encodeName( arg ) );
240 return *this; 241 return *this;
241} 242}
242 243
243void OProcess::clearArguments() 244void OProcess::clearArguments()
244{ 245{
245 arguments.clear(); 246 arguments.clear();
246} 247}
247 248
248bool OProcess::start( RunMode runmode, Communication comm ) 249bool OProcess::start( RunMode runmode, Communication comm )
249{ 250{
250 uint i; 251 uint i;
251 uint n = arguments.count(); 252 uint n = arguments.count();
252 char **arglist; 253 char **arglist;
253 254
254 if ( runs || ( 0 == n ) ) 255 if ( runs || ( 0 == n ) )
255 { 256 {
256 return false; // cannot start a process that is already running 257 return false; // cannot start a process that is already running
257 // or if no executable has been assigned 258 // or if no executable has been assigned
258 } 259 }
259 run_mode = runmode; 260 run_mode = runmode;
260 status = 0; 261 status = 0;
261 262
262 QCString shellCmd; 263 QCString shellCmd;
263 if ( d && d->useShell ) 264 if ( d && d->useShell )
264 { 265 {
265 if ( d->shell.isEmpty() ) 266 if ( d->shell.isEmpty() )
266 { 267 {
267 qWarning( "Could not find a valid shell" ); 268 qWarning( "Could not find a valid shell" );
268 return false; 269 return false;
269 } 270 }
270 271
271 arglist = static_cast<char **>( malloc( ( 4 ) * sizeof( char * ) ) ); 272 arglist = static_cast<char **>( malloc( ( 4 ) * sizeof( char * ) ) );
272 for ( i = 0; i < n; i++ ) 273 for ( i = 0; i < n; i++ )
273 { 274 {
274 shellCmd += arguments[ i ]; 275 shellCmd += arguments[ i ];
275 shellCmd += " "; // CC: to separate the arguments 276 shellCmd += " "; // CC: to separate the arguments
276 } 277 }
277 278
278 arglist[ 0 ] = d->shell.data(); 279 arglist[ 0 ] = d->shell.data();
279 arglist[ 1 ] = ( char * ) "-c"; 280 arglist[ 1 ] = ( char * ) "-c";
280 arglist[ 2 ] = shellCmd.data(); 281 arglist[ 2 ] = shellCmd.data();
281 arglist[ 3 ] = 0; 282 arglist[ 3 ] = 0;
282 } 283 }
283 else 284 else
284 { 285 {
285 arglist = static_cast<char **>( malloc( ( n + 1 ) * sizeof( char * ) ) ); 286 arglist = static_cast<char **>( malloc( ( n + 1 ) * sizeof( char * ) ) );
286 for ( i = 0; i < n; i++ ) 287 for ( i = 0; i < n; i++ )
287 arglist[ i ] = arguments[ i ].data(); 288 arglist[ i ] = arguments[ i ].data();
288 arglist[ n ] = 0; 289 arglist[ n ] = 0;
289 } 290 }
290 291
291 if ( !setupCommunication( comm ) ) 292 if ( !setupCommunication( comm ) )
292 qWarning( "Could not setup Communication!" ); 293 qWarning( "Could not setup Communication!" );
293 294
294 // We do this in the parent because if we do it in the child process 295 // We do this in the parent because if we do it in the child process
295 // gdb gets confused when the application runs from gdb. 296 // gdb gets confused when the application runs from gdb.
296 uid_t uid = getuid(); 297 uid_t uid = getuid();
297 gid_t gid = getgid(); 298 gid_t gid = getgid();
298#ifdef HAVE_INITGROUPS 299#ifdef HAVE_INITGROUPS
299 300
300 struct passwd *pw = getpwuid( uid ); 301 struct passwd *pw = getpwuid( uid );
301#endif 302#endif
302 303
303 int fd[ 2 ]; 304 int fd[ 2 ];
304 if ( 0 > pipe( fd ) ) 305 if ( 0 > pipe( fd ) )
305 { 306 {
306 fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue 307 fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue
307 } 308 }
308 309
309 runs = true; 310 runs = true;
310 311
311 QApplication::flushX(); 312 QApplication::flushX();
312 313
313 // WABA: Note that we use fork() and not vfork() because 314 // WABA: Note that we use fork() and not vfork() because
314 // vfork() has unclear semantics and is not standardized. 315 // vfork() has unclear semantics and is not standardized.
315 pid_ = fork(); 316 pid_ = fork();
316 317
317 if ( 0 == pid_ ) 318 if ( 0 == pid_ )
318 { 319 {
319 if ( fd[ 0 ] ) 320 if ( fd[ 0 ] )
320 close( fd[ 0 ] ); 321 close( fd[ 0 ] );
321 if ( !runPrivileged() ) 322 if ( !runPrivileged() )
322 { 323 {
323 setgid( gid ); 324 setgid( gid );
324#if defined( HAVE_INITGROUPS) 325#if defined( HAVE_INITGROUPS)
325 326
326 if ( pw ) 327 if ( pw )
327 initgroups( pw->pw_name, pw->pw_gid ); 328 initgroups( pw->pw_name, pw->pw_gid );
328#endif 329#endif
329 330
330 setuid( uid ); 331 setuid( uid );
331 } 332 }
332 // The child process 333 // The child process
333 if ( !commSetupDoneC() ) 334 if ( !commSetupDoneC() )
334 qWarning( "Could not finish comm setup in child!" ); 335 qWarning( "Could not finish comm setup in child!" );
335 336
336 setupEnvironment(); 337 setupEnvironment();
337 338
338 // Matthias 339 // Matthias
339 if ( run_mode == DontCare ) 340 if ( run_mode == DontCare )
340 setpgid( 0, 0 ); 341 setpgid( 0, 0 );
341 // restore default SIGPIPE handler (Harri) 342 // restore default SIGPIPE handler (Harri)
342 struct sigaction act; 343 struct sigaction act;
343 sigemptyset( &( act.sa_mask ) ); 344 sigemptyset( &( act.sa_mask ) );
344 sigaddset( &( act.sa_mask ), SIGPIPE ); 345 sigaddset( &( act.sa_mask ), SIGPIPE );
345 act.sa_handler = SIG_DFL; 346 act.sa_handler = SIG_DFL;
346 act.sa_flags = 0; 347 act.sa_flags = 0;
347 sigaction( SIGPIPE, &act, 0L ); 348 sigaction( SIGPIPE, &act, 0L );
348 349
349 // We set the close on exec flag. 350 // We set the close on exec flag.
350 // Closing of fd[1] indicates that the execvp succeeded! 351 // Closing of fd[1] indicates that the execvp succeeded!
351 if ( fd[ 1 ] ) 352 if ( fd[ 1 ] )
352 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC ); 353 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC );
353 execvp( arglist[ 0 ], arglist ); 354 execvp( arglist[ 0 ], arglist );
354 char resultByte = 1; 355 char resultByte = 1;
355 if ( fd[ 1 ] ) 356 if ( fd[ 1 ] )
356 write( fd[ 1 ], &resultByte, 1 ); 357 write( fd[ 1 ], &resultByte, 1 );
357 _exit( -1 ); 358 _exit( -1 );
358 } 359 }
359 else if ( -1 == pid_ ) 360 else if ( -1 == pid_ )
360 { 361 {
361 // forking failed 362 // forking failed
362 363
363 runs = false; 364 runs = false;
364 free( arglist ); 365 free( arglist );
365 return false; 366 return false;
366 } 367 }
367 else 368 else
368 { 369 {
369 if ( fd[ 1 ] ) 370 if ( fd[ 1 ] )
370 close( fd[ 1 ] ); 371 close( fd[ 1 ] );
371 // the parent continues here 372 // the parent continues here
372 373
373 // Discard any data for stdin that might still be there 374 // Discard any data for stdin that might still be there
374 input_data = 0; 375 input_data = 0;
375 376
376 // Check whether client could be started. 377 // Check whether client could be started.
377 if ( fd[ 0 ] ) 378 if ( fd[ 0 ] )
378 for ( ;; ) 379 for ( ;; )
379 { 380 {
380 char resultByte; 381 char resultByte;
381 int n = ::read( fd[ 0 ], &resultByte, 1 ); 382 int n = ::read( fd[ 0 ], &resultByte, 1 );
382 if ( n == 1 ) 383 if ( n == 1 )
383 { 384 {
384 // Error 385 // Error
385 runs = false; 386 runs = false;
386 close( fd[ 0 ] ); 387 close( fd[ 0 ] );
387 free( arglist ); 388 free( arglist );
388 pid_ = 0; 389 pid_ = 0;
389 return false; 390 return false;
390 } 391 }
391 if ( n == -1 ) 392 if ( n == -1 )
392 { 393 {
393 if ( ( errno == ECHILD ) || ( errno == EINTR ) ) 394 if ( ( errno == ECHILD ) || ( errno == EINTR ) )
394 continue; // Ignore 395 continue; // Ignore
395 } 396 }
396 break; // success 397 break; // success
397 } 398 }
398 if ( fd[ 0 ] ) 399 if ( fd[ 0 ] )
399 close( fd[ 0 ] ); 400 close( fd[ 0 ] );
400 401
401 if ( !commSetupDoneP() ) // finish communication socket setup for the parent 402 if ( !commSetupDoneP() ) // finish communication socket setup for the parent
402 qWarning( "Could not finish comm setup in parent!" ); 403 qWarning( "Could not finish comm setup in parent!" );
403 404
404 if ( run_mode == Block ) 405 if ( run_mode == Block )
405 { 406 {
406 commClose(); 407 commClose();
407 408
408 // The SIGCHLD handler of the process controller will catch 409 // The SIGCHLD handler of the process controller will catch
409 // the exit and set the status 410 // the exit and set the status
410 while ( runs ) 411 while ( runs )
411 { 412 {
412 OProcessController::theOProcessController-> 413 OProcessController::theOProcessController->
413 slotDoHousekeeping( 0 ); 414 slotDoHousekeeping( 0 );
414 } 415 }
415 runs = FALSE; 416 runs = FALSE;
416 emit processExited( this ); 417 emit processExited( this );
417 } 418 }
418 } 419 }
419 free( arglist ); 420 free( arglist );
420 return true; 421 return true;
421} 422}
422 423
423 424
424 425