2011-03-12 03:03:13 +03:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
2012-04-12 02:20:58 +04:00
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
2011-03-12 03:03:13 +03:00
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
2012-04-12 02:20:58 +04:00
Lesser General Public License for more details .
2011-03-12 03:03:13 +03:00
2012-04-12 02:20:58 +04:00
You should have received a copy of the GNU Lesser General Public License
2011-03-12 03:03:13 +03:00
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <sys/socket.h>
# include <sys/un.h>
# include <sys/types.h>
# include <fcntl.h>
# include <unistd.h>
# include <string.h>
# include <errno.h>
2013-04-01 05:28:42 +04:00
# include <sys/poll.h>
2011-03-12 03:03:13 +03:00
# include <stddef.h>
2013-11-15 21:05:27 +04:00
# include <getopt.h>
2011-03-12 03:03:13 +03:00
# include "log.h"
# include "util.h"
# include "socket-util.h"
2013-04-01 05:28:42 +04:00
# include "sd-daemon.h"
# include "sd-bus.h"
# include "bus-internal.h"
# include "bus-message.h"
2013-10-16 08:10:04 +04:00
# include "bus-util.h"
2013-11-15 21:05:27 +04:00
# include "build.h"
2013-12-21 07:19:51 +04:00
# include "strv.h"
2013-12-31 01:12:46 +04:00
# include "def.h"
2013-11-15 21:05:27 +04:00
2013-12-31 01:12:46 +04:00
static const char * arg_address = DEFAULT_SYSTEM_BUS_PATH ;
2013-12-21 07:19:51 +04:00
static char * arg_command_line_buffer = NULL ;
2013-11-15 21:05:27 +04:00
static int help ( void ) {
printf ( " %s [OPTIONS...] \n \n "
2013-12-21 06:59:07 +04:00
" Connect STDIO or a socket to a given bus address. \n \n "
2013-11-15 21:05:27 +04:00
" -h --help Show this help \n "
" --version Show package version \n "
2013-12-21 19:26:55 +04:00
" --address=ADDRESS Connect to the bus specified by ADDRESS \n "
2013-12-31 01:12:46 +04:00
" (default: " DEFAULT_SYSTEM_BUS_PATH " ) \n " ,
2013-12-21 06:59:07 +04:00
program_invocation_short_name ) ;
2013-11-15 21:05:27 +04:00
return 0 ;
}
static int parse_argv ( int argc , char * argv [ ] ) {
enum {
ARG_VERSION = 0x100 ,
2013-12-21 06:59:07 +04:00
ARG_ADDRESS ,
2013-11-15 21:05:27 +04:00
} ;
static const struct option options [ ] = {
2013-12-21 06:59:07 +04:00
{ " help " , no_argument , NULL , ' h ' } ,
{ " version " , no_argument , NULL , ARG_VERSION } ,
{ " address " , required_argument , NULL , ARG_ADDRESS } ,
{ NULL , 0 , NULL , 0 }
2013-11-15 21:05:27 +04:00
} ;
int c ;
assert ( argc > = 0 ) ;
assert ( argv ) ;
2013-12-21 22:58:14 +04:00
while ( ( c = getopt_long ( argc , argv , " h " , options , NULL ) ) > = 0 ) {
2013-11-15 21:05:27 +04:00
switch ( c ) {
case ' h ' :
help ( ) ;
return 0 ;
case ARG_VERSION :
puts ( PACKAGE_STRING ) ;
puts ( SYSTEMD_FEATURES ) ;
return 0 ;
2013-12-21 06:59:07 +04:00
case ARG_ADDRESS :
arg_address = optarg ;
break ;
2013-11-15 21:05:27 +04:00
case ' ? ' :
return - EINVAL ;
default :
2013-12-21 06:59:07 +04:00
assert_not_reached ( " Unhandled option " ) ;
2013-11-15 21:05:27 +04:00
}
}
2013-12-21 07:19:51 +04:00
/* If the first command line argument is only "x" characters
* we ' ll write who we are talking to into it , so that " ps " is
* explanatory */
arg_command_line_buffer = argv [ optind ] ;
if ( argc > optind + 1 | |
( arg_command_line_buffer & & arg_command_line_buffer [ strspn ( arg_command_line_buffer , " x " ) ] ! = 0 ) ) {
log_error ( " Too many arguments " ) ;
return - EINVAL ;
}
2013-11-15 21:05:27 +04:00
return 1 ;
}
2011-03-12 03:03:13 +03:00
2013-12-26 06:08:52 +04:00
static int rename_service ( sd_bus * a , sd_bus * b ) {
2013-12-23 05:59:03 +04:00
_cleanup_bus_creds_unref_ sd_bus_creds * creds = NULL ;
_cleanup_free_ char * p = NULL , * name = NULL ;
const char * comm ;
char * * cmdline ;
uid_t uid ;
pid_t pid ;
int r ;
2013-12-26 06:08:52 +04:00
assert ( a ) ;
2013-12-23 05:59:03 +04:00
assert ( b ) ;
r = sd_bus_get_peer_creds ( b , SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_CMDLINE | SD_BUS_CREDS_COMM , & creds ) ;
if ( r < 0 )
return r ;
r = sd_bus_creds_get_uid ( creds , & uid ) ;
if ( r < 0 )
return r ;
r = sd_bus_creds_get_pid ( creds , & pid ) ;
if ( r < 0 )
return r ;
r = sd_bus_creds_get_cmdline ( creds , & cmdline ) ;
if ( r < 0 )
return r ;
r = sd_bus_creds_get_comm ( creds , & comm ) ;
if ( r < 0 )
return r ;
name = uid_to_name ( uid ) ;
if ( ! name )
return - ENOMEM ;
p = strv_join ( cmdline , " " ) ;
if ( ! p )
return - ENOMEM ;
/* The status string gets the full command line ... */
sd_notifyf ( false ,
2013-12-31 02:22:26 +04:00
" STATUS=Processing requests from client PID " PID_FMT " (%s); UID " UID_FMT " (%s) " ,
pid , p ,
uid , name ) ;
2013-12-23 05:59:03 +04:00
/* ... and the argv line only the short comm */
if ( arg_command_line_buffer ) {
size_t m , w ;
m = strlen ( arg_command_line_buffer ) ;
w = snprintf ( arg_command_line_buffer , m ,
2013-12-31 02:22:26 +04:00
" [PID " PID_FMT " /%s; UID " UID_FMT " /%s] " ,
pid , comm ,
uid , name ) ;
2013-12-23 05:59:03 +04:00
if ( m > w )
memset ( arg_command_line_buffer + w , 0 , m - w ) ;
}
2013-12-31 02:22:26 +04:00
log_debug ( " Running on behalf of PID " PID_FMT " (%s), UID " UID_FMT " (%s), %s " ,
pid , p ,
uid , name ,
2013-12-26 06:08:52 +04:00
a - > unique_name ) ;
;
2013-12-23 05:59:03 +04:00
return 0 ;
}
static int synthesize_name_acquired ( sd_bus * a , sd_bus * b , sd_bus_message * m ) {
_cleanup_bus_message_unref_ sd_bus_message * n = NULL ;
const char * name , * old_owner , * new_owner ;
int r ;
assert ( a ) ;
assert ( b ) ;
assert ( m ) ;
/* If we get NameOwnerChanged for our own name, we need to
* synthesize NameLost / NameAcquired , since socket clients need
* that , even though it is obsoleted on kdbus */
if ( ! a - > is_kernel )
return 0 ;
if ( ! sd_bus_message_is_signal ( m , " org.freedesktop.DBus " , " NameOwnerChanged " ) | |
! streq_ptr ( m - > path , " /org/freedesktop/DBus " ) | |
! streq_ptr ( m - > sender , " org.freedesktop.DBus " ) )
return 0 ;
r = sd_bus_message_read ( m , " sss " , & name , & old_owner , & new_owner ) ;
if ( r < 0 )
return r ;
r = sd_bus_message_rewind ( m , true ) ;
if ( r < 0 )
return r ;
if ( streq ( old_owner , a - > unique_name ) ) {
r = sd_bus_message_new_signal (
b ,
" /org/freedesktop/DBus " ,
" org.freedesktop.DBus " ,
" NameLost " ,
& n ) ;
} else if ( streq ( new_owner , a - > unique_name ) ) {
r = sd_bus_message_new_signal (
b ,
" /org/freedesktop/DBus " ,
" org.freedesktop.DBus " ,
" NameAcquired " ,
& n ) ;
} else
return 0 ;
if ( r < 0 )
return r ;
r = sd_bus_message_append ( n , " s " , name ) ;
if ( r < 0 )
return r ;
r = bus_message_append_sender ( n , " org.freedesktop.DBus " ) ;
if ( r < 0 )
return r ;
r = bus_seal_synthetic_message ( b , n ) ;
if ( r < 0 )
return r ;
return sd_bus_send ( b , n , NULL ) ;
}
2013-12-26 19:07:38 +04:00
static int process_policy ( sd_bus * a , sd_bus * b , sd_bus_message * m ) {
_cleanup_bus_message_unref_ sd_bus_message * n = NULL ;
int r ;
assert ( a ) ;
assert ( b ) ;
assert ( m ) ;
if ( ! sd_bus_message_is_method_call ( m , " org.freedesktop.DBus.Properties " , " GetAll " ) )
return 0 ;
if ( ! streq_ptr ( m - > path , " /org/gnome/DisplayManager/Slave " ) )
return 0 ;
r = sd_bus_message_new_method_errorf ( m , & n , SD_BUS_ERROR_ACCESS_DENIED , " gdm, you are stupid " ) ;
if ( r < 0 )
return r ;
r = bus_message_append_sender ( n , " org.freedesktop.DBus " ) ;
if ( r < 0 ) {
log_error ( " Failed to append sender to gdm reply: %s " , strerror ( - r ) ) ;
return r ;
}
r = bus_seal_synthetic_message ( b , n ) ;
if ( r < 0 ) {
log_error ( " Failed to seal gdm reply: %s " , strerror ( - r ) ) ;
return r ;
}
r = sd_bus_send ( b , n , NULL ) ;
if ( r < 0 ) {
log_error ( " Failed to send gdm reply: %s " , strerror ( - r ) ) ;
return r ;
}
return 1 ;
}
2013-12-23 05:59:03 +04:00
static int process_hello ( sd_bus * a , sd_bus * b , sd_bus_message * m , bool * got_hello ) {
_cleanup_bus_message_unref_ sd_bus_message * n = NULL ;
bool is_hello ;
int r ;
assert ( a ) ;
assert ( b ) ;
assert ( m ) ;
assert ( got_hello ) ;
/* As reaction to hello we need to respond with two messages:
* the callback reply and the NameAcquired for the unique
* name , since hello is otherwise obsolete on kdbus . */
is_hello =
sd_bus_message_is_method_call ( m , " org.freedesktop.DBus " , " Hello " ) & &
streq_ptr ( m - > destination , " org.freedesktop.DBus " ) ;
if ( ! is_hello ) {
if ( * got_hello )
return 0 ;
log_error ( " First packet isn't hello (it's %s.%s), aborting. " , m - > interface , m - > member ) ;
return - EIO ;
}
if ( * got_hello ) {
log_error ( " Got duplicate hello, aborting. " ) ;
return - EIO ;
}
* got_hello = true ;
if ( ! a - > is_kernel )
return 0 ;
r = sd_bus_message_new_method_return ( m , & n ) ;
if ( r < 0 ) {
log_error ( " Failed to generate HELLO reply: %s " , strerror ( - r ) ) ;
return r ;
}
r = sd_bus_message_append ( n , " s " , a - > unique_name ) ;
if ( r < 0 ) {
log_error ( " Failed to append unique name to HELLO reply: %s " , strerror ( - r ) ) ;
return r ;
}
r = bus_message_append_sender ( n , " org.freedesktop.DBus " ) ;
if ( r < 0 ) {
log_error ( " Failed to append sender to HELLO reply: %s " , strerror ( - r ) ) ;
return r ;
}
r = bus_seal_synthetic_message ( b , n ) ;
if ( r < 0 ) {
log_error ( " Failed to seal HELLO reply: %s " , strerror ( - r ) ) ;
return r ;
}
r = sd_bus_send ( b , n , NULL ) ;
if ( r < 0 ) {
log_error ( " Failed to send HELLO reply: %s " , strerror ( - r ) ) ;
return r ;
}
n = sd_bus_message_unref ( n ) ;
r = sd_bus_message_new_signal (
b ,
" /org/freedesktop/DBus " ,
" org.freedesktop.DBus " ,
" NameAcquired " ,
& n ) ;
if ( r < 0 ) {
log_error ( " Failed to allocate initial NameAcquired message: %s " , strerror ( - r ) ) ;
return r ;
}
r = sd_bus_message_append ( n , " s " , a - > unique_name ) ;
if ( r < 0 ) {
log_error ( " Failed to append unique name to NameAcquired message: %s " , strerror ( - r ) ) ;
return r ;
}
r = bus_message_append_sender ( n , " org.freedesktop.DBus " ) ;
if ( r < 0 ) {
log_error ( " Failed to append sender to NameAcquired message: %s " , strerror ( - r ) ) ;
return r ;
}
r = bus_seal_synthetic_message ( b , n ) ;
if ( r < 0 ) {
log_error ( " Failed to seal NameAcquired message: %s " , strerror ( - r ) ) ;
return r ;
}
r = sd_bus_send ( b , n , NULL ) ;
if ( r < 0 ) {
log_error ( " Failed to send NameAcquired message: %s " , strerror ( - r ) ) ;
return r ;
}
return 1 ;
}
2011-03-12 03:03:13 +03:00
int main ( int argc , char * argv [ ] ) {
2013-12-21 07:19:51 +04:00
2013-04-01 05:28:42 +04:00
_cleanup_bus_unref_ sd_bus * a = NULL , * b = NULL ;
sd_id128_t server_id ;
2013-11-15 21:05:27 +04:00
int r , in_fd , out_fd ;
2013-12-23 05:59:03 +04:00
bool got_hello = false ;
2013-12-21 07:19:51 +04:00
bool is_unix ;
2013-12-24 18:03:32 +04:00
struct ucred ucred = { } ;
_cleanup_free_ char * peersec = NULL ;
2011-03-12 03:03:13 +03:00
2012-01-12 08:09:06 +04:00
log_set_target ( LOG_TARGET_JOURNAL_OR_KMSG ) ;
2011-03-12 03:03:13 +03:00
log_parse_environment ( ) ;
log_open ( ) ;
2013-11-15 21:05:27 +04:00
r = parse_argv ( argc , argv ) ;
if ( r < = 0 )
goto finish ;
r = sd_listen_fds ( 0 ) ;
if ( r = = 0 ) {
in_fd = STDIN_FILENO ;
out_fd = STDOUT_FILENO ;
} else if ( r = = 1 ) {
in_fd = SD_LISTEN_FDS_START ;
out_fd = SD_LISTEN_FDS_START ;
} else {
2013-12-24 19:39:37 +04:00
log_error ( " Illegal number of file descriptors passed " ) ;
2013-11-15 21:05:27 +04:00
goto finish ;
}
2013-04-01 05:28:42 +04:00
is_unix =
2013-11-15 21:05:27 +04:00
sd_is_socket ( in_fd , AF_UNIX , 0 , 0 ) > 0 & &
sd_is_socket ( out_fd , AF_UNIX , 0 , 0 ) > 0 ;
2013-04-01 05:28:42 +04:00
2013-12-24 18:03:32 +04:00
if ( is_unix ) {
2013-12-24 18:53:04 +04:00
getpeercred ( in_fd , & ucred ) ;
2013-12-24 18:03:32 +04:00
getpeersec ( in_fd , & peersec ) ;
}
2013-04-01 05:28:42 +04:00
r = sd_bus_new ( & a ) ;
if ( r < 0 ) {
log_error ( " Failed to allocate bus: %s " , strerror ( - r ) ) ;
2011-03-12 03:03:13 +03:00
goto finish ;
}
2013-12-21 06:59:07 +04:00
r = sd_bus_set_address ( a , arg_address ) ;
2013-04-01 05:28:42 +04:00
if ( r < 0 ) {
log_error ( " Failed to set address to connect to: %s " , strerror ( - r ) ) ;
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-05-17 06:25:56 +04:00
r = sd_bus_negotiate_fds ( a , is_unix ) ;
2013-04-01 05:28:42 +04:00
if ( r < 0 ) {
log_error ( " Failed to set FD negotiation: %s " , strerror ( - r ) ) ;
2011-03-12 03:03:13 +03:00
goto finish ;
}
2013-12-24 18:03:32 +04:00
if ( ucred . pid > 0 ) {
a - > fake_creds . pid = ucred . pid ;
a - > fake_creds . uid = ucred . uid ;
a - > fake_creds . gid = ucred . gid ;
a - > fake_creds_valid = true ;
}
if ( peersec ) {
a - > fake_label = peersec ;
peersec = NULL ;
}
2013-12-26 06:08:52 +04:00
a - > manual_peer_interface = true ;
2013-04-01 05:28:42 +04:00
r = sd_bus_start ( a ) ;
if ( r < 0 ) {
log_error ( " Failed to start bus client: %s " , strerror ( - r ) ) ;
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-04-01 05:28:42 +04:00
r = sd_bus_get_server_id ( a , & server_id ) ;
if ( r < 0 ) {
log_error ( " Failed to get server ID: %s " , strerror ( - r ) ) ;
2011-03-12 03:03:13 +03:00
goto finish ;
}
2013-04-01 05:28:42 +04:00
r = sd_bus_new ( & b ) ;
if ( r < 0 ) {
log_error ( " Failed to allocate bus: %s " , strerror ( - r ) ) ;
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-11-15 21:05:27 +04:00
r = sd_bus_set_fd ( b , in_fd , out_fd ) ;
2013-04-01 05:28:42 +04:00
if ( r < 0 ) {
log_error ( " Failed to set fds: %s " , strerror ( - r ) ) ;
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-04-01 05:28:42 +04:00
r = sd_bus_set_server ( b , 1 , server_id ) ;
if ( r < 0 ) {
log_error ( " Failed to set server mode: %s " , strerror ( - r ) ) ;
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-05-17 06:25:56 +04:00
r = sd_bus_negotiate_fds ( b , is_unix ) ;
2013-04-01 05:28:42 +04:00
if ( r < 0 ) {
log_error ( " Failed to set FD negotiation: %s " , strerror ( - r ) ) ;
2011-03-12 03:03:13 +03:00
goto finish ;
}
2013-04-01 05:28:42 +04:00
r = sd_bus_set_anonymous ( b , true ) ;
if ( r < 0 ) {
log_error ( " Failed to set anonymous authentication: %s " , strerror ( - r ) ) ;
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-12-26 06:08:52 +04:00
b - > manual_peer_interface = true ;
2013-04-01 05:28:42 +04:00
r = sd_bus_start ( b ) ;
if ( r < 0 ) {
log_error ( " Failed to start bus client: %s " , strerror ( - r ) ) ;
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-12-26 06:08:52 +04:00
r = rename_service ( a , b ) ;
2013-12-23 05:59:03 +04:00
if ( r < 0 )
log_debug ( " Failed to rename process: %s " , strerror ( - r ) ) ;
2013-12-21 07:19:51 +04:00
2013-12-23 05:59:03 +04:00
if ( a - > is_kernel ) {
2013-12-23 22:16:49 +04:00
_cleanup_free_ char * match = NULL ;
2013-12-23 05:59:03 +04:00
const char * unique ;
r = sd_bus_get_unique_name ( a , & unique ) ;
if ( r < 0 ) {
log_error ( " Failed to get unique name: %s " , strerror ( - r ) ) ;
2013-12-21 07:19:51 +04:00
goto finish ;
}
2013-12-23 05:59:03 +04:00
match = strjoin ( " type='signal', "
" sender='org.freedesktop.DBus', "
" path='/org/freedesktop/DBus', "
" interface='org.freedesktop.DBus', "
" member='NameOwnerChanged', "
" arg1=' " ,
unique ,
" ' " ,
NULL ) ;
if ( ! match ) {
log_oom ( ) ;
2013-12-21 07:19:51 +04:00
goto finish ;
}
2013-12-23 05:59:03 +04:00
r = sd_bus_add_match ( a , match , NULL , NULL ) ;
if ( r < 0 ) {
log_error ( " Failed to add match for NameLost: %s " , strerror ( - r ) ) ;
goto finish ;
}
2013-12-21 07:19:51 +04:00
2013-12-23 05:59:03 +04:00
free ( match ) ;
match = strjoin ( " type='signal', "
" sender='org.freedesktop.DBus', "
" path='/org/freedesktop/DBus', "
" interface='org.freedesktop.DBus', "
" member='NameOwnerChanged', "
" arg2=' " ,
unique ,
" ' " ,
NULL ) ;
if ( ! match ) {
log_oom ( ) ;
goto finish ;
}
2013-12-21 07:19:51 +04:00
2013-12-23 05:59:03 +04:00
r = sd_bus_add_match ( a , match , NULL , NULL ) ;
if ( r < 0 ) {
log_error ( " Failed to add match for NameAcquired: %s " , strerror ( - r ) ) ;
goto finish ;
2013-12-21 07:19:51 +04:00
}
}
2013-04-01 05:28:42 +04:00
for ( ; ; ) {
_cleanup_bus_message_unref_ sd_bus_message * m = NULL ;
2013-12-22 19:41:24 +04:00
int events_a , events_b , fd ;
uint64_t timeout_a , timeout_b , t ;
2013-04-01 05:28:42 +04:00
struct timespec _ts , * ts ;
2013-12-21 20:46:35 +04:00
struct pollfd * pollfd ;
2013-12-22 19:41:24 +04:00
int k ;
2013-12-23 05:59:03 +04:00
if ( got_hello ) {
r = sd_bus_process ( a , & m ) ;
if ( r < 0 ) {
/* treat 'connection reset by peer' as clean exit condition */
if ( r = = - ECONNRESET )
r = 0 ;
else
log_error ( " Failed to process bus a: %s " , strerror ( - r ) ) ;
2011-03-12 03:03:13 +03:00
2013-12-21 07:03:12 +04:00
goto finish ;
}
2013-12-23 05:59:03 +04:00
if ( m ) {
/* We officially got EOF, let's quit */
if ( sd_bus_message_is_signal ( m , " org.freedesktop.DBus.Local " , " Disconnected " ) ) {
r = 0 ;
goto finish ;
}
k = synthesize_name_acquired ( a , b , m ) ;
if ( k < 0 ) {
r = k ;
log_error ( " Failed to synthesize message: %s " , strerror ( - r ) ) ;
goto finish ;
}
k = sd_bus_send ( b , m , NULL ) ;
if ( k < 0 ) {
r = k ;
log_error ( " Failed to send message: %s " , strerror ( - r ) ) ;
goto finish ;
}
2013-04-01 05:28:42 +04:00
}
2011-03-12 03:03:13 +03:00
2013-12-23 05:59:03 +04:00
if ( r > 0 )
continue ;
}
2013-12-22 19:41:24 +04:00
r = sd_bus_process ( b , & m ) ;
if ( r < 0 ) {
/* treat 'connection reset by peer' as clean exit condition */
if ( r = = - ECONNRESET )
r = 0 ;
else
log_error ( " Failed to process bus b: %s " , strerror ( - r ) ) ;
2013-04-01 05:28:42 +04:00
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-12-22 19:41:24 +04:00
if ( m ) {
/* We officially got EOF, let's quit */
if ( sd_bus_message_is_signal ( m , " org.freedesktop.DBus.Local " , " Disconnected " ) ) {
r = 0 ;
2013-12-21 20:23:08 +04:00
goto finish ;
}
2011-03-12 03:03:13 +03:00
2013-12-23 05:59:03 +04:00
k = process_hello ( a , b , m , & got_hello ) ;
2013-12-22 19:41:24 +04:00
if ( k < 0 ) {
r = k ;
2013-12-21 20:23:08 +04:00
goto finish ;
}
2013-12-23 05:59:03 +04:00
if ( k > 0 )
r = k ;
else {
2013-12-26 19:07:38 +04:00
k = process_policy ( a , b , m ) ;
if ( k < 0 ) {
r = k ;
goto finish ;
}
2013-12-23 05:59:03 +04:00
k = sd_bus_send ( a , m , NULL ) ;
if ( k < 0 ) {
r = k ;
log_error ( " Failed to send message: %s " , strerror ( - r ) ) ;
goto finish ;
}
}
2013-04-01 05:28:42 +04:00
}
2011-03-12 03:03:13 +03:00
2013-12-22 19:41:24 +04:00
if ( r > 0 )
continue ;
fd = sd_bus_get_fd ( a ) ;
if ( fd < 0 ) {
log_error ( " Failed to get fd: %s " , strerror ( - r ) ) ;
goto finish ;
}
events_a = sd_bus_get_events ( a ) ;
if ( events_a < 0 ) {
log_error ( " Failed to get events mask: %s " , strerror ( - r ) ) ;
goto finish ;
}
r = sd_bus_get_timeout ( a , & timeout_a ) ;
if ( r < 0 ) {
log_error ( " Failed to get timeout: %s " , strerror ( - r ) ) ;
goto finish ;
}
events_b = sd_bus_get_events ( b ) ;
if ( events_b < 0 ) {
log_error ( " Failed to get events mask: %s " , strerror ( - r ) ) ;
goto finish ;
}
r = sd_bus_get_timeout ( b , & timeout_b ) ;
if ( r < 0 ) {
log_error ( " Failed to get timeout: %s " , strerror ( - r ) ) ;
goto finish ;
}
t = timeout_a ;
if ( t = = ( uint64_t ) - 1 | | ( timeout_b ! = ( uint64_t ) - 1 & & timeout_b < timeout_a ) )
t = timeout_b ;
2011-03-12 03:03:13 +03:00
2013-04-01 05:28:42 +04:00
if ( t = = ( uint64_t ) - 1 )
ts = NULL ;
else {
usec_t nw ;
2011-03-12 03:03:13 +03:00
2013-04-01 05:28:42 +04:00
nw = now ( CLOCK_MONOTONIC ) ;
if ( t > nw )
t - = nw ;
else
t = 0 ;
2011-03-12 03:03:13 +03:00
2013-04-01 05:28:42 +04:00
ts = timespec_store ( & _ts , t ) ;
2011-03-12 03:03:13 +03:00
}
2013-12-21 20:46:35 +04:00
pollfd = ( struct pollfd [ 3 ] ) {
2013-12-22 19:41:24 +04:00
{ . fd = fd , . events = events_a , } ,
{ . fd = in_fd , . events = events_b & POLLIN , } ,
{ . fd = out_fd , . events = events_b & POLLOUT , }
2013-12-21 20:46:35 +04:00
} ;
2013-04-01 05:28:42 +04:00
2013-12-21 20:46:35 +04:00
r = ppoll ( pollfd , 3 , ts , NULL ) ;
2013-04-01 05:28:42 +04:00
if ( r < 0 ) {
log_error ( " ppoll() failed: %m " ) ;
goto finish ;
}
}
2011-03-12 03:03:13 +03:00
2013-04-01 05:28:42 +04:00
r = 0 ;
2011-03-12 03:03:13 +03:00
finish :
2013-12-21 07:03:12 +04:00
sd_bus_flush ( a ) ;
sd_bus_flush ( b ) ;
2013-04-01 05:28:42 +04:00
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS ;
2011-03-12 03:03:13 +03:00
}