]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/escape/escape.c
tree-wide: beautify remaining copyright statements
[thirdparty/systemd.git] / src / escape / escape.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b1a5a998 2/***
96b2fb93 3 Copyright © 2014 Michael Biebl
b1a5a998
MB
4***/
5
3f6fd1ba 6#include <getopt.h>
b1a5a998
MB
7#include <stdio.h>
8#include <stdlib.h>
9
b5efdb8a 10#include "alloc-util.h"
b1a5a998 11#include "log.h"
07630cea 12#include "string-util.h"
a1948c7b 13#include "strv.h"
3f6fd1ba 14#include "unit-name.h"
b1a5a998 15
a1948c7b
LP
16static enum {
17 ACTION_ESCAPE,
18 ACTION_UNESCAPE,
19 ACTION_MANGLE
20} arg_action = ACTION_ESCAPE;
21static const char *arg_suffix = NULL;
22static const char *arg_template = NULL;
23static bool arg_path = false;
24
601185b4 25static void help(void) {
a1948c7b 26 printf("%s [OPTIONS...] [NAME...]\n\n"
ab7e3ef5 27 "Escape strings for usage in systemd unit names.\n\n"
a1948c7b
LP
28 " -h --help Show this help\n"
29 " --version Show package version\n"
30 " --suffix=SUFFIX Unit suffix to append to escaped strings\n"
31 " --template=TEMPLATE Insert strings as instance into template\n"
32 " -u --unescape Unescape strings\n"
33 " -m --mangle Mangle strings\n"
601185b4
ZJS
34 " -p --path When escaping/unescaping assume the string is a path\n"
35 , program_invocation_short_name);
a1948c7b
LP
36}
37
38static int parse_argv(int argc, char *argv[]) {
39
40 enum {
41 ARG_VERSION = 0x100,
42 ARG_SUFFIX,
43 ARG_TEMPLATE
44 };
45
46 static const struct option options[] = {
47 { "help", no_argument, NULL, 'h' },
48 { "version", no_argument, NULL, ARG_VERSION },
49 { "suffix", required_argument, NULL, ARG_SUFFIX },
50 { "template", required_argument, NULL, ARG_TEMPLATE },
51 { "unescape", no_argument, NULL, 'u' },
52 { "mangle", no_argument, NULL, 'm' },
53 { "path", no_argument, NULL, 'p' },
54 {}
55 };
56
57 int c;
58
59 assert(argc >= 0);
60 assert(argv);
61
601185b4 62 while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0)
a1948c7b
LP
63
64 switch (c) {
65
66 case 'h':
601185b4
ZJS
67 help();
68 return 0;
a1948c7b
LP
69
70 case ARG_VERSION:
3f6fd1ba 71 return version();
a1948c7b
LP
72
73 case ARG_SUFFIX:
74
75 if (unit_type_from_string(optarg) < 0) {
76 log_error("Invalid unit suffix type %s.", optarg);
77 return -EINVAL;
78 }
79
80 arg_suffix = optarg;
81 break;
82
83 case ARG_TEMPLATE:
84
7410616c 85 if (!unit_name_is_valid(optarg, UNIT_NAME_TEMPLATE)) {
a1948c7b
LP
86 log_error("Template name %s is not valid.", optarg);
87 return -EINVAL;
88 }
89
90 arg_template = optarg;
91 break;
92
93 case 'u':
94 arg_action = ACTION_UNESCAPE;
95 break;
96
97 case 'm':
98 arg_action = ACTION_MANGLE;
99 break;
100
101 case 'p':
102 arg_path = true;
103 break;
104
105 case '?':
106 return -EINVAL;
107
108 default:
109 assert_not_reached("Unhandled option");
110 }
b1a5a998 111
a1948c7b
LP
112 if (optind >= argc) {
113 log_error("Not enough arguments.");
114 return -EINVAL;
b1a5a998
MB
115 }
116
a1948c7b
LP
117 if (arg_template && arg_suffix) {
118 log_error("--suffix= and --template= may not be combined.");
119 return -EINVAL;
120 }
121
122 if ((arg_template || arg_suffix) && arg_action != ACTION_ESCAPE) {
123 log_error("--suffix= and --template= are not compatible with --unescape or --mangle.");
124 return -EINVAL;
125 }
126
127 if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE)) {
128 log_error("--path may not be combined with --mangle.");
129 return -EINVAL;
130 }
131
132 return 1;
133}
134
135int main(int argc, char *argv[]) {
136 char **i;
137 int r;
138
139 log_parse_environment();
140 log_open();
141
142 r = parse_argv(argc, argv);
143 if (r <= 0)
144 goto finish;
145
146 STRV_FOREACH(i, argv + optind) {
147 _cleanup_free_ char *e = NULL;
148
149 switch (arg_action) {
150
151 case ACTION_ESCAPE:
7410616c
LP
152 if (arg_path) {
153 r = unit_name_path_escape(*i, &e);
154 if (r < 0) {
155 log_error_errno(r, "Failed to escape string: %m");
156 goto finish;
157 }
158 } else {
a1948c7b 159 e = unit_name_escape(*i);
7410616c
LP
160 if (!e) {
161 r = log_oom();
162 goto finish;
163 }
a1948c7b
LP
164 }
165
166 if (arg_template) {
167 char *x;
168
7410616c
LP
169 r = unit_name_replace_instance(arg_template, e, &x);
170 if (r < 0) {
171 log_error_errno(r, "Failed to replace instance: %m");
a1948c7b
LP
172 goto finish;
173 }
174
175 free(e);
176 e = x;
177 } else if (arg_suffix) {
178 char *x;
179
605405c6 180 x = strjoin(e, ".", arg_suffix);
a1948c7b
LP
181 if (!x) {
182 r = log_oom();
183 goto finish;
184 }
185
186 free(e);
187 e = x;
188 }
189
190 break;
191
192 case ACTION_UNESCAPE:
193 if (arg_path)
7410616c 194 r = unit_name_path_unescape(*i, &e);
a1948c7b 195 else
7410616c 196 r = unit_name_unescape(*i, &e);
a1948c7b 197
7410616c
LP
198 if (r < 0) {
199 log_error_errno(r, "Failed to unescape string: %m");
a1948c7b
LP
200 goto finish;
201 }
202 break;
203
204 case ACTION_MANGLE:
37cbc1d5 205 r = unit_name_mangle(*i, 0, &e);
7410616c
LP
206 if (r < 0) {
207 log_error_errno(r, "Failed to mangle name: %m");
a1948c7b
LP
208 goto finish;
209 }
210 break;
211 }
212
213 if (i != argv+optind)
214 fputc(' ', stdout);
b1a5a998 215
a1948c7b 216 fputs(e, stdout);
b1a5a998
MB
217 }
218
a1948c7b 219 fputc('\n', stdout);
b1a5a998 220
a1948c7b 221finish:
ff9c82cc 222 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b1a5a998 223}