From: Lennart Poettering Date: Mon, 7 Jul 2014 20:23:00 +0000 (+0200) Subject: escape: beef up new systemd-escape tool X-Git-Tag: v216~715 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=a1948c7bfeb87b54bc7715a44490c01593ee6e23 escape: beef up new systemd-escape tool Add various options for making it easy unescape, or mangle, or format as template instance or append a suffix. --- diff --git a/.gitignore b/.gitignore index e3ddbf8d3..52b78ae19 100644 --- a/.gitignore +++ b/.gitignore @@ -64,6 +64,7 @@ /systemd-delta /systemd-detect-virt /systemd-efi-boot-generator +/systemd-escape /systemd-firstboot /systemd-fsck /systemd-fstab-generator diff --git a/src/escape/Makefile b/src/escape/Makefile new file mode 120000 index 000000000..d0b0e8e00 --- /dev/null +++ b/src/escape/Makefile @@ -0,0 +1 @@ +../Makefile \ No newline at end of file diff --git a/src/escape/escape.c b/src/escape/escape.c index 0a59a05e2..ae0c183ec 100644 --- a/src/escape/escape.c +++ b/src/escape/escape.c @@ -21,26 +21,219 @@ #include #include +#include #include "log.h" #include "unit-name.h" +#include "build.h" +#include "strv.h" -int main(int argc, char *argv[]) { - char *escaped_name = NULL; +static enum { + ACTION_ESCAPE, + ACTION_UNESCAPE, + ACTION_MANGLE +} arg_action = ACTION_ESCAPE; +static const char *arg_suffix = NULL; +static const char *arg_template = NULL; +static bool arg_path = false; + +static int help(void) { + + printf("%s [OPTIONS...] [NAME...]\n\n" + "Show system and user paths.\n\n" + " -h --help Show this help\n" + " --version Show package version\n" + " --suffix=SUFFIX Unit suffix to append to escaped strings\n" + " --template=TEMPLATE Insert strings as instance into template\n" + " -u --unescape Unescape strings\n" + " -m --mangle Mangle strings\n" + " -p --path When escaping/unescaping assume the string is a path\n", + program_invocation_short_name); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_VERSION = 0x100, + ARG_SUFFIX, + ARG_TEMPLATE + }; + + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "suffix", required_argument, NULL, ARG_SUFFIX }, + { "template", required_argument, NULL, ARG_TEMPLATE }, + { "unescape", no_argument, NULL, 'u' }, + { "mangle", no_argument, NULL, 'm' }, + { "path", no_argument, NULL, 'p' }, + {} + }; + + int c; + + assert(argc >= 0); + assert(argv); + + while ((c = getopt_long(argc, argv, "hump", options, NULL)) >= 0) { + + switch (c) { + + case 'h': + return help(); + + case ARG_VERSION: + puts(PACKAGE_STRING); + puts(SYSTEMD_FEATURES); + return 0; + + case ARG_SUFFIX: + + if (unit_type_from_string(optarg) < 0) { + log_error("Invalid unit suffix type %s.", optarg); + return -EINVAL; + } + + arg_suffix = optarg; + break; + + case ARG_TEMPLATE: + + if (!unit_name_is_valid(optarg, true) || !unit_name_is_template(optarg)) { + log_error("Template name %s is not valid.", optarg); + return -EINVAL; + } + + arg_template = optarg; + break; + + case 'u': + arg_action = ACTION_UNESCAPE; + break; + + case 'm': + arg_action = ACTION_MANGLE; + break; + + case 'p': + arg_path = true; + break; + + case '?': + return -EINVAL; + + default: + assert_not_reached("Unhandled option"); + } + } - if (argc != 2) { - log_error("This program requires on argument."); - return EXIT_FAILURE; + if (optind >= argc) { + log_error("Not enough arguments."); + return -EINVAL; } - escaped_name = unit_name_escape(argv[1]); + if (arg_template && arg_suffix) { + log_error("--suffix= and --template= may not be combined."); + return -EINVAL; + } + + if ((arg_template || arg_suffix) && arg_action != ACTION_ESCAPE) { + log_error("--suffix= and --template= are not compatible with --unescape or --mangle."); + return -EINVAL; + } + + if (arg_path && !IN_SET(arg_action, ACTION_ESCAPE, ACTION_UNESCAPE)) { + log_error("--path may not be combined with --mangle."); + return -EINVAL; + } + + return 1; +} + +int main(int argc, char *argv[]) { + char **i; + int r; + + log_parse_environment(); + log_open(); + + r = parse_argv(argc, argv); + if (r <= 0) + goto finish; + + STRV_FOREACH(i, argv + optind) { + _cleanup_free_ char *e = NULL; + + switch (arg_action) { + + case ACTION_ESCAPE: + if (arg_path) + e = unit_name_path_escape(*i); + else + e = unit_name_escape(*i); + + if (!e) { + r = log_oom(); + goto finish; + } + + if (arg_template) { + char *x; + + x = unit_name_replace_instance(arg_template, e); + if (!x) { + r = log_oom(); + goto finish; + } + + free(e); + e = x; + } else if (arg_suffix) { + char *x; + + x = strjoin(e, ".", arg_suffix, NULL); + if (!x) { + r = log_oom(); + goto finish; + } + + free(e); + e = x; + } + + break; + + case ACTION_UNESCAPE: + if (arg_path) + e = unit_name_path_unescape(*i); + else + e = unit_name_unescape(*i); + + if (!e) { + r = log_oom(); + goto finish; + } + break; + + case ACTION_MANGLE: + e = unit_name_mangle(*i, MANGLE_NOGLOB); + if (!e) { + r = log_oom(); + goto finish; + } + break; + } + + if (i != argv+optind) + fputc(' ', stdout); - if (!escaped_name) { - log_error("Failed to escape name."); - return EXIT_FAILURE; + fputs(e, stdout); } - printf("%s", escaped_name); + fputc('\n', stdout); - return EXIT_SUCCESS; +finish: + return r ? EXIT_FAILURE : EXIT_SUCCESS; }