2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-04-18 05:08:16 +04: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/>.
* * */
# include <errno.h>
# include <dbus/dbus.h>
2010-07-04 18:44:58 +04:00
# include <sys/prctl.h>
2010-04-18 05:08:16 +04:00
# include "dbus-execute.h"
2010-07-04 18:44:58 +04:00
# include "missing.h"
# include "ioprio.h"
2010-07-04 22:38:14 +04:00
# include "strv.h"
2011-04-16 03:54:49 +04:00
# include "dbus-common.h"
2010-04-18 05:08:16 +04:00
2010-07-10 06:49:37 +04:00
DEFINE_BUS_PROPERTY_APPEND_ENUM ( bus_execute_append_kill_mode , kill_mode , KillMode ) ;
2010-04-18 05:08:16 +04:00
DEFINE_BUS_PROPERTY_APPEND_ENUM ( bus_execute_append_input , exec_input , ExecInput ) ;
DEFINE_BUS_PROPERTY_APPEND_ENUM ( bus_execute_append_output , exec_output , ExecOutput ) ;
2010-07-04 18:44:58 +04:00
2011-04-16 03:54:49 +04:00
int bus_execute_append_env_files ( DBusMessageIter * i , const char * property , void * data ) {
2011-03-04 05:44:43 +03:00
char * * env_files = data , * * j ;
DBusMessageIter sub , sub2 ;
assert ( i ) ;
assert ( property ) ;
if ( ! dbus_message_iter_open_container ( i , DBUS_TYPE_ARRAY , " (sb) " , & sub ) )
return - ENOMEM ;
STRV_FOREACH ( j , env_files ) {
dbus_bool_t b = false ;
char * fn = * j ;
if ( fn [ 0 ] = = ' - ' ) {
b = true ;
fn + + ;
}
if ( ! dbus_message_iter_open_container ( & sub , DBUS_TYPE_STRUCT , NULL , & sub2 ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & fn ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_BOOLEAN , & b ) | |
! dbus_message_iter_close_container ( & sub , & sub2 ) )
return - ENOMEM ;
}
if ( ! dbus_message_iter_close_container ( i , & sub ) )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_oom_score_adjust ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
int32_t n ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
2010-08-31 03:33:39 +04:00
if ( c - > oom_score_adjust_set )
n = c - > oom_score_adjust ;
2010-07-04 18:44:58 +04:00
else {
char * t ;
n = 0 ;
2010-08-31 03:33:39 +04:00
if ( read_one_line_file ( " /proc/self/oom_score_adj " , & t ) > = 0 ) {
2010-07-04 18:44:58 +04:00
safe_atoi ( t , & n ) ;
free ( t ) ;
2010-08-31 03:33:39 +04:00
} else if ( read_one_line_file ( " /proc/self/oom_adj " , & t ) > = 0 ) {
safe_atoi ( t , & n ) ;
free ( t ) ;
if ( n = = OOM_ADJUST_MAX )
n = OOM_SCORE_ADJ_MAX ;
else
n = ( n * OOM_SCORE_ADJ_MAX ) / - OOM_DISABLE ;
2010-07-04 18:44:58 +04:00
}
}
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_INT32 , & n ) )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_nice ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
int32_t n ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
if ( c - > nice_set )
n = c - > nice ;
else
n = getpriority ( PRIO_PROCESS , 0 ) ;
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_INT32 , & n ) )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_ioprio ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
int32_t n ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
if ( c - > ioprio_set )
n = c - > ioprio ;
else
n = ioprio_get ( IOPRIO_WHO_PROCESS , 0 ) ;
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_INT32 , & n ) )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_cpu_sched_policy ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
int32_t n ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
if ( c - > cpu_sched_set )
n = c - > cpu_sched_policy ;
else
n = sched_getscheduler ( 0 ) ;
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_INT32 , & n ) )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_cpu_sched_priority ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
int32_t n ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
if ( c - > cpu_sched_set )
n = c - > cpu_sched_priority ;
else {
struct sched_param p ;
n = 0 ;
zero ( p ) ;
if ( sched_getparam ( 0 , & p ) > = 0 )
n = p . sched_priority ;
}
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_INT32 , & n ) )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_affinity ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
dbus_bool_t b ;
DBusMessageIter sub ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
2010-07-04 22:38:14 +04:00
if ( ! dbus_message_iter_open_container ( i , DBUS_TYPE_ARRAY , " y " , & sub ) )
2010-07-04 18:44:58 +04:00
return - ENOMEM ;
if ( c - > cpuset )
b = dbus_message_iter_append_fixed_array ( & sub , DBUS_TYPE_BYTE , & c - > cpuset , CPU_ALLOC_SIZE ( c - > cpuset_ncpus ) ) ;
else
b = dbus_message_iter_append_fixed_array ( & sub , DBUS_TYPE_BYTE , & c - > cpuset , 0 ) ;
if ( ! b )
return - ENOMEM ;
if ( ! dbus_message_iter_close_container ( i , & sub ) )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_timer_slack_nsec ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
uint64_t u ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
2010-07-04 23:12:10 +04:00
if ( c - > timer_slack_nsec_set )
u = ( uint64_t ) c - > timer_slack_nsec ;
2010-07-04 18:44:58 +04:00
else
u = ( uint64_t ) prctl ( PR_GET_TIMERSLACK ) ;
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_UINT64 , & u ) )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_capability_bs ( DBusMessageIter * i , const char * property , void * data ) {
2011-03-18 05:13:15 +03:00
ExecContext * c = data ;
uint64_t normal , inverted ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
2011-06-15 12:16:49 +04:00
/* We store this negated internally, to match the kernel, but
2011-03-18 05:13:15 +03:00
* we expose it normalized . */
normal = * ( uint64_t * ) data ;
inverted = ~ normal ;
2011-04-16 03:54:49 +04:00
return bus_property_append_uint64 ( i , property , & inverted ) ;
2011-03-18 05:13:15 +03:00
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_capabilities ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
char * t = NULL ;
const char * s ;
dbus_bool_t b ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
if ( c - > capabilities )
s = t = cap_to_text ( c - > capabilities , NULL ) ;
else
s = " " ;
2010-08-12 03:01:55 +04:00
if ( ! s )
2010-07-04 18:44:58 +04:00
return - ENOMEM ;
b = dbus_message_iter_append_basic ( i , DBUS_TYPE_STRING , & s ) ;
2010-08-12 03:01:55 +04:00
if ( t )
cap_free ( t ) ;
2010-07-04 18:44:58 +04:00
if ( ! b )
return - ENOMEM ;
return 0 ;
}
2011-04-16 03:54:49 +04:00
int bus_execute_append_rlimits ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 18:44:58 +04:00
ExecContext * c = data ;
int r ;
uint64_t u ;
assert ( i ) ;
assert ( property ) ;
assert ( c ) ;
assert_se ( ( r = rlimit_from_string ( property ) ) > = 0 ) ;
if ( c - > rlimit [ r ] )
u = ( uint64_t ) c - > rlimit [ r ] - > rlim_max ;
else {
struct rlimit rl ;
zero ( rl ) ;
getrlimit ( r , & rl ) ;
u = ( uint64_t ) rl . rlim_max ;
}
if ( ! dbus_message_iter_append_basic ( i , DBUS_TYPE_UINT64 , & u ) )
return - ENOMEM ;
return 0 ;
}
2010-07-04 22:38:14 +04:00
2011-04-16 03:54:49 +04:00
int bus_execute_append_command ( DBusMessageIter * i , const char * property , void * data ) {
2010-07-04 22:38:14 +04:00
ExecCommand * c = data ;
DBusMessageIter sub , sub2 , sub3 ;
assert ( i ) ;
assert ( property ) ;
2011-08-29 21:44:52 +04:00
if ( ! dbus_message_iter_open_container ( i , DBUS_TYPE_ARRAY , " (sasbttttuii) " , & sub ) )
2010-07-04 22:38:14 +04:00
return - ENOMEM ;
LIST_FOREACH ( command , c , c ) {
char * * l ;
uint32_t pid ;
int32_t code , status ;
2011-08-29 21:44:52 +04:00
dbus_bool_t b ;
2010-07-04 22:38:14 +04:00
if ( ! c - > path )
continue ;
if ( ! dbus_message_iter_open_container ( & sub , DBUS_TYPE_STRUCT , NULL , & sub2 ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_STRING , & c - > path ) | |
! dbus_message_iter_open_container ( & sub2 , DBUS_TYPE_ARRAY , " s " , & sub3 ) )
return - ENOMEM ;
STRV_FOREACH ( l , c - > argv )
if ( ! dbus_message_iter_append_basic ( & sub3 , DBUS_TYPE_STRING , l ) )
return - ENOMEM ;
pid = ( uint32_t ) c - > exec_status . pid ;
code = ( int32_t ) c - > exec_status . code ;
status = ( int32_t ) c - > exec_status . status ;
2011-08-29 21:44:52 +04:00
b = ! ! c - > ignore ;
2010-07-04 22:38:14 +04:00
if ( ! dbus_message_iter_close_container ( & sub2 , & sub3 ) | |
2011-08-29 21:44:52 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_BOOLEAN , & b ) | |
2010-07-04 22:38:14 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_UINT64 , & c - > exec_status . start_timestamp . realtime ) | |
2011-04-07 23:35:37 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_UINT64 , & c - > exec_status . start_timestamp . monotonic ) | |
2010-07-04 22:38:14 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_UINT64 , & c - > exec_status . exit_timestamp . realtime ) | |
2011-04-07 23:35:37 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_UINT64 , & c - > exec_status . exit_timestamp . monotonic ) | |
2010-08-12 00:04:22 +04:00
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_UINT32 , & pid ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_INT32 , & code ) | |
! dbus_message_iter_append_basic ( & sub2 , DBUS_TYPE_INT32 , & status ) )
2010-07-04 22:38:14 +04:00
return - ENOMEM ;
if ( ! dbus_message_iter_close_container ( & sub , & sub2 ) )
return - ENOMEM ;
}
if ( ! dbus_message_iter_close_container ( i , & sub ) )
return - ENOMEM ;
return 0 ;
}
2012-01-16 03:23:59 +04:00
const BusProperty bus_exec_context_properties [ ] = {
{ " Environment " , bus_property_append_strv , " as " , offsetof ( ExecContext , environment ) , true } ,
{ " EnvironmentFiles " , bus_execute_append_env_files , " a(sb) " , offsetof ( ExecContext , environment_files ) , true } ,
{ " UMask " , bus_property_append_mode , " u " , offsetof ( ExecContext , umask ) } ,
{ " LimitCPU " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitFSIZE " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitDATA " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitSTACK " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitCORE " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitRSS " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitNOFILE " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitAS " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitNPROC " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitMEMLOCK " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitLOCKS " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitSIGPENDING " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitMSGQUEUE " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitNICE " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitRTPRIO " , bus_execute_append_rlimits , " t " , 0 } ,
{ " LimitRTTIME " , bus_execute_append_rlimits , " t " , 0 } ,
{ " WorkingDirectory " , bus_property_append_string , " s " , offsetof ( ExecContext , working_directory ) , true } ,
{ " RootDirectory " , bus_property_append_string , " s " , offsetof ( ExecContext , root_directory ) , true } ,
{ " OOMScoreAdjust " , bus_execute_append_oom_score_adjust , " i " , 0 } ,
{ " Nice " , bus_execute_append_nice , " i " , 0 } ,
{ " IOScheduling " , bus_execute_append_ioprio , " i " , 0 } ,
{ " CPUSchedulingPolicy " , bus_execute_append_cpu_sched_policy , " i " , 0 } ,
{ " CPUSchedulingPriority " , bus_execute_append_cpu_sched_priority , " i " , 0 } ,
{ " CPUAffinity " , bus_execute_append_affinity , " ay " , 0 } ,
{ " TimerSlackNSec " , bus_execute_append_timer_slack_nsec , " t " , 0 } ,
{ " CPUSchedulingResetOnFork " , bus_property_append_bool , " b " , offsetof ( ExecContext , cpu_sched_reset_on_fork ) } ,
{ " NonBlocking " , bus_property_append_bool , " b " , offsetof ( ExecContext , non_blocking ) } ,
{ " StandardInput " , bus_execute_append_input , " s " , offsetof ( ExecContext , std_input ) } ,
{ " StandardOutput " , bus_execute_append_output , " s " , offsetof ( ExecContext , std_output ) } ,
{ " StandardError " , bus_execute_append_output , " s " , offsetof ( ExecContext , std_error ) } ,
{ " TTYPath " , bus_property_append_string , " s " , offsetof ( ExecContext , tty_path ) , true } ,
{ " TTYReset " , bus_property_append_bool , " b " , offsetof ( ExecContext , tty_reset ) } ,
{ " TTYVHangup " , bus_property_append_bool , " b " , offsetof ( ExecContext , tty_vhangup ) } ,
{ " TTYVTDisallocate " , bus_property_append_bool , " b " , offsetof ( ExecContext , tty_vt_disallocate ) } ,
{ " SyslogPriority " , bus_property_append_int , " i " , offsetof ( ExecContext , syslog_priority ) } ,
{ " SyslogIdentifier " , bus_property_append_string , " s " , offsetof ( ExecContext , syslog_identifier ) , true } ,
{ " SyslogLevelPrefix " , bus_property_append_bool , " b " , offsetof ( ExecContext , syslog_level_prefix ) } ,
{ " Capabilities " , bus_execute_append_capabilities , " s " , 0 } ,
{ " SecureBits " , bus_property_append_int , " i " , offsetof ( ExecContext , secure_bits ) } ,
{ " CapabilityBoundingSet " , bus_execute_append_capability_bs , " t " , offsetof ( ExecContext , capability_bounding_set_drop ) } ,
{ " User " , bus_property_append_string , " s " , offsetof ( ExecContext , user ) , true } ,
{ " Group " , bus_property_append_string , " s " , offsetof ( ExecContext , group ) , true } ,
{ " SupplementaryGroups " , bus_property_append_strv , " as " , offsetof ( ExecContext , supplementary_groups ) , true } ,
{ " TCPWrapName " , bus_property_append_string , " s " , offsetof ( ExecContext , tcpwrap_name ) , true } ,
{ " PAMName " , bus_property_append_string , " s " , offsetof ( ExecContext , pam_name ) , true } ,
{ " ReadWriteDirectories " , bus_property_append_strv , " as " , offsetof ( ExecContext , read_write_dirs ) , true } ,
{ " ReadOnlyDirectories " , bus_property_append_strv , " as " , offsetof ( ExecContext , read_only_dirs ) , true } ,
{ " InaccessibleDirectories " , bus_property_append_strv , " as " , offsetof ( ExecContext , inaccessible_dirs ) , true } ,
{ " MountFlags " , bus_property_append_ul , " t " , offsetof ( ExecContext , mount_flags ) } ,
{ " PrivateTmp " , bus_property_append_bool , " b " , offsetof ( ExecContext , private_tmp ) } ,
{ " PrivateNetwork " , bus_property_append_bool , " b " , offsetof ( ExecContext , private_network ) } ,
{ " SameProcessGroup " , bus_property_append_bool , " b " , offsetof ( ExecContext , same_pgrp ) } ,
{ " KillMode " , bus_execute_append_kill_mode , " s " , offsetof ( ExecContext , kill_mode ) } ,
{ " KillSignal " , bus_property_append_int , " i " , offsetof ( ExecContext , kill_signal ) } ,
{ " UtmpIdentifier " , bus_property_append_string , " s " , offsetof ( ExecContext , utmp_id ) , true } ,
{ " ControlGroupModify " , bus_property_append_bool , " b " , offsetof ( ExecContext , control_group_modify ) } ,
2012-01-21 04:47:53 +04:00
{ " ControlGroupPersistent " , bus_property_append_tristate_false , " b " , offsetof ( ExecContext , control_group_persistent ) } ,
2012-02-09 06:18:04 +04:00
{ " IgnoreSIGPIPE " , bus_property_append_bool , " b " , offsetof ( ExecContext , ignore_sigpipe ) } ,
2012-01-16 03:23:59 +04:00
{ NULL , }
} ;