chiark / gitweb /
sd-dhcp6-client: support custom DUIDs
[elogind.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, true) || !unit_name_is_template(optarg)) {
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                                 e = unit_name_path_escape(*i);
171                         else
172                                 e = unit_name_escape(*i);
173
174                         if (!e) {
175                                 r = log_oom();
176                                 goto finish;
177                         }
178
179                         if (arg_template) {
180                                 char *x;
181
182                                 x = unit_name_replace_instance(arg_template, e);
183                                 if (!x) {
184                                         r = log_oom();
185                                         goto finish;
186                                 }
187
188                                 free(e);
189                                 e = x;
190                         } else if (arg_suffix) {
191                                 char *x;
192
193                                 x = strjoin(e, ".", arg_suffix, NULL);
194                                 if (!x) {
195                                         r = log_oom();
196                                         goto finish;
197                                 }
198
199                                 free(e);
200                                 e = x;
201                         }
202
203                         break;
204
205                 case ACTION_UNESCAPE:
206                         if (arg_path)
207                                 e = unit_name_path_unescape(*i);
208                         else
209                                 e = unit_name_unescape(*i);
210
211                         if (!e) {
212                                 r = log_oom();
213                                 goto finish;
214                         }
215                         break;
216
217                 case ACTION_MANGLE:
218                         e = unit_name_mangle(*i, MANGLE_NOGLOB);
219                         if (!e) {
220                                 r = log_oom();
221                                 goto finish;
222                         }
223                         break;
224                 }
225
226                 if (i != argv+optind)
227                         fputc(' ', stdout);
228
229                 fputs(e, stdout);
230         }
231
232         fputc('\n', stdout);
233
234 finish:
235         return r <= 0 ? EXIT_FAILURE : EXIT_SUCCESS;
236 }