From a699513cfc3e3f318b1cd4cfb85324021864975b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Holger=20Wei=C3=9F?= Date: Thu, 1 Aug 2013 23:02:48 +0200 Subject: [PATCH] Teach the client about backslash escape sequences Let send_nsca(8)'s "-d" and "-e" flags accept C-style escape sequences, so that e.g. "-e '\n'" can be specified. Octal numbers with a leading zero and hexadecimal numbers prefixed with "0x" are also accepted. --- man/send_nsca.in | 8 +++-- src/client/send_nsca.c | 82 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/man/send_nsca.in b/man/send_nsca.in index 8ed1478..bc21ca2 100644 --- a/man/send_nsca.in +++ b/man/send_nsca.in @@ -148,7 +148,9 @@ instead of a horizontal tab to separate the fields when parsing host or service check results. The .I delimiter -must be a single character. +must be a single character, a C-style backslash escape sequence, the +octal value of a character with a leading zero, or the hexadecimal value +of a character prefixed with \(lq0x\(rq. Any .SM ASCII character other than a backslash, newline, @@ -170,7 +172,9 @@ instead of an character to separate multiple host or service check results. The .I separator -must be a single character. +must be a single character, a C-style backslash escape sequence, the +octal value of a character with a leading zero, or the hexadecimal value +of a character prefixed with \(lq0x\(rq. Any .SM ASCII character is allowed, but note that multiline check result messages diff --git a/src/client/send_nsca.c b/src/client/send_nsca.c index 1c06fe8..f986ad5 100644 --- a/src/client/send_nsca.c +++ b/src/client/send_nsca.c @@ -29,9 +29,11 @@ # include #endif +#include #if HAVE_INTTYPES_H # include #endif +#include #include #include #include @@ -69,6 +71,7 @@ int exit_code = EXIT_SUCCESS; static options *get_options(int, char **); static void free_options(options *); +static int parse_backslash_escape(const char *); static void delay_execution(unsigned int); static unsigned long random_number(unsigned long); static void forget_config(void); @@ -155,7 +158,9 @@ get_options(int argc, char **argv) } } - while ((option = getopt(argc, argv, "Cc:D:d:e:H:ho:p:SstVv")) != -1) + while ((option = getopt(argc, argv, "Cc:D:d:e:H:ho:p:SstVv")) != -1) { + int character; + switch (option) { case 'C': opt->raw_commands = true; @@ -171,18 +176,19 @@ get_options(int argc, char **argv) die("-D argument must be a positive integer"); break; case 'd': - if (strlen(optarg) != 1) + if ((character = parse_backslash_escape(optarg)) == EOF) die("-d argument must be a single character"); - if (*optarg == '\27' - || *optarg == '\n' - || *optarg == '\\') + if (character == '\27' + || character == '\n' + || character == '\0' + || character == '\\') die("Illegal delimiter specified with -d"); - opt->delimiter = *optarg; + opt->delimiter = (char)character; break; case 'e': - if (strlen(optarg) != 1) + if ((character = parse_backslash_escape(optarg)) == EOF) die("-e argument must be a single character"); - opt->separator = *optarg; + opt->separator = (char)character; break; case 'H': if (opt->server != NULL) @@ -226,7 +232,7 @@ get_options(int argc, char **argv) default: usage(EXIT_FAILURE); } - + } if (opt->delimiter == opt->separator) die("Field delimiter must be different from record separator"); if (argc - optind > 0) @@ -248,6 +254,64 @@ free_options(options *opt) free(opt); } +static int +parse_backslash_escape(const char *sequence) +{ + char numeric[6]; /* Space for "0x345". */ + + switch (strlen(sequence)) { + case 1: + return (unsigned char)sequence[0]; + case 2: + if (sequence[0] == '\\') + switch (sequence[1]) { + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + case 'v': + return '\v'; + case 'x': /* Fall through. */ + case '0': + break; + default: + return (unsigned char)sequence[1]; + } + /* Otherwise, fall through. */ + case 3: /* Fall through. */ + case 4: /* Fall through. */ + case 5: + /* + * We support octal numbers with a leading zero and hexadecimal + * numbers prefixed with "0x" in addition to numeric backslash + * escape sequences. + */ + if (sequence[0] == '0' || sequence[0] == '\\') { + char *end; + long value; + + (void)strcpy(numeric, sequence); + if (numeric[0] == '\\') /* \x42 -> 0x42 */ + numeric[0] = '0'; + value = strtol(numeric, &end, 0); + if (*end == '\0' && value >= 0 && value <= CHAR_MAX) + return (unsigned char)value; + /* Otherwise, fall through. */ + } + /* Otherwise, fall through. */ + default: + return EOF; + } +} + static void delay_execution(unsigned int max_delay) { -- 2.11.4.GIT