2010-02-01 05:33:24 +03:00
/*-*- Mode: C; c-basic-offset: 8 -*-*/
2010-02-03 15:03:47 +03:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( 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
General Public License for more details .
You should have received a copy of the GNU General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-02-01 05:33:24 +03:00
# include <errno.h>
# include "dbus.h"
# include "log.h"
2010-04-18 05:08:16 +04:00
# include "dbus-manager.h"
2010-05-10 01:53:52 +04:00
# include "strv.h"
2010-07-08 04:43:18 +04:00
# include "bus-errors.h"
2010-02-01 05:33:24 +03:00
2010-05-23 05:45:33 +04:00
# define BUS_MANAGER_INTERFACE \
" <interface name= \" org.freedesktop.systemd1.Manager \" > \n " \
" <method name= \" GetUnit \" > \n " \
" <arg name= \" name \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" unit \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
" <method name= \" LoadUnit \" > \n " \
" <arg name= \" name \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" unit \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
2010-06-01 21:47:46 +04:00
" <method name= \" StartUnit \" > \n " \
" <arg name= \" name \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" mode \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" job \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
" <method name= \" StopUnit \" > \n " \
" <arg name= \" name \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" mode \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" job \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
" <method name= \" ReloadUnit \" > \n " \
" <arg name= \" name \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" mode \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" job \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
" <method name= \" RestartUnit \" > \n " \
" <arg name= \" name \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" mode \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" job \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
2010-07-06 07:06:40 +04:00
" <method name= \" TryRestartUnit \" > \n " \
" <arg name= \" name \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" mode \" type= \" s \" direction= \" in \" /> \n " \
" <arg name= \" job \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
2010-05-23 05:45:33 +04:00
" <method name= \" GetJob \" > \n " \
" <arg name= \" id \" type= \" u \" direction= \" in \" /> \n " \
" <arg name= \" job \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
" <method name= \" ClearJobs \" /> \n " \
" <method name= \" ListUnits \" > \n " \
" <arg name= \" units \" type= \" a(sssssouso) \" direction= \" out \" /> \n " \
" </method> \n " \
" <method name= \" ListJobs \" > \n " \
" <arg name= \" jobs \" type= \" a(usssoo) \" direction= \" out \" /> \n " \
" </method> \n " \
" <method name= \" Subscribe \" /> \n " \
" <method name= \" Unsubscribe \" /> \n " \
" <method name= \" Dump \" /> \n " \
" <method name= \" CreateSnapshot \" > \n " \
" <arg name= \" name \" type= \" s \" direction= \" in \" /> \n " \
" <arg nane= \" cleanup \" type= \" b \" direction= \" in \" /> \n " \
" <arg name= \" unit \" type= \" o \" direction= \" out \" /> \n " \
" </method> \n " \
" <method name= \" Reload \" /> \n " \
" <method name= \" Reexecute \" /> \n " \
" <method name= \" Exit \" /> \n " \
" <method name= \" SetEnvironment \" > \n " \
" <arg name= \" names \" type= \" as \" direction= \" in \" /> \n " \
" </method> \n " \
" <method name= \" UnsetEnvironment \" > \n " \
" <arg name= \" names \" type= \" as \" direction= \" in \" /> \n " \
" </method> \n " \
" <signal name= \" UnitNew \" > \n " \
" <arg name= \" id \" type= \" s \" /> \n " \
" <arg name= \" unit \" type= \" o \" /> \n " \
" </signal> \n " \
" <signal name= \" UnitRemoved \" > \n " \
" <arg name= \" id \" type= \" s \" /> \n " \
" <arg name= \" unit \" type= \" o \" /> \n " \
" </signal> \n " \
" <signal name= \" JobNew \" > \n " \
" <arg name= \" id \" type= \" u \" /> \n " \
" <arg name= \" job \" type= \" o \" /> \n " \
" </signal> \n " \
" <signal name= \" JobRemoved \" > \n " \
" <arg name= \" id \" type= \" u \" /> \n " \
" <arg name= \" job \" type= \" o \" /> \n " \
" <arg name= \" success \" type= \" b \" /> \n " \
" </signal> " \
" <property name= \" Version \" type= \" s \" access= \" read \" /> \n " \
" <property name= \" RunningAs \" type= \" s \" access= \" read \" /> \n " \
2010-07-04 05:42:55 +04:00
" <property name= \" StartupTimestamp \" type= \" t \" access= \" read \" /> \n " \
2010-05-23 05:45:33 +04:00
" <property name= \" LogLevel \" type= \" s \" access= \" read \" /> \n " \
" <property name= \" LogTarget \" type= \" s \" access= \" read \" /> \n " \
" <property name= \" NNames \" type= \" u \" access= \" read \" /> \n " \
" <property name= \" NJobs \" type= \" u \" access= \" read \" /> \n " \
" <property name= \" Environment \" type= \" as \" access= \" read \" /> \n " \
2010-07-04 06:47:19 +04:00
" <property name= \" ConfirmSpawn \" type= \" b \" access= \" read \" /> \n " \
2010-07-07 02:00:59 +04:00
" <property name= \" ShowStatus \" type= \" b \" access= \" read \" /> \n " \
2010-07-04 06:47:19 +04:00
" <property name= \" UnitPath \" type= \" as \" access= \" read \" /> \n " \
" <property name= \" SysVInitPath \" type= \" as \" access= \" read \" /> \n " \
" <property name= \" SysVRcndPath \" type= \" as \" access= \" read \" /> \n " \
" <property name= \" NotifySocket \" type= \" s \" access= \" read \" /> \n " \
2010-05-23 05:45:33 +04:00
" </interface> \n "
2010-02-01 05:33:24 +03:00
# define INTROSPECTION_BEGIN \
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
2010-05-23 05:45:33 +04:00
" <node> \n " \
BUS_MANAGER_INTERFACE \
2010-02-01 05:33:24 +03:00
BUS_PROPERTIES_INTERFACE \
BUS_INTROSPECTABLE_INTERFACE
# define INTROSPECTION_END \
2010-05-23 05:45:33 +04:00
" </node> \n "
const char bus_manager_interface [ ] = BUS_MANAGER_INTERFACE ;
2010-02-01 05:33:24 +03:00
2010-04-18 05:08:16 +04:00
static DEFINE_BUS_PROPERTY_APPEND_ENUM ( bus_manager_append_running_as , manager_running_as , ManagerRunningAs ) ;
2010-04-10 19:40:18 +04:00
static int bus_manager_append_log_target ( Manager * m , DBusMessageIter * i , const char * property , void * data ) {
const char * t ;
assert ( m ) ;
assert ( i ) ;
assert ( property ) ;
t = log_target_to_string ( log_get_target ( ) ) ;
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_STRING , & t ) )
return - ENOMEM ;
return 0 ;
}
static int bus_manager_append_log_level ( Manager * m , DBusMessageIter * i , const char * property , void * data ) {
const char * t ;
assert ( m ) ;
assert ( i ) ;
assert ( property ) ;
t = log_level_to_string ( log_get_max_level ( ) ) ;
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_STRING , & t ) )
return - ENOMEM ;
return 0 ;
}
2010-04-22 04:56:42 +04:00
static int bus_manager_append_n_names ( Manager * m , DBusMessageIter * i , const char * property , void * data ) {
uint32_t u ;
assert ( m ) ;
assert ( i ) ;
assert ( property ) ;
u = hashmap_size ( m - > units ) ;
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_UINT32 , & u ) )
return - ENOMEM ;
return 0 ;
}
static int bus_manager_append_n_jobs ( Manager * m , DBusMessageIter * i , const char * property , void * data ) {
uint32_t u ;
assert ( m ) ;
assert ( i ) ;
assert ( property ) ;
u = hashmap_size ( m - > jobs ) ;
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_UINT32 , & u ) )
return - ENOMEM ;
return 0 ;
}
2010-07-06 21:02:54 +04:00
static const char * message_get_sender_with_fallback ( DBusMessage * m ) {
const char * s ;
assert ( m ) ;
if ( ( s = dbus_message_get_sender ( m ) ) )
return s ;
/* When the message came in from a direct connection the
* message will have no sender . We fix that here . */
return " :no-sender " ;
}
2010-06-19 05:04:04 +04:00
static DBusHandlerResult bus_manager_message_handler ( DBusConnection * connection , DBusMessage * message , void * data ) {
2010-02-01 05:33:24 +03:00
Manager * m = data ;
2010-04-10 19:40:18 +04:00
const BusProperty properties [ ] = {
2010-07-04 06:47:19 +04:00
{ " org.freedesktop.systemd1.Manager " , " Version " , bus_property_append_string , " s " , PACKAGE_STRING } ,
{ " org.freedesktop.systemd1.Manager " , " RunningAs " , bus_manager_append_running_as , " s " , & m - > running_as } ,
{ " org.freedesktop.systemd1.Manager " , " StartupTimestamp " , bus_property_append_uint64 , " t " , & m - > startup_timestamp . realtime } ,
{ " org.freedesktop.systemd1.Manager " , " LogLevel " , bus_manager_append_log_level , " s " , NULL } ,
{ " org.freedesktop.systemd1.Manager " , " LogTarget " , bus_manager_append_log_target , " s " , NULL } ,
{ " org.freedesktop.systemd1.Manager " , " NNames " , bus_manager_append_n_names , " u " , NULL } ,
{ " org.freedesktop.systemd1.Manager " , " NJobs " , bus_manager_append_n_jobs , " u " , NULL } ,
{ " org.freedesktop.systemd1.Manager " , " Environment " , bus_property_append_strv , " as " , m - > environment } ,
{ " org.freedesktop.systemd1.Manager " , " ConfirmSpawn " , bus_property_append_bool , " b " , & m - > confirm_spawn } ,
2010-07-07 02:00:59 +04:00
{ " org.freedesktop.systemd1.Manager " , " ShowStatus " , bus_property_append_bool , " b " , & m - > show_status } ,
2010-07-04 06:47:19 +04:00
{ " org.freedesktop.systemd1.Manager " , " UnitPath " , bus_property_append_strv , " as " , m - > lookup_paths . unit_path } ,
{ " org.freedesktop.systemd1.Manager " , " SysVInitPath " , bus_property_append_strv , " as " , m - > lookup_paths . sysvinit_path } ,
{ " org.freedesktop.systemd1.Manager " , " SysVRcndPath " , bus_property_append_strv , " as " , m - > lookup_paths . sysvrcnd_path } ,
{ " org.freedesktop.systemd1.Manager " , " NotifySocket " , bus_property_append_string , " s " , m - > notify_socket } ,
2010-04-10 19:40:18 +04:00
{ NULL , NULL , NULL , NULL , NULL }
} ;
int r ;
2010-02-01 05:33:24 +03:00
DBusError error ;
DBusMessage * reply = NULL ;
char * path = NULL ;
2010-06-01 21:47:46 +04:00
JobType job_type = _JOB_TYPE_INVALID ;
2010-02-01 05:33:24 +03:00
assert ( connection ) ;
assert ( message ) ;
assert ( m ) ;
dbus_error_init ( & error ) ;
2010-04-18 05:08:16 +04:00
if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " GetUnit " ) ) {
2010-02-01 05:33:24 +03:00
const char * name ;
Unit * u ;
if ( ! dbus_message_get_args (
message ,
& error ,
DBUS_TYPE_STRING , & name ,
DBUS_TYPE_INVALID ) )
2010-06-19 05:04:04 +04:00
return bus_send_error_reply ( m , connection , message , & error , - EINVAL ) ;
2010-02-01 05:33:24 +03:00
2010-07-08 04:43:18 +04:00
if ( ! ( u = manager_get_unit ( m , name ) ) ) {
dbus_set_error ( & error , BUS_ERROR_NO_SUCH_UNIT , " Unit %s is not loaded. " , name ) ;
return bus_send_error_reply ( m , connection , message , & error , - ENOENT ) ;
}
2010-02-01 05:33:24 +03:00
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
if ( ! ( path = unit_dbus_path ( u ) ) )
goto oom ;
if ( ! dbus_message_append_args (
reply ,
DBUS_TYPE_OBJECT_PATH , & path ,
DBUS_TYPE_INVALID ) )
goto oom ;
2010-04-18 05:08:16 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " LoadUnit " ) ) {
2010-02-01 05:33:24 +03:00
const char * name ;
Unit * u ;
if ( ! dbus_message_get_args (
message ,
& error ,
DBUS_TYPE_STRING , & name ,
DBUS_TYPE_INVALID ) )
2010-06-19 05:04:04 +04:00
return bus_send_error_reply ( m , connection , message , & error , - EINVAL ) ;
2010-02-01 05:33:24 +03:00
2010-07-08 04:43:18 +04:00
if ( ( r = manager_load_unit ( m , name , NULL , & error , & u ) ) < 0 )
return bus_send_error_reply ( m , connection , message , & error , r ) ;
2010-02-01 05:33:24 +03:00
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
if ( ! ( path = unit_dbus_path ( u ) ) )
goto oom ;
if ( ! dbus_message_append_args (
reply ,
DBUS_TYPE_OBJECT_PATH , & path ,
DBUS_TYPE_INVALID ) )
goto oom ;
2010-06-01 21:47:46 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " StartUnit " ) )
job_type = JOB_START ;
else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " StopUnit " ) )
job_type = JOB_STOP ;
else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " ReloadUnit " ) )
job_type = JOB_RELOAD ;
else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " RestartUnit " ) )
job_type = JOB_RESTART ;
2010-07-06 07:06:40 +04:00
else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " TryRestartUnit " ) )
job_type = JOB_TRY_RESTART ;
2010-06-01 21:47:46 +04:00
else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " GetJob " ) ) {
2010-02-01 05:33:24 +03:00
uint32_t id ;
Job * j ;
if ( ! dbus_message_get_args (
message ,
& error ,
DBUS_TYPE_UINT32 , & id ,
DBUS_TYPE_INVALID ) )
2010-06-19 05:04:04 +04:00
return bus_send_error_reply ( m , connection , message , & error , - EINVAL ) ;
2010-02-01 05:33:24 +03:00
2010-07-08 04:43:18 +04:00
if ( ! ( j = manager_get_job ( m , id ) ) ) {
dbus_set_error ( & error , BUS_ERROR_NO_SUCH_JOB , " Job %u does not exist. " , ( unsigned ) id ) ;
return bus_send_error_reply ( m , connection , message , & error , - ENOENT ) ;
}
2010-02-01 05:33:24 +03:00
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
if ( ! ( path = job_dbus_path ( j ) ) )
goto oom ;
if ( ! dbus_message_append_args (
reply ,
DBUS_TYPE_OBJECT_PATH , & path ,
DBUS_TYPE_INVALID ) )
goto oom ;
2010-04-18 05:08:16 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " ClearJobs " ) ) {
2010-02-01 05:33:24 +03:00
manager_clear_jobs ( m ) ;
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
2010-04-18 05:08:16 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " ListUnits " ) ) {
2010-02-01 05:33:24 +03:00
DBusMessageIter iter , sub ;
Iterator i ;
Unit * u ;
const char * k ;
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
dbus_message_iter_init_append ( reply , & iter ) ;
2010-04-13 22:59:01 +04:00
if ( ! dbus_message_iter_open_container ( & iter , DBUS_TYPE_ARRAY , " (sssssouso) " , & sub ) )
2010-02-01 05:33:24 +03:00
goto oom ;
HASHMAP_FOREACH_KEY ( u , k , m - > units , i ) {
2010-02-03 16:21:48 +03:00
char * u_path , * j_path ;
2010-06-01 21:47:46 +04:00
const char * description , * load_state , * active_state , * sub_state , * sjob_type ;
2010-02-01 05:33:24 +03:00
DBusMessageIter sub2 ;
uint32_t job_id ;
2010-04-15 05:11:11 +04:00
if ( k ! = u - > meta . id )
2010-02-01 05:33:24 +03:00
continue ;
if ( ! dbus_message_iter_open_container ( & sub , DBUS_TYPE_STRUCT , NULL , & sub2 ) )
goto oom ;
description = unit_description ( u ) ;
load_state = unit_load_state_to_string ( u - > meta . load_state ) ;
active_state = unit_active_state_to_string ( unit_active_state ( u ) ) ;
2010-04-13 22:59:01 +04:00
sub_state = unit_sub_state_to_string ( u ) ;
2010-02-01 05:33:24 +03:00
2010-02-03 16:21:48 +03:00
if ( ! ( u_path = unit_dbus_path ( u ) ) )
2010-02-01 05:33:24 +03:00
goto oom ;
if ( u - > meta . job ) {
job_id = ( uint32_t ) u - > meta . job - > id ;
2010-02-03 16:21:48 +03:00
if ( ! ( j_path = job_dbus_path ( u - > meta . job ) ) ) {
free ( u_path ) ;
2010-02-01 05:33:24 +03:00
goto oom ;
}
2010-06-01 21:47:46 +04:00
sjob_type = job_type_to_string ( u - > meta . job - > type ) ;
2010-02-01 05:33:24 +03:00
} else {
job_id = 0 ;
2010-02-03 16:21:48 +03:00
j_path = u_path ;
2010-06-01 21:47:46 +04:00
sjob_type = " " ;
2010-02-01 05:33:24 +03:00
}
2010-04-15 05:11:11 +04:00
if ( ! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & u - > meta . id ) | |
2010-02-01 05:33:24 +03:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & description ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & load_state ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & active_state ) | |
2010-04-13 22:59:01 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & sub_state ) | |
2010-02-03 16:21:48 +03:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_OBJECT_PATH , & u_path ) | |
2010-02-01 05:33:24 +03:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_UINT32 , & job_id ) | |
2010-06-01 21:47:46 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & sjob_type ) | |
2010-02-03 16:21:48 +03:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_OBJECT_PATH , & j_path ) ) {
free ( u_path ) ;
2010-02-01 05:33:24 +03:00
if ( u - > meta . job )
2010-02-03 16:21:48 +03:00
free ( j_path ) ;
2010-02-01 05:33:24 +03:00
goto oom ;
}
2010-02-03 16:21:48 +03:00
free ( u_path ) ;
2010-02-01 05:33:24 +03:00
if ( u - > meta . job )
2010-02-03 16:21:48 +03:00
free ( j_path ) ;
2010-02-01 05:33:24 +03:00
if ( ! dbus_message_iter_close_container ( & sub , & sub2 ) )
goto oom ;
}
if ( ! dbus_message_iter_close_container ( & iter , & sub ) )
goto oom ;
2010-04-18 05:08:16 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " ListJobs " ) ) {
2010-02-01 05:33:24 +03:00
DBusMessageIter iter , sub ;
Iterator i ;
Job * j ;
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
dbus_message_iter_init_append ( reply , & iter ) ;
if ( ! dbus_message_iter_open_container ( & iter , DBUS_TYPE_ARRAY , " (usssoo) " , & sub ) )
goto oom ;
HASHMAP_FOREACH ( j , m - > jobs , i ) {
2010-02-03 16:21:48 +03:00
char * u_path , * j_path ;
2010-04-15 05:11:11 +04:00
const char * state , * type ;
2010-02-01 05:33:24 +03:00
uint32_t id ;
DBusMessageIter sub2 ;
if ( ! dbus_message_iter_open_container ( & sub , DBUS_TYPE_STRUCT , NULL , & sub2 ) )
goto oom ;
id = ( uint32_t ) j - > id ;
state = job_state_to_string ( j - > state ) ;
2010-02-03 14:39:44 +03:00
type = job_type_to_string ( j - > type ) ;
2010-02-01 05:33:24 +03:00
2010-02-03 16:21:48 +03:00
if ( ! ( j_path = job_dbus_path ( j ) ) )
2010-02-01 05:33:24 +03:00
goto oom ;
2010-02-03 16:21:48 +03:00
if ( ! ( u_path = unit_dbus_path ( j - > unit ) ) ) {
free ( j_path ) ;
2010-02-01 05:33:24 +03:00
goto oom ;
}
if ( ! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_UINT32 , & id ) | |
2010-04-15 05:11:11 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & j - > unit - > meta . id ) | |
2010-02-01 05:33:24 +03:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & type ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & state ) | |
2010-02-03 16:21:48 +03:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_OBJECT_PATH , & j_path ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_OBJECT_PATH , & u_path ) ) {
free ( j_path ) ;
free ( u_path ) ;
2010-02-01 05:33:24 +03:00
goto oom ;
}
2010-02-03 16:21:48 +03:00
free ( j_path ) ;
free ( u_path ) ;
2010-02-01 05:33:24 +03:00
if ( ! dbus_message_iter_close_container ( & sub , & sub2 ) )
goto oom ;
}
if ( ! dbus_message_iter_close_container ( & iter , & sub ) )
goto oom ;
2010-04-18 05:08:16 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " Subscribe " ) ) {
2010-02-05 02:38:41 +03:00
char * client ;
2010-07-05 02:58:07 +04:00
Set * s ;
if ( ! ( s = BUS_CONNECTION_SUBSCRIBED ( m , connection ) ) ) {
if ( ! ( s = set_new ( string_hash_func , string_compare_func ) ) )
goto oom ;
if ( ! ( dbus_connection_set_data ( connection , m - > subscribed_data_slot , s , NULL ) ) ) {
set_free ( s ) ;
goto oom ;
}
}
2010-02-05 02:38:41 +03:00
2010-07-06 21:02:54 +04:00
if ( ! ( client = strdup ( message_get_sender_with_fallback ( message ) ) ) )
2010-02-05 02:38:41 +03:00
goto oom ;
2010-07-05 02:58:07 +04:00
if ( ( r = set_put ( s , client ) ) < 0 ) {
free ( client ) ;
2010-06-19 05:04:04 +04:00
return bus_send_error_reply ( m , connection , message , NULL , r ) ;
2010-07-05 02:58:07 +04:00
}
2010-02-05 02:38:41 +03:00
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
2010-04-18 05:08:16 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " Unsubscribe " ) ) {
2010-02-05 02:38:41 +03:00
char * client ;
2010-07-08 04:43:18 +04:00
if ( ! ( client = set_remove ( BUS_CONNECTION_SUBSCRIBED ( m , connection ) , ( char * ) message_get_sender_with_fallback ( message ) ) ) ) {
dbus_set_error ( & error , BUS_ERROR_NOT_SUBSCRIBED , " Client is not subscribed. " ) ;
return bus_send_error_reply ( m , connection , message , & error , - ENOENT ) ;
}
2010-02-05 02:38:41 +03:00
free ( client ) ;
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
2010-04-18 05:08:16 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " Dump " ) ) {
2010-04-10 19:37:56 +04:00
FILE * f ;
char * dump = NULL ;
size_t size ;
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
if ( ! ( f = open_memstream ( & dump , & size ) ) )
goto oom ;
manager_dump_units ( m , f , NULL ) ;
manager_dump_jobs ( m , f , NULL ) ;
if ( ferror ( f ) ) {
fclose ( f ) ;
free ( dump ) ;
goto oom ;
}
fclose ( f ) ;
if ( ! dbus_message_append_args ( reply , DBUS_TYPE_STRING , & dump , DBUS_TYPE_INVALID ) ) {
free ( dump ) ;
goto oom ;
}
free ( dump ) ;
2010-04-18 05:08:16 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " CreateSnapshot " ) ) {
const char * name ;
dbus_bool_t cleanup ;
Snapshot * s ;
if ( ! dbus_message_get_args (
message ,
& error ,
DBUS_TYPE_STRING , & name ,
DBUS_TYPE_BOOLEAN , & cleanup ,
DBUS_TYPE_INVALID ) )
2010-06-19 05:04:04 +04:00
return bus_send_error_reply ( m , connection , message , & error , - EINVAL ) ;
2010-04-18 05:08:16 +04:00
if ( name & & name [ 0 ] = = 0 )
name = NULL ;
2010-07-08 04:43:18 +04:00
if ( ( r = snapshot_create ( m , name , cleanup , & error , & s ) ) < 0 )
return bus_send_error_reply ( m , connection , message , & error , r ) ;
2010-04-18 05:08:16 +04:00
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
if ( ! ( path = unit_dbus_path ( UNIT ( s ) ) ) )
goto oom ;
if ( ! dbus_message_append_args (
reply ,
DBUS_TYPE_OBJECT_PATH , & path ,
DBUS_TYPE_INVALID ) )
goto oom ;
2010-04-10 19:37:56 +04:00
2010-02-01 05:33:24 +03:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.DBus.Introspectable " , " Introspect " ) ) {
char * introspection = NULL ;
FILE * f ;
Iterator i ;
Unit * u ;
Job * j ;
const char * k ;
size_t size ;
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
/* We roll our own introspection code here, instead of
* relying on bus_default_message_handler ( ) because we
* need to generate our introspection string
* dynamically . */
if ( ! ( f = open_memstream ( & introspection , & size ) ) )
goto oom ;
fputs ( INTROSPECTION_BEGIN , f ) ;
HASHMAP_FOREACH_KEY ( u , k , m - > units , i ) {
char * p ;
2010-04-15 05:11:11 +04:00
if ( k ! = u - > meta . id )
2010-02-01 05:33:24 +03:00
continue ;
if ( ! ( p = bus_path_escape ( k ) ) ) {
fclose ( f ) ;
free ( introspection ) ;
goto oom ;
}
fprintf ( f , " <node name= \" unit/%s \" /> " , p ) ;
free ( p ) ;
}
HASHMAP_FOREACH ( j , m - > jobs , i )
fprintf ( f , " <node name= \" job/%lu \" /> " , ( unsigned long ) j - > id ) ;
fputs ( INTROSPECTION_END , f ) ;
if ( ferror ( f ) ) {
fclose ( f ) ;
free ( introspection ) ;
goto oom ;
}
fclose ( f ) ;
if ( ! introspection )
goto oom ;
if ( ! dbus_message_append_args ( reply , DBUS_TYPE_STRING , & introspection , DBUS_TYPE_INVALID ) ) {
free ( introspection ) ;
goto oom ;
}
free ( introspection ) ;
2010-04-21 05:27:44 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " Reload " ) ) {
assert ( ! m - > queued_message ) ;
/* Instead of sending the reply back right away, we
* just remember that we need to and then send it
* after the reload is finished . That way the caller
* knows when the reload finished . */
if ( ! ( m - > queued_message = dbus_message_new_method_return ( message ) ) )
goto oom ;
2010-07-07 04:21:16 +04:00
m - > queued_message_connection = connection ;
2010-04-21 05:27:44 +04:00
m - > exit_code = MANAGER_RELOAD ;
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " Reexecute " ) ) {
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
m - > exit_code = MANAGER_REEXECUTE ;
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " Exit " ) ) {
2010-07-08 04:43:18 +04:00
if ( m - > running_as = = MANAGER_SYSTEM ) {
dbus_set_error ( & error , BUS_ERROR_NOT_SUPPORTED , " Exit is only supported for session managers. " ) ;
return bus_send_error_reply ( m , connection , message , & error , - ENOTSUP ) ;
}
2010-04-21 05:27:44 +04:00
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
m - > exit_code = MANAGER_EXIT ;
2010-05-10 01:53:52 +04:00
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " SetEnvironment " ) ) {
char * * l = NULL , * * e = NULL ;
if ( ( r = bus_parse_strv ( message , & l ) ) < 0 ) {
if ( r = = - ENOMEM )
goto oom ;
2010-06-19 05:04:04 +04:00
return bus_send_error_reply ( m , connection , message , NULL , r ) ;
2010-05-10 01:53:52 +04:00
}
2010-06-16 23:54:17 +04:00
e = strv_env_merge ( 2 , m - > environment , l ) ;
2010-05-10 01:53:52 +04:00
strv_free ( l ) ;
if ( ! e )
goto oom ;
if ( ! ( reply = dbus_message_new_method_return ( message ) ) ) {
strv_free ( e ) ;
goto oom ;
}
strv_free ( m - > environment ) ;
m - > environment = e ;
} else if ( dbus_message_is_method_call ( message , " org.freedesktop.systemd1.Manager " , " UnsetEnvironment " ) ) {
char * * l = NULL , * * e = NULL ;
if ( ( r = bus_parse_strv ( message , & l ) ) < 0 ) {
if ( r = = - ENOMEM )
goto oom ;
2010-06-19 05:04:04 +04:00
return bus_send_error_reply ( m , connection , message , NULL , r ) ;
2010-05-10 01:53:52 +04:00
}
2010-06-16 23:54:17 +04:00
e = strv_env_delete ( m - > environment , 1 , l ) ;
2010-05-10 01:53:52 +04:00
strv_free ( l ) ;
if ( ! e )
goto oom ;
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
strv_free ( m - > environment ) ;
m - > environment = e ;
2010-02-01 05:33:24 +03:00
} else
2010-06-19 05:04:04 +04:00
return bus_default_message_handler ( m , connection , message , NULL , properties ) ;
2010-02-01 05:33:24 +03:00
2010-06-01 21:47:46 +04:00
if ( job_type ! = _JOB_TYPE_INVALID ) {
const char * name , * smode ;
JobMode mode ;
Job * j ;
Unit * u ;
if ( ! dbus_message_get_args (
message ,
& error ,
DBUS_TYPE_STRING , & name ,
DBUS_TYPE_STRING , & smode ,
DBUS_TYPE_INVALID ) )
2010-06-19 05:04:04 +04:00
return bus_send_error_reply ( m , connection , message , & error , - EINVAL ) ;
2010-06-01 21:47:46 +04:00
2010-07-08 04:43:18 +04:00
if ( ( mode = job_mode_from_string ( smode ) ) = = _JOB_MODE_INVALID ) {
dbus_set_error ( & error , BUS_ERROR_INVALID_JOB_MODE , " Job mode %s is invalid. " , smode ) ;
return bus_send_error_reply ( m , connection , message , & error , - EINVAL ) ;
}
2010-06-01 21:47:46 +04:00
2010-07-08 04:43:18 +04:00
if ( ( r = manager_load_unit ( m , name , NULL , & error , & u ) ) < 0 )
return bus_send_error_reply ( m , connection , message , & error , r ) ;
2010-06-01 21:47:46 +04:00
2010-07-08 04:43:18 +04:00
if ( job_type = = JOB_START & & u - > meta . only_by_dependency ) {
dbus_set_error ( & error , BUS_ERROR_ONLY_BY_DEPENDENCY , " Unit may be activated by dependency only. " ) ;
return bus_send_error_reply ( m , connection , message , & error , - EPERM ) ;
}
2010-06-01 21:47:46 +04:00
2010-07-08 04:43:18 +04:00
if ( ( r = manager_add_job ( m , job_type , u , mode , true , & error , & j ) ) < 0 )
return bus_send_error_reply ( m , connection , message , & error , r ) ;
2010-06-01 21:47:46 +04:00
2010-07-06 21:02:54 +04:00
if ( ! ( j - > bus_client = strdup ( message_get_sender_with_fallback ( message ) ) ) )
2010-07-05 02:58:07 +04:00
goto oom ;
j - > bus = connection ;
2010-06-01 21:47:46 +04:00
if ( ! ( reply = dbus_message_new_method_return ( message ) ) )
goto oom ;
if ( ! ( path = job_dbus_path ( j ) ) )
goto oom ;
if ( ! dbus_message_append_args (
reply ,
DBUS_TYPE_OBJECT_PATH , & path ,
DBUS_TYPE_INVALID ) )
goto oom ;
}
2010-02-01 05:33:24 +03:00
free ( path ) ;
if ( reply ) {
if ( ! dbus_connection_send ( connection , reply , NULL ) )
goto oom ;
dbus_message_unref ( reply ) ;
}
return DBUS_HANDLER_RESULT_HANDLED ;
oom :
free ( path ) ;
if ( reply )
dbus_message_unref ( reply ) ;
dbus_error_free ( & error ) ;
return DBUS_HANDLER_RESULT_NEED_MEMORY ;
}
const DBusObjectPathVTable bus_manager_vtable = {
. message_function = bus_manager_message_handler
} ;