]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/escape/escape.c
Merge pull request #1406 from blaskovic/journal-remote-typo
[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 "log.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 }