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