]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/escape/escape.c
Merge pull request #17823 from poettering/resolved-just-bypass
[thirdparty/systemd.git] / src / escape / escape.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <getopt.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6
7 #include "alloc-util.h"
8 #include "log.h"
9 #include "main-func.h"
10 #include "pretty-print.h"
11 #include "string-util.h"
12 #include "strv.h"
13 #include "unit-name.h"
14
15 static enum {
16 ACTION_ESCAPE,
17 ACTION_UNESCAPE,
18 ACTION_MANGLE
19 } arg_action = ACTION_ESCAPE;
20 static const char *arg_suffix = NULL;
21 static const char *arg_template = NULL;
22 static bool arg_path = false;
23 static bool arg_instance = false;
24
25 static int help(void) {
26 _cleanup_free_ char *link = NULL;
27 int r;
28
29 r = terminal_urlify_man("systemd-escape", "1", &link);
30 if (r < 0)
31 return log_oom();
32
33 printf("%s [OPTIONS...] [NAME...]\n\n"
34 "Escape strings for usage in systemd unit names.\n\n"
35 " -h --help Show this help\n"
36 " --version Show package version\n"
37 " --suffix=SUFFIX Unit suffix to append to escaped strings\n"
38 " --template=TEMPLATE Insert strings as instance into template\n"
39 " --instance With --unescape, show just the instance part\n"
40 " -u --unescape Unescape strings\n"
41 " -m --mangle Mangle strings\n"
42 " -p --path When escaping/unescaping assume the string is a path\n"
43 "\nSee the %s for details.\n",
44 program_invocation_short_name,
45 link);
46
47 return 0;
48 }
49
50 static int parse_argv(int argc, char *argv[]) {
51
52 enum {
53 ARG_VERSION = 0x100,
54 ARG_SUFFIX,
55 ARG_TEMPLATE
56 };
57
58 static const struct option options[] = {
59 { "help", no_argument, NULL, 'h' },
60 { "version", no_argument, NULL, ARG_VERSION },
61 { "suffix", required_argument, NULL, ARG_SUFFIX },
62 { "template", required_argument, NULL, ARG_TEMPLATE },
63 { "unescape", no_argument, NULL, 'u' },
64 { "mangle", no_argument, NULL, 'm' },
65 { "path", no_argument, NULL, 'p' },
66 { "instance", no_argument, NULL, 'i' },
67 {}
68 };
69
70 int c;
71
72 assert(argc >= 0);
73 assert(argv);
74
75 while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0)
76
77 switch (c) {
78
79 case 'h':
80 return help();
81
82 case ARG_VERSION:
83 return version();
84
85 case ARG_SUFFIX: {
86 UnitType t = unit_type_from_string(optarg);
87 if (t < 0)
88 return log_error_errno(t, "Invalid unit suffix type \"%s\".", optarg);
89
90 arg_suffix = optarg;
91 break;
92 }
93
94 case ARG_TEMPLATE:
95 if (!unit_name_is_valid(optarg, UNIT_NAME_TEMPLATE))
96 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
97 "Template name %s is not valid.", optarg);
98
99 arg_template = optarg;
100 break;
101
102 case 'u':
103 arg_action = ACTION_UNESCAPE;
104 break;
105
106 case 'm':
107 arg_action = ACTION_MANGLE;
108 break;
109
110 case 'p':
111 arg_path = true;
112 break;
113
114 case 'i':
115 arg_instance = true;
116 break;
117
118 case '?':
119 return -EINVAL;
120
121 default:
122 assert_not_reached("Unhandled option");
123 }
124
125 if (optind >= argc)
126 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
127 "Not enough arguments.");
128
129 if (arg_template && arg_suffix)
130 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
131 "--suffix= and --template= may not be combined.");
132
133 if ((arg_template || arg_suffix) && arg_action == ACTION_MANGLE)
134 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
135 "--suffix= and --template= are not compatible with --mangle.");
136
137 if (arg_suffix && arg_action == ACTION_UNESCAPE)
138 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
139 "--suffix is not compatible with --unescape.");
140
141 if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE))
142 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
143 "--path may not be combined with --mangle.");
144
145 if (arg_instance && arg_action != ACTION_UNESCAPE)
146 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
147 "--instance must be used in conjunction with --unescape.");
148
149 if (arg_instance && arg_template)
150 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
151 "--instance may not be combined with --template.");
152
153 return 1;
154 }
155
156 static int run(int argc, char *argv[]) {
157 char **i;
158 int r;
159
160 log_setup();
161
162 r = parse_argv(argc, argv);
163 if (r <= 0)
164 return r;
165
166 STRV_FOREACH(i, argv + optind) {
167 _cleanup_free_ char *e = NULL;
168
169 switch (arg_action) {
170
171 case ACTION_ESCAPE:
172 if (arg_path) {
173 r = unit_name_path_escape(*i, &e);
174 if (r < 0)
175 return log_error_errno(r, "Failed to escape string: %m");
176 } else {
177 e = unit_name_escape(*i);
178 if (!e)
179 return log_oom();
180 }
181
182 if (arg_template) {
183 char *x;
184
185 r = unit_name_replace_instance(arg_template, e, &x);
186 if (r < 0)
187 return log_error_errno(r, "Failed to replace instance: %m");
188
189 free_and_replace(e, x);
190 } else if (arg_suffix) {
191 char *x;
192
193 x = strjoin(e, ".", arg_suffix);
194 if (!x)
195 return log_oom();
196
197 free_and_replace(e, x);
198 }
199
200 break;
201
202 case ACTION_UNESCAPE: {
203 _cleanup_free_ char *name = NULL;
204
205 if (arg_template || arg_instance) {
206 _cleanup_free_ char *template = NULL;
207
208 r = unit_name_to_instance(*i, &name);
209 if (r < 0)
210 return log_error_errno(r, "Failed to extract instance: %m");
211 if (isempty(name))
212 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
213 "Unit %s is missing the instance name.", *i);
214
215 r = unit_name_template(*i, &template);
216 if (r < 0)
217 return log_error_errno(r, "Failed to extract template: %m");
218 if (arg_template && !streq(arg_template, template))
219 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
220 "Unit %s template %s does not match specified template %s.",
221 *i, template, arg_template);
222 } else {
223 name = strdup(*i);
224 if (!name)
225 return log_oom();
226 }
227
228 if (arg_path)
229 r = unit_name_path_unescape(name, &e);
230 else
231 r = unit_name_unescape(name, &e);
232 if (r < 0)
233 return log_error_errno(r, "Failed to unescape string: %m");
234
235 break;
236 }
237
238 case ACTION_MANGLE:
239 r = unit_name_mangle(*i, 0, &e);
240 if (r < 0)
241 return log_error_errno(r, "Failed to mangle name: %m");
242
243 break;
244 }
245
246 if (i != argv + optind)
247 fputc(' ', stdout);
248
249 fputs(e, stdout);
250 }
251
252 fputc('\n', stdout);
253
254 return 0;
255 }
256
257 DEFINE_MAIN_FUNCTION(run);