]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/escape/escape.c
dhcp6-option: Add helper function for uncompressed domain names
[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 void help(void) {
41 printf("%s [OPTIONS...] [NAME...]\n\n"
42 "Show system and user paths.\n\n"
43 " -h --help Show this help\n"
44 " --version Show package version\n"
45 " --suffix=SUFFIX Unit suffix to append to escaped strings\n"
46 " --template=TEMPLATE Insert strings as instance into template\n"
47 " -u --unescape Unescape strings\n"
48 " -m --mangle Mangle strings\n"
49 " -p --path When escaping/unescaping assume the string is a path\n"
50 , program_invocation_short_name);
51 }
52
53 static int parse_argv(int argc, char *argv[]) {
54
55 enum {
56 ARG_VERSION = 0x100,
57 ARG_SUFFIX,
58 ARG_TEMPLATE
59 };
60
61 static const struct option options[] = {
62 { "help", no_argument, NULL, 'h' },
63 { "version", no_argument, NULL, ARG_VERSION },
64 { "suffix", required_argument, NULL, ARG_SUFFIX },
65 { "template", required_argument, NULL, ARG_TEMPLATE },
66 { "unescape", no_argument, NULL, 'u' },
67 { "mangle", no_argument, NULL, 'm' },
68 { "path", no_argument, NULL, 'p' },
69 {}
70 };
71
72 int c;
73
74 assert(argc >= 0);
75 assert(argv);
76
77 while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0)
78
79 switch (c) {
80
81 case 'h':
82 help();
83 return 0;
84
85 case ARG_VERSION:
86 puts(PACKAGE_STRING);
87 puts(SYSTEMD_FEATURES);
88 return 0;
89
90 case ARG_SUFFIX:
91
92 if (unit_type_from_string(optarg) < 0) {
93 log_error("Invalid unit suffix type %s.", optarg);
94 return -EINVAL;
95 }
96
97 arg_suffix = optarg;
98 break;
99
100 case ARG_TEMPLATE:
101
102 if (!unit_name_is_valid(optarg, UNIT_NAME_TEMPLATE)) {
103 log_error("Template name %s is not valid.", optarg);
104 return -EINVAL;
105 }
106
107 arg_template = optarg;
108 break;
109
110 case 'u':
111 arg_action = ACTION_UNESCAPE;
112 break;
113
114 case 'm':
115 arg_action = ACTION_MANGLE;
116 break;
117
118 case 'p':
119 arg_path = true;
120 break;
121
122 case '?':
123 return -EINVAL;
124
125 default:
126 assert_not_reached("Unhandled option");
127 }
128
129 if (optind >= argc) {
130 log_error("Not enough arguments.");
131 return -EINVAL;
132 }
133
134 if (arg_template && arg_suffix) {
135 log_error("--suffix= and --template= may not be combined.");
136 return -EINVAL;
137 }
138
139 if ((arg_template || arg_suffix) && arg_action != ACTION_ESCAPE) {
140 log_error("--suffix= and --template= are not compatible with --unescape or --mangle.");
141 return -EINVAL;
142 }
143
144 if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE)) {
145 log_error("--path may not be combined with --mangle.");
146 return -EINVAL;
147 }
148
149 return 1;
150 }
151
152 int main(int argc, char *argv[]) {
153 char **i;
154 int r;
155
156 log_parse_environment();
157 log_open();
158
159 r = parse_argv(argc, argv);
160 if (r <= 0)
161 goto finish;
162
163 STRV_FOREACH(i, argv + optind) {
164 _cleanup_free_ char *e = NULL;
165
166 switch (arg_action) {
167
168 case ACTION_ESCAPE:
169 if (arg_path) {
170 r = unit_name_path_escape(*i, &e);
171 if (r < 0) {
172 log_error_errno(r, "Failed to escape string: %m");
173 goto finish;
174 }
175 } else {
176 e = unit_name_escape(*i);
177 if (!e) {
178 r = log_oom();
179 goto finish;
180 }
181 }
182
183 if (arg_template) {
184 char *x;
185
186 r = unit_name_replace_instance(arg_template, e, &x);
187 if (r < 0) {
188 log_error_errno(r, "Failed to replace instance: %m");
189 goto finish;
190 }
191
192 free(e);
193 e = x;
194 } else if (arg_suffix) {
195 char *x;
196
197 x = strjoin(e, ".", arg_suffix, NULL);
198 if (!x) {
199 r = log_oom();
200 goto finish;
201 }
202
203 free(e);
204 e = x;
205 }
206
207 break;
208
209 case ACTION_UNESCAPE:
210 if (arg_path)
211 r = unit_name_path_unescape(*i, &e);
212 else
213 r = unit_name_unescape(*i, &e);
214
215 if (r < 0) {
216 log_error_errno(r, "Failed to unescape string: %m");
217 goto finish;
218 }
219 break;
220
221 case ACTION_MANGLE:
222 r = unit_name_mangle(*i, UNIT_NAME_NOGLOB, &e);
223 if (r < 0) {
224 log_error_errno(r, "Failed to mangle name: %m");
225 goto finish;
226 }
227 break;
228 }
229
230 if (i != argv+optind)
231 fputc(' ', stdout);
232
233 fputs(e, stdout);
234 }
235
236 fputc('\n', stdout);
237
238 finish:
239 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
240 }