#include <sys/types.h>
#include <unistd.h>
#include <linux/limits.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <time.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.h>
#include <string.h>
extern size_t strnlen(const char *s, size_t maxlen);
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <search.h>
#include <getopt.h>
typedef void (*__free_fn_t) (void *__nodep);
extern void tdestroy (void *__root, __free_fn_t __freefct);
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#define DBUS_API_SUBJECT_TO_CHANGE "Very Annoying and Silly!"
#include <dbus/dbus.h>
#include <named/dbus_service.h>
typedef struct dbcs_s
{
DBusConnection *connection;
DBusDispatchStatus dispatchStatus;
uint32_t status;
dbus_svc_WatchHandler wh;
void * wh_arg;
const char * unique_name;
dbus_svc_MessageHandler mh;
void * def_mh_obj;
dbus_svc_MessageHandler mf;
void * def_mf_obj;
dbus_svc_ShutdownHandler sh;
void * sh_obj;
dbus_svc_ErrorHandler eh;
dbus_svc_ErrorHandler dh;
void * roots;
void * timeouts;
void * watches;
void * filters;
int n;
fd_set r_fds;
fd_set s_r_fds;
fd_set w_fds;
fd_set s_w_fds;
fd_set e_fds;
fd_set s_e_fds;
DBusMessage *currentMessage;
int rejectMessage;
} DBusConnectionState;
typedef struct root_s
{
char *path;
char *if_prefix;
DBUS_SVC cs;
dbus_svc_MessageHandler mh;
void *object;
void *tree;
} Root;
typedef struct mhn_s
{
char *path;
dbus_svc_MessageHandler mh;
void *object;
} MessageHandlerNode;
typedef struct mfn_s
{
DBusConnectionState *cs;
dbus_svc_MessageHandler mf;
void *obj;
int n_matches;
char **matches;
} MessageFilterNode;
typedef struct dbto_s
{
DBusTimeout *to;
DBusConnectionState *cs;
struct timeval tv;
} DBusConnectionTimeout;
static void no_free( void *p){ p=0; }
static int ptr_key_comparator( const void *p1, const void *p2 )
{
return
( (p1 == p2)
? 0
:( (p1 > p2)
? 1
: -1
)
);
}
static DBusHandlerResult
default_message_filter
( DBusConnection *connection,
DBusMessage *message,
void *p
)
{
DBusConnectionState *cs = p;
uint32_t type =dbus_message_get_type( message ),
serial =dbus_message_get_serial( message );
uint8_t reply =dbus_message_get_no_reply( message )==0;
const char
*path = dbus_message_get_path( message ),
*dest = dbus_message_get_destination( message ),
*member = dbus_message_get_member( message ),
*interface=dbus_message_get_interface( message ),
*sender =dbus_message_get_sender( message ),
*signature=dbus_message_get_signature( message );
connection = connection;
if(cs->mf)
return
(*(cs->mf))( cs, type, reply, serial, dest, path, member, interface, 0L,
sender, signature, message, 0L, 0L, 0L, cs->def_mf_obj
) ;
return HANDLED;
}
uint8_t
dbus_svc_add_filter
( DBusConnectionState *cs, dbus_svc_MessageHandler mh, void *obj, int n_matches, ... )
{
DBusError error;
va_list va;
char *m;
va_start(va, n_matches );
cs->mf = mh;
cs->def_mf_obj = obj;
if ( ! dbus_connection_add_filter (cs->connection, default_message_filter, cs, NULL))
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_connection_add_filter failed");
va_end(va);
return( 0 );
}
if( n_matches )
{
memset(&error,'\0',sizeof(DBusError));
dbus_error_init(&error);
while( n_matches-- )
{
m = va_arg(va, char* ) ;
dbus_bus_add_match(cs->connection, m, &error);
if( dbus_error_is_set(&error))
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_add_filter: dbus_bus_add_match failed for %s: %s %s",
m, error.name, error.message
);
va_end(va);
return(0);
}
}
}
return( 1 );
}
uint8_t
dbus_svc_get_args_va(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, va_list va)
{
DBusError error;
memset(&error,'\0',sizeof(DBusError));
dbus_error_init(&error);
if( (!dbus_message_get_args_valist(msg, &error, firstType, va)) || dbus_error_is_set(&error) )
{
if( dbus_error_is_set(&error) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_get_args failed: %s %s",error.name, error.message);
dbus_error_free(&error);
}else
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_get_args failed: dbus_message_get_args_valist failed");
return( 0 );
}
return( 1 );
}
uint8_t
dbus_svc_get_args(DBusConnectionState *cs, DBusMessage* msg, dbus_svc_DataType firstType, ...)
{
va_list va;
uint8_t r;
va_start(va, firstType);
r = dbus_svc_get_args_va( cs, msg, firstType, va);
va_end(va);
return r;
}
uint8_t
dbus_svc_send_va
( DBusConnectionState *cs,
dbus_svc_MessageType type,
int32_t reply_serial,
uint32_t *new_serial,
const char *destination,
const char *path,
const char *interface,
const char *member,
dbus_svc_DataType firstType,
va_list va
)
{
DBusMessageIter iter;
char *e;
DBusMessage *msg =
dbus_svc_new_message
( cs,
type,
reply_serial,
destination,
path,
interface,
member
);
if(msg == 0L)
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_svc_new_message failed");
return 0;
}
if( type != DBUS_MESSAGE_TYPE_ERROR )
{
if( !dbus_message_append_args_valist( msg, firstType, va ) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args_valist failed");
return 0;
}
}else
{
if( firstType == DBUS_TYPE_STRING )
{
e = 0L;
e = va_arg( va, char* );
if( (e == 0L) || !dbus_message_set_error_name( msg, e ) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_set_error_name failed");
return 0;
}
firstType = va_arg(va, int);
if( firstType == DBUS_TYPE_STRING )
{
e = 0L;
e = va_arg( va, char* );
if( e == 0L )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: NULL error message");
return 0;
}
dbus_message_iter_init_append (msg, &iter);
if( !dbus_message_iter_append_basic
(&iter, DBUS_TYPE_STRING, &e)
)
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_iter_append_basic failed");
return 0;
}
}
}else
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: unhandled type for error name: %c", firstType);
return 0;
}
}
if( !dbus_connection_send(cs->connection, msg, new_serial) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed");
return 0;
}
if( cs->dh != 0L ) (*(cs->dh))("Sending message");
dbus_connection_flush(cs->connection);
return 1;
}
uint8_t
dbus_svc_send
( DBusConnectionState *cs,
dbus_svc_MessageType type,
int32_t reply_serial,
uint32_t *new_serial,
const char *destination,
const char *path,
const char *interface,
const char *member,
dbus_svc_DataType firstType,
...
)
{
uint8_t r;
va_list va;
va_start(va, firstType);
r = dbus_svc_send_va(cs, type, reply_serial, new_serial, destination, path,interface,member,firstType,va);
va_end(va);
return ( r ) ;
}
dbus_svc_MessageHandle
dbus_svc_new_message
( DBusConnectionState* cs,
dbus_svc_MessageType type,
int32_t reply_serial,
const char *destination,
const char *path,
const char *interface,
const char *member
)
{
DBusMessage *msg = dbus_message_new(type);
if( msg == 0L)
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed");
return 0;
}
if( reply_serial != -1 )
{
if( !dbus_message_set_reply_serial(msg,reply_serial) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_reply_serial failed");
return 0;
}
}
if( (destination !=0L) && !dbus_message_set_destination(msg, destination) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_destination failed");
return 0;
}
if( !dbus_message_set_path(msg, path) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_path failed");
return 0;
}
if( ! dbus_message_set_interface(msg,interface) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_interface failed - %s", interface);
return 0;
}
if( !dbus_message_set_member(msg,member) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_new_message: dbus_message_set_member failed");
return 0;
}
return msg;
}
extern uint8_t
dbus_svc_send_message
(
DBusConnectionState *cs,
dbus_svc_MessageHandle msg,
uint32_t *new_serial
)
{
if( !dbus_connection_send(cs->connection, msg, new_serial) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_send failed");
return 0;
}
if( cs->dh != 0L ) (*(cs->dh))("Sending message");
dbus_connection_flush(cs->connection);
return 1;
}
uint8_t
dbus_svc_message_append_args(DBusConnectionState *cs, dbus_svc_MessageHandle msg, dbus_svc_DataType firstType, ...)
{
va_list va;
va_start(va, firstType);
if( !dbus_message_append_args_valist( msg, firstType, va ) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_send: dbus_message_append_args failed");
return 0;
}
va_end(va);
return ( 1 ) ;
}
dbus_svc_MessageHandle
dbus_svc_call
( DBusConnectionState *cs,
const char *destination,
const char *path,
const char *member,
const char *interface,
dbus_svc_DataType firstType,
...
)
{
DBusMessage *message=0L, *reply=0L;
va_list va;
DBusError error;
int reply_timeout=20000;
va_start(va, firstType);
memset(&error,'\0',sizeof(DBusError));
dbus_error_init(&error);
if(( message =
dbus_message_new_method_call
( destination,
path,
interface,
member
)
) == 0L
)
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_new_method_call failed");
va_end(va);
return(0L);
};
if( !dbus_message_append_args_valist( message, firstType, va ) )
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_append_args_valist failed");
va_end(va);
return(0L);
}
if((reply =
dbus_connection_send_with_reply_and_block
(cs->connection,
message, reply_timeout,
&error
)
) == 0L
)
{
if( cs->eh != 0L ) (*(cs->eh))("dbus_svc_call: dbus_message_send_with_reply_and_block failed: %s %s",
error.name, error.message
);
va_end(va);
return(0L);
}
return reply;
}
dbus_svc_MessageIterator
dbus_svc_message_iterator_new( DBusConnectionState *cs, DBusMessage *msg)
{
DBusMessageIter *iter = malloc( sizeof(DBusMessageIter) );
void *p =cs;
p++;
if( iter != 0L )
{
if( !dbus_message_iter_init( msg, iter ))
{
free( iter ) ;
iter = 0L;
}
}
return iter;
}
uint32_t
dbus_svc_message_next_arg_type( DBusConnectionState *cs, dbus_svc_MessageIterator iter )
{
void *p =cs;
p++;
return dbus_message_iter_get_arg_type( iter );
}
void
dbus_svc_message_next_arg( DBusConnectionState *cs, dbus_svc_MessageIterator iter, void *value )
{
void *p =cs;
p++;
dbus_message_iter_get_basic( iter, value );
dbus_message_iter_next( iter );
}
uint32_t
dbus_svc_message_element_type(DBusConnectionState *cs , dbus_svc_MessageIterator iter)
{
void *p =cs;
p++;
return dbus_message_iter_get_element_type(iter);
}
void
dbus_svc_message_get_elements( DBusConnectionState *cs , dbus_svc_MessageIterator iter, uint32_t *n, void *array )
{
void *p =cs;
p++;
dbus_message_iter_get_fixed_array( iter, n, array);
}
void dbus_svc_message_iterator_free( DBusConnectionState *cs, dbus_svc_MessageIterator iter )
{
void *p =cs;
p++;
free( iter );
}
uint8_t dbus_svc_message_type( DBusMessage *msg )
{
return dbus_message_get_type( msg );
}
static DBusConnectionState *
dbcs_new( DBusConnection *connection )
{
DBusConnectionState *dbcs = (DBusConnectionState *) malloc( sizeof(DBusConnectionState) );
if ( dbcs )
{
memset( dbcs, '\0', sizeof( DBusConnectionState ));
dbcs->connection = connection;
}
return(dbcs);
}
static DBusConnectionTimeout *
timeout_new( DBusTimeout *timeout )
{
DBusConnectionTimeout *to = (DBusConnectionTimeout *) malloc ( sizeof(DBusConnectionTimeout) );
if( to != 0L )
{
to->to = timeout;
dbus_timeout_set_data(timeout, to, 0L);
if( dbus_timeout_get_enabled(timeout) )
gettimeofday(&(to->tv),0L);
else
{
to->tv.tv_sec = 0 ;
to->tv.tv_usec = 0 ;
}
}
return( to );
}
static dbus_bool_t
add_timeout( DBusTimeout *timeout, void *csp )
{
DBusConnectionState *cs = csp;
DBusConnectionTimeout *to = timeout_new(timeout);
if( cs->dh != 0L ) (*(cs->dh))("add_timeout: %d", dbus_timeout_get_interval(timeout));
to->cs = cs;
if ( to )
{
if( tsearch((void*)to, &(cs->timeouts), ptr_key_comparator) != 0L )
return TRUE;
}
if( cs->eh != 0L ) (*(cs->eh))("add_timeout: out of memory");
return FALSE;
}
static void
remove_timeout( DBusTimeout *timeout, void *csp )
{
DBusConnectionState *cs = csp;
DBusConnectionTimeout *to = dbus_timeout_get_data(timeout);
if( (to != 0L) && (to->to == timeout) )
{
if( cs->dh != 0L ) (*(cs->dh))("remove_timeout: %d", dbus_timeout_get_interval(to->to));
if( tdelete((const void*)to, &(cs->timeouts), ptr_key_comparator) != 0L )
{
free(to);
}else
if( cs->eh != 0L ) (*(cs->eh))("remove_timeout: can't happen?!?: timeout data %p not found", to);
}else
if( cs->eh != 0L ) (*(cs->eh))("remove_timeout: can't happen?!?: timeout %p did not record data %p %p",
timeout, to, ((to != 0L) ? to->to : 0L)
);
}
static void
toggle_timeout( DBusTimeout *timeout, void *csp )
{
DBusConnectionState *cs = csp;
DBusConnectionTimeout **top = tfind( (const void*) dbus_timeout_get_data(timeout),
&(cs->timeouts),
ptr_key_comparator
),
*to=0L;
if( (top != 0L) && ((to=*top) != 0L) && (to->to == timeout) )
{
if( cs->dh != 0L ) (*(cs->dh))("toggle_timeout: %d", dbus_timeout_get_interval(to->to));
if( dbus_timeout_get_enabled(timeout) )
gettimeofday(&(to->tv),0L);
else
{
to->tv.tv_sec = 0 ;
to->tv.tv_usec = 0 ;
}
}else
if( cs->eh != 0L ) (*(cs->eh))("toggle_timeout: can't happen?!?: timeout %p %s %p %p", timeout,
((to==0L) ? "did not record data" : "not found"),
to, ((to != 0L) ? to->to : 0L)
);
}
static void
process_timeout( const void *p, const VISIT which, const int level)
{
DBusConnectionState *cs;
void * const *tpp = p;
DBusConnectionTimeout *to;
struct timeval tv;
float now, then, interval;
int l = level ? 1 : 0;
l=l;
gettimeofday(&tv,0L);
if( (tpp != 0L) && (*tpp != 0L) && ((which == postorder) || (which == leaf)) )
{
to = (DBusConnectionTimeout*)*tpp;
cs = to->cs;
if ( !dbus_timeout_get_enabled(to->to) )
return;
cs = dbus_timeout_get_data(to->to);
then = ((float)to->tv.tv_sec) + (((float)to->tv.tv_usec) / 1000000.0);
if( then != 0.0 )
{
interval = ((float)dbus_timeout_get_interval(to->to)) / 1000.0;
now = ((float)tv.tv_sec) + (( (float)tv.tv_usec) / 1000000.0);
if( (now - then) >= interval )
{
if( cs->dh != 0L ) (*(cs->dh))("handle_timeout: %d - %f %f %f", dbus_timeout_get_interval(to->to), then, now, interval);
dbus_timeout_handle( to->to );
to->tv=tv;
}
}else
{
to->tv = tv;
}
}
}
static void
process_timeouts ( DBusConnectionState *cs )
{
twalk( cs->timeouts, process_timeout );
}
static void
set_watch_fds( DBusWatch *watch, DBusConnectionState *cs )
{
uint8_t flags = dbus_watch_get_flags(watch);
int fd = dbus_watch_get_fd(watch);
if ( cs->n <= fd )
cs->n = fd + 1;
if ( dbus_watch_get_enabled(watch) )
{
if ( flags & DBUS_WATCH_READABLE )
{
FD_SET(fd , &(cs->r_fds));
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_ENABLE | WATCH_READ, cs->wh_arg );
}else
{
FD_CLR(fd , &(cs->r_fds));
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_READ, cs->wh_arg );
}
if ( flags & DBUS_WATCH_WRITABLE )
{
FD_SET(fd , &(cs->w_fds));
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_ENABLE | WATCH_WRITE, cs->wh_arg );
}else
{
FD_CLR(fd , &(cs->w_fds));
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg );
}
if ( flags & DBUS_WATCH_ERROR )
{
FD_SET(fd , &(cs->e_fds));
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_ENABLE | WATCH_ERROR, cs->wh_arg );
}else
{
FD_CLR(fd , &(cs->e_fds));
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg );
}
}else
{
if( FD_ISSET( fd, &(cs->r_fds)) )
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_READ, cs->wh_arg );
FD_CLR(fd , &(cs->r_fds));
if( FD_ISSET( fd, &(cs->w_fds)) )
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_WRITE, cs->wh_arg );
FD_CLR(fd , &(cs->w_fds));
if( FD_ISSET( fd, &(cs->e_fds)) )
if( cs->wh != 0L )
(*(cs->wh))( fd, WATCH_ERROR, cs->wh_arg );
FD_CLR(fd , &(cs->e_fds));
}
}
static dbus_bool_t
add_watch ( DBusWatch *watch, void *csp )
{
DBusConnectionState *cs = csp;
dbus_watch_set_data(watch, cs, no_free );
if( cs->dh != 0L ) (*(cs->dh))("add_watch: %d", dbus_watch_get_fd(watch));
if( tsearch((const void*)watch,&(cs->watches),ptr_key_comparator) == 0L )
{
if( cs->eh != 0L ) (*(cs->eh))("add_watch: out of memory");
return FALSE;
}
set_watch_fds(watch,cs);
return TRUE;
}
static void
remove_watch ( DBusWatch *watch, void *csp )
{
DBusConnectionState *cs = csp;
int fd = dbus_watch_get_fd(watch);
if( tdelete((const void*)watch, &(cs->watches), ptr_key_comparator) == 0L )
if( cs->eh != 0L ) (*(cs->eh))("remove_watch: can't happen?!?: watch not found");
if( cs->dh != 0L ) (*(cs->dh))("remove_watch: %d", dbus_watch_get_fd(watch));
FD_CLR(fd , &(cs->r_fds));
FD_CLR(fd , &(cs->w_fds));
FD_CLR(fd , &(cs->e_fds));
if( cs->wh != 0L )
(*(cs->wh))(dbus_watch_get_fd(watch), WATCH_READ | WATCH_WRITE | WATCH_ERROR, cs->wh_arg );
}
static void
toggle_watch ( DBusWatch *watch, void *csp )
{
DBusConnectionState *cs = csp;
if( cs->dh != 0L ) (*(cs->dh))("toggle_watch: %d", dbus_watch_get_fd(watch));
set_watch_fds(watch,cs);
}
static void
process_watch( const void *p, const VISIT which, const int level)
{
void * const *wpp=p;
DBusWatch *w;
int fd;
uint8_t flags;
DBusConnectionState *cs;
int l = level ? 1 : 0;
l=l;
if((wpp != 0L) && (*wpp != 0L) && ( (which == postorder) || (which == leaf) ) )
{
w = (DBusWatch*)*wpp;
cs = dbus_watch_get_data( w );
if( cs == 0 )
return;
if( ! dbus_watch_get_enabled(w) )
return;
fd = dbus_watch_get_fd( w );
flags = dbus_watch_get_flags( w );
if( cs->dh != 0L ) (*(cs->dh))("handle_watch: %d", dbus_watch_get_fd( w ));
if ( (flags & DBUS_WATCH_READABLE) && (FD_ISSET(fd, &(cs->s_r_fds))) )
dbus_watch_handle(w, DBUS_WATCH_READABLE);
if ( (flags & DBUS_WATCH_WRITABLE) && (FD_ISSET(fd, &(cs->s_w_fds))) )
dbus_watch_handle(w, DBUS_WATCH_READABLE);
if ( (flags & DBUS_WATCH_ERROR) && (FD_ISSET(fd, &(cs->s_e_fds))) )
dbus_watch_handle(w, DBUS_WATCH_ERROR);
}
}
static void
process_watches ( DBusConnectionState *cs )
{
twalk( cs->watches, process_watch );
}
void dbus_svc_handle_watch( DBusConnectionState *cs, int fd, dbus_svc_WatchFlags action )
{
switch( action & 7 )
{
case WATCH_READ:
FD_SET(fd, &(cs->s_r_fds));
break;
case WATCH_WRITE:
FD_SET(fd, &(cs->s_w_fds));
break;
case WATCH_ERROR:
FD_SET(fd, &(cs->s_e_fds));
break;
}
}
static void
dispatch_status
( DBusConnection *connection,
DBusDispatchStatus new_status,
void *csp
)
{
connection=connection;
DBusConnectionState *cs = csp;
cs->dispatchStatus = new_status;
}
void
dbus_svc_main_loop( DBusConnectionState *cs, void (*idle_handler)(DBusConnectionState *) )
{
struct timeval timeout={0,200000};
int n_fds;
while( cs->status != SHUTDOWN )
{
cs->s_r_fds = cs->r_fds;
cs->s_w_fds = cs->w_fds;
cs->s_e_fds = cs->e_fds;
timeout.tv_sec = 0;
timeout.tv_usec= 200000;
if ( (n_fds = select(cs->n, &(cs->s_r_fds), &(cs->s_w_fds), &(cs->s_e_fds), &timeout)) < 0 )
{
if (errno != EINTR)
{
if( cs->eh != 0L ) (*(cs->eh))( "select failed: %d : %s", errno, strerror(errno));
return;
}
}
if( n_fds > 0 )
process_watches(cs);
process_timeouts(cs);
if ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE )
dbus_connection_dispatch( cs->connection );
if( idle_handler != 0L )
(*idle_handler)(cs);
}
}
void dbus_svc_dispatch(DBusConnectionState *cs)
{
process_watches(cs);
FD_ZERO(&(cs->s_r_fds));
FD_ZERO(&(cs->s_w_fds));
FD_ZERO(&(cs->s_e_fds));
process_timeouts(cs);
while ( cs->dispatchStatus != DBUS_DISPATCH_COMPLETE )
dbus_connection_dispatch( cs->connection );
}
void
dbus_svc_quit( DBusConnectionState *cs )
{
cs->status = SHUTDOWN;
}
static DBusConnectionState *
connection_setup
( DBusConnection *connection,
dbus_svc_WatchHandler wh,
dbus_svc_ErrorHandler eh,
dbus_svc_ErrorHandler dh,
void *wh_arg
)
{
DBusConnectionState *cs = dbcs_new( connection );
if ( cs == 0L )
{
if(eh)(*(eh))("connection_setup: out of memory");
goto fail;
}
cs->wh = wh;
cs->wh_arg = wh_arg;
cs->eh = eh;
cs->dh = dh;
if (!dbus_connection_set_watch_functions
( cs->connection,
add_watch,
remove_watch,
toggle_watch,
cs,
no_free
)
)
{
if( cs->eh != 0L ) (*(cs->eh))("connection_setup: dbus_connection_set_watch_functions failed");
goto fail;
}
if (!dbus_connection_set_timeout_functions
( connection,
add_timeout,
remove_timeout,
toggle_timeout,
cs,
no_free
)
)
{
if( cs->eh != 0L ) (*(cs->eh))("connection_setup: dbus_connection_set_timeout_functions failed");
goto fail;
}
dbus_connection_set_dispatch_status_function
( connection,
dispatch_status,
cs,
no_free
);
if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
dbus_connection_ref(connection);
return cs;
fail:
if( cs != 0L )
free(cs);
dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
return 0L;
}
DBusConnectionState *
dbus_svc_init
(
dbus_svc_DBUS_TYPE bus,
char *name,
dbus_svc_WatchHandler wh ,
dbus_svc_ErrorHandler eh ,
dbus_svc_ErrorHandler dh ,
void *wh_arg
)
{
DBusConnection *connection;
DBusError error;
DBusConnectionState *cs;
char *session_bus_address=0L;
memset(&error,'\0',sizeof(DBusError));
dbus_error_init(&error);
switch( bus )
{
case DBUS_PRIVATE_SYSTEM:
if ( (connection = dbus_connection_open_private("unix:path=/var/run/dbus/system_bus_socket", &error)) == 0L )
{
if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
return ( 0L );
}
if ( ! dbus_bus_register(connection,&error) )
{
if(eh)(*eh)("dbus_bus_register failed: %s %s", error.name, error.message);
dbus_connection_close(connection);
free(connection);
return ( 0L );
}
break;
case DBUS_PRIVATE_SESSION:
session_bus_address = getenv("DBUS_SESSION_BUS_ADDRESS");
if ( session_bus_address == 0L )
{
if(eh)(*eh)("dbus_svc_init failed: DBUS_SESSION_BUS_ADDRESS environment variable not set");
return ( 0L );
}
if ( (connection = dbus_connection_open_private(session_bus_address, &error)) == 0L )
{
if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
return ( 0L );
}
if ( ! dbus_bus_register(connection,&error) )
{
if(eh)(*eh)("dbus_bus_register failed: %s %s", error.name, error.message);
dbus_connection_close(connection);
free(connection);
return ( 0L );
}
break;
case DBUS_SYSTEM:
case DBUS_SESSION:
if ( (connection = dbus_bus_get (bus, &error)) == 0L )
{
if(eh)(*eh)("dbus_svc_init failed: %s %s",error.name, error.message);
return ( 0L );
}
break;
default:
if(eh)(*eh)("dbus_svc_init failed: unknown bus type %d", bus);
return ( 0L );
}
dbus_connection_set_exit_on_disconnect(connection, FALSE);
if ( (cs = connection_setup(connection, wh, eh, dh, wh_arg)) == 0L )
{
if(eh)(*eh)("dbus_svc_init failed: connection_setup failed");
return( 0L );
}
if( name == 0L )
return( cs );
cs->unique_name = dbus_bus_get_unique_name(connection);
switch
( dbus_bus_request_name
( connection, name,
#ifdef DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT
DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT ,
#else
0 ,
#endif
&error
)
)
{
case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
break;
case DBUS_REQUEST_NAME_REPLY_EXISTS:
case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
if(eh)(*eh)("dbus_svc_init: dbus_bus_request_name failed: Name already registered");
goto give_up;
default:
if(eh)(*eh)("dbus_svc_init: dbus_bus_request_name failed: %s %s", error.name, error.message);
goto give_up;
}
return ( cs );
give_up:
dbus_connection_close( connection );
dbus_connection_unref( connection );
if( cs )
{
dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL);
dbus_connection_set_watch_functions (connection, NULL, NULL, NULL, NULL, NULL);
dbus_connection_set_timeout_functions (connection, NULL, NULL, NULL, NULL, NULL);
free(cs);
}
return ( 0L );
}
const char *dbus_svc_unique_name(DBusConnectionState *cs)
{
return cs->unique_name;
}
void
dbus_svc_shutdown ( DBusConnectionState *cs )
{
if (!dbus_connection_set_watch_functions
( cs->connection,
NULL, NULL, NULL, NULL, NULL
)
) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_watch_functions: No Memory."
"Setting watch functions to NULL failed."
);
if (!dbus_connection_set_timeout_functions
( cs->connection,
NULL, NULL, NULL, NULL, NULL
)
) if( cs->eh != 0L ) (*(cs->eh))("connection_shutdown: dbus_connection_set_timeout_functions: No Memory."
"Setting timeout functions to NULL failed."
);
dbus_connection_set_dispatch_status_function (cs->connection, NULL, NULL, NULL);
tdestroy( cs->timeouts, free);
cs->timeouts=0L;
tdestroy( cs->watches, no_free);
cs->watches=0L;
dbus_connection_close( cs->connection );
dbus_connection_unref( cs->connection );
free( cs );
}