]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/escape/escape.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / escape / escape.c
CommitLineData
b1a5a998
MB
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
3f6fd1ba 22#include <getopt.h>
b1a5a998
MB
23#include <stdio.h>
24#include <stdlib.h>
25
b5efdb8a 26#include "alloc-util.h"
b1a5a998 27#include "log.h"
07630cea 28#include "string-util.h"
a1948c7b 29#include "strv.h"
3f6fd1ba 30#include "unit-name.h"
b1a5a998 31
a1948c7b
LP
32static enum {
33 ACTION_ESCAPE,
34 ACTION_UNESCAPE,
35 ACTION_MANGLE
36} arg_action = ACTION_ESCAPE;
37static const char *arg_suffix = NULL;
38static const char *arg_template = NULL;
39static bool arg_path = false;
40
601185b4 41static void help(void) {
a1948c7b
LP
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"
601185b4
ZJS
50 " -p --path When escaping/unescaping assume the string is a path\n"
51 , program_invocation_short_name);
a1948c7b
LP
52}
53
54static 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
601185b4 78 while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0)
a1948c7b
LP
79
80 switch (c) {
81
82 case 'h':
601185b4
ZJS
83 help();
84 return 0;
a1948c7b
LP
85
86 case ARG_VERSION:
3f6fd1ba 87 return version();
a1948c7b
LP
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
7410616c 101 if (!unit_name_is_valid(optarg, UNIT_NAME_TEMPLATE)) {
a1948c7b
LP
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 }
b1a5a998 127
a1948c7b
LP
128 if (optind >= argc) {
129 log_error("Not enough arguments.");
130 return -EINVAL;
b1a5a998
MB
131 }
132
a1948c7b
LP
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
151int 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:
7410616c
LP
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 {
a1948c7b 175 e = unit_name_escape(*i);
7410616c
LP
176 if (!e) {
177 r = log_oom();
178 goto finish;
179 }
a1948c7b
LP
180 }
181
182 if (arg_template) {
183 char *x;
184
7410616c
LP
185 r = unit_name_replace_instance(arg_template, e, &x);
186 if (r < 0) {
187 log_error_errno(r, "Failed to replace instance: %m");
a1948c7b
LP
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)
7410616c 210 r = unit_name_path_unescape(*i, &e);
a1948c7b 211 else
7410616c 212 r = unit_name_unescape(*i, &e);
a1948c7b 213
7410616c
LP
214 if (r < 0) {
215 log_error_errno(r, "Failed to unescape string: %m");
a1948c7b
LP
216 goto finish;
217 }
218 break;
219
220 case ACTION_MANGLE:
7410616c
LP
221 r = unit_name_mangle(*i, UNIT_NAME_NOGLOB, &e);
222 if (r < 0) {
223 log_error_errno(r, "Failed to mangle name: %m");
a1948c7b
LP
224 goto finish;
225 }
226 break;
227 }
228
229 if (i != argv+optind)
230 fputc(' ', stdout);
b1a5a998 231
a1948c7b 232 fputs(e, stdout);
b1a5a998
MB
233 }
234
a1948c7b 235 fputc('\n', stdout);
b1a5a998 236
a1948c7b 237finish:
ff9c82cc 238 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b1a5a998 239}