]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/escape/escape.c
Merge pull request #1695 from evverx/fix-cap-bounding-merging
[thirdparty/systemd.git] / src / escape / escape.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2014 Michael Biebl
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <getopt.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "alloc-util.h"
27 #include "log.h"
28 #include "string-util.h"
29 #include "strv.h"
30 #include "unit-name.h"
31
32 static enum {
33 ACTION_ESCAPE,
34 ACTION_UNESCAPE,
35 ACTION_MANGLE
36 } arg_action = ACTION_ESCAPE;
37 static const char *arg_suffix = NULL;
38 static const char *arg_template = NULL;
39 static bool arg_path = false;
40
41 static void help(void) {
42 printf("%s [OPTIONS...] [NAME...]\n\n"
43 "Show system and user paths.\n\n"
44 " -h --help Show this help\n"
45 " --version Show package version\n"
46 " --suffix=SUFFIX Unit suffix to append to escaped strings\n"
47 " --template=TEMPLATE Insert strings as instance into template\n"
48 " -u --unescape Unescape strings\n"
49 " -m --mangle Mangle strings\n"
50 " -p --path When escaping/unescaping assume the string is a path\n"
51 , program_invocation_short_name);
52 }
53
54 static int parse_argv(int argc, char *argv[]) {
55
56 enum {
57 ARG_VERSION = 0x100,
58 ARG_SUFFIX,
59 ARG_TEMPLATE
60 };
61
62 static const struct option options[] = {
63 { "help", no_argument, NULL, 'h' },
64 { "version", no_argument, NULL, ARG_VERSION },
65 { "suffix", required_argument, NULL, ARG_SUFFIX },
66 { "template", required_argument, NULL, ARG_TEMPLATE },
67 { "unescape", no_argument, NULL, 'u' },
68 { "mangle", no_argument, NULL, 'm' },
69 { "path", no_argument, NULL, 'p' },
70 {}
71 };
72
73 int c;
74
75 assert(argc >= 0);
76 assert(argv);
77
78 while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0)
79
80 switch (c) {
81
82 case 'h':
83 help();
84 return 0;
85
86 case ARG_VERSION:
87 return version();
88
89 case ARG_SUFFIX:
90
91 if (unit_type_from_string(optarg) < 0) {
92 log_error("Invalid unit suffix type %s.", optarg);
93 return -EINVAL;
94 }
95
96 arg_suffix = optarg;
97 break;
98
99 case ARG_TEMPLATE:
100
101 if (!unit_name_is_valid(optarg, UNIT_NAME_TEMPLATE)) {
102 log_error("Template name %s is not valid.", optarg);
103 return -EINVAL;
104 }
105
106 arg_template = optarg;
107 break;
108
109 case 'u':
110 arg_action = ACTION_UNESCAPE;
111 break;
112
113 case 'm':
114 arg_action = ACTION_MANGLE;
115 break;
116
117 case 'p':
118 arg_path = true;
119 break;
120
121 case '?':
122 return -EINVAL;
123
124 default:
125 assert_not_reached("Unhandled option");
126 }
127
128 if (optind >= argc) {
129 log_error("Not enough arguments.");
130 return -EINVAL;
131 }
132
133 if (arg_template && arg_suffix) {
134 log_error("--suffix= and --template= may not be combined.");
135 return -EINVAL;
136 }
137
138 if ((arg_template || arg_suffix) && arg_action != ACTION_ESCAPE) {
139 log_error("--suffix= and --template= are not compatible with --unescape or --mangle.");
140 return -EINVAL;
141 }
142
143 if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE)) {
144 log_error("--path may not be combined with --mangle.");
145 return -EINVAL;
146 }
147
148 return 1;
149 }
150
151 int main(int argc, char *argv[]) {
152 char **i;
153 int r;
154
155 log_parse_environment();
156 log_open();
157
158 r = parse_argv(argc, argv);
159 if (r <= 0)
160 goto finish;
161
162 STRV_FOREACH(i, argv + optind) {
163 _cleanup_free_ char *e = NULL;
164
165 switch (arg_action) {
166
167 case ACTION_ESCAPE:
168 if (arg_path) {
169 r = unit_name_path_escape(*i, &e);
170 if (r < 0) {
171 log_error_errno(r, "Failed to escape string: %m");
172 goto finish;
173 }
174 } else {
175 e = unit_name_escape(*i);
176 if (!e) {
177 r = log_oom();
178 goto finish;
179 }
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 log_error_errno(r, "Failed to replace instance: %m");
188 goto finish;
189 }
190
191 free(e);
192 e = x;
193 } else if (arg_suffix) {
194 char *x;
195
196 x = strjoin(e, ".", arg_suffix, NULL);
197 if (!x) {
198 r = log_oom();
199 goto finish;
200 }
201
202 free(e);
203 e = x;
204 }
205
206 break;
207
208 case ACTION_UNESCAPE:
209 if (arg_path)
210 r = unit_name_path_unescape(*i, &e);
211 else
212 r = unit_name_unescape(*i, &e);
213
214 if (r < 0) {
215 log_error_errno(r, "Failed to unescape string: %m");
216 goto finish;
217 }
218 break;
219
220 case ACTION_MANGLE:
221 r = unit_name_mangle(*i, UNIT_NAME_NOGLOB, &e);
222 if (r < 0) {
223 log_error_errno(r, "Failed to mangle name: %m");
224 goto finish;
225 }
226 break;
227 }
228
229 if (i != argv+optind)
230 fputc(' ', stdout);
231
232 fputs(e, stdout);
233 }
234
235 fputc('\n', stdout);
236
237 finish:
238 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
239 }