1/* $NetBSD: dbus_service.c,v 1.2 2011/02/16 03:46:54 christos Exp $ */ 2 3/* dbus_service.c 4 * 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 11 * 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. 17 * 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. 22 * 23 */ 24 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> 38extern 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> 45typedef void (*__free_fn_t) (void *__nodep); 46extern 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> 54 55#include <named/dbus_service.h> 56#include <isc/result.h> 57 58typedef struct dbcs_s 59{ 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; 90 91typedef struct root_s 92{ 93 char *path; 94 char *if_prefix; 95 DBUS_SVC cs; 96 dbus_svc_MessageHandler mh; 97 void *object; 98 void *tree; 99} Root; 100 101typedef struct mhn_s 102{ 103 char *path; 104 dbus_svc_MessageHandler mh; 105 void *object; 106} MessageHandlerNode; 107 108typedef struct mfn_s 109{ 110 DBusConnectionState *cs; 111 dbus_svc_MessageHandler mf; 112 void *obj; 113 int n_matches; 114 char **matches; 115} MessageFilterNode; 116 117typedef struct dbto_s 118{ 119 DBusTimeout *to; 120 DBusConnectionState *cs; 121 struct timeval tv; 122} DBusConnectionTimeout; 123 124static void no_free( void *p){ p=0; } 125 126static int ptr_key_comparator( const void *p1, const void *p2 ) 127{ 128 return 129 ( (p1 == p2) 130 ? 0 131 :( (p1 > p2) 132 ? 1 133 : -1 134 ) 135 ); 136} 137 138static DBusHandlerResult 139default_message_filter 140( DBusConnection *connection, 141 DBusMessage *message, 142 void *p 143) 144{ 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 161 ) ; 162 return HANDLED; 163} 164 165uint8_t 166dbus_svc_add_filter 167( DBusConnectionState *cs, dbus_svc_MessageHandler mh, void *obj, int n_matches, ... ) 168{ 169 DBusError error; 170 va_list va; 171 char *m; 172 173 va_start(va, n_matches ); 174 175 cs->mf = mh; 176 cs->def_mf_obj = obj; 177 178 if ( ! dbus_connection_add_filter (cs->connection, default_message_filter, cs, NULL)) 179 { 180 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_connection_add_filter failed"); 181 va_end(va); 182 return( 0 ); 183 } 184 185 if( n_matches ) 186 { 187 memset(&error,'\0',sizeof(DBusError)); 188 dbus_error_init(&error); 189 while( n_matches-- ) 190 { 191 m = va_arg(va, char* ) ; 192 193 dbus_bus_add_match(cs->connection, m, &error); 194 195 if( dbus_error_is_set(&error)) 196 { 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 199 ); 200 va_end(va); 201 return(0); 202 } 203 } 204 } 205 va_end(va); 206 return( 1 ); 207} 208 209 210uint8_t 211dbus_svc_get_args_va(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, va_list va) 212{ 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) ) 217 { 218 if( dbus_error_is_set(&error) ) 219 { 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 ); 225 } 226 return( 1 ); 227} 228 229uint8_t 230dbus_svc_get_args(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, ...) 231{ 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; 238} 239 240uint8_t 241dbus_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 252) 253{ 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 265 ); 266 267 if(msg == 0L) 268 { 269 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_svc_new_message failed"); 270 return 0; 271 } 272 273 if( type != DBUS_MESSAGE_TYPE_ERROR ) 274 { 275 if( !dbus_message_append_args_valist( msg, firstType, va ) ) 276 { 277 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args_valist failed"); 278 return 0; 279 } 280 }else 281 { 282 if( firstType == DBUS_TYPE_STRING ) 283 { 284 e = 0L; 285 e = va_arg( va, char* ); 286 if( (e == 0L) || !dbus_message_set_error_name( msg, e ) ) 287 { 288 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_set_error_name failed"); 289 return 0; 290 } 291 firstType = va_arg(va, int); 292 if( firstType == DBUS_TYPE_STRING ) 293 { 294 e = 0L; 295 e = va_arg( va, char* ); 296 if( e == 0L ) 297 { 298 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: NULL error message"); 299 return 0; 300 } 301 dbus_message_iter_init_append (msg, &iter); 302 if( !dbus_message_iter_append_basic 303 (&iter, DBUS_TYPE_STRING, &e) 304 ) 305 { 306 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_iter_append_basic failed"); 307 return 0; 308 } 309 } 310 }else 311 { 312 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: unhandled type for error name: %c", firstType); 313 return 0; 314 } 315 } 316 317 if( !dbus_connection_send(cs->connection, msg, new_serial) ) 318 { 319 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed"); 320 return 0; 321 } 322 if( cs->dh != 0L ) (*(cs->dh))("Sending message"); 323 dbus_connection_flush(cs->connection); 324 return 1; 325} 326 327uint8_t 328dbus_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, 338 ... 339) 340{ 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 ) ; 347} 348 349dbus_svc_MessageHandle 350dbus_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 358) 359{ 360 DBusMessage *msg = dbus_message_new(type); 361 362 if( msg == 0L) 363 { 364 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed"); 365 return 0; 366 } 367 368 if( reply_serial != -1 ) 369 { 370 if( !dbus_message_set_reply_serial(msg,reply_serial) ) 371 { 372 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed"); 373 return 0; 374 } 375 } 376 377 if( (destination !=0L) && !dbus_message_set_destination(msg, destination) ) 378 { 379 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_destination failed"); 380 return 0; 381 } 382 383 if( !dbus_message_set_path(msg, path) ) 384 { 385 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_path failed"); 386 return 0; 387 } 388 389 if( ! dbus_message_set_interface(msg,interface) ) 390 { 391 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_interface failed - %s", interface); 392 return 0; 393 } 394 395 if( !dbus_message_set_member(msg,member) ) 396 { 397 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_member failed"); 398 return 0; 399 } 400 401 return msg; 402} 403 404extern uint8_t 405dbus_svc_send_message 406( 407 DBusConnectionState *cs, 408 dbus_svc_MessageHandle msg, 409 uint32_t *new_serial 410) 411{ 412 if( !dbus_connection_send(cs->connection, msg, new_serial) ) 413 { 414 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed"); 415 return 0; 416 } 417 if( cs->dh != 0L ) (*(cs->dh))("Sending message"); 418 dbus_connection_flush(cs->connection); 419 return 1; 420} 421 422uint8_t 423dbus_svc_message_append_args(DBusConnectionState *cs, dbus_svc_MessageHandle msg, dbus_svc_DataType firstType, ...) 424{ 425 va_list va; 426 va_start(va, firstType); 427 if( !dbus_message_append_args_valist( msg, firstType, va ) ) 428 { 429 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args failed"); 430 va_end(va); 431 return 0; 432 } 433 va_end(va); 434 return ( 1 ) ; 435} 436 437dbus_svc_MessageHandle 438dbus_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 ... 446) 447{ 448 DBusMessage *message=0L, *reply=0L; 449 va_list va; 450 DBusError error; 451 int reply_timeout=20000; 452 453 va_start(va, firstType); 454 455 memset(&error,'\0',sizeof(DBusError)); 456 dbus_error_init(&error); 457 458 if(( message = 459 dbus_message_new_method_call 460 ( destination, 461 path, 462 interface, 463 member 464 ) 465 ) == 0L 466 ) 467 { 468 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_new_method_call failed"); 469 va_end(va); 470 return(0L); 471 }; 472 473 if( !dbus_message_append_args_valist( message, firstType, va ) ) 474 { 475 if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_append_args_valist failed"); 476 va_end(va); 477 return(0L); 478 } 479 480 if((reply = 481 dbus_connection_send_with_reply_and_block 482 (cs->connection, 483 message, reply_timeout, 484 &error 485 ) 486 ) == 0L 487 ) 488 { 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 491 ); 492 va_end(va); 493 return(0L); 494 } 495 va_end(va); 496 return reply; 497} 498 499dbus_svc_MessageIterator 500dbus_svc_message_iterator_new( DBusConnectionState *cs, DBusMessage *msg) 501{ 502 DBusMessageIter *iter = malloc( sizeof(DBusMessageIter) ); 503 void *p =cs; 504 p++; 505 if( iter != 0L ) 506 { 507 if( !dbus_message_iter_init( msg, iter )) 508 { 509 free( iter ) ; 510 iter = 0L; 511 } 512 } 513 return iter; 514} 515 516uint32_t 517dbus_svc_message_next_arg_type( DBusConnectionState *cs, dbus_svc_MessageIterator iter ) 518{ 519 void *p =cs; 520 p++; 521 return dbus_message_iter_get_arg_type( iter ); 522} 523 524void 525dbus_svc_message_next_arg( DBusConnectionState *cs, dbus_svc_MessageIterator iter, void *value ) 526{ 527 void *p =cs; 528 p++; 529 dbus_message_iter_get_basic( iter, value ); 530 dbus_message_iter_next( iter ); 531} 532 533uint32_t 534dbus_svc_message_element_type(DBusConnectionState *cs , dbus_svc_MessageIterator iter) 535{ 536 void *p =cs; 537 p++; 538 return dbus_message_iter_get_element_type(iter); 539} 540 541void 542dbus_svc_message_get_elements( DBusConnectionState *cs , dbus_svc_MessageIterator iter, uint32_t *n, void *array ) 543{ 544 void *p =cs; 545 p++; 546 dbus_message_iter_get_fixed_array( iter, n, array); 547} 548 549void dbus_svc_message_iterator_free( DBusConnectionState *cs, dbus_svc_MessageIterator iter ) 550{ 551 void *p =cs; 552 p++; 553 free( iter ); 554} 555 556uint8_t dbus_svc_message_type( DBusMessage *msg ) 557{ 558 return dbus_message_get_type( msg ); 559} 560 561static DBusConnectionState * 562dbcs_new( DBusConnection *connection ) 563{ 564 DBusConnectionState *dbcs = (DBusConnectionState *) malloc( sizeof(DBusConnectionState) ); 565 if ( dbcs ) 566 { 567 memset( dbcs, '\0', sizeof( DBusConnectionState )); 568 dbcs->connection = connection; 569 } 570 return(dbcs); 571} 572 573static DBusConnectionTimeout * 574timeout_new( DBusTimeout *timeout ) 575{ 576 DBusConnectionTimeout *to = (DBusConnectionTimeout *) malloc ( sizeof(DBusConnectionTimeout) ); 577 if( to != 0L ) 578 { 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 584 { 585 to->tv.tv_sec = 0 ; 586 to->tv.tv_usec = 0 ; 587 } 588 } 589 return( to ); 590} 591 592static dbus_bool_t 593add_timeout( DBusTimeout *timeout, void *csp ) 594{ 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 ) 600 { 601 if( tsearch((void*)to, &(cs->timeouts), ptr_key_comparator) != 0L ) 602 return TRUE; 603 } 604 if( cs->eh != 0L ) (*(cs->eh))("add_timeout: out of memory"); 605 return FALSE; 606} 607 608static void 609remove_timeout( DBusTimeout *timeout, void *csp ) 610{ 611 DBusConnectionState *cs = csp; 612 DBusConnectionTimeout *to = dbus_timeout_get_data(timeout); 613 if( (to != 0L) && (to->to == timeout) ) 614 { 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 ) 617 { 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) 624 ); 625} 626 627static void 628toggle_timeout( DBusTimeout *timeout, void *csp ) 629{ 630 DBusConnectionState *cs = csp; 631 DBusConnectionTimeout **top = tfind( (const void*) dbus_timeout_get_data(timeout), 632 &(cs->timeouts), 633 ptr_key_comparator 634 ), 635 *to=0L; 636 if( (top != 0L) && ((to=*top) != 0L) && (to->to == timeout) ) 637 { 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 642 { 643 to->tv.tv_sec = 0 ; 644 to->tv.tv_usec = 0 ; 645 } 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) 650 ); 651} 652 653static void 654process_timeout( const void *p, const VISIT which, const int level) 655{ 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; 663 664 gettimeofday(&tv,0L); 665 666 if( (tpp != 0L) && (*tpp != 0L) && ((which == postorder) || (which == leaf)) ) 667 { 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 ) 675 { 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 ) 679 { 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; 683 } 684 }else 685 { 686 to->tv = tv; 687 } 688 } 689} 690 691static void 692process_timeouts ( DBusConnectionState *cs ) 693{ 694 twalk( cs->timeouts, process_timeout ); 695} 696 697static void 698set_watch_fds( DBusWatch *watch, DBusConnectionState *cs ) 699{ 700 uint8_t flags = dbus_watch_get_flags(watch); 701 int fd = dbus_watch_get_fd(watch); 702 703 if ( cs->n <= fd ) 704 cs->n = fd + 1; 705 706 if ( dbus_watch_get_enabled(watch) ) 707 { 708 if ( flags & DBUS_WATCH_READABLE ) 709 { 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 714 { 715 FD_CLR(fd , &(cs->r_fds)); 716 if( cs->wh != 0L ) 717 (*(cs->wh))( fd, WATCH_READ, cs->wh_arg ); 718 } 719 720 if ( flags & DBUS_WATCH_WRITABLE ) 721 { 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 726 { 727 FD_CLR(fd , &(cs->w_fds)); 728 if( cs->wh != 0L ) 729 (*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg ); 730 } 731 if ( flags & DBUS_WATCH_ERROR ) 732 { 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 737 { 738 FD_CLR(fd , &(cs->e_fds)); 739 if( cs->wh != 0L ) 740 (*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg ); 741 } 742 }else 743 { 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)); 748 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)); 753 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)); 758 } 759} 760 761static dbus_bool_t 762add_watch ( DBusWatch *watch, void *csp ) 763{ 764 DBusConnectionState *cs = csp; 765 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 ) 769 { 770 if( cs->eh != 0L ) (*(cs->eh))("add_watch: out of memory"); 771 return FALSE; 772 } 773 set_watch_fds(watch,cs); 774 return TRUE; 775} 776 777static void 778remove_watch ( DBusWatch *watch, void *csp ) 779{ 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 ); 790} 791 792static void 793toggle_watch ( DBusWatch *watch, void *csp ) 794{ 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); 798} 799 800static void 801process_watch( const void *p, const VISIT which, const int level) 802{ 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; 810 811 if((wpp != 0L) && (*wpp != 0L) && ( (which == postorder) || (which == leaf) ) ) 812 { 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); 828 } 829} 830 831static void 832process_watches ( DBusConnectionState *cs ) 833{ 834 twalk( cs->watches, process_watch ); 835} 836 837void dbus_svc_handle_watch( DBusConnectionState *cs, int fd, dbus_svc_WatchFlags action ) 838{ 839 switch( action & 7 ) 840 { 841 case WATCH_READ: 842 FD_SET(fd, &(cs->s_r_fds)); 843 break; 844 845 case WATCH_WRITE: 846 FD_SET(fd, &(cs->s_w_fds)); 847 break; 848 849 case WATCH_ERROR: 850 FD_SET(fd, &(cs->s_e_fds)); 851 break; 852 } 853} 854 855static void 856dispatch_status 857( DBusConnection *connection, 858 DBusDispatchStatus new_status, 859 void *csp 860) 861{ 862 connection=connection; 863 DBusConnectionState *cs = csp; 864 cs->dispatchStatus = new_status; 865} 866 867void 868dbus_svc_main_loop( DBusConnectionState *cs, void (*idle_handler)(DBusConnectionState *) ) 869{ 870 struct timeval timeout={0,200000}; 871 int n_fds; 872 873 while( cs->status != SHUTDOWN ) 874 { 875 cs->s_r_fds = cs->r_fds; 876 cs->s_w_fds = cs->w_fds; 877 cs->s_e_fds = cs->e_fds; 878 879 timeout.tv_sec = 0; 880 timeout.tv_usec= 200000; 881 882 if ( (n_fds = select(cs->n, &(cs->s_r_fds), &(cs->s_w_fds), &(cs->s_e_fds), &timeout)) < 0 ) 883 { 884 if (errno != EINTR) 885 { 886 if( cs->eh != 0L ) (*(cs->eh))( "select failed: %d : %s", errno, strerror(errno)); 887 return; 888 } 889 } 890 891 if( n_fds > 0 ) 892 process_watches(cs); 893 894 process_timeouts(cs); 895 896 if ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE ) 897 dbus_connection_dispatch( cs->connection ); 898 899 if( idle_handler != 0L ) 900 (*idle_handler)(cs); 901 } 902} 903 904void dbus_svc_dispatch(DBusConnectionState *cs) 905{ 906 process_watches(cs); 907 908 FD_ZERO(&(cs->s_r_fds)); 909 FD_ZERO(&(cs->s_w_fds)); 910 FD_ZERO(&(cs->s_e_fds)); 911 912 process_timeouts(cs); 913 914 while ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE ) 915 dbus_connection_dispatch( cs->connection ); 916} 917 918void 919dbus_svc_quit( DBusConnectionState *cs ) 920{ 921 cs->status = SHUTDOWN; 922} 923 924static isc_result_t 925connection_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 932) 933{ 934 *dbus = dbcs_new( connection ); 935 936 if ( *dbus == 0L ) 937 { 938 if(eh)(*(eh))("connection_setup: out of memory"); 939 goto fail; 940 } 941 (*dbus)->wh = wh; 942 (*dbus)->wh_arg = wh_arg; 943 (*dbus)->eh = eh; 944 (*dbus)->dh = dh; 945 946 if (!dbus_connection_set_watch_functions 947 ( (*dbus)->connection, 948 add_watch, 949 remove_watch, 950 toggle_watch, 951 *dbus, 952 no_free 953 ) 954 ) 955 { 956 if( (*dbus)->eh != 0L ) (*((*dbus)->eh))("connection_setup: dbus_connection_set_watch_functions failed"); 957 goto fail; 958 } 959 960 if (!dbus_connection_set_timeout_functions 961 ( connection, 962 add_timeout, 963 remove_timeout, 964 toggle_timeout, 965 *dbus, 966 no_free 967 ) 968 ) 969 { 970 if( (*dbus)->eh != 0L ) (*((*dbus)->eh))("connection_setup: dbus_connection_set_timeout_functions failed"); 971 goto fail; 972 } 973 974 dbus_connection_set_dispatch_status_function 975 ( connection, 976 dispatch_status, 977 *dbus, 978 no_free 979 ); 980 981 if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE) 982 dbus_connection_ref(connection); 983 984 return ISC_R_SUCCESS; 985 986 fail: 987 if( *dbus != 0L ) 988 free(*dbus); 989 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); 993 994 return ISC_R_FAILURE; 995} 996 997isc_result_t 998dbus_svc_init 999( 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 1007) 1008{ 1009 DBusConnection *connection; 1010 DBusError error; 1011 char *session_bus_address=0L; 1012 1013 memset(&error,'\0',sizeof(DBusError)); 1014 1015 dbus_error_init(&error); 1016 1017 switch( bus ) 1018 { 1019 /* DBUS_PRIVATE_* bus types are the only type which allow reconnection if the dbus-daemon is restarted 1020 */ 1021 case DBUS_PRIVATE_SYSTEM: 1022 1023 if ( (connection = dbus_connection_open_private("unix:path=/var/run/dbus/system_bus_socket", &error)) == 0L ) 1024 { 1025 if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message); 1026 return ISC_R_FAILURE; 1027 } 1028 1029 if ( ! dbus_bus_register(connection,&error) ) 1030 { 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; 1035 } 1036 break; 1037 1038 case DBUS_PRIVATE_SESSION: 1039 1040 session_bus_address = getenv("DBUS_SESSION_BUS_ADDRESS"); 1041 if ( session_bus_address == 0L ) 1042 { 1043 if(eh)(*eh)("dbus_svc_init failed: DBUS_SESSION_BUS_ADDRESS environment variable not set"); 1044 return ISC_R_FAILURE; 1045 } 1046 1047 if ( (connection = dbus_connection_open_private(session_bus_address, &error)) == 0L ) 1048 { 1049 if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message); 1050 return ISC_R_FAILURE; 1051 } 1052 1053 if ( ! dbus_bus_register(connection,&error) ) 1054 { 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; 1059 } 1060 break; 1061 1062 case DBUS_SYSTEM: 1063 case DBUS_SESSION: 1064 1065 if ( (connection = dbus_bus_get (bus, &error)) == 0L ) 1066 { 1067 if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message); 1068 return ISC_R_FAILURE; 1069 } 1070 break; 1071 1072 default: 1073 if(eh)(*eh)("dbus_svc_init failed: unknown bus type %d", bus); 1074 return ISC_R_FAILURE; 1075 } 1076 1077 dbus_connection_set_exit_on_disconnect(connection, FALSE); 1078 1079 if ( (connection_setup(connection, dbus, wh, eh, dh, wh_arg)) != ISC_R_SUCCESS) 1080 { 1081 if(eh)(*eh)("dbus_svc_init failed: connection_setup failed"); 1082 return ISC_R_FAILURE; 1083 } 1084 1085 if( name == 0L ) 1086 return ISC_R_SUCCESS; 1087 1088 (*dbus)->unique_name = dbus_bus_get_unique_name(connection); 1089 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 1096 0 , 1097#endif 1098 &error 1099 ) 1100 ) 1101 { 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; 1112 } 1113 return ISC_R_SUCCESS; 1114 1115 give_up: 1116 dbus_connection_close( connection ); 1117 dbus_connection_unref( connection ); 1118 if( *dbus ) 1119 { 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); 1124 } 1125 return ISC_R_FAILURE; 1126} 1127 1128const char *dbus_svc_unique_name(DBusConnectionState *cs) 1129{ 1130 return cs->unique_name; 1131} 1132 1133void 1134dbus_svc_shutdown ( DBusConnectionState *cs ) 1135{ 1136 if (!dbus_connection_set_watch_functions 1137 ( cs->connection, 1138 NULL, NULL, NULL, NULL, NULL 1139 ) 1140 ) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_watch_functions: No Memory." 1141 "Setting watch functions to NULL failed." 1142 ); 1143 1144 if (!dbus_connection_set_timeout_functions 1145 ( cs->connection, 1146 NULL, NULL, NULL, NULL, NULL 1147 ) 1148 ) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_timeout_functions: No Memory." 1149 "Setting timeout functions to NULL failed." 1150 ); 1151 1152 dbus_connection_set_dispatch_status_function (cs->connection, NULL, NULL, NULL); 1153 1154 tdestroy( cs->timeouts, free); 1155 cs->timeouts=0L; 1156 tdestroy( cs->watches, no_free); 1157 cs->watches=0L; 1158 1159 dbus_connection_close( cs->connection ); 1160 dbus_connection_unref( cs->connection ); 1161 1162 free( cs ); 1163} 1164