]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/escape/escape.c
escape: beef up new systemd-escape tool
[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 <stdio.h>
23 #include <stdlib.h>
24 #include <getopt.h>
25
26 #include "log.h"
27 #include "unit-name.h"
28 #include "build.h"
29 #include "strv.h"
30
31 static enum {
32 ACTION_ESCAPE,
33 ACTION_UNESCAPE,
34 ACTION_MANGLE
35 } arg_action = ACTION_ESCAPE;
36 static const char *arg_suffix = NULL;
37 static const char *arg_template = NULL;
38 static bool arg_path = false;
39
40 static int help(void) {
41
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 return 0;
54 }
55
56 static int parse_argv(int argc, char *argv[]) {
57
58 enum {
59 ARG_VERSION = 0x100,
60 ARG_SUFFIX,
61 ARG_TEMPLATE
62 };
63
64 static const struct option options[] = {
65 { "help", no_argument, NULL, 'h' },
66 { "version", no_argument, NULL, ARG_VERSION },
67 { "suffix", required_argument, NULL, ARG_SUFFIX },
68 { "template", required_argument, NULL, ARG_TEMPLATE },
69 { "unescape", no_argument, NULL, 'u' },
70 { "mangle", no_argument, NULL, 'm' },
71 { "path", no_argument, NULL, 'p' },
72 {}
73 };
74
75 int c;
76
77 assert(argc >= 0);
78 assert(argv);
79
80 while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0) {
81
82 switch (c) {
83
84 case 'h':
85 return help();
86
87 case ARG_VERSION:
88 puts(PACKAGE_STRING);
89 puts(SYSTEMD_FEATURES);
90 return 0;
91
92 case ARG_SUFFIX:
93
94 if (unit_type_from_string(optarg) < 0) {
95 log_error("Invalid unit suffix type %s.", optarg);
96 return -EINVAL;
97 }
98
99 arg_suffix = optarg;
100 break;
101
102 case ARG_TEMPLATE:
103
104 if (!unit_name_is_valid(optarg, true) || !unit_name_is_template(optarg)) {
105 log_error("Template name %s is not valid.", optarg);
106 return -EINVAL;
107 }
108
109 arg_template = optarg;
110 break;
111
112 case 'u':
113 arg_action = ACTION_UNESCAPE;
114 break;
115
116 case 'm':
117 arg_action = ACTION_MANGLE;
118 break;
119
120 case 'p':
121 arg_path = true;
122 break;
123
124 case '?':
125 return -EINVAL;
126
127 default:
128 assert_not_reached("Unhandled option");
129 }
130 }
131
132 if (optind >= argc) {
133 log_error("Not enough arguments.");
134 return -EINVAL;
135 }
136
137 if (arg_template && arg_suffix) {
138 log_error("--suffix= and --template= may not be combined.");
139 return -EINVAL;
140 }
141
142 if ((arg_template || arg_suffix) && arg_action != ACTION_ESCAPE) {
143 log_error("--suffix= and --template= are not compatible with --unescape or --mangle.");
144 return -EINVAL;
145 }
146
147 if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE)) {
148 log_error("--path may not be combined with --mangle.");
149 return -EINVAL;
150 }
151
152 return 1;
153 }
154
155 int main(int argc, char *argv[]) {
156 char **i;
157 int r;
158
159 log_parse_environment();
160 log_open();
161
162 r = parse_argv(argc, argv);
163 if (r <= 0)
164 goto finish;
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 e = unit_name_path_escape(*i);
174 else
175 e = unit_name_escape(*i);
176
177 if (!e) {
178 r = log_oom();
179 goto finish;
180 }
181
182 if (arg_template) {
183 char *x;
184
185 x = unit_name_replace_instance(arg_template, e);
186 if (!x) {
187 r = log_oom();
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 e = unit_name_path_unescape(*i);
211 else
212 e = unit_name_unescape(*i);
213
214 if (!e) {
215 r = log_oom();
216 goto finish;
217 }
218 break;
219
220 case ACTION_MANGLE:
221 e = unit_name_mangle(*i, MANGLE_NOGLOB);
222 if (!e) {
223 r = log_oom();
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 ? EXIT_FAILURE : EXIT_SUCCESS;
239 }