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