~andreserl/ubuntu/lucid/bind9/bind9-apport-533601

« back to all changes in this revision

Viewing changes to contrib/dbus/dbus_service.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones, LaMont Jones, Internet Software Consortium, Inc, localization folks
  • Date: 2008-08-02 14:20:20 UTC
  • mfrom: (1.2.1 upstream) (6.1.24 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080802142020-l1hon9jy8lbbjxmg
[LaMont Jones]

* default to using resolvconf if it is installed
* fix sonames and dependencies.  Closes: #149259, #492418
* Do not build-depend libcap2-dev on non-linux.  Closes: #493392
* drop unused query-loc manpage.  Closes: #492564
* lwresd: Deliver /etc/bind directory.  Closes: #490027
* fix query-source comment in default install

[Internet Software Consortium, Inc]

* 9.5.0-P2.  Closes: #492949

[localization folks]

* l10n: Spanish debconf translation.  Closes: #492425 (Ignacio Mondino)
* l10n: Swedish debconf templates.  Closes: #491369 (Martin Ågren)
* l10n: Japanese debconf translations.  Closes: #492048 (Hideki Yamane
  (Debian-JP))
* l10n: Finnish translation.  Closes: #490630 (Esko Arajärvi)
* l10n: Italian debconf translations.  Closes: #492587 (Alessandro Vietta)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  dbus_service.c
 
2
 *
 
3
 *  D-BUS Service Utilities
 
4
 *  
 
5
 *  Provides MINIMAL utilities for construction of D-BUS "Services".
 
6
 *  
 
7
 *  Copyright(C) Jason Vas Dias, Red Hat Inc., 2005
 
8
 *  Modified by Adam Tkac, Red Hat Inc., 2007
 
9
 *
 
10
 *  This program is free software; you can redistribute it and/or modify
 
11
 *  it under the terms of the GNU General Public License as published by
 
12
 *  the Free Software Foundation at 
 
13
 *           http://www.fsf.org/licensing/licenses/gpl.txt
 
14
 *  and included in this software distribution as the "LICENSE" file.
 
15
 *
 
16
 *  This program is distributed in the hope that it will be useful,
 
17
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 *  GNU General Public License for more details.
 
20
 *
 
21
 */
 
22
 
 
23
#include <sys/types.h>
 
24
#include <unistd.h>
 
25
#include <linux/limits.h>
 
26
#include <sys/time.h>
 
27
#include <sys/socket.h>
 
28
#include <sys/select.h>
 
29
#include <sys/wait.h>
 
30
#include <sys/ioctl.h>
 
31
#include <time.h>
 
32
#include <signal.h>
 
33
#include <syslog.h>
 
34
#include <fcntl.h>
 
35
#include <string.h>
 
36
extern size_t strnlen(const char *s, size_t maxlen);
 
37
#include <netinet/in.h>
 
38
#include <arpa/inet.h>
 
39
#include <netdb.h>
 
40
#include <ifaddrs.h>
 
41
#include <search.h>
 
42
#include <getopt.h>
 
43
typedef void (*__free_fn_t) (void *__nodep);
 
44
extern void tdestroy (void *__root, __free_fn_t __freefct);
 
45
#include <stdint.h>
 
46
#include <stdio.h>
 
47
#include <stdlib.h>
 
48
#include <stdarg.h>
 
49
#include <errno.h>
 
50
#define  DBUS_API_SUBJECT_TO_CHANGE  "Very Annoying and Silly!"
 
51
#include <dbus/dbus.h>
 
52
 
 
53
#include <named/dbus_service.h>
 
54
#include <isc/result.h>
 
55
 
 
56
typedef struct dbcs_s
 
57
{
 
58
    DBusConnection *connection;
 
59
    DBusDispatchStatus dispatchStatus;
 
60
    uint32_t        status;
 
61
    dbus_svc_WatchHandler wh;
 
62
    void *          wh_arg;
 
63
    const char    * unique_name;
 
64
    dbus_svc_MessageHandler mh;
 
65
    void          * def_mh_obj;
 
66
    dbus_svc_MessageHandler mf;
 
67
    void          * def_mf_obj;
 
68
    dbus_svc_ShutdownHandler sh;
 
69
    void          * sh_obj;  
 
70
    dbus_svc_ErrorHandler eh;
 
71
    dbus_svc_ErrorHandler dh;
 
72
    /*{ glibc b-trees: */
 
73
    void *          roots;
 
74
    void *          timeouts;  
 
75
    void *          watches;
 
76
    void *          filters;
 
77
    /*}*/
 
78
    int             n; 
 
79
    fd_set          r_fds;
 
80
    fd_set          s_r_fds;
 
81
    fd_set          w_fds;
 
82
    fd_set          s_w_fds;
 
83
    fd_set          e_fds;  
 
84
    fd_set          s_e_fds;
 
85
    DBusMessage     *currentMessage;
 
86
    int             rejectMessage;
 
87
} DBusConnectionState;
 
88
 
 
89
typedef struct root_s
 
90
{
 
91
    char *path;    
 
92
    char *if_prefix;
 
93
    DBUS_SVC cs;
 
94
    dbus_svc_MessageHandler mh;        
 
95
    void *object;
 
96
    void *tree;
 
97
} Root;
 
98
 
 
99
typedef struct mhn_s
 
100
{
 
101
    char *path;    
 
102
    dbus_svc_MessageHandler mh;    
 
103
    void *object;
 
104
} MessageHandlerNode;
 
105
 
 
106
typedef struct mfn_s
 
107
{
 
108
    DBusConnectionState *cs;
 
109
    dbus_svc_MessageHandler mf;
 
110
    void *obj;
 
111
    int n_matches;
 
112
    char **matches;
 
113
} MessageFilterNode;
 
114
 
 
115
typedef struct dbto_s
 
116
{
 
117
    DBusTimeout   *to;
 
118
    DBusConnectionState *cs;
 
119
    struct timeval tv;
 
120
} DBusConnectionTimeout;
 
121
 
 
122
static void no_free( void *p){ p=0; }
 
123
 
 
124
static int ptr_key_comparator( const void *p1, const void *p2 )
 
125
{
 
126
    return
 
127
        (  (p1 == p2) 
 
128
           ? 0
 
129
           :( (p1 > p2)
 
130
              ? 1
 
131
              : -1
 
132
            )
 
133
        );
 
134
}
 
135
 
 
136
static DBusHandlerResult
 
137
default_message_filter 
 
138
(   DBusConnection     *connection,
 
139
    DBusMessage        *message,
 
140
    void               *p
 
141
)
 
142
{
 
143
    DBusConnectionState *cs = p;
 
144
    uint32_t type  =dbus_message_get_type( message ),
 
145
           serial  =dbus_message_get_serial( message );
 
146
    uint8_t  reply =dbus_message_get_no_reply( message )==0;
 
147
    const char 
 
148
        *path =    dbus_message_get_path( message ),
 
149
        *dest =    dbus_message_get_destination( message ),
 
150
        *member =  dbus_message_get_member( message ),
 
151
        *interface=dbus_message_get_interface( message ),
 
152
        *sender   =dbus_message_get_sender( message ),
 
153
        *signature=dbus_message_get_signature( message );
 
154
    connection = connection;
 
155
    if(cs->mf)
 
156
        return
 
157
        (*(cs->mf))( cs, type, reply, serial, dest, path, member, interface, 0L,
 
158
                    sender, signature, message, 0L, 0L, 0L, cs->def_mf_obj
 
159
                  ) ;
 
160
    return HANDLED;
 
161
}
 
162
 
 
163
uint8_t
 
164
dbus_svc_add_filter
 
165
(  DBusConnectionState *cs, dbus_svc_MessageHandler mh, void *obj, int n_matches, ... )
 
166
{
 
167
    DBusError error;
 
168
    va_list va;
 
169
    char *m;
 
170
 
 
171
    va_start(va, n_matches );
 
172
    
 
173
    cs->mf = mh;
 
174
    cs->def_mf_obj = obj;
 
175
 
 
176
    if ( ! dbus_connection_add_filter (cs->connection, default_message_filter, cs, NULL))
 
177
    {
 
178
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_connection_add_filter failed");
 
179
        va_end(va);
 
180
        return( 0 );
 
181
    }
 
182
 
 
183
    if( n_matches )
 
184
    {
 
185
        memset(&error,'\0',sizeof(DBusError));
 
186
        dbus_error_init(&error);
 
187
        while( n_matches-- )
 
188
        {
 
189
            m = va_arg(va, char* ) ;
 
190
 
 
191
            dbus_bus_add_match(cs->connection, m, &error);
 
192
 
 
193
            if( dbus_error_is_set(&error))
 
194
            {
 
195
                if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_bus_add_match failed for %s: %s %s",
 
196
                                               m, error.name, error.message
 
197
                                              );
 
198
                va_end(va);
 
199
                return(0);
 
200
            }
 
201
        }
 
202
    }
 
203
    va_end(va);
 
204
    return( 1 );
 
205
}
 
206
 
 
207
 
 
208
uint8_t
 
209
dbus_svc_get_args_va(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, va_list va)
 
210
{
 
211
    DBusError error;
 
212
    memset(&error,'\0',sizeof(DBusError));
 
213
    dbus_error_init(&error);
 
214
    if( (!dbus_message_get_args_valist(msg, &error, firstType, va)) || dbus_error_is_set(&error) )
 
215
    {
 
216
        if(  dbus_error_is_set(&error) )
 
217
        {
 
218
            if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_get_args failed: %s %s",error.name, error.message);
 
219
            dbus_error_free(&error);
 
220
        }else
 
221
            if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_get_args failed: dbus_message_get_args_valist failed");
 
222
        return( 0 );
 
223
    }
 
224
    return( 1 );
 
225
}
 
226
 
 
227
uint8_t
 
228
dbus_svc_get_args(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, ...)
 
229
{
 
230
    va_list va;
 
231
    uint8_t r;
 
232
    va_start(va, firstType);
 
233
    r = dbus_svc_get_args_va( cs, msg, firstType, va);
 
234
    va_end(va);
 
235
    return r;
 
236
}
 
237
 
 
238
uint8_t 
 
239
dbus_svc_send_va
 
240
(  DBusConnectionState *cs,
 
241
   dbus_svc_MessageType type,   
 
242
   int32_t reply_serial,
 
243
   uint32_t *new_serial,
 
244
   const char *destination,
 
245
   const char *path,
 
246
   const char *interface,
 
247
   const char *member,
 
248
   dbus_svc_DataType firstType,
 
249
   va_list va
 
250
)
 
251
{
 
252
    DBusMessageIter iter;
 
253
    char *e;
 
254
    DBusMessage *msg = 
 
255
        dbus_svc_new_message
 
256
        (   cs,
 
257
            type,
 
258
            reply_serial,
 
259
            destination,
 
260
            path,
 
261
            interface,
 
262
            member
 
263
        );
 
264
 
 
265
    if(msg == 0L)
 
266
    {
 
267
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_svc_new_message failed");
 
268
        return 0;
 
269
    }
 
270
 
 
271
    if( type != DBUS_MESSAGE_TYPE_ERROR )
 
272
    {
 
273
        if( !dbus_message_append_args_valist( msg, firstType, va ) )
 
274
        {
 
275
            if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args_valist failed");
 
276
            return 0;
 
277
        }
 
278
    }else
 
279
    {
 
280
        if( firstType == DBUS_TYPE_STRING )
 
281
        {
 
282
            e = 0L;
 
283
            e = va_arg( va, char* );        
 
284
            if( (e == 0L) ||  !dbus_message_set_error_name( msg, e ) )
 
285
            {
 
286
                if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_set_error_name failed");
 
287
                return 0;
 
288
            }
 
289
            firstType = va_arg(va, int);
 
290
            if( firstType == DBUS_TYPE_STRING )
 
291
            {
 
292
                e = 0L;
 
293
                e =  va_arg( va, char* );
 
294
                if( e == 0L )
 
295
                {
 
296
                    if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: NULL error message");
 
297
                    return 0;                               
 
298
                }
 
299
                dbus_message_iter_init_append (msg, &iter);             
 
300
                if( !dbus_message_iter_append_basic 
 
301
                    (&iter, DBUS_TYPE_STRING, &e)
 
302
                  )
 
303
                {
 
304
                    if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_iter_append_basic failed");
 
305
                    return 0;                               
 
306
                }
 
307
            }
 
308
        }else
 
309
        {
 
310
            if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: unhandled type for error name: %c", firstType);
 
311
            return 0;       
 
312
        }
 
313
    }
 
314
 
 
315
    if( !dbus_connection_send(cs->connection, msg, new_serial) )
 
316
    {
 
317
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed");
 
318
        return 0;
 
319
    }
 
320
    if( cs->dh != 0L ) (*(cs->dh))("Sending message");
 
321
    dbus_connection_flush(cs->connection);
 
322
    return 1;
 
323
}
 
324
 
 
325
uint8_t 
 
326
dbus_svc_send
 
327
(  DBusConnectionState *cs,
 
328
   dbus_svc_MessageType type,
 
329
   int32_t reply_serial,
 
330
   uint32_t *new_serial,
 
331
   const char *destination,
 
332
   const char *path,
 
333
   const char *interface,
 
334
   const char *member,
 
335
   dbus_svc_DataType firstType,
 
336
   ...
 
337
)
 
338
{
 
339
    uint8_t r;
 
340
    va_list va;
 
341
    va_start(va, firstType);
 
342
    r = dbus_svc_send_va(cs, type, reply_serial, new_serial, destination, path,interface,member,firstType,va);
 
343
    va_end(va);
 
344
    return ( r ) ;
 
345
}
 
346
 
 
347
dbus_svc_MessageHandle
 
348
dbus_svc_new_message
 
349
( DBusConnectionState* cs,
 
350
  dbus_svc_MessageType type,
 
351
  int32_t reply_serial,
 
352
  const char *destination,
 
353
  const char *path,
 
354
  const char *interface,
 
355
  const char *member
 
356
)
 
357
{
 
358
    DBusMessage *msg = dbus_message_new(type);
 
359
    
 
360
    if( msg == 0L)
 
361
    {
 
362
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed");
 
363
        return 0;
 
364
    }
 
365
 
 
366
    if( reply_serial != -1 )
 
367
    {
 
368
        if( !dbus_message_set_reply_serial(msg,reply_serial) )
 
369
        {
 
370
            if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed");
 
371
            return 0;
 
372
        }    
 
373
    }
 
374
            
 
375
    if( (destination !=0L) && !dbus_message_set_destination(msg, destination) )
 
376
    {
 
377
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_destination failed");
 
378
        return 0;
 
379
    }
 
380
 
 
381
    if( !dbus_message_set_path(msg, path) )
 
382
    {
 
383
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_path failed");
 
384
        return 0;
 
385
    }
 
386
 
 
387
    if( ! dbus_message_set_interface(msg,interface) )
 
388
    {
 
389
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_interface failed - %s", interface);
 
390
        return 0;
 
391
    }
 
392
 
 
393
    if( !dbus_message_set_member(msg,member) )
 
394
    {
 
395
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_member failed");
 
396
        return 0;
 
397
    }
 
398
 
 
399
    return msg;    
 
400
}
 
401
 
 
402
extern uint8_t
 
403
dbus_svc_send_message
 
404
(
 
405
    DBusConnectionState *cs, 
 
406
    dbus_svc_MessageHandle msg, 
 
407
    uint32_t *new_serial 
 
408
)
 
409
{
 
410
    if( !dbus_connection_send(cs->connection, msg, new_serial) )
 
411
    {
 
412
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed");
 
413
        return 0;
 
414
    }
 
415
    if( cs->dh != 0L ) (*(cs->dh))("Sending message");
 
416
    dbus_connection_flush(cs->connection);   
 
417
    return 1;
 
418
}
 
419
 
 
420
uint8_t
 
421
dbus_svc_message_append_args(DBusConnectionState *cs, dbus_svc_MessageHandle msg, dbus_svc_DataType firstType, ...)
 
422
{
 
423
    va_list va;
 
424
    va_start(va, firstType);
 
425
    if( !dbus_message_append_args_valist( msg, firstType, va ) )
 
426
    {
 
427
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args failed");
 
428
        va_end(va);
 
429
        return 0;       
 
430
    }
 
431
    va_end(va);
 
432
    return ( 1 ) ;
 
433
}
 
434
 
 
435
dbus_svc_MessageHandle 
 
436
dbus_svc_call
 
437
( DBusConnectionState *cs,
 
438
  const char *destination,
 
439
  const char *path,
 
440
  const char *member,
 
441
  const char *interface,
 
442
  dbus_svc_DataType firstType,
 
443
  ... 
 
444
)
 
445
{
 
446
    DBusMessage *message=0L, *reply=0L;
 
447
    va_list va;
 
448
    DBusError error;
 
449
    int reply_timeout=20000;
 
450
 
 
451
    va_start(va, firstType);
 
452
 
 
453
    memset(&error,'\0',sizeof(DBusError));
 
454
    dbus_error_init(&error);
 
455
 
 
456
    if(( message = 
 
457
         dbus_message_new_method_call 
 
458
         (  destination,
 
459
            path,
 
460
            interface,
 
461
            member
 
462
         )
 
463
       ) == 0L
 
464
      )
 
465
    {
 
466
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_new_method_call failed");
 
467
        va_end(va);
 
468
        return(0L);
 
469
    };
 
470
 
 
471
    if( !dbus_message_append_args_valist( message, firstType, va ) )
 
472
    {
 
473
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_append_args_valist failed");
 
474
        va_end(va);
 
475
        return(0L);
 
476
    }
 
477
 
 
478
    if((reply = 
 
479
        dbus_connection_send_with_reply_and_block 
 
480
        (cs->connection,
 
481
         message, reply_timeout,
 
482
         &error
 
483
        )
 
484
       ) == 0L    
 
485
      )
 
486
    {
 
487
        if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_send_with_reply_and_block failed: %s %s",
 
488
                    error.name, error.message
 
489
                   );
 
490
        va_end(va);
 
491
        return(0L);
 
492
    }
 
493
    va_end(va);
 
494
    return reply;
 
495
}
 
496
 
 
497
dbus_svc_MessageIterator
 
498
dbus_svc_message_iterator_new( DBusConnectionState *cs, DBusMessage *msg)
 
499
{
 
500
    DBusMessageIter *iter = malloc( sizeof(DBusMessageIter) );
 
501
    void *p =cs;
 
502
    p++;
 
503
    if( iter != 0L )
 
504
    {
 
505
        if( !dbus_message_iter_init( msg, iter ))
 
506
        {
 
507
            free( iter ) ;
 
508
            iter = 0L;
 
509
        }
 
510
    }
 
511
    return iter;
 
512
}
 
513
 
 
514
uint32_t
 
515
dbus_svc_message_next_arg_type( DBusConnectionState *cs, dbus_svc_MessageIterator iter )
 
516
{
 
517
    void *p =cs;
 
518
    p++;
 
519
    return dbus_message_iter_get_arg_type( iter );
 
520
}
 
521
 
 
522
void
 
523
dbus_svc_message_next_arg( DBusConnectionState *cs, dbus_svc_MessageIterator iter, void *value )
 
524
{
 
525
    void *p =cs;
 
526
    p++;
 
527
    dbus_message_iter_get_basic( iter, value );
 
528
    dbus_message_iter_next( iter );
 
529
}
 
530
 
 
531
uint32_t
 
532
dbus_svc_message_element_type(DBusConnectionState *cs , dbus_svc_MessageIterator  iter)
 
533
{
 
534
    void *p =cs;
 
535
    p++;
 
536
    return dbus_message_iter_get_element_type(iter);
 
537
}
 
538
 
 
539
void
 
540
dbus_svc_message_get_elements( DBusConnectionState *cs , dbus_svc_MessageIterator  iter, uint32_t *n, void *array )
 
541
{
 
542
    void *p =cs;
 
543
    p++;
 
544
    dbus_message_iter_get_fixed_array( iter, n, array);
 
545
}
 
546
 
 
547
void dbus_svc_message_iterator_free(  DBusConnectionState *cs, dbus_svc_MessageIterator iter )
 
548
{
 
549
    void *p =cs;
 
550
    p++;
 
551
    free( iter );
 
552
}
 
553
 
 
554
uint8_t dbus_svc_message_type(  DBusMessage *msg )
 
555
{
 
556
    return dbus_message_get_type( msg );
 
557
}
 
558
 
 
559
static DBusConnectionState *
 
560
dbcs_new( DBusConnection *connection )
 
561
{
 
562
    DBusConnectionState *dbcs = (DBusConnectionState *) malloc( sizeof(DBusConnectionState) );
 
563
    if ( dbcs )
 
564
    {
 
565
        memset( dbcs, '\0', sizeof( DBusConnectionState ));
 
566
        dbcs->connection = connection;
 
567
    }
 
568
    return(dbcs);
 
569
}
 
570
 
 
571
static DBusConnectionTimeout *
 
572
timeout_new( DBusTimeout *timeout )
 
573
{
 
574
    DBusConnectionTimeout *to = (DBusConnectionTimeout *) malloc ( sizeof(DBusConnectionTimeout) );
 
575
    if( to != 0L )
 
576
    {
 
577
        to->to = timeout;
 
578
        dbus_timeout_set_data(timeout, to, 0L);
 
579
        if( dbus_timeout_get_enabled(timeout) )
 
580
            gettimeofday(&(to->tv),0L);
 
581
        else
 
582
        {
 
583
            to->tv.tv_sec = 0 ;
 
584
            to->tv.tv_usec = 0 ;
 
585
        }           
 
586
    }
 
587
    return( to );
 
588
}
 
589
 
 
590
static dbus_bool_t
 
591
add_timeout( DBusTimeout *timeout, void *csp )
 
592
{
 
593
    DBusConnectionState   *cs = csp;
 
594
    DBusConnectionTimeout *to = timeout_new(timeout);
 
595
    if( cs->dh != 0L ) (*(cs->dh))("add_timeout: %d", dbus_timeout_get_interval(timeout));
 
596
    to->cs = cs;
 
597
    if ( to )
 
598
    {
 
599
        if( tsearch((void*)to, &(cs->timeouts), ptr_key_comparator) != 0L )
 
600
            return TRUE;
 
601
    }
 
602
    if( cs->eh != 0L ) (*(cs->eh))("add_timeout: out of memory");
 
603
    return FALSE;
 
604
}
 
605
 
 
606
static void
 
607
remove_timeout( DBusTimeout *timeout, void *csp )
 
608
{
 
609
    DBusConnectionState   *cs = csp;
 
610
    DBusConnectionTimeout *to = dbus_timeout_get_data(timeout);
 
611
    if( (to != 0L) && (to->to == timeout) )
 
612
    {
 
613
        if( cs->dh != 0L ) (*(cs->dh))("remove_timeout: %d", dbus_timeout_get_interval(to->to));
 
614
        if( tdelete((const void*)to, &(cs->timeouts), ptr_key_comparator) != 0L )
 
615
        {
 
616
            free(to);
 
617
        }else
 
618
            if( cs->eh != 0L ) (*(cs->eh))("remove_timeout: can't happen?!?: timeout data %p not found", to);           
 
619
    }else
 
620
        if( cs->eh != 0L ) (*(cs->eh))("remove_timeout: can't happen?!?: timeout %p did not record data %p %p", 
 
621
                    timeout, to, ((to != 0L) ? to->to : 0L)
 
622
                   );
 
623
}
 
624
 
 
625
static void
 
626
toggle_timeout( DBusTimeout *timeout, void *csp )
 
627
{
 
628
    DBusConnectionState   *cs = csp;
 
629
    DBusConnectionTimeout **top = tfind( (const void*) dbus_timeout_get_data(timeout), 
 
630
                                         &(cs->timeouts),
 
631
                                         ptr_key_comparator
 
632
                                       ),
 
633
                           *to=0L;
 
634
    if( (top != 0L) && ((to=*top) != 0L) && (to->to == timeout) )
 
635
    {
 
636
        if( cs->dh != 0L ) (*(cs->dh))("toggle_timeout: %d", dbus_timeout_get_interval(to->to));
 
637
        if(  dbus_timeout_get_enabled(timeout) )
 
638
            gettimeofday(&(to->tv),0L);
 
639
        else
 
640
        {
 
641
            to->tv.tv_sec = 0 ;
 
642
            to->tv.tv_usec = 0 ;
 
643
        }
 
644
    }else
 
645
        if( cs->eh != 0L ) (*(cs->eh))("toggle_timeout: can't happen?!?: timeout %p %s %p %p", timeout, 
 
646
                    ((to==0L) ? "did not record data" : "not found"),
 
647
                    to, ((to != 0L) ? to->to : 0L)
 
648
                   );   
 
649
}
 
650
 
 
651
static void
 
652
process_timeout( const void *p, const VISIT which, const int level)
 
653
{
 
654
    DBusConnectionState   *cs;
 
655
    void * const *tpp = p;
 
656
    DBusConnectionTimeout *to;
 
657
    struct timeval tv;
 
658
    float now, then, interval;
 
659
    int l = level ? 1 : 0;
 
660
    l=l;
 
661
 
 
662
    gettimeofday(&tv,0L);
 
663
    
 
664
    if( (tpp != 0L) && (*tpp != 0L) && ((which == postorder) || (which == leaf)) ) 
 
665
    {
 
666
        to = (DBusConnectionTimeout*)*tpp;
 
667
        cs = to->cs;
 
668
        if ( !dbus_timeout_get_enabled(to->to) )
 
669
            return;
 
670
        cs = dbus_timeout_get_data(to->to);
 
671
        then = ((float)to->tv.tv_sec) + (((float)to->tv.tv_usec)  / 1000000.0);
 
672
        if( then != 0.0 )
 
673
        {
 
674
            interval = ((float)dbus_timeout_get_interval(to->to)) / 1000.0;
 
675
            now = ((float)tv.tv_sec) + (( (float)tv.tv_usec) /   1000000.0);
 
676
            if( (now - then) >= interval )
 
677
            {
 
678
                if( cs->dh != 0L ) (*(cs->dh))("handle_timeout: %d - %f %f %f",  dbus_timeout_get_interval(to->to), then, now, interval);
 
679
                dbus_timeout_handle( to->to );
 
680
                to->tv=tv;
 
681
            }
 
682
        }else
 
683
        {
 
684
            to->tv = tv;
 
685
        }
 
686
    }
 
687
}
 
688
 
 
689
static void
 
690
process_timeouts ( DBusConnectionState *cs )
 
691
{
 
692
    twalk( cs->timeouts, process_timeout );
 
693
}
 
694
 
 
695
static void 
 
696
set_watch_fds( DBusWatch *watch, DBusConnectionState *cs )
 
697
{
 
698
    uint8_t flags = dbus_watch_get_flags(watch);
 
699
    int fd = dbus_watch_get_fd(watch);
 
700
 
 
701
    if ( cs->n <= fd )
 
702
        cs->n = fd + 1;
 
703
 
 
704
    if ( dbus_watch_get_enabled(watch) )
 
705
    {
 
706
        if ( flags & DBUS_WATCH_READABLE )
 
707
        {
 
708
            FD_SET(fd , &(cs->r_fds));
 
709
            if( cs->wh != 0L )
 
710
                (*(cs->wh))( fd, WATCH_ENABLE | WATCH_READ, cs->wh_arg ); 
 
711
        }else       
 
712
        {
 
713
            FD_CLR(fd , &(cs->r_fds));
 
714
            if( cs->wh != 0L )
 
715
                (*(cs->wh))( fd, WATCH_READ, cs->wh_arg ); 
 
716
        }
 
717
 
 
718
        if ( flags & DBUS_WATCH_WRITABLE )
 
719
        {
 
720
            FD_SET(fd , &(cs->w_fds));
 
721
            if( cs->wh != 0L )
 
722
                (*(cs->wh))( fd, WATCH_ENABLE | WATCH_WRITE, cs->wh_arg );       
 
723
        }else       
 
724
        {
 
725
            FD_CLR(fd , &(cs->w_fds));
 
726
            if( cs->wh != 0L )
 
727
                (*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg );      
 
728
        }
 
729
        if ( flags & DBUS_WATCH_ERROR )
 
730
        {
 
731
            FD_SET(fd , &(cs->e_fds));
 
732
            if( cs->wh != 0L )
 
733
                (*(cs->wh))( fd, WATCH_ENABLE | WATCH_ERROR, cs->wh_arg );      
 
734
        }else       
 
735
        {
 
736
            FD_CLR(fd , &(cs->e_fds));
 
737
            if( cs->wh != 0L )
 
738
                (*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg );     
 
739
        }       
 
740
    }else
 
741
    {
 
742
        if( FD_ISSET( fd, &(cs->r_fds)) )
 
743
            if( cs->wh != 0L )
 
744
                (*(cs->wh))( fd, WATCH_READ, cs->wh_arg );
 
745
        FD_CLR(fd , &(cs->r_fds));
 
746
 
 
747
        if( FD_ISSET( fd, &(cs->w_fds)) )
 
748
            if( cs->wh != 0L )
 
749
                (*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg );     
 
750
        FD_CLR(fd , &(cs->w_fds));
 
751
        
 
752
        if( FD_ISSET( fd, &(cs->e_fds)) )
 
753
            if( cs->wh != 0L )
 
754
                (*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg );
 
755
        FD_CLR(fd , &(cs->e_fds));
 
756
    }   
 
757
}
 
758
 
 
759
static dbus_bool_t
 
760
add_watch ( DBusWatch *watch, void *csp )
 
761
{    
 
762
    DBusConnectionState *cs = csp;
 
763
 
 
764
    dbus_watch_set_data(watch, cs, no_free );
 
765
    if( cs->dh != 0L ) (*(cs->dh))("add_watch: %d", dbus_watch_get_fd(watch));
 
766
    if( tsearch((const void*)watch,&(cs->watches),ptr_key_comparator) == 0L )
 
767
    {
 
768
        if( cs->eh != 0L ) (*(cs->eh))("add_watch: out of memory");
 
769
        return FALSE;
 
770
    }    
 
771
    set_watch_fds(watch,cs);
 
772
    return TRUE;
 
773
}
 
774
 
 
775
static void
 
776
remove_watch ( DBusWatch *watch, void *csp )
 
777
{
 
778
    DBusConnectionState *cs = csp;
 
779
    int  fd = dbus_watch_get_fd(watch);
 
780
    if( tdelete((const void*)watch, &(cs->watches), ptr_key_comparator) == 0L )
 
781
        if( cs->eh != 0L ) (*(cs->eh))("remove_watch: can't happen?!?: watch not found");
 
782
    if( cs->dh != 0L ) (*(cs->dh))("remove_watch: %d", dbus_watch_get_fd(watch));
 
783
    FD_CLR(fd , &(cs->r_fds));
 
784
    FD_CLR(fd , &(cs->w_fds));
 
785
    FD_CLR(fd , &(cs->e_fds));
 
786
    if( cs->wh != 0L )
 
787
        (*(cs->wh))(dbus_watch_get_fd(watch), WATCH_READ | WATCH_WRITE | WATCH_ERROR, cs->wh_arg );
 
788
}
 
789
 
 
790
static void
 
791
toggle_watch ( DBusWatch *watch, void *csp )
 
792
{
 
793
    DBusConnectionState *cs = csp;    
 
794
    if( cs->dh != 0L ) (*(cs->dh))("toggle_watch: %d", dbus_watch_get_fd(watch));
 
795
    set_watch_fds(watch,cs);
 
796
}
 
797
 
 
798
static void
 
799
process_watch( const void *p, const VISIT which, const int level)
 
800
{
 
801
    void * const *wpp=p;
 
802
    DBusWatch *w;
 
803
    int fd;
 
804
    uint8_t flags;
 
805
    DBusConnectionState *cs;
 
806
    int l = level ? 1 : 0;
 
807
    l=l;
 
808
 
 
809
    if((wpp != 0L) && (*wpp != 0L) && ( (which == postorder) || (which == leaf) ) )
 
810
    {
 
811
        w = (DBusWatch*)*wpp;
 
812
        cs = dbus_watch_get_data( w );
 
813
        if( cs == 0 )
 
814
            return;
 
815
        if( ! dbus_watch_get_enabled(w) )
 
816
            return;
 
817
        fd = dbus_watch_get_fd( w );
 
818
        flags = dbus_watch_get_flags( w );
 
819
        if( cs->dh != 0L ) (*(cs->dh))("handle_watch: %d", dbus_watch_get_fd( w ));
 
820
        if ( (flags & DBUS_WATCH_READABLE) && (FD_ISSET(fd, &(cs->s_r_fds))) )
 
821
            dbus_watch_handle(w, DBUS_WATCH_READABLE);
 
822
        if ( (flags & DBUS_WATCH_WRITABLE) && (FD_ISSET(fd, &(cs->s_w_fds))) )
 
823
            dbus_watch_handle(w, DBUS_WATCH_READABLE);
 
824
        if ( (flags & DBUS_WATCH_ERROR) && (FD_ISSET(fd, &(cs->s_e_fds))) )
 
825
            dbus_watch_handle(w, DBUS_WATCH_ERROR);
 
826
    }
 
827
 
828
 
 
829
static void
 
830
process_watches ( DBusConnectionState *cs )
 
831
{
 
832
    twalk( cs->watches, process_watch );
 
833
}
 
834
 
 
835
void dbus_svc_handle_watch(  DBusConnectionState *cs, int fd, dbus_svc_WatchFlags action )
 
836
{
 
837
    switch( action & 7 )
 
838
    {
 
839
    case WATCH_READ:
 
840
        FD_SET(fd, &(cs->s_r_fds));
 
841
        break;
 
842
 
 
843
    case WATCH_WRITE:
 
844
        FD_SET(fd, &(cs->s_w_fds));
 
845
        break;
 
846
        
 
847
    case WATCH_ERROR:
 
848
        FD_SET(fd, &(cs->s_e_fds));
 
849
        break;
 
850
    }
 
851
}
 
852
 
 
853
static void
 
854
dispatch_status
 
855
(   DBusConnection *connection, 
 
856
    DBusDispatchStatus new_status,
 
857
    void *csp 
 
858
)
 
859
{
 
860
    connection=connection;
 
861
    DBusConnectionState *cs = csp;
 
862
    cs->dispatchStatus = new_status;
 
863
}
 
864
 
 
865
void
 
866
dbus_svc_main_loop( DBusConnectionState *cs, void (*idle_handler)(DBusConnectionState *) )
 
867
{
 
868
    struct timeval timeout={0,200000};
 
869
    int n_fds;
 
870
 
 
871
    while( cs->status != SHUTDOWN )
 
872
    {
 
873
        cs->s_r_fds = cs->r_fds;
 
874
        cs->s_w_fds = cs->w_fds;
 
875
        cs->s_e_fds = cs->e_fds;
 
876
        
 
877
        timeout.tv_sec = 0;
 
878
        timeout.tv_usec= 200000;
 
879
 
 
880
        if ( (n_fds = select(cs->n, &(cs->s_r_fds), &(cs->s_w_fds), &(cs->s_e_fds), &timeout)) < 0 )
 
881
        {           
 
882
            if (errno != EINTR) 
 
883
            {
 
884
                if( cs->eh != 0L ) (*(cs->eh))( "select failed: %d : %s", errno, strerror(errno));
 
885
                return;
 
886
            }
 
887
        }
 
888
 
 
889
        if( n_fds > 0 )
 
890
            process_watches(cs);
 
891
 
 
892
        process_timeouts(cs);
 
893
 
 
894
        if ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE )
 
895
            dbus_connection_dispatch( cs->connection );
 
896
 
 
897
        if( idle_handler != 0L )
 
898
            (*idle_handler)(cs);
 
899
    }
 
900
}
 
901
 
 
902
void dbus_svc_dispatch(DBusConnectionState *cs)
 
903
{
 
904
    process_watches(cs);
 
905
    
 
906
    FD_ZERO(&(cs->s_r_fds));
 
907
    FD_ZERO(&(cs->s_w_fds));
 
908
    FD_ZERO(&(cs->s_e_fds));
 
909
 
 
910
    process_timeouts(cs);
 
911
 
 
912
    while ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE )
 
913
        dbus_connection_dispatch( cs->connection );
 
914
}
 
915
 
 
916
void 
 
917
dbus_svc_quit( DBusConnectionState *cs )
 
918
{
 
919
    cs->status = SHUTDOWN;
 
920
}
 
921
 
 
922
static isc_result_t
 
923
connection_setup 
 
924
(   DBusConnection *connection,
 
925
    DBUS_SVC *dbus,
 
926
    dbus_svc_WatchHandler wh, 
 
927
    dbus_svc_ErrorHandler eh, 
 
928
    dbus_svc_ErrorHandler dh,
 
929
    void *wh_arg
 
930
)
 
931
{
 
932
    *dbus = dbcs_new( connection );
 
933
    
 
934
    if ( *dbus == 0L )
 
935
    {
 
936
        if(eh)(*(eh))("connection_setup: out of memory");
 
937
        goto fail;
 
938
    }
 
939
    (*dbus)->wh = wh;
 
940
    (*dbus)->wh_arg = wh_arg;
 
941
    (*dbus)->eh = eh;
 
942
    (*dbus)->dh = dh;
 
943
 
 
944
    if (!dbus_connection_set_watch_functions 
 
945
         (    (*dbus)->connection,
 
946
              add_watch,
 
947
              remove_watch,
 
948
              toggle_watch,
 
949
              *dbus,
 
950
              no_free
 
951
          )
 
952
       )
 
953
    {
 
954
        if( (*dbus)->eh != 0L ) (*((*dbus)->eh))("connection_setup: dbus_connection_set_watch_functions failed");
 
955
        goto fail; 
 
956
    }
 
957
      
 
958
    if (!dbus_connection_set_timeout_functions 
 
959
         (    connection,
 
960
              add_timeout,
 
961
              remove_timeout,
 
962
              toggle_timeout,
 
963
              *dbus, 
 
964
              no_free
 
965
         )
 
966
       )
 
967
    {
 
968
        if( (*dbus)->eh != 0L ) (*((*dbus)->eh))("connection_setup: dbus_connection_set_timeout_functions failed");
 
969
        goto fail;
 
970
    }
 
971
 
 
972
    dbus_connection_set_dispatch_status_function 
 
973
    (   connection, 
 
974
        dispatch_status, 
 
975
        *dbus, 
 
976
        no_free
 
977
    ); 
 
978
 
 
979
    if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
 
980
        dbus_connection_ref(connection);    
 
981
    
 
982
    return ISC_R_SUCCESS;
 
983
  
 
984
 fail:
 
985
    if( *dbus != 0L )
 
986
        free(*dbus);
 
987
  
 
988
    dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
 
989
    dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
 
990
    dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
 
991
  
 
992
    return ISC_R_FAILURE;
 
993
}
 
994
 
 
995
isc_result_t
 
996
dbus_svc_init
 
997
(
 
998
    dbus_svc_DBUS_TYPE    bus,
 
999
    char                  *name, 
 
1000
    DBUS_SVC              *dbus,
 
1001
    dbus_svc_WatchHandler wh ,
 
1002
    dbus_svc_ErrorHandler eh ,
 
1003
    dbus_svc_ErrorHandler dh ,
 
1004
    void *wh_arg
 
1005
)
 
1006
{
 
1007
    DBusConnection       *connection;
 
1008
    DBusError            error;
 
1009
    char *session_bus_address=0L;
 
1010
 
 
1011
    memset(&error,'\0',sizeof(DBusError));
 
1012
 
 
1013
    dbus_error_init(&error);
 
1014
 
 
1015
    switch( bus )
 
1016
    {
 
1017
        /* DBUS_PRIVATE_* bus types are the only type which allow reconnection if the dbus-daemon is restarted
 
1018
         */
 
1019
    case DBUS_PRIVATE_SYSTEM:
 
1020
       
 
1021
        if ( (connection = dbus_connection_open_private("unix:path=/var/run/dbus/system_bus_socket", &error)) == 0L )
 
1022
        {
 
1023
            if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
 
1024
            return ISC_R_FAILURE;
 
1025
        }
 
1026
 
 
1027
        if ( ! dbus_bus_register(connection,&error) )
 
1028
        {
 
1029
            if(eh)(*eh)("dbus_bus_register failed: %s %s", error.name, error.message);
 
1030
            dbus_connection_close(connection);
 
1031
            free(connection);
 
1032
            return ISC_R_FAILURE;
 
1033
        }
 
1034
        break;
 
1035
 
 
1036
    case DBUS_PRIVATE_SESSION:
 
1037
        
 
1038
        session_bus_address = getenv("DBUS_SESSION_BUS_ADDRESS");
 
1039
        if ( session_bus_address == 0L )
 
1040
        {
 
1041
            if(eh)(*eh)("dbus_svc_init failed: DBUS_SESSION_BUS_ADDRESS environment variable not set");
 
1042
            return ISC_R_FAILURE;
 
1043
        }
 
1044
 
 
1045
        if ( (connection = dbus_connection_open_private(session_bus_address, &error)) == 0L )
 
1046
        {
 
1047
            if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
 
1048
            return ISC_R_FAILURE;
 
1049
        }
 
1050
 
 
1051
        if ( ! dbus_bus_register(connection,&error) )
 
1052
        {
 
1053
            if(eh)(*eh)("dbus_bus_register failed: %s %s", error.name, error.message);
 
1054
            dbus_connection_close(connection);
 
1055
            free(connection);
 
1056
            return ISC_R_FAILURE;
 
1057
        }
 
1058
        break;
 
1059
 
 
1060
    case DBUS_SYSTEM:
 
1061
    case DBUS_SESSION:
 
1062
 
 
1063
        if ( (connection = dbus_bus_get (bus, &error)) == 0L )
 
1064
        {
 
1065
            if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
 
1066
            return ISC_R_FAILURE;
 
1067
        }
 
1068
        break;
 
1069
 
 
1070
    default:
 
1071
        if(eh)(*eh)("dbus_svc_init failed: unknown bus type %d", bus);
 
1072
        return ISC_R_FAILURE;
 
1073
    }
 
1074
    
 
1075
    dbus_connection_set_exit_on_disconnect(connection, FALSE);
 
1076
 
 
1077
    if ( (connection_setup(connection, dbus, wh, eh, dh, wh_arg)) != ISC_R_SUCCESS)
 
1078
    {
 
1079
        if(eh)(*eh)("dbus_svc_init failed: connection_setup failed");
 
1080
        return ISC_R_FAILURE;
 
1081
    }
 
1082
 
 
1083
    if( name == 0L )
 
1084
        return ISC_R_SUCCESS;
 
1085
    
 
1086
    (*dbus)->unique_name = dbus_bus_get_unique_name(connection);
 
1087
 
 
1088
    switch
 
1089
        (   dbus_bus_request_name 
 
1090
            (   connection, name, 
 
1091
#ifdef DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
 
1092
                DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT ,
 
1093
#else
 
1094
                0 ,
 
1095
#endif
 
1096
                &error
 
1097
            ) 
 
1098
        )
 
1099
    {   
 
1100
    case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: 
 
1101
        break;
 
1102
    case DBUS_REQUEST_NAME_REPLY_EXISTS:
 
1103
    case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
 
1104
    case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
 
1105
        if(eh)(*eh)("dbus_svc_init: dbus_bus_request_name failed:  Name already registered");
 
1106
        goto give_up;
 
1107
    default:
 
1108
        if(eh)(*eh)("dbus_svc_init: dbus_bus_request_name failed: %s %s", error.name, error.message);
 
1109
        goto give_up;
 
1110
    }
 
1111
    return ISC_R_SUCCESS;
 
1112
 
 
1113
 give_up:
 
1114
    dbus_connection_close( connection );
 
1115
    dbus_connection_unref( connection );
 
1116
    if( *dbus )
 
1117
    {
 
1118
        dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
 
1119
        dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
 
1120
        dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
 
1121
        free(*dbus);    
 
1122
    }
 
1123
    return ISC_R_FAILURE;
 
1124
}
 
1125
 
 
1126
const char *dbus_svc_unique_name(DBusConnectionState *cs)
 
1127
{
 
1128
    return cs->unique_name;
 
1129
}
 
1130
 
 
1131
void
 
1132
dbus_svc_shutdown ( DBusConnectionState *cs )                          
 
1133
{
 
1134
    if (!dbus_connection_set_watch_functions 
 
1135
         (   cs->connection,
 
1136
             NULL, NULL, NULL, NULL, NULL
 
1137
         )
 
1138
       ) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_watch_functions: No Memory."
 
1139
                     "Setting watch functions to NULL failed."
 
1140
                    );
 
1141
  
 
1142
    if (!dbus_connection_set_timeout_functions 
 
1143
         (   cs->connection,
 
1144
             NULL, NULL, NULL, NULL, NULL
 
1145
         )
 
1146
       ) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_timeout_functions: No Memory."
 
1147
                     "Setting timeout functions to NULL failed."
 
1148
                    );
 
1149
 
 
1150
    dbus_connection_set_dispatch_status_function (cs->connection, NULL, NULL, NULL);
 
1151
    
 
1152
    tdestroy( cs->timeouts, free);
 
1153
    cs->timeouts=0L;
 
1154
    tdestroy( cs->watches, no_free);
 
1155
    cs->watches=0L;
 
1156
    
 
1157
    dbus_connection_close( cs->connection );
 
1158
    dbus_connection_unref( cs->connection );
 
1159
 
 
1160
    free( cs );
 
1161
}