1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
6 #include "creds-util.h"
11 #include "specifier.h"
12 #include "string-util.h"
14 #include "unit-name.h"
15 #include "unit-printf.h"
17 static int specifier_prefix_and_instance(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
18 const Unit
*u
= ASSERT_PTR(userdata
);
20 return unit_name_to_prefix_and_instance(u
->id
, ret
);
23 static int specifier_prefix(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
24 const Unit
*u
= ASSERT_PTR(userdata
);
26 return unit_name_to_prefix(u
->id
, ret
);
29 static int specifier_prefix_unescaped(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
30 _cleanup_free_
char *p
= NULL
;
31 const Unit
*u
= ASSERT_PTR(userdata
);
34 r
= unit_name_to_prefix(u
->id
, &p
);
38 return unit_name_unescape(p
, ret
);
41 static int specifier_instance_unescaped(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
42 const Unit
*u
= ASSERT_PTR(userdata
);
44 return unit_name_unescape(strempty(u
->instance
), ret
);
47 static int specifier_last_component(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
48 const Unit
*u
= ASSERT_PTR(userdata
);
49 _cleanup_free_
char *prefix
= NULL
;
53 r
= unit_name_to_prefix(u
->id
, &prefix
);
57 dash
= strrchr(prefix
, '-');
59 return specifier_string(specifier
, dash
+ 1, root
, userdata
, ret
);
61 *ret
= TAKE_PTR(prefix
);
65 static int specifier_last_component_unescaped(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
66 _cleanup_free_
char *p
= NULL
;
69 r
= specifier_last_component(specifier
, data
, root
, userdata
, &p
);
73 return unit_name_unescape(p
, ret
);
76 static int specifier_filename(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
77 const Unit
*u
= ASSERT_PTR(userdata
);
80 return unit_name_path_unescape(u
->instance
, ret
);
82 return unit_name_to_path(u
->id
, ret
);
85 static void bad_specifier(const Unit
*u
, char specifier
) {
86 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
);
89 static int specifier_cgroup(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
90 const Unit
*u
= ASSERT_PTR(userdata
);
92 bad_specifier(u
, specifier
);
94 return unit_get_cgroup_path_with_fallback(u
, ret
);
97 static int specifier_cgroup_root(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
98 const Unit
*u
= ASSERT_PTR(userdata
);
100 bad_specifier(u
, specifier
);
102 return strdup_to(ret
, u
->manager
->cgroup_root
);
105 static int specifier_cgroup_slice(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
106 const Unit
*u
= ASSERT_PTR(userdata
), *slice
;
108 bad_specifier(u
, specifier
);
110 slice
= UNIT_GET_SLICE(u
);
112 return unit_get_cgroup_path_with_fallback(slice
, ret
);
114 return strdup_to(ret
, u
->manager
->cgroup_root
);
117 static int specifier_special_directory(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
118 const Unit
*u
= ASSERT_PTR(userdata
);
120 return strdup_to(ret
, u
->manager
->prefix
[PTR_TO_UINT(data
)]);
123 static int specifier_credentials_dir(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
124 const Unit
*u
= ASSERT_PTR(userdata
);
129 d
= strjoin(u
->manager
->prefix
[EXEC_DIRECTORY_RUNTIME
], "/credentials/", u
->id
);
137 static int specifier_shared_data_dir(char specifier
, const void *data
, const char *root
, const void *userdata
, char **ret
) {
138 const Unit
*u
= ASSERT_PTR(userdata
);
142 return sd_path_lookup(MANAGER_IS_SYSTEM(u
->manager
) ? SD_PATH_SYSTEM_SHARED
: SD_PATH_USER_SHARED
, NULL
, ret
);
145 int unit_name_printf(const Unit
*u
, const char* format
, char **ret
) {
147 * This will use the passed string as format string and replace the following specifiers (which should all be
148 * safe for inclusion in unit names):
150 * %n: the full id of the unit (foo-aaa@bar.waldo)
151 * %N: the id of the unit without the suffix (foo-aaa@bar)
152 * %p: the prefix (foo-aaa)
153 * %i: the instance (bar)
154 * %j: the last component of the prefix (aaa)
157 const Specifier table
[] = {
158 { 'i', specifier_string
, u
->instance
},
159 { 'j', specifier_last_component
, NULL
},
160 { 'n', specifier_string
, u
->id
},
161 { 'N', specifier_prefix_and_instance
, NULL
},
162 { 'p', specifier_prefix
, NULL
},
164 COMMON_SYSTEM_SPECIFIERS
,
166 COMMON_CREDS_SPECIFIERS(u
->manager
->runtime_scope
),
174 return specifier_printf(format
, UNIT_NAME_MAX
, table
, NULL
, u
, ret
);
177 int unit_full_printf_full(const Unit
*u
, const char *format
, size_t max_length
, char **ret
) {
178 /* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of
179 * additional codes (which are likely not suitable for unescaped inclusion in unit names):
181 * %f: the unescaped instance if set, otherwise the id unescaped as path
183 * %c: cgroup path of unit (deprecated)
184 * %r: where units in this slice are placed in the cgroup tree (deprecated)
185 * %R: the root of this systemd's instance tree (deprecated)
187 * %C: the cache directory root (e.g. /var/cache or $XDG_CACHE_HOME)
188 * %d: the credentials directory ($CREDENTIALS_DIRECTORY)
189 * %D: the shared data root (e.g. /usr/share or $XDG_DATA_HOME)
190 * %E: the configuration directory root (e.g. /etc or $XDG_CONFIG_HOME)
191 * %L: the log directory root (e.g. /var/log or $XDG_STATE_HOME/log)
192 * %S: the state directory root (e.g. /var/lib or $XDG_STATE_HOME)
193 * %t: the runtime directory root (e.g. /run or $XDG_RUNTIME_DIR)
195 * %h: the homedir of the running user
196 * %s: the shell of the running user
198 * NOTICE: When you add new entries here, please be careful: specifiers which depend on settings of
199 * the unit file itself are broken by design, as they would resolve differently depending on whether
200 * they are used before or after the relevant configuration setting. Hence: don't add them.
207 const Specifier table
[] = {
208 { 'i', specifier_string
, u
->instance
},
209 { 'I', specifier_instance_unescaped
, NULL
},
210 { 'j', specifier_last_component
, NULL
},
211 { 'J', specifier_last_component_unescaped
, NULL
},
212 { 'n', specifier_string
, u
->id
},
213 { 'N', specifier_prefix_and_instance
, NULL
},
214 { 'p', specifier_prefix
, NULL
},
215 { 'P', specifier_prefix_unescaped
, NULL
},
217 { 'f', specifier_filename
, NULL
},
218 { 'y', specifier_real_path
, u
->fragment_path
},
219 { 'Y', specifier_real_directory
, u
->fragment_path
},
221 { 'c', specifier_cgroup
, NULL
}, /* deprecated, see 1b89b0c499cd4bf0ff389caab4ecaae6e75f9d4e */
222 { 'r', specifier_cgroup_slice
, NULL
}, /* deprecated, see 1b89b0c499cd4bf0ff389caab4ecaae6e75f9d4e */
223 { 'R', specifier_cgroup_root
, NULL
}, /* deprecated, see 1b89b0c499cd4bf0ff389caab4ecaae6e75f9d4e */
225 { 'C', specifier_special_directory
, UINT_TO_PTR(EXEC_DIRECTORY_CACHE
) },
226 { 'd', specifier_credentials_dir
, NULL
},
227 { 'D', specifier_shared_data_dir
, NULL
},
228 { 'E', specifier_special_directory
, UINT_TO_PTR(EXEC_DIRECTORY_CONFIGURATION
) },
229 { 'L', specifier_special_directory
, UINT_TO_PTR(EXEC_DIRECTORY_LOGS
) },
230 { 'S', specifier_special_directory
, UINT_TO_PTR(EXEC_DIRECTORY_STATE
) },
231 { 't', specifier_special_directory
, UINT_TO_PTR(EXEC_DIRECTORY_RUNTIME
) },
233 { 'h', specifier_user_home
, NULL
},
234 { 's', specifier_user_shell
, NULL
},
236 COMMON_SYSTEM_SPECIFIERS
,
238 COMMON_CREDS_SPECIFIERS(u
->manager
->runtime_scope
),
240 COMMON_TMP_SPECIFIERS
,
244 return specifier_printf(format
, max_length
, table
, NULL
, u
, ret
);
247 int unit_full_printf(const Unit
*u
, const char *text
, char **ret
) {
248 return unit_full_printf_full(u
, text
, LONG_LINE_MAX
, ret
);
251 int unit_path_printf(const Unit
*u
, const char *text
, char **ret
) {
252 return unit_full_printf_full(u
, text
, PATH_MAX
-1, ret
);
255 int unit_fd_printf(const Unit
*u
, const char *text
, char **ret
) {
256 return unit_full_printf_full(u
, text
, FDNAME_MAX
, ret
);
259 int unit_cred_printf(const Unit
*u
, const char *text
, char **ret
) {
260 return unit_full_printf_full(u
, text
, CREDENTIAL_NAME_MAX
, ret
);
263 int unit_env_printf(const Unit
*u
, const char *text
, char **ret
) {
264 return unit_full_printf_full(u
, text
, sc_arg_max(), ret
);