summaryrefslogtreecommitdiff
authorMichael Krelin <hacker@klever.net>2007-07-15 23:55:02 (UTC)
committer Michael Krelin <hacker@klever.net>2007-07-15 23:55:02 (UTC)
commit174edcd91bcb969c4ee71a824849d8737223dd8f (patch) (unidiff)
tree912ef42f7902a1c400ed469e8abc322346765ef3
parent655a28b22bfb5cb2b8080eaf8f3c3d0ef769882e (diff)
downloadopie-174edcd91bcb969c4ee71a824849d8737223dd8f.zip
opie-174edcd91bcb969c4ee71a824849d8737223dd8f.tar.gz
opie-174edcd91bcb969c4ee71a824849d8737223dd8f.tar.bz2
unbreak error handling while preserving functionality
- exit after disconnecting - spit out error message on error - don't close fd in the loop, once is enough
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/obex/obexserver.cpp15
1 files changed, 9 insertions, 6 deletions
diff --git a/core/obex/obexserver.cpp b/core/obex/obexserver.cpp
index 786e9f7..286961f 100644
--- a/core/obex/obexserver.cpp
+++ b/core/obex/obexserver.cpp
@@ -25,497 +25,500 @@
25 Boston, MA 02111-1307, USA. 25 Boston, MA 02111-1307, USA.
26 26
27*/ 27*/
28/* 28/*
29 * The OBEX server class implementation 29 * The OBEX server class implementation
30 * Based on OBEX server from GPE (thanks, guys) 30 * Based on OBEX server from GPE (thanks, guys)
31 */ 31 */
32 32
33#include "obexserver.h" 33#include "obexserver.h"
34#include <unistd.h> 34#include <unistd.h>
35#include <opie2/odebug.h> 35#include <opie2/odebug.h>
36#include <sys/types.h> 36#include <sys/types.h>
37#include <sys/wait.h> 37#include <sys/wait.h>
38#include <errno.h> 38#include <errno.h>
39#include <stdlib.h> 39#include <stdlib.h>
40#include <stdio.h> 40#include <stdio.h>
41#include <fcntl.h> 41#include <fcntl.h>
42#include <qapplication.h> 42#include <qapplication.h>
43#include <opie2/oprocctrl.h> 43#include <opie2/oprocctrl.h>
44#include <qstring.h> 44#include <qstring.h>
45#include <qfile.h> 45#include <qfile.h>
46 46
47using namespace Opie::Core; 47using namespace Opie::Core;
48using namespace Opie::Core::Internal; 48using namespace Opie::Core::Internal;
49using namespace OpieObex; 49using namespace OpieObex;
50 50
51ObexServer::ObexServer(int trans) : 51ObexServer::ObexServer(int trans) :
52 OProcess(tr("ObexServer"), 0, "ObexServer") 52 OProcess(tr("ObexServer"), 0, "ObexServer")
53{ 53{
54 transport = trans; 54 transport = trans;
55 m_obex = NULL; 55 m_obex = NULL;
56} 56}
57 57
58ObexServer::~ObexServer() 58ObexServer::~ObexServer()
59{ 59{
60 stop(); 60 stop();
61} 61}
62 62
63/** 63/**
64 * Function handles the file received 64 * Function handles the file received
65 * @param name the file name 65 * @param name the file name
66 * @param data the file data 66 * @param data the file data
67 * @param data_len the data length 67 * @param data_len the data length
68 * @return 0 on success -1 on error 68 * @return 0 on success -1 on error
69 */ 69 */
70static int file_received(uint8_t* name, const uint8_t* data, size_t data_len) 70static int file_received(uint8_t* name, const uint8_t* data, size_t data_len)
71{ 71{
72 QString path("/tmp/"); 72 QString path("/tmp/");
73 path += (char*)name; 73 path += (char*)name;
74 QFile out(path); 74 QFile out(path);
75 int err = 0; 75 int err = 0;
76 76
77 if (!out.open(IO_Raw | IO_ReadWrite | IO_Truncate)) { 77 if (!out.open(IO_Raw | IO_ReadWrite | IO_Truncate)) {
78 printf("File %s open error %d\n", (const char*)path, errno); 78 printf("File %s open error %d\n", (const char*)path, errno);
79 err = -1; 79 err = -1;
80 goto out; 80 goto out;
81 } 81 }
82 if (out.writeBlock((const char*)data, data_len) < 0) { 82 if (out.writeBlock((const char*)data, data_len) < 0) {
83 printf("File %s write error %d\n", (const char*)path, errno); 83 printf("File %s write error %d\n", (const char*)path, errno);
84 err = -1; 84 err = -1;
85 goto out; 85 goto out;
86 } 86 }
87out: 87out:
88 out.close(); 88 out.close();
89 if (err == 0) { 89 if (err == 0) {
90 printf("Wrote %s (%d bytes)\n", (const char*)path, data_len); 90 printf("Wrote %s (%d bytes)\n", (const char*)path, data_len);
91 fflush(stdout); 91 fflush(stdout);
92 } 92 }
93 return err; 93 return err;
94} 94}
95 95
96/** 96/**
97 * Function handles the situation when the PUT request has been done 97 * Function handles the situation when the PUT request has been done
98 * @param handle OBEX connection handle 98 * @param handle OBEX connection handle
99 * @param object OBEX object itself 99 * @param object OBEX object itself
100 */ 100 */
101static int put_done(obex_t* handle, obex_object_t* object) 101static int put_done(obex_t* handle, obex_object_t* object)
102{ 102{
103 obex_headerdata_t hv; //Received file header 103 obex_headerdata_t hv; //Received file header
104 uint8_t hi; //Type of the request 104 uint8_t hi; //Type of the request
105 uint32_t hlen; //File (file name) length 105 uint32_t hlen; //File (file name) length
106 int err = 0; 106 int err = 0;
107 107
108 const uint8_t *body = NULL; 108 const uint8_t *body = NULL;
109 int body_len = 0; 109 int body_len = 0;
110 uint8_t* name = NULL; 110 uint8_t* name = NULL;
111 111
112 while (OBEX_ObjectGetNextHeader (handle, object, &hi, &hv, &hlen)) { 112 while (OBEX_ObjectGetNextHeader (handle, object, &hi, &hv, &hlen)) {
113 switch(hi) { 113 switch(hi) {
114 case OBEX_HDR_BODY: 114 case OBEX_HDR_BODY:
115 body = hv.bs; 115 body = hv.bs;
116 body_len = hlen; 116 body_len = hlen;
117 break; 117 break;
118 118
119 case OBEX_HDR_NAME: 119 case OBEX_HDR_NAME:
120 name = new uint8_t[(hlen / 2) + 1]; 120 name = new uint8_t[(hlen / 2) + 1];
121 OBEX_UnicodeToChar(name, hv.bs, hlen); 121 OBEX_UnicodeToChar(name, hv.bs, hlen);
122 break; 122 break;
123 123
124 default: 124 default:
125 break; 125 break;
126 } 126 }
127 } 127 }
128 128
129 if (body) 129 if (body)
130 err = file_received(name, body, body_len); 130 err = file_received(name, body, body_len);
131 131
132 if (name) 132 if (name)
133 delete[] name; 133 delete[] name;
134 return err; 134 return err;
135} 135}
136 136
137/** 137/**
138 * Function handles OBEX request 138 * Function handles OBEX request
139 * @param handle OBEX connection handle 139 * @param handle OBEX connection handle
140 * @param object OBEX object itself 140 * @param object OBEX object itself
141 * @param mode 141 * @param mode
142 * @param event event code 142 * @param event event code
143 * @param cmd OBEX command itself 143 * @param cmd OBEX command itself
144 */ 144 */
145static void handle_request (obex_t* handle, obex_object_t* object, 145static void handle_request (obex_t* handle, obex_object_t* object,
146 int event, int cmd) 146 int event, int cmd)
147{ 147{
148 (void)event; 148 (void)event;
149 switch(cmd){ 149 switch(cmd){
150 case OBEX_CMD_SETPATH: 150 case OBEX_CMD_SETPATH:
151 OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); 151 OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
152 break; 152 break;
153 case OBEX_CMD_PUT: 153 case OBEX_CMD_PUT:
154 if (put_done (handle, object) < 0) 154 if (put_done (handle, object) < 0)
155 OBEX_ObjectSetRsp (object, OBEX_RSP_INTERNAL_SERVER_ERROR, 155 OBEX_ObjectSetRsp (object, OBEX_RSP_INTERNAL_SERVER_ERROR,
156 OBEX_RSP_INTERNAL_SERVER_ERROR); 156 OBEX_RSP_INTERNAL_SERVER_ERROR);
157 else 157 else
158 OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); 158 OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
159 break; 159 break;
160 case OBEX_CMD_CONNECT: 160 case OBEX_CMD_CONNECT:
161 OBEX_ObjectSetRsp (object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS); 161 OBEX_ObjectSetRsp (object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS);
162 break; 162 break;
163 case OBEX_CMD_DISCONNECT: 163 case OBEX_CMD_DISCONNECT:
164 OBEX_ObjectSetRsp (object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS); 164 OBEX_ObjectSetRsp (object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS);
165 break; 165 break;
166 default: 166 default:
167 printf("Denied %02x request\n", cmd); 167 printf("Denied %02x request\n", cmd);
168 fflush(stdout); 168 fflush(stdout);
169 OBEX_ObjectSetRsp (object, OBEX_RSP_NOT_IMPLEMENTED, 169 OBEX_ObjectSetRsp (object, OBEX_RSP_NOT_IMPLEMENTED,
170 OBEX_RSP_NOT_IMPLEMENTED); 170 OBEX_RSP_NOT_IMPLEMENTED);
171 break; 171 break;
172 } 172 }
173} 173}
174 174
175 175
176/** 176/**
177 * Function handles OBEX event when a client is connected to the server 177 * Function handles OBEX event when a client is connected to the server
178 * @param handle OBEX connection handle 178 * @param handle OBEX connection handle
179 * @param object OBEX object itself 179 * @param object OBEX object itself
180 * @param mode 180 * @param mode
181 * @param event event code 181 * @param event event code
182 * @param obex_cmd OBEX command itself 182 * @param obex_cmd OBEX command itself
183 * @param obex_rsp OBEX responce 183 * @param obex_rsp OBEX responce
184 */ 184 */
185static void obex_conn_event (obex_t *handle, obex_object_t *object, 185static void obex_conn_event (obex_t *handle, obex_object_t *object,
186 int mode, int event, int obex_cmd, int obex_rsp) 186 int mode, int event, int obex_cmd, int obex_rsp)
187{ 187{
188 (void)mode; 188 (void)mode;
189 (void)obex_rsp; 189 (void)obex_rsp;
190 190
191 switch(event) { 191 switch(event) {
192 case OBEX_EV_REQHINT: 192 case OBEX_EV_REQHINT:
193 switch(obex_cmd) { 193 switch(obex_cmd) {
194 case OBEX_CMD_PUT: 194 case OBEX_CMD_PUT:
195 case OBEX_CMD_CONNECT: 195 case OBEX_CMD_CONNECT:
196 case OBEX_CMD_DISCONNECT: 196 case OBEX_CMD_DISCONNECT:
197 OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); 197 OBEX_ObjectSetRsp (object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
198 break; 198 break;
199 default: 199 default:
200 OBEX_ObjectSetRsp (object, OBEX_RSP_NOT_IMPLEMENTED, 200 OBEX_ObjectSetRsp (object, OBEX_RSP_NOT_IMPLEMENTED,
201 OBEX_RSP_NOT_IMPLEMENTED); 201 OBEX_RSP_NOT_IMPLEMENTED);
202 break; 202 break;
203 } 203 }
204 break; 204 break;
205 205
206 case OBEX_EV_REQ: 206 case OBEX_EV_REQ:
207 /* Comes when a server-request has been received. */ 207 /* Comes when a server-request has been received. */
208 handle_request (handle, object, event, obex_cmd); 208 handle_request (handle, object, event, obex_cmd);
209 break; 209 break;
210 case OBEX_EV_REQDONE: 210 case OBEX_EV_REQDONE:
211 switch(obex_cmd) { 211 switch(obex_cmd) {
212 case OBEX_CMD_PUT: 212 case OBEX_CMD_PUT:
213 case OBEX_CMD_CONNECT: 213 case OBEX_CMD_CONNECT:
214 break; 214 break;
215 case OBEX_CMD_DISCONNECT: 215 case OBEX_CMD_DISCONNECT:
216 OBEX_TransportDisconnect(handle); 216 OBEX_TransportDisconnect(handle);
217 _exit(0);
217 break; 218 break;
218 default: 219 default:
219 break; 220 break;
220 } 221 }
221 break; 222 break;
222 case OBEX_EV_LINKERR: 223 case OBEX_EV_LINKERR:
223 break; 224 break;
224 } 225 }
225} 226}
226 227
227/** 228/**
228 * Function handles OBEX event 229 * Function handles OBEX event
229 * @param handle OBEX connection handle 230 * @param handle OBEX connection handle
230 * @param object OBEX object itself 231 * @param object OBEX object itself
231 * @param mode 232 * @param mode
232 * @param event event code 233 * @param event event code
233 * @param obex_cmd OBEX command itself 234 * @param obex_cmd OBEX command itself
234 * @param obex_rsp OBEX responce 235 * @param obex_rsp OBEX responce
235 */ 236 */
236static void obex_event (obex_t* handle, obex_object_t* object, int mode, 237static void obex_event (obex_t* handle, obex_object_t* object, int mode,
237 int event, int obex_cmd, int obex_rsp) 238 int event, int obex_cmd, int obex_rsp)
238{ 239{
239 240
240 obex_t *obex; //OBEX connection handle 241 obex_t *obex; //OBEX connection handle
241 242
242 switch (event) { 243 switch (event) {
243 case OBEX_EV_ACCEPTHINT: 244 case OBEX_EV_ACCEPTHINT:
244 obex = OBEX_ServerAccept (handle, obex_conn_event, NULL); 245 obex = OBEX_ServerAccept (handle, obex_conn_event, NULL);
245 break; 246 break;
246 247
247 default: 248 default:
248 obex_conn_event(handle, object, mode, event, obex_cmd, obex_rsp); 249 obex_conn_event(handle, object, mode, event, obex_cmd, obex_rsp);
249 } 250 }
250} 251}
251 252
252/** 253/**
253 * Function registers OBEX push service on a specified channel 254 * Function registers OBEX push service on a specified channel
254 * Based on The same function from GPE. 255 * Based on The same function from GPE.
255 * @param session SDP session 256 * @param session SDP session
256 * @param chan channel to listen 257 * @param chan channel to listen
257 * @name name to show 258 * @name name to show
258 */ 259 */
259sdp_session_t* ObexServer::addOpushSvc(uint8_t chan, const char* name) 260sdp_session_t* ObexServer::addOpushSvc(uint8_t chan, const char* name)
260{ 261{
261 sdp_list_t *svclass_id, *pfseq, *apseq, *root; 262 sdp_list_t *svclass_id, *pfseq, *apseq, *root;
262 uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; 263 uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid;
263 sdp_profile_desc_t profile[1]; 264 sdp_profile_desc_t profile[1];
264 sdp_list_t *aproto, *proto[3]; 265 sdp_list_t *aproto, *proto[3];
265 sdp_record_t record; 266 sdp_record_t record;
266 sdp_data_t *channel; 267 sdp_data_t *channel;
267 uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; 268 uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
268 //uint8_t formats[] = { 0xff }; 269 //uint8_t formats[] = { 0xff };
269 void *dtds[sizeof(formats)], *values[sizeof(formats)]; 270 void *dtds[sizeof(formats)], *values[sizeof(formats)];
270 unsigned int i; 271 unsigned int i;
271 uint8_t dtd = SDP_UINT8; 272 uint8_t dtd = SDP_UINT8;
272 sdp_data_t *sflist; 273 sdp_data_t *sflist;
273 int err = 0; 274 int err = 0;
274 sdp_session_t* lsession = 0; 275 sdp_session_t* lsession = 0;
275 276
276 memset((void *)&record, 0, sizeof(sdp_record_t)); 277 memset((void *)&record, 0, sizeof(sdp_record_t));
277 record.handle = 0xffffffff; 278 record.handle = 0xffffffff;
278 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); 279 sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
279 root = sdp_list_append(0, &root_uuid); 280 root = sdp_list_append(0, &root_uuid);
280 sdp_set_browse_groups(&record, root); 281 sdp_set_browse_groups(&record, root);
281 282
282 sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID); 283 sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID);
283 svclass_id = sdp_list_append(0, &opush_uuid); 284 svclass_id = sdp_list_append(0, &opush_uuid);
284 sdp_set_service_classes(&record, svclass_id); 285 sdp_set_service_classes(&record, svclass_id);
285 286
286 sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID); 287 sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID);
287 profile[0].version = 0x0100; 288 profile[0].version = 0x0100;
288 pfseq = sdp_list_append(0, profile); 289 pfseq = sdp_list_append(0, profile);
289 sdp_set_profile_descs(&record, pfseq); 290 sdp_set_profile_descs(&record, pfseq);
290 291
291 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); 292 sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
292 proto[0] = sdp_list_append(0, &l2cap_uuid); 293 proto[0] = sdp_list_append(0, &l2cap_uuid);
293 apseq = sdp_list_append(0, proto[0]); 294 apseq = sdp_list_append(0, proto[0]);
294 295
295 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); 296 sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
296 proto[1] = sdp_list_append(0, &rfcomm_uuid); 297 proto[1] = sdp_list_append(0, &rfcomm_uuid);
297 channel = sdp_data_alloc(SDP_UINT8, &chan); 298 channel = sdp_data_alloc(SDP_UINT8, &chan);
298 proto[1] = sdp_list_append(proto[1], channel); 299 proto[1] = sdp_list_append(proto[1], channel);
299 apseq = sdp_list_append(apseq, proto[1]); 300 apseq = sdp_list_append(apseq, proto[1]);
300 301
301 sdp_uuid16_create(&obex_uuid, OBEX_UUID); 302 sdp_uuid16_create(&obex_uuid, OBEX_UUID);
302 proto[2] = sdp_list_append(0, &obex_uuid); 303 proto[2] = sdp_list_append(0, &obex_uuid);
303 apseq = sdp_list_append(apseq, proto[2]); 304 apseq = sdp_list_append(apseq, proto[2]);
304 305
305 aproto = sdp_list_append(0, apseq); 306 aproto = sdp_list_append(0, apseq);
306 sdp_set_access_protos(&record, aproto); 307 sdp_set_access_protos(&record, aproto);
307 308
308 for (i = 0; i < sizeof(formats); i++) 309 for (i = 0; i < sizeof(formats); i++)
309 { 310 {
310 dtds[i] = &dtd; 311 dtds[i] = &dtd;
311 values[i] = &formats[i]; 312 values[i] = &formats[i];
312 } 313 }
313 sflist = sdp_seq_alloc(dtds, values, sizeof(formats)); 314 sflist = sdp_seq_alloc(dtds, values, sizeof(formats));
314 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist); 315 sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist);
315 316
316 sdp_set_info_attr(&record, name, 0, 0); 317 sdp_set_info_attr(&record, name, 0, 0);
317 318
318 // connect to the local SDP server, register the service record, and 319 // connect to the local SDP server, register the service record, and
319 // disconnect 320 // disconnect
320 lsession = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); 321 lsession = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
321 if (lsession == NULL) 322 if (lsession == NULL)
322 goto errout; 323 goto errout;
323 err = sdp_record_register(lsession, &record, 0); 324 err = sdp_record_register(lsession, &record, 0);
324 if (err) { 325 if (err) {
325 sdp_close(lsession); 326 sdp_close(lsession);
326 lsession = NULL; 327 lsession = NULL;
327 } 328 }
328errout: 329errout:
329 sdp_data_free(channel); 330 sdp_data_free(channel);
330 sdp_list_free(proto[0], 0); 331 sdp_list_free(proto[0], 0);
331 sdp_list_free(proto[1], 0); 332 sdp_list_free(proto[1], 0);
332 sdp_list_free(proto[2], 0); 333 sdp_list_free(proto[2], 0);
333 sdp_list_free(apseq, 0); 334 sdp_list_free(apseq, 0);
334 sdp_list_free(aproto, 0); 335 sdp_list_free(aproto, 0);
335 336
336 return lsession; 337 return lsession;
337} 338}
338 339
339int ObexServer::initObex(void) 340int ObexServer::initObex(void)
340{ 341{
341 int channel = 10; //Channel on which we do listen 342 int channel = 10; //Channel on which we do listen
342 if (m_obex) 343 if (m_obex)
343 return 0; 344 return 0;
344 m_obex = ::OBEX_Init(transport, obex_event, 0); 345 m_obex = ::OBEX_Init(transport, obex_event, 0);
345 if (!m_obex) { 346 if (!m_obex) {
346 printf("OBEX initialization error %d\n", errno); 347 printf("OBEX initialization error %d\n", errno);
347 return -1; 348 return -1;
348 } 349 }
349 if (transport == OBEX_TRANS_BLUETOOTH) { 350 if (transport == OBEX_TRANS_BLUETOOTH) {
350 ::BtOBEX_ServerRegister(m_obex, NULL, channel); 351 ::BtOBEX_ServerRegister(m_obex, NULL, channel);
351 m_session = addOpushSvc(channel, "OBEX Object Push"); 352 m_session = addOpushSvc(channel, "OBEX Object Push");
352 if (!m_session) { 353 if (!m_session) {
353 printf("OBEX registration error %d\n", errno); 354 printf("OBEX registration error %d\n", errno);
354 ::OBEX_Cleanup(m_obex); 355 ::OBEX_Cleanup(m_obex);
355 m_obex = NULL; 356 m_obex = NULL;
356 return -1; 357 return -1;
357 } 358 }
358 } else if (transport == OBEX_TRANS_IRDA) 359 } else if (transport == OBEX_TRANS_IRDA)
359 ::IrOBEX_ServerRegister(m_obex, "OBEX"); 360 ::IrOBEX_ServerRegister(m_obex, "OBEX");
360 return 0; 361 return 0;
361} 362}
362 363
363bool ObexServer::start(RunMode runmode, Communication comm) 364bool ObexServer::start(RunMode runmode, Communication comm)
364{ 365{
365 if ( runs ) 366 if ( runs )
366 { 367 {
367 return false; // cannot start a process that is already running 368 return false; // cannot start a process that is already running
368 // or if no executable has been assigned 369 // or if no executable has been assigned
369 } 370 }
370 run_mode = runmode; 371 run_mode = runmode;
371 status = 0; 372 status = 0;
372 373
373 if ( !setupCommunication( comm ) ) 374 if ( !setupCommunication( comm ) )
374 qWarning( "Could not setup Communication!" ); 375 qWarning( "Could not setup Communication!" );
375 376
376 // We do this in the parent because if we do it in the child process 377 // We do this in the parent because if we do it in the child process
377 // gdb gets confused when the application runs from gdb. 378 // gdb gets confused when the application runs from gdb.
378 uid_t uid = getuid(); 379 uid_t uid = getuid();
379 gid_t gid = getgid(); 380 gid_t gid = getgid();
380#ifdef HAVE_INITGROUPS 381#ifdef HAVE_INITGROUPS
381 382
382 struct passwd *pw = getpwuid( uid ); 383 struct passwd *pw = getpwuid( uid );
383#endif 384#endif
384 385
385 int fd[ 2 ]; 386 int fd[ 2 ];
386 if ( 0 > pipe( fd ) ) 387 if ( 0 > pipe( fd ) )
387 { 388 {
388 fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue 389 fd[ 0 ] = fd[ 1 ] = 0; // Pipe failed.. continue
389 } 390 }
390 391
391 runs = true; 392 runs = true;
392 393
393 QApplication::flushX(); 394 QApplication::flushX();
394 395
395 // WABA: Note that we use fork() and not vfork() because 396 // WABA: Note that we use fork() and not vfork() because
396 // vfork() has unclear semantics and is not standardized. 397 // vfork() has unclear semantics and is not standardized.
397 pid_ = fork(); 398 pid_ = fork();
398 399
399 if ( 0 == pid_ ) 400 if ( 0 == pid_ )
400 { 401 {
401 if ( fd[ 0 ] ) 402 if ( fd[ 0 ] )
402 close( fd[ 0 ] ); 403 close( fd[ 0 ] );
403 if ( !runPrivileged() ) 404 if ( !runPrivileged() )
404 { 405 {
405 setgid( gid ); 406 setgid( gid );
406#if defined( HAVE_INITGROUPS) 407#if defined( HAVE_INITGROUPS)
407 408
408 if ( pw ) 409 if ( pw )
409 initgroups( pw->pw_name, pw->pw_gid ); 410 initgroups( pw->pw_name, pw->pw_gid );
410#endif 411#endif
411 412
412 setuid( uid ); 413 setuid( uid );
413 } 414 }
414 // The child process 415 // The child process
415 if ( !commSetupDoneC() ) 416 if ( !commSetupDoneC() )
416 qWarning( "Could not finish comm setup in child!" ); 417 qWarning( "Could not finish comm setup in child!" );
417 418
418 setupEnvironment(); 419 setupEnvironment();
419 420
420 // Matthias 421 // Matthias
421 if ( run_mode == DontCare ) 422 if ( run_mode == DontCare )
422 setpgid( 0, 0 ); 423 setpgid( 0, 0 );
423 // restore default SIGPIPE handler (Harri) 424 // restore default SIGPIPE handler (Harri)
424 struct sigaction act; 425 struct sigaction act;
425 sigemptyset( &( act.sa_mask ) ); 426 sigemptyset( &( act.sa_mask ) );
426 sigaddset( &( act.sa_mask ), SIGPIPE ); 427 sigaddset( &( act.sa_mask ), SIGPIPE );
427 act.sa_handler = SIG_DFL; 428 act.sa_handler = SIG_DFL;
428 act.sa_flags = 0; 429 act.sa_flags = 0;
429 sigaction( SIGPIPE, &act, 0L ); 430 sigaction( SIGPIPE, &act, 0L );
430 431
431 // We set the close on exec flag. 432 // We set the close on exec flag.
432 // Closing of fd[1] indicates that the execvp succeeded! 433 // Closing of fd[1] indicates that the execvp succeeded!
433 if ( fd[ 1 ] ) 434 if ( fd[ 1 ] )
434 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC ); 435 fcntl( fd[ 1 ], F_SETFD, FD_CLOEXEC );
435 436
436 if (initObex() == 0) { 437 if (initObex() == 0) {
438 if ( fd[ 1 ] ) {
439 ::close(fd[1]);
440 fd[1] = 0;
441 }
437 do { 442 do {
438 if ( fd[ 1 ] ) { 443 if (OBEX_HandleInput(m_obex, 60) < 0) {
439 ::close(fd[1]); 444 fprintf(stderr,"failed to OBEX_HandleInput(), errno=%d\n");
440 fd[1] = 0; 445 _exit(1);
441 } 446 }
442 if (OBEX_HandleInput(m_obex, 10) < 0)
443 _exit(0);
444 } while(1); 447 } while(1);
445 } 448 }
446 char resultByte = 1; 449 char resultByte = 1;
447 if ( fd[ 1 ] ) 450 if ( fd[ 1 ] )
448 write( fd[ 1 ], &resultByte, 1 ); 451 write( fd[ 1 ], &resultByte, 1 );
449 _exit( -1 ); 452 _exit( -1 );
450 } 453 }
451 else if ( -1 == pid_ ) 454 else if ( -1 == pid_ )
452 { 455 {
453 // forking failed 456 // forking failed
454 457
455 runs = false; 458 runs = false;
456 return false; 459 return false;
457 } 460 }
458 else 461 else
459 { 462 {
460 if ( fd[ 1 ] ) 463 if ( fd[ 1 ] )
461 close( fd[ 1 ] ); 464 close( fd[ 1 ] );
462 // the parent continues here 465 // the parent continues here
463 466
464 // Discard any data for stdin that might still be there 467 // Discard any data for stdin that might still be there
465 input_data = 0; 468 input_data = 0;
466 469
467 // Check whether client could be started. 470 // Check whether client could be started.
468 if ( fd[ 0 ] ) 471 if ( fd[ 0 ] )
469 for ( ;; ) 472 for ( ;; )
470 { 473 {
471 char resultByte; 474 char resultByte;
472 int n = ::read( fd[ 0 ], &resultByte, 1 ); 475 int n = ::read( fd[ 0 ], &resultByte, 1 );
473 if ( n == 1 ) 476 if ( n == 1 )
474 { 477 {
475 // Error 478 // Error
476 runs = false; 479 runs = false;
477 close( fd[ 0 ] ); 480 close( fd[ 0 ] );
478 pid_ = 0; 481 pid_ = 0;
479 return false; 482 return false;
480 } 483 }
481 if ( n == -1 ) 484 if ( n == -1 )
482 { 485 {
483 if ( ( errno == ECHILD ) || ( errno == EINTR ) ) 486 if ( ( errno == ECHILD ) || ( errno == EINTR ) )
484 continue; // Ignore 487 continue; // Ignore
485 } 488 }
486 break; // success 489 break; // success
487 } 490 }
488 if ( fd[ 0 ] ) 491 if ( fd[ 0 ] )
489 close( fd[ 0 ] ); 492 close( fd[ 0 ] );
490 493
491 if ( !commSetupDoneP() ) // finish communication socket setup for the parent 494 if ( !commSetupDoneP() ) // finish communication socket setup for the parent
492 qWarning( "Could not finish comm setup in parent!" ); 495 qWarning( "Could not finish comm setup in parent!" );
493 496
494 if ( run_mode == Block ) 497 if ( run_mode == Block )
495 { 498 {
496 commClose(); 499 commClose();
497 500
498 // The SIGCHLD handler of the process controller will catch 501 // The SIGCHLD handler of the process controller will catch
499 // the exit and set the status 502 // the exit and set the status
500 while ( runs ) 503 while ( runs )
501 { 504 {
502 OProcessController::theOProcessController-> 505 OProcessController::theOProcessController->
503 slotDoHousekeeping( 0 ); 506 slotDoHousekeeping( 0 );
504 } 507 }
505 runs = FALSE; 508 runs = FALSE;
506 emit processExited( this ); 509 emit processExited( this );
507 } 510 }
508 } 511 }
509 return true; 512 return true;
510} 513}
511 514
512/* 515/*
513 * Stop forwarding process 516 * Stop forwarding process
514 */ 517 */
515int ObexServer::stop() 518int ObexServer::stop()
516{ 519{
517 kill(SIGTERM); 520 kill(SIGTERM);
518 return 0; 521 return 0;
519} 522}
520 523
521//eof 524//eof