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