No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / contrib / dbus / dbus_service.c
blobddf0e1fc0cacb0a3744fb2f0a770b98c8620bb59
1 /* $NetBSD$ */
3 /* dbus_service.c
5 * D-BUS Service Utilities
6 *
7 * Provides MINIMAL utilities for construction of D-BUS "Services".
8 *
9 * Copyright(C) Jason Vas Dias, Red Hat Inc., 2005
10 * Modified by Adam Tkac, Red Hat Inc., 2007
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation at
15 * http://www.fsf.org/licensing/licenses/gpl.txt
16 * and included in this software distribution as the "LICENSE" file.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <linux/limits.h>
28 #include <sys/time.h>
29 #include <sys/socket.h>
30 #include <sys/select.h>
31 #include <sys/wait.h>
32 #include <sys/ioctl.h>
33 #include <time.h>
34 #include <signal.h>
35 #include <syslog.h>
36 #include <fcntl.h>
37 #include <string.h>
38 extern size_t strnlen(const char *s, size_t maxlen);
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <netdb.h>
42 #include <ifaddrs.h>
43 #include <search.h>
44 #include <getopt.h>
45 typedef void (*__free_fn_t) (void *__nodep);
46 extern void tdestroy (void *__root, __free_fn_t __freefct);
47 #include <stdint.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <stdarg.h>
51 #include <errno.h>
52 #define DBUS_API_SUBJECT_TO_CHANGE "Very Annoying and Silly!"
53 #include <dbus/dbus.h>
55 #include <named/dbus_service.h>
56 #include <isc/result.h>
58 typedef struct dbcs_s
60 DBusConnection *connection;
61 DBusDispatchStatus dispatchStatus;
62 uint32_t status;
63 dbus_svc_WatchHandler wh;
64 void * wh_arg;
65 const char * unique_name;
66 dbus_svc_MessageHandler mh;
67 void * def_mh_obj;
68 dbus_svc_MessageHandler mf;
69 void * def_mf_obj;
70 dbus_svc_ShutdownHandler sh;
71 void * sh_obj;
72 dbus_svc_ErrorHandler eh;
73 dbus_svc_ErrorHandler dh;
74 /*{ glibc b-trees: */
75 void * roots;
76 void * timeouts;
77 void * watches;
78 void * filters;
79 /*}*/
80 int n;
81 fd_set r_fds;
82 fd_set s_r_fds;
83 fd_set w_fds;
84 fd_set s_w_fds;
85 fd_set e_fds;
86 fd_set s_e_fds;
87 DBusMessage *currentMessage;
88 int rejectMessage;
89 } DBusConnectionState;
91 typedef struct root_s
93 char *path;
94 char *if_prefix;
95 DBUS_SVC cs;
96 dbus_svc_MessageHandler mh;
97 void *object;
98 void *tree;
99 } Root;
101 typedef struct mhn_s
103 char *path;
104 dbus_svc_MessageHandler mh;
105 void *object;
106 } MessageHandlerNode;
108 typedef struct mfn_s
110 DBusConnectionState *cs;
111 dbus_svc_MessageHandler mf;
112 void *obj;
113 int n_matches;
114 char **matches;
115 } MessageFilterNode;
117 typedef struct dbto_s
119 DBusTimeout *to;
120 DBusConnectionState *cs;
121 struct timeval tv;
122 } DBusConnectionTimeout;
124 static void no_free( void *p){ p=0; }
126 static int ptr_key_comparator( const void *p1, const void *p2 )
128 return
129 ( (p1 == p2)
131 :( (p1 > p2)
133 : -1
138 static DBusHandlerResult
139 default_message_filter
140 ( DBusConnection *connection,
141 DBusMessage *message,
142 void *p
145 DBusConnectionState *cs = p;
146 uint32_t type =dbus_message_get_type( message ),
147 serial =dbus_message_get_serial( message );
148 uint8_t reply =dbus_message_get_no_reply( message )==0;
149 const char
150 *path = dbus_message_get_path( message ),
151 *dest = dbus_message_get_destination( message ),
152 *member = dbus_message_get_member( message ),
153 *interface=dbus_message_get_interface( message ),
154 *sender =dbus_message_get_sender( message ),
155 *signature=dbus_message_get_signature( message );
156 connection = connection;
157 if(cs->mf)
158 return
159 (*(cs->mf))( cs, type, reply, serial, dest, path, member, interface, 0L,
160 sender, signature, message, 0L, 0L, 0L, cs->def_mf_obj
162 return HANDLED;
165 uint8_t
166 dbus_svc_add_filter
167 ( DBusConnectionState *cs, dbus_svc_MessageHandler mh, void *obj, int n_matches, ... )
169 DBusError error;
170 va_list va;
171 char *m;
173 va_start(va, n_matches );
175 cs->mf = mh;
176 cs->def_mf_obj = obj;
178 if ( ! dbus_connection_add_filter (cs->connection, default_message_filter, cs, NULL))
180 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_connection_add_filter failed");
181 va_end(va);
182 return( 0 );
185 if( n_matches )
187 memset(&error,'\0',sizeof(DBusError));
188 dbus_error_init(&error);
189 while( n_matches-- )
191 m = va_arg(va, char* ) ;
193 dbus_bus_add_match(cs->connection, m, &error);
195 if( dbus_error_is_set(&error))
197 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_bus_add_match failed for %s: %s %s",
198 m, error.name, error.message
200 va_end(va);
201 return(0);
205 va_end(va);
206 return( 1 );
210 uint8_t
211 dbus_svc_get_args_va(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, va_list va)
213 DBusError error;
214 memset(&error,'\0',sizeof(DBusError));
215 dbus_error_init(&error);
216 if( (!dbus_message_get_args_valist(msg, &error, firstType, va)) || dbus_error_is_set(&error) )
218 if( dbus_error_is_set(&error) )
220 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_get_args failed: %s %s",error.name, error.message);
221 dbus_error_free(&error);
222 }else
223 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_get_args failed: dbus_message_get_args_valist failed");
224 return( 0 );
226 return( 1 );
229 uint8_t
230 dbus_svc_get_args(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, ...)
232 va_list va;
233 uint8_t r;
234 va_start(va, firstType);
235 r = dbus_svc_get_args_va( cs, msg, firstType, va);
236 va_end(va);
237 return r;
240 uint8_t
241 dbus_svc_send_va
242 ( DBusConnectionState *cs,
243 dbus_svc_MessageType type,
244 int32_t reply_serial,
245 uint32_t *new_serial,
246 const char *destination,
247 const char *path,
248 const char *interface,
249 const char *member,
250 dbus_svc_DataType firstType,
251 va_list va
254 DBusMessageIter iter;
255 char *e;
256 DBusMessage *msg =
257 dbus_svc_new_message
258 ( cs,
259 type,
260 reply_serial,
261 destination,
262 path,
263 interface,
264 member
267 if(msg == 0L)
269 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_svc_new_message failed");
270 return 0;
273 if( type != DBUS_MESSAGE_TYPE_ERROR )
275 if( !dbus_message_append_args_valist( msg, firstType, va ) )
277 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args_valist failed");
278 return 0;
280 }else
282 if( firstType == DBUS_TYPE_STRING )
284 e = 0L;
285 e = va_arg( va, char* );
286 if( (e == 0L) || !dbus_message_set_error_name( msg, e ) )
288 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_set_error_name failed");
289 return 0;
291 firstType = va_arg(va, int);
292 if( firstType == DBUS_TYPE_STRING )
294 e = 0L;
295 e = va_arg( va, char* );
296 if( e == 0L )
298 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: NULL error message");
299 return 0;
301 dbus_message_iter_init_append (msg, &iter);
302 if( !dbus_message_iter_append_basic
303 (&iter, DBUS_TYPE_STRING, &e)
306 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_iter_append_basic failed");
307 return 0;
310 }else
312 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: unhandled type for error name: %c", firstType);
313 return 0;
317 if( !dbus_connection_send(cs->connection, msg, new_serial) )
319 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed");
320 return 0;
322 if( cs->dh != 0L ) (*(cs->dh))("Sending message");
323 dbus_connection_flush(cs->connection);
324 return 1;
327 uint8_t
328 dbus_svc_send
329 ( DBusConnectionState *cs,
330 dbus_svc_MessageType type,
331 int32_t reply_serial,
332 uint32_t *new_serial,
333 const char *destination,
334 const char *path,
335 const char *interface,
336 const char *member,
337 dbus_svc_DataType firstType,
341 uint8_t r;
342 va_list va;
343 va_start(va, firstType);
344 r = dbus_svc_send_va(cs, type, reply_serial, new_serial, destination, path,interface,member,firstType,va);
345 va_end(va);
346 return ( r ) ;
349 dbus_svc_MessageHandle
350 dbus_svc_new_message
351 ( DBusConnectionState* cs,
352 dbus_svc_MessageType type,
353 int32_t reply_serial,
354 const char *destination,
355 const char *path,
356 const char *interface,
357 const char *member
360 DBusMessage *msg = dbus_message_new(type);
362 if( msg == 0L)
364 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed");
365 return 0;
368 if( reply_serial != -1 )
370 if( !dbus_message_set_reply_serial(msg,reply_serial) )
372 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed");
373 return 0;
377 if( (destination !=0L) && !dbus_message_set_destination(msg, destination) )
379 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_destination failed");
380 return 0;
383 if( !dbus_message_set_path(msg, path) )
385 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_path failed");
386 return 0;
389 if( ! dbus_message_set_interface(msg,interface) )
391 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_interface failed - %s", interface);
392 return 0;
395 if( !dbus_message_set_member(msg,member) )
397 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_member failed");
398 return 0;
401 return msg;
404 extern uint8_t
405 dbus_svc_send_message
407 DBusConnectionState *cs,
408 dbus_svc_MessageHandle msg,
409 uint32_t *new_serial
412 if( !dbus_connection_send(cs->connection, msg, new_serial) )
414 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed");
415 return 0;
417 if( cs->dh != 0L ) (*(cs->dh))("Sending message");
418 dbus_connection_flush(cs->connection);
419 return 1;
422 uint8_t
423 dbus_svc_message_append_args(DBusConnectionState *cs, dbus_svc_MessageHandle msg, dbus_svc_DataType firstType, ...)
425 va_list va;
426 va_start(va, firstType);
427 if( !dbus_message_append_args_valist( msg, firstType, va ) )
429 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args failed");
430 va_end(va);
431 return 0;
433 va_end(va);
434 return ( 1 ) ;
437 dbus_svc_MessageHandle
438 dbus_svc_call
439 ( DBusConnectionState *cs,
440 const char *destination,
441 const char *path,
442 const char *member,
443 const char *interface,
444 dbus_svc_DataType firstType,
445 ...
448 DBusMessage *message=0L, *reply=0L;
449 va_list va;
450 DBusError error;
451 int reply_timeout=20000;
453 va_start(va, firstType);
455 memset(&error,'\0',sizeof(DBusError));
456 dbus_error_init(&error);
458 if(( message =
459 dbus_message_new_method_call
460 ( destination,
461 path,
462 interface,
463 member
465 ) == 0L
468 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_new_method_call failed");
469 va_end(va);
470 return(0L);
473 if( !dbus_message_append_args_valist( message, firstType, va ) )
475 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_append_args_valist failed");
476 va_end(va);
477 return(0L);
480 if((reply =
481 dbus_connection_send_with_reply_and_block
482 (cs->connection,
483 message, reply_timeout,
484 &error
486 ) == 0L
489 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_send_with_reply_and_block failed: %s %s",
490 error.name, error.message
492 va_end(va);
493 return(0L);
495 va_end(va);
496 return reply;
499 dbus_svc_MessageIterator
500 dbus_svc_message_iterator_new( DBusConnectionState *cs, DBusMessage *msg)
502 DBusMessageIter *iter = malloc( sizeof(DBusMessageIter) );
503 void *p =cs;
504 p++;
505 if( iter != 0L )
507 if( !dbus_message_iter_init( msg, iter ))
509 free( iter ) ;
510 iter = 0L;
513 return iter;
516 uint32_t
517 dbus_svc_message_next_arg_type( DBusConnectionState *cs, dbus_svc_MessageIterator iter )
519 void *p =cs;
520 p++;
521 return dbus_message_iter_get_arg_type( iter );
524 void
525 dbus_svc_message_next_arg( DBusConnectionState *cs, dbus_svc_MessageIterator iter, void *value )
527 void *p =cs;
528 p++;
529 dbus_message_iter_get_basic( iter, value );
530 dbus_message_iter_next( iter );
533 uint32_t
534 dbus_svc_message_element_type(DBusConnectionState *cs , dbus_svc_MessageIterator iter)
536 void *p =cs;
537 p++;
538 return dbus_message_iter_get_element_type(iter);
541 void
542 dbus_svc_message_get_elements( DBusConnectionState *cs , dbus_svc_MessageIterator iter, uint32_t *n, void *array )
544 void *p =cs;
545 p++;
546 dbus_message_iter_get_fixed_array( iter, n, array);
549 void dbus_svc_message_iterator_free( DBusConnectionState *cs, dbus_svc_MessageIterator iter )
551 void *p =cs;
552 p++;
553 free( iter );
556 uint8_t dbus_svc_message_type( DBusMessage *msg )
558 return dbus_message_get_type( msg );
561 static DBusConnectionState *
562 dbcs_new( DBusConnection *connection )
564 DBusConnectionState *dbcs = (DBusConnectionState *) malloc( sizeof(DBusConnectionState) );
565 if ( dbcs )
567 memset( dbcs, '\0', sizeof( DBusConnectionState ));
568 dbcs->connection = connection;
570 return(dbcs);
573 static DBusConnectionTimeout *
574 timeout_new( DBusTimeout *timeout )
576 DBusConnectionTimeout *to = (DBusConnectionTimeout *) malloc ( sizeof(DBusConnectionTimeout) );
577 if( to != 0L )
579 to->to = timeout;
580 dbus_timeout_set_data(timeout, to, 0L);
581 if( dbus_timeout_get_enabled(timeout) )
582 gettimeofday(&(to->tv),0L);
583 else
585 to->tv.tv_sec = 0 ;
586 to->tv.tv_usec = 0 ;
589 return( to );
592 static dbus_bool_t
593 add_timeout( DBusTimeout *timeout, void *csp )
595 DBusConnectionState *cs = csp;
596 DBusConnectionTimeout *to = timeout_new(timeout);
597 if( cs->dh != 0L ) (*(cs->dh))("add_timeout: %d", dbus_timeout_get_interval(timeout));
598 to->cs = cs;
599 if ( to )
601 if( tsearch((void*)to, &(cs->timeouts), ptr_key_comparator) != 0L )
602 return TRUE;
604 if( cs->eh != 0L ) (*(cs->eh))("add_timeout: out of memory");
605 return FALSE;
608 static void
609 remove_timeout( DBusTimeout *timeout, void *csp )
611 DBusConnectionState *cs = csp;
612 DBusConnectionTimeout *to = dbus_timeout_get_data(timeout);
613 if( (to != 0L) && (to->to == timeout) )
615 if( cs->dh != 0L ) (*(cs->dh))("remove_timeout: %d", dbus_timeout_get_interval(to->to));
616 if( tdelete((const void*)to, &(cs->timeouts), ptr_key_comparator) != 0L )
618 free(to);
619 }else
620 if( cs->eh != 0L ) (*(cs->eh))("remove_timeout: can't happen?!?: timeout data %p not found", to);
621 }else
622 if( cs->eh != 0L ) (*(cs->eh))("remove_timeout: can't happen?!?: timeout %p did not record data %p %p",
623 timeout, to, ((to != 0L) ? to->to : 0L)
627 static void
628 toggle_timeout( DBusTimeout *timeout, void *csp )
630 DBusConnectionState *cs = csp;
631 DBusConnectionTimeout **top = tfind( (const void*) dbus_timeout_get_data(timeout),
632 &(cs->timeouts),
633 ptr_key_comparator
635 *to=0L;
636 if( (top != 0L) && ((to=*top) != 0L) && (to->to == timeout) )
638 if( cs->dh != 0L ) (*(cs->dh))("toggle_timeout: %d", dbus_timeout_get_interval(to->to));
639 if( dbus_timeout_get_enabled(timeout) )
640 gettimeofday(&(to->tv),0L);
641 else
643 to->tv.tv_sec = 0 ;
644 to->tv.tv_usec = 0 ;
646 }else
647 if( cs->eh != 0L ) (*(cs->eh))("toggle_timeout: can't happen?!?: timeout %p %s %p %p", timeout,
648 ((to==0L) ? "did not record data" : "not found"),
649 to, ((to != 0L) ? to->to : 0L)
653 static void
654 process_timeout( const void *p, const VISIT which, const int level)
656 DBusConnectionState *cs;
657 void * const *tpp = p;
658 DBusConnectionTimeout *to;
659 struct timeval tv;
660 float now, then, interval;
661 int l = level ? 1 : 0;
662 l=l;
664 gettimeofday(&tv,0L);
666 if( (tpp != 0L) && (*tpp != 0L) && ((which == postorder) || (which == leaf)) )
668 to = (DBusConnectionTimeout*)*tpp;
669 cs = to->cs;
670 if ( !dbus_timeout_get_enabled(to->to) )
671 return;
672 cs = dbus_timeout_get_data(to->to);
673 then = ((float)to->tv.tv_sec) + (((float)to->tv.tv_usec) / 1000000.0);
674 if( then != 0.0 )
676 interval = ((float)dbus_timeout_get_interval(to->to)) / 1000.0;
677 now = ((float)tv.tv_sec) + (( (float)tv.tv_usec) / 1000000.0);
678 if( (now - then) >= interval )
680 if( cs->dh != 0L ) (*(cs->dh))("handle_timeout: %d - %f %f %f", dbus_timeout_get_interval(to->to), then, now, interval);
681 dbus_timeout_handle( to->to );
682 to->tv=tv;
684 }else
686 to->tv = tv;
691 static void
692 process_timeouts ( DBusConnectionState *cs )
694 twalk( cs->timeouts, process_timeout );
697 static void
698 set_watch_fds( DBusWatch *watch, DBusConnectionState *cs )
700 uint8_t flags = dbus_watch_get_flags(watch);
701 int fd = dbus_watch_get_fd(watch);
703 if ( cs->n <= fd )
704 cs->n = fd + 1;
706 if ( dbus_watch_get_enabled(watch) )
708 if ( flags & DBUS_WATCH_READABLE )
710 FD_SET(fd , &(cs->r_fds));
711 if( cs->wh != 0L )
712 (*(cs->wh))( fd, WATCH_ENABLE | WATCH_READ, cs->wh_arg );
713 }else
715 FD_CLR(fd , &(cs->r_fds));
716 if( cs->wh != 0L )
717 (*(cs->wh))( fd, WATCH_READ, cs->wh_arg );
720 if ( flags & DBUS_WATCH_WRITABLE )
722 FD_SET(fd , &(cs->w_fds));
723 if( cs->wh != 0L )
724 (*(cs->wh))( fd, WATCH_ENABLE | WATCH_WRITE, cs->wh_arg );
725 }else
727 FD_CLR(fd , &(cs->w_fds));
728 if( cs->wh != 0L )
729 (*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg );
731 if ( flags & DBUS_WATCH_ERROR )
733 FD_SET(fd , &(cs->e_fds));
734 if( cs->wh != 0L )
735 (*(cs->wh))( fd, WATCH_ENABLE | WATCH_ERROR, cs->wh_arg );
736 }else
738 FD_CLR(fd , &(cs->e_fds));
739 if( cs->wh != 0L )
740 (*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg );
742 }else
744 if( FD_ISSET( fd, &(cs->r_fds)) )
745 if( cs->wh != 0L )
746 (*(cs->wh))( fd, WATCH_READ, cs->wh_arg );
747 FD_CLR(fd , &(cs->r_fds));
749 if( FD_ISSET( fd, &(cs->w_fds)) )
750 if( cs->wh != 0L )
751 (*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg );
752 FD_CLR(fd , &(cs->w_fds));
754 if( FD_ISSET( fd, &(cs->e_fds)) )
755 if( cs->wh != 0L )
756 (*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg );
757 FD_CLR(fd , &(cs->e_fds));
761 static dbus_bool_t
762 add_watch ( DBusWatch *watch, void *csp )
764 DBusConnectionState *cs = csp;
766 dbus_watch_set_data(watch, cs, no_free );
767 if( cs->dh != 0L ) (*(cs->dh))("add_watch: %d", dbus_watch_get_fd(watch));
768 if( tsearch((const void*)watch,&(cs->watches),ptr_key_comparator) == 0L )
770 if( cs->eh != 0L ) (*(cs->eh))("add_watch: out of memory");
771 return FALSE;
773 set_watch_fds(watch,cs);
774 return TRUE;
777 static void
778 remove_watch ( DBusWatch *watch, void *csp )
780 DBusConnectionState *cs = csp;
781 int fd = dbus_watch_get_fd(watch);
782 if( tdelete((const void*)watch, &(cs->watches), ptr_key_comparator) == 0L )
783 if( cs->eh != 0L ) (*(cs->eh))("remove_watch: can't happen?!?: watch not found");
784 if( cs->dh != 0L ) (*(cs->dh))("remove_watch: %d", dbus_watch_get_fd(watch));
785 FD_CLR(fd , &(cs->r_fds));
786 FD_CLR(fd , &(cs->w_fds));
787 FD_CLR(fd , &(cs->e_fds));
788 if( cs->wh != 0L )
789 (*(cs->wh))(dbus_watch_get_fd(watch), WATCH_READ | WATCH_WRITE | WATCH_ERROR, cs->wh_arg );
792 static void
793 toggle_watch ( DBusWatch *watch, void *csp )
795 DBusConnectionState *cs = csp;
796 if( cs->dh != 0L ) (*(cs->dh))("toggle_watch: %d", dbus_watch_get_fd(watch));
797 set_watch_fds(watch,cs);
800 static void
801 process_watch( const void *p, const VISIT which, const int level)
803 void * const *wpp=p;
804 DBusWatch *w;
805 int fd;
806 uint8_t flags;
807 DBusConnectionState *cs;
808 int l = level ? 1 : 0;
809 l=l;
811 if((wpp != 0L) && (*wpp != 0L) && ( (which == postorder) || (which == leaf) ) )
813 w = (DBusWatch*)*wpp;
814 cs = dbus_watch_get_data( w );
815 if( cs == 0 )
816 return;
817 if( ! dbus_watch_get_enabled(w) )
818 return;
819 fd = dbus_watch_get_fd( w );
820 flags = dbus_watch_get_flags( w );
821 if( cs->dh != 0L ) (*(cs->dh))("handle_watch: %d", dbus_watch_get_fd( w ));
822 if ( (flags & DBUS_WATCH_READABLE) && (FD_ISSET(fd, &(cs->s_r_fds))) )
823 dbus_watch_handle(w, DBUS_WATCH_READABLE);
824 if ( (flags & DBUS_WATCH_WRITABLE) && (FD_ISSET(fd, &(cs->s_w_fds))) )
825 dbus_watch_handle(w, DBUS_WATCH_READABLE);
826 if ( (flags & DBUS_WATCH_ERROR) && (FD_ISSET(fd, &(cs->s_e_fds))) )
827 dbus_watch_handle(w, DBUS_WATCH_ERROR);
831 static void
832 process_watches ( DBusConnectionState *cs )
834 twalk( cs->watches, process_watch );
837 void dbus_svc_handle_watch( DBusConnectionState *cs, int fd, dbus_svc_WatchFlags action )
839 switch( action & 7 )
841 case WATCH_READ:
842 FD_SET(fd, &(cs->s_r_fds));
843 break;
845 case WATCH_WRITE:
846 FD_SET(fd, &(cs->s_w_fds));
847 break;
849 case WATCH_ERROR:
850 FD_SET(fd, &(cs->s_e_fds));
851 break;
855 static void
856 dispatch_status
857 ( DBusConnection *connection,
858 DBusDispatchStatus new_status,
859 void *csp
862 connection=connection;
863 DBusConnectionState *cs = csp;
864 cs->dispatchStatus = new_status;
867 void
868 dbus_svc_main_loop( DBusConnectionState *cs, void (*idle_handler)(DBusConnectionState *) )
870 struct timeval timeout={0,200000};
871 int n_fds;
873 while( cs->status != SHUTDOWN )
875 cs->s_r_fds = cs->r_fds;
876 cs->s_w_fds = cs->w_fds;
877 cs->s_e_fds = cs->e_fds;
879 timeout.tv_sec = 0;
880 timeout.tv_usec= 200000;
882 if ( (n_fds = select(cs->n, &(cs->s_r_fds), &(cs->s_w_fds), &(cs->s_e_fds), &timeout)) < 0 )
884 if (errno != EINTR)
886 if( cs->eh != 0L ) (*(cs->eh))( "select failed: %d : %s", errno, strerror(errno));
887 return;
891 if( n_fds > 0 )
892 process_watches(cs);
894 process_timeouts(cs);
896 if ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE )
897 dbus_connection_dispatch( cs->connection );
899 if( idle_handler != 0L )
900 (*idle_handler)(cs);
904 void dbus_svc_dispatch(DBusConnectionState *cs)
906 process_watches(cs);
908 FD_ZERO(&(cs->s_r_fds));
909 FD_ZERO(&(cs->s_w_fds));
910 FD_ZERO(&(cs->s_e_fds));
912 process_timeouts(cs);
914 while ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE )
915 dbus_connection_dispatch( cs->connection );
918 void
919 dbus_svc_quit( DBusConnectionState *cs )
921 cs->status = SHUTDOWN;
924 static isc_result_t
925 connection_setup
926 ( DBusConnection *connection,
927 DBUS_SVC *dbus,
928 dbus_svc_WatchHandler wh,
929 dbus_svc_ErrorHandler eh,
930 dbus_svc_ErrorHandler dh,
931 void *wh_arg
934 *dbus = dbcs_new( connection );
936 if ( *dbus == 0L )
938 if(eh)(*(eh))("connection_setup: out of memory");
939 goto fail;
941 (*dbus)->wh = wh;
942 (*dbus)->wh_arg = wh_arg;
943 (*dbus)->eh = eh;
944 (*dbus)->dh = dh;
946 if (!dbus_connection_set_watch_functions
947 ( (*dbus)->connection,
948 add_watch,
949 remove_watch,
950 toggle_watch,
951 *dbus,
952 no_free
956 if( (*dbus)->eh != 0L ) (*((*dbus)->eh))("connection_setup: dbus_connection_set_watch_functions failed");
957 goto fail;
960 if (!dbus_connection_set_timeout_functions
961 ( connection,
962 add_timeout,
963 remove_timeout,
964 toggle_timeout,
965 *dbus,
966 no_free
970 if( (*dbus)->eh != 0L ) (*((*dbus)->eh))("connection_setup: dbus_connection_set_timeout_functions failed");
971 goto fail;
974 dbus_connection_set_dispatch_status_function
975 ( connection,
976 dispatch_status,
977 *dbus,
978 no_free
981 if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
982 dbus_connection_ref(connection);
984 return ISC_R_SUCCESS;
986 fail:
987 if( *dbus != 0L )
988 free(*dbus);
990 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
991 dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
992 dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
994 return ISC_R_FAILURE;
997 isc_result_t
998 dbus_svc_init
1000 dbus_svc_DBUS_TYPE bus,
1001 char *name,
1002 DBUS_SVC *dbus,
1003 dbus_svc_WatchHandler wh ,
1004 dbus_svc_ErrorHandler eh ,
1005 dbus_svc_ErrorHandler dh ,
1006 void *wh_arg
1009 DBusConnection *connection;
1010 DBusError error;
1011 char *session_bus_address=0L;
1013 memset(&error,'\0',sizeof(DBusError));
1015 dbus_error_init(&error);
1017 switch( bus )
1019 /* DBUS_PRIVATE_* bus types are the only type which allow reconnection if the dbus-daemon is restarted
1021 case DBUS_PRIVATE_SYSTEM:
1023 if ( (connection = dbus_connection_open_private("unix:path=/var/run/dbus/system_bus_socket", &error)) == 0L )
1025 if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
1026 return ISC_R_FAILURE;
1029 if ( ! dbus_bus_register(connection,&error) )
1031 if(eh)(*eh)("dbus_bus_register failed: %s %s", error.name, error.message);
1032 dbus_connection_close(connection);
1033 free(connection);
1034 return ISC_R_FAILURE;
1036 break;
1038 case DBUS_PRIVATE_SESSION:
1040 session_bus_address = getenv("DBUS_SESSION_BUS_ADDRESS");
1041 if ( session_bus_address == 0L )
1043 if(eh)(*eh)("dbus_svc_init failed: DBUS_SESSION_BUS_ADDRESS environment variable not set");
1044 return ISC_R_FAILURE;
1047 if ( (connection = dbus_connection_open_private(session_bus_address, &error)) == 0L )
1049 if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
1050 return ISC_R_FAILURE;
1053 if ( ! dbus_bus_register(connection,&error) )
1055 if(eh)(*eh)("dbus_bus_register failed: %s %s", error.name, error.message);
1056 dbus_connection_close(connection);
1057 free(connection);
1058 return ISC_R_FAILURE;
1060 break;
1062 case DBUS_SYSTEM:
1063 case DBUS_SESSION:
1065 if ( (connection = dbus_bus_get (bus, &error)) == 0L )
1067 if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
1068 return ISC_R_FAILURE;
1070 break;
1072 default:
1073 if(eh)(*eh)("dbus_svc_init failed: unknown bus type %d", bus);
1074 return ISC_R_FAILURE;
1077 dbus_connection_set_exit_on_disconnect(connection, FALSE);
1079 if ( (connection_setup(connection, dbus, wh, eh, dh, wh_arg)) != ISC_R_SUCCESS)
1081 if(eh)(*eh)("dbus_svc_init failed: connection_setup failed");
1082 return ISC_R_FAILURE;
1085 if( name == 0L )
1086 return ISC_R_SUCCESS;
1088 (*dbus)->unique_name = dbus_bus_get_unique_name(connection);
1090 switch
1091 ( dbus_bus_request_name
1092 ( connection, name,
1093 #ifdef DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
1094 DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT ,
1095 #else
1097 #endif
1098 &error
1102 case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
1103 break;
1104 case DBUS_REQUEST_NAME_REPLY_EXISTS:
1105 case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
1106 case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
1107 if(eh)(*eh)("dbus_svc_init: dbus_bus_request_name failed: Name already registered");
1108 goto give_up;
1109 default:
1110 if(eh)(*eh)("dbus_svc_init: dbus_bus_request_name failed: %s %s", error.name, error.message);
1111 goto give_up;
1113 return ISC_R_SUCCESS;
1115 give_up:
1116 dbus_connection_close( connection );
1117 dbus_connection_unref( connection );
1118 if( *dbus )
1120 dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
1121 dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
1122 dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
1123 free(*dbus);
1125 return ISC_R_FAILURE;
1128 const char *dbus_svc_unique_name(DBusConnectionState *cs)
1130 return cs->unique_name;
1133 void
1134 dbus_svc_shutdown ( DBusConnectionState *cs )
1136 if (!dbus_connection_set_watch_functions
1137 ( cs->connection,
1138 NULL, NULL, NULL, NULL, NULL
1140 ) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_watch_functions: No Memory."
1141 "Setting watch functions to NULL failed."
1144 if (!dbus_connection_set_timeout_functions
1145 ( cs->connection,
1146 NULL, NULL, NULL, NULL, NULL
1148 ) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_timeout_functions: No Memory."
1149 "Setting timeout functions to NULL failed."
1152 dbus_connection_set_dispatch_status_function (cs->connection, NULL, NULL, NULL);
1154 tdestroy( cs->timeouts, free);
1155 cs->timeouts=0L;
1156 tdestroy( cs->watches, no_free);
1157 cs->watches=0L;
1159 dbus_connection_close( cs->connection );
1160 dbus_connection_unref( cs->connection );
1162 free( cs );