2017-11-18 19:09:20 +03:00
/* SPDX-License-Identifier: LGPL-2.1+ */
2012-09-18 13:27:56 +04:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
* * */
2015-10-27 05:01:06 +03:00
# include "alloc-util.h"
2015-10-24 23:58:24 +03:00
# include "cgroup-util.h"
2016-11-07 18:14:59 +03:00
# include "format-util.h"
2015-10-24 23:58:24 +03:00
# include "macro.h"
2012-09-18 13:27:56 +04:00
# include "specifier.h"
2015-10-24 23:58:24 +03:00
# include "string-util.h"
2012-09-18 13:27:56 +04:00
# include "strv.h"
# include "unit-name.h"
# include "unit-printf.h"
2015-10-26 00:32:30 +03:00
# include "unit.h"
# include "user-util.h"
2012-09-18 13:27:56 +04:00
2013-09-17 19:03:46 +04:00
static int specifier_prefix_and_instance ( char specifier , void * data , void * userdata , char * * ret ) {
2012-09-18 13:27:56 +04:00
Unit * u = userdata ;
2013-09-17 19:03:46 +04:00
2012-09-18 13:27:56 +04:00
assert ( u ) ;
2015-04-30 21:21:00 +03:00
return unit_name_to_prefix_and_instance ( u - > id , ret ) ;
2012-09-18 13:27:56 +04:00
}
2013-09-17 19:03:46 +04:00
static int specifier_prefix ( char specifier , void * data , void * userdata , char * * ret ) {
2012-09-18 13:27:56 +04:00
Unit * u = userdata ;
2013-09-17 19:03:46 +04:00
2012-09-18 13:27:56 +04:00
assert ( u ) ;
2015-04-30 21:21:00 +03:00
return unit_name_to_prefix ( u - > id , ret ) ;
2012-09-18 13:27:56 +04:00
}
2013-09-17 19:03:46 +04:00
static int specifier_prefix_unescaped ( char specifier , void * data , void * userdata , char * * ret ) {
_cleanup_free_ char * p = NULL ;
2015-04-30 21:21:00 +03:00
Unit * u = userdata ;
int r ;
2012-09-18 13:27:56 +04:00
assert ( u ) ;
2015-04-30 21:21:00 +03:00
r = unit_name_to_prefix ( u - > id , & p ) ;
if ( r < 0 )
return r ;
2012-09-18 13:27:56 +04:00
2015-04-30 21:21:00 +03:00
return unit_name_unescape ( p , ret ) ;
2012-09-18 13:27:56 +04:00
}
2013-09-17 19:03:46 +04:00
static int specifier_instance_unescaped ( char specifier , void * data , void * userdata , char * * ret ) {
2012-09-18 13:27:56 +04:00
Unit * u = userdata ;
2013-09-17 19:03:46 +04:00
2012-09-18 13:27:56 +04:00
assert ( u ) ;
2015-10-24 23:55:56 +03:00
return unit_name_unescape ( strempty ( u - > instance ) , ret ) ;
2012-09-18 13:27:56 +04:00
}
2018-04-23 23:43:20 +03:00
static int specifier_last_component ( char specifier , void * data , void * userdata , char * * ret ) {
Unit * u = userdata ;
_cleanup_free_ char * prefix = NULL ;
char * dash ;
int r ;
assert ( u ) ;
r = unit_name_to_prefix ( u - > id , & prefix ) ;
if ( r < 0 )
return r ;
dash = strrchr ( prefix , ' - ' ) ;
if ( dash )
return specifier_string ( specifier , dash + 1 , userdata , ret ) ;
* ret = TAKE_PTR ( prefix ) ;
return 0 ;
}
static int specifier_last_component_unescaped ( char specifier , void * data , void * userdata , char * * ret ) {
_cleanup_free_ char * p = NULL ;
int r ;
r = specifier_last_component ( specifier , data , userdata , & p ) ;
if ( r < 0 )
return r ;
return unit_name_unescape ( p , ret ) ;
}
2013-09-17 19:03:46 +04:00
static int specifier_filename ( char specifier , void * data , void * userdata , char * * ret ) {
2012-09-18 13:27:56 +04:00
Unit * u = userdata ;
2013-09-17 19:03:46 +04:00
2012-09-18 13:27:56 +04:00
assert ( u ) ;
if ( u - > instance )
2015-04-30 21:21:00 +03:00
return unit_name_path_unescape ( u - > instance , ret ) ;
2013-09-17 19:03:46 +04:00
else
2015-04-30 21:21:00 +03:00
return unit_name_to_path ( u - > id , ret ) ;
2012-09-18 13:27:56 +04:00
}
2016-12-07 20:58:09 +03:00
static void bad_specifier ( Unit * u , char specifier ) {
log_unit_warning ( u , " Specifier '%%%c' used in unit configuration, which is deprecated. Please update your unit file, as it does not work as intended. " , specifier ) ;
}
2013-09-17 19:03:46 +04:00
static int specifier_cgroup ( char specifier , void * data , void * userdata , char * * ret ) {
2012-09-18 13:27:56 +04:00
Unit * u = userdata ;
2013-09-17 19:03:46 +04:00
char * n ;
2012-09-18 13:27:56 +04:00
assert ( u ) ;
2016-12-07 20:58:09 +03:00
bad_specifier ( u , specifier ) ;
2013-12-16 07:59:31 +04:00
if ( u - > cgroup_path )
n = strdup ( u - > cgroup_path ) ;
else
n = unit_default_cgroup_path ( u ) ;
2013-09-17 19:03:46 +04:00
if ( ! n )
return - ENOMEM ;
* ret = n ;
return 0 ;
2012-09-18 13:27:56 +04:00
}
2013-09-17 19:03:46 +04:00
static int specifier_cgroup_root ( char specifier , void * data , void * userdata , char * * ret ) {
2012-09-18 13:27:56 +04:00
Unit * u = userdata ;
2013-09-17 19:03:46 +04:00
char * n ;
2012-09-18 13:27:56 +04:00
2013-06-20 05:45:08 +04:00
assert ( u ) ;
2012-09-18 13:27:56 +04:00
2016-12-07 20:58:09 +03:00
bad_specifier ( u , specifier ) ;
2015-04-30 13:33:54 +03:00
n = strdup ( u - > manager - > cgroup_root ) ;
if ( ! n )
return - ENOMEM ;
2012-09-18 13:27:56 +04:00
2015-04-30 13:33:54 +03:00
* ret = n ;
return 0 ;
}
2013-09-17 19:03:46 +04:00
2015-04-30 13:33:54 +03:00
static int specifier_cgroup_slice ( char specifier , void * data , void * userdata , char * * ret ) {
Unit * u = userdata ;
char * n ;
assert ( u ) ;
2016-12-07 20:58:09 +03:00
bad_specifier ( u , specifier ) ;
2015-04-30 13:33:54 +03:00
if ( UNIT_ISSET ( u - > slice ) ) {
Unit * slice ;
slice = UNIT_DEREF ( u - > slice ) ;
if ( slice - > cgroup_path )
n = strdup ( slice - > cgroup_path ) ;
else
n = unit_default_cgroup_path ( slice ) ;
} else
n = strdup ( u - > manager - > cgroup_root ) ;
2015-10-24 23:55:56 +03:00
if ( ! n )
return - ENOMEM ;
2012-09-18 13:27:56 +04:00
2013-09-17 19:03:46 +04:00
* ret = n ;
return 0 ;
2012-09-18 13:27:56 +04:00
}
2017-10-11 15:02:36 +03:00
static int specifier_special_directory ( char specifier , void * data , void * userdata , char * * ret ) {
2012-09-18 13:27:56 +04:00
Unit * u = userdata ;
2013-09-17 19:03:46 +04:00
char * n = NULL ;
2012-09-18 13:27:56 +04:00
assert ( u ) ;
2017-10-11 15:02:36 +03:00
n = strdup ( u - > manager - > prefix [ PTR_TO_UINT ( data ) ] ) ;
2013-12-16 07:59:31 +04:00
if ( ! n )
return - ENOMEM ;
2013-09-17 19:03:46 +04:00
* ret = n ;
return 0 ;
2012-09-18 13:27:56 +04:00
}
2013-09-17 19:03:46 +04:00
int unit_name_printf ( Unit * u , const char * format , char * * ret ) {
2012-09-18 13:27:56 +04:00
/*
2016-12-05 21:12:54 +03:00
* This will use the passed string as format string and replace the following specifiers ( which should all be
* safe for inclusion in unit names ) :
2012-09-18 13:27:56 +04:00
*
* % n : the full id of the unit ( foo @ bar . waldo )
* % N : the id of the unit without the suffix ( foo @ bar )
* % p : the prefix ( foo )
* % i : the instance ( bar )
2016-12-05 21:12:54 +03:00
*
* % U : the UID of the running user
* % u : the username of the running user
*
* % m : the machine ID of the running system
* % H : the host name of the running system
* % b : the boot ID of the running system
2012-09-18 13:27:56 +04:00
*/
const Specifier table [ ] = {
{ ' n ' , specifier_string , u - > id } ,
{ ' N ' , specifier_prefix_and_instance , NULL } ,
{ ' p ' , specifier_prefix , NULL } ,
{ ' i ' , specifier_string , u - > instance } ,
2016-12-05 21:12:54 +03:00
{ ' U ' , specifier_user_id , NULL } ,
{ ' u ' , specifier_user_name , NULL } ,
{ ' m ' , specifier_machine_id , NULL } ,
{ ' H ' , specifier_host_name , NULL } ,
{ ' b ' , specifier_boot_id , NULL } ,
{ }
2012-09-18 13:27:56 +04:00
} ;
assert ( u ) ;
assert ( format ) ;
2013-09-17 19:03:46 +04:00
assert ( ret ) ;
2012-09-18 13:27:56 +04:00
2013-09-17 19:03:46 +04:00
return specifier_printf ( format , table , u , ret ) ;
2012-09-18 13:27:56 +04:00
}
2013-09-17 19:03:46 +04:00
int unit_full_printf ( Unit * u , const char * format , char * * ret ) {
2012-09-18 13:27:56 +04:00
2016-12-05 21:12:54 +03:00
/* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes
* ( which are likely not suitable for unescaped inclusion in unit names ) :
*
* % f : the unescaped instance if set , otherwise the id unescaped as path
2017-10-11 15:02:36 +03:00
*
2016-12-07 20:58:09 +03:00
* % c : cgroup path of unit ( deprecated )
* % r : where units in this slice are placed in the cgroup tree ( deprecated )
* % R : the root of this systemd ' s instance tree ( deprecated )
2017-10-11 15:02:36 +03:00
*
* % t : the runtime directory root ( e . g . / run or $ XDG_RUNTIME_DIR )
* % S : the state directory root ( e . g . / var / lib or $ XDG_CONFIG_HOME )
* % C : the cache directory root ( e . g . / var / cache or $ XDG_CACHE_HOME )
* % L : the log directory root ( e . g . / var / log or $ XDG_CONFIG_HOME / log )
2016-12-05 21:12:54 +03:00
*
* % h : the homedir of the running user
* % s : the shell of the running user
2012-09-18 13:27:56 +04:00
*
2016-12-05 21:12:54 +03:00
* % v : ` uname - r ` of the running system
2016-12-07 21:03:22 +03:00
*
* NOTICE : When you add new entries here , please be careful : specifiers which depend on settings of the unit
* file itself are broken by design , as they would resolve differently depending on whether they are used
* before or after the relevant configuration setting . Hence : don ' t add them .
2012-09-18 13:27:56 +04:00
*/
const Specifier table [ ] = {
2018-04-23 23:43:20 +03:00
{ ' n ' , specifier_string , u - > id } ,
{ ' N ' , specifier_prefix_and_instance , NULL } ,
{ ' p ' , specifier_prefix , NULL } ,
{ ' P ' , specifier_prefix_unescaped , NULL } ,
{ ' i ' , specifier_string , u - > instance } ,
{ ' I ' , specifier_instance_unescaped , NULL } ,
{ ' j ' , specifier_last_component , NULL } ,
{ ' J ' , specifier_last_component_unescaped , NULL } ,
{ ' f ' , specifier_filename , NULL } ,
{ ' c ' , specifier_cgroup , NULL } ,
{ ' r ' , specifier_cgroup_slice , NULL } ,
{ ' R ' , specifier_cgroup_root , NULL } ,
{ ' t ' , specifier_special_directory , UINT_TO_PTR ( EXEC_DIRECTORY_RUNTIME ) } ,
{ ' S ' , specifier_special_directory , UINT_TO_PTR ( EXEC_DIRECTORY_STATE ) } ,
{ ' C ' , specifier_special_directory , UINT_TO_PTR ( EXEC_DIRECTORY_CACHE ) } ,
{ ' L ' , specifier_special_directory , UINT_TO_PTR ( EXEC_DIRECTORY_LOGS ) } ,
{ ' U ' , specifier_user_id , NULL } ,
{ ' u ' , specifier_user_name , NULL } ,
{ ' h ' , specifier_user_home , NULL } ,
{ ' s ' , specifier_user_shell , NULL } ,
{ ' m ' , specifier_machine_id , NULL } ,
{ ' H ' , specifier_host_name , NULL } ,
{ ' b ' , specifier_boot_id , NULL } ,
{ ' v ' , specifier_kernel_release , NULL } ,
2013-07-19 10:45:27 +04:00
{ }
2012-09-18 13:27:56 +04:00
} ;
2013-09-17 19:03:46 +04:00
assert ( u ) ;
2012-09-18 13:27:56 +04:00
assert ( format ) ;
2013-09-17 19:03:46 +04:00
assert ( ret ) ;
2012-09-18 13:27:56 +04:00
2013-09-17 19:03:46 +04:00
return specifier_printf ( format , table , u , ret ) ;
2012-09-18 13:27:56 +04:00
}
2013-09-17 19:03:46 +04:00
int unit_full_printf_strv ( Unit * u , char * * l , char * * * ret ) {
2012-09-18 13:27:56 +04:00
size_t n ;
char * * r , * * i , * * j ;
2013-09-17 19:03:46 +04:00
int q ;
2012-09-18 13:27:56 +04:00
/* Applies unit_full_printf to every entry in l */
assert ( u ) ;
n = strv_length ( l ) ;
r = new ( char * , n + 1 ) ;
if ( ! r )
2013-09-17 19:03:46 +04:00
return - ENOMEM ;
2012-09-18 13:27:56 +04:00
for ( i = l , j = r ; * i ; i + + , j + + ) {
2013-09-17 19:03:46 +04:00
q = unit_full_printf ( u , * i , j ) ;
if ( q < 0 )
2012-09-18 13:27:56 +04:00
goto fail ;
}
* j = NULL ;
2013-09-17 19:03:46 +04:00
* ret = r ;
return 0 ;
2012-09-18 13:27:56 +04:00
fail :
for ( j - - ; j > = r ; j - - )
free ( * j ) ;
free ( r ) ;
2013-09-17 19:03:46 +04:00
return q ;
2012-09-18 13:27:56 +04:00
}