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