summaryrefslogtreecommitdiff
path: root/noncore/net/opietooth/lib/forwarder.cc
Unidiff
Diffstat (limited to 'noncore/net/opietooth/lib/forwarder.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/net/opietooth/lib/forwarder.cc203
1 files changed, 203 insertions, 0 deletions
diff --git a/noncore/net/opietooth/lib/forwarder.cc b/noncore/net/opietooth/lib/forwarder.cc
new file mode 100644
index 0000000..c38f5b8
--- a/dev/null
+++ b/noncore/net/opietooth/lib/forwarder.cc
@@ -0,0 +1,203 @@
1/* $Id$
2 *Bluetooth serial forwarder class implementation
3 *
4 *(c) Copyright 2006 GPL
5 *
6 *This software is provided under the GNU public license, incorporated
7 *herein by reference. The software is provided without warranty or
8 *support.
9 */
10#include "bt-serial.h"
11#include <sys/types.h>
12#include <sys/wait.h>
13#include <errno.h>
14#include <stdlib.h>
15#include <fcntl.h>
16#include <qapplication.h>
17#include <opie2/oprocctrl.h>
18#include "forwarder.h"
19using namespace OpieTooth;
20using namespace Opie::Core;
21using namespace Opie::Core::Internal;
22
23SerialForwarder::SerialForwarder(QString& devName, int dspeed) :
24 OProcess(), device(devName), speed(dspeed)
25{
26 status = false;
27}
28
29SerialForwarder::~SerialForwarder()
30{
31 stop();
32}
33
34
35bool SerialForwarder::start(RunMode runmode, Communication comm)
36{
37 int htmp; //temporary device
38 int result; //call result
39
40 if ( runs )
41 {
42 return false; // cannot start a process that is already running
43 // or if no executable has been assigned
44 }
45 //First, check if serial device is usable
46 htmp = ::openSerial(device);
47 if (htmp < 0)
48 return false;
49 close(htmp);
50
51 run_mode = runmode;
52 status = 0;
53
54 if(::bt_serialStart() < 0)
55 return false;
56
57 if ( !setupCommunication( comm ) )
58 qWarning( "Could not setup Communication!" );
59
60 // We do this in the parent because if we do it in the child process
61 // gdb gets confused when the application runs from gdb.
62 uid_t uid = getuid();
63 gid_t gid = getgid();
64#ifdef HAVE_INITGROUPS
65
66 struct passwd *pw = getpwuid( uid );
67#endif
68
69 int fd[ 2 ];
70 if ( 0 > pipe( fd ) )
71 {
72 fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue
73 }
74
75 runs = true;
76
77 QApplication::flushX();
78
79 // WABA: Note that we use fork() and not vfork() because
80 // vfork() has unclear semantics and is not standardized.
81 pid_ = fork();
82
83 if ( 0 == pid_ )
84 {
85 if ( fd[ 0 ] )
86 close( fd[ 0 ] );
87 if ( !runPrivileged() )
88 {
89 setgid( gid );
90#if defined( HAVE_INITGROUPS)
91
92 if ( pw )
93 initgroups( pw->pw_name, pw->pw_gid );
94#endif
95
96 setuid( uid );
97 }
98 // The child process
99 if ( !commSetupDoneC() )
100 qWarning( "Could not finish comm setup in child!" );
101
102 setupEnvironment();
103
104 // Matthias
105 if ( run_mode == DontCare )
106 setpgid( 0, 0 );
107 // restore default SIGPIPE handler (Harri)
108 struct sigaction act;
109 sigemptyset( &( act.sa_mask ) );
110 sigaddset( &( act.sa_mask ), SIGPIPE );
111 act.sa_handler = SIG_DFL;
112 act.sa_flags = 0;
113 sigaction( SIGPIPE, &act, 0L );
114
115 // We set the close on exec flag.
116 // Closing of fd[1] indicates that the execvp succeeded!
117 if ( fd[ 1 ] )
118 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC );
119 do {
120 BTSerialConn conn; //Connection handler
121 if ( fd[ 1 ] ) {
122 ::close(fd[1]);
123 fd[1] = 0;
124 }
125 result = ::bt_serialForward(&conn, device);
126 } while(result == 0);
127
128 char resultByte = 1;
129 if ( fd[ 1 ] )
130 write( fd[ 1 ], &resultByte, 1 );
131 _exit( -1 );
132 }
133 else if ( -1 == pid_ )
134 {
135 // forking failed
136
137 runs = false;
138 return false;
139 }
140 else
141 {
142 if ( fd[ 1 ] )
143 close( fd[ 1 ] );
144 // the parent continues here
145
146 // Discard any data for stdin that might still be there
147 input_data = 0;
148
149 // Check whether client could be started.
150 if ( fd[ 0 ] )
151 for ( ;; )
152 {
153 char resultByte;
154 int n = ::read( fd[ 0 ], &resultByte, 1 );
155 if ( n == 1 )
156 {
157 // Error
158 runs = false;
159 close( fd[ 0 ] );
160 pid_ = 0;
161 return false;
162 }
163 if ( n == -1 )
164 {
165 if ( ( errno == ECHILD ) || ( errno == EINTR ) )
166 continue; // Ignore
167 }
168 break; // success
169 }
170 if ( fd[ 0 ] )
171 close( fd[ 0 ] );
172
173 if ( !commSetupDoneP() ) // finish communication socket setup for the parent
174 qWarning( "Could not finish comm setup in parent!" );
175
176 if ( run_mode == Block )
177 {
178 commClose();
179
180 // The SIGCHLD handler of the process controller will catch
181 // the exit and set the status
182 while ( runs )
183 {
184 OProcessController::theOProcessController->
185 slotDoHousekeeping( 0 );
186 }
187 runs = FALSE;
188 emit processExited( this );
189 }
190 }
191 return true;
192}
193
194/*
195 * Stop forwarding process
196 */
197int SerialForwarder::stop()
198{
199 kill(SIGTERM);
200 ::bt_serialStop();
201 return 0;
202}
203//eof