diff options
Diffstat (limited to 'src/util/unescape.c')
-rw-r--r-- | src/util/unescape.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/src/util/unescape.c b/src/util/unescape.c new file mode 100644 index 0000000..4eacbba --- /dev/null +++ b/src/util/unescape.c @@ -0,0 +1,208 @@ +/*++ +/* NAME +/* unescape 3 +/* SUMMARY +/* translate C-like escape sequences +/* SYNOPSIS +/* #include <stringops.h> +/* +/* VSTRING *unescape(result, input) +/* VSTRING *result; +/* const char *input; +/* +/* VSTRING *escape(result, input, len) +/* VSTRING *result; +/* const char *input; +/* ssize_t len; +/* DESCRIPTION +/* unescape() translates C-like escape sequences in the null-terminated +/* string \fIinput\fR and places the result in \fIresult\fR. The result +/* is null-terminated, and is the function result value. +/* +/* escape() does the reverse transformation. +/* +/* Escape sequences and their translations: +/* .IP \ea +/* Bell character. +/* .IP \eb +/* Backspace character. +/* .IP \ef +/* formfeed character. +/* .IP \en +/* newline character +/* .IP \er +/* Carriage-return character. +/* .IP \et +/* Horizontal tab character. +/* .IP \ev +/* Vertical tab character. +/* .IP \e\e +/* Backslash character. +/* .IP \e\fInum\fR +/* 8-bit character whose ASCII value is the 1..3 digit +/* octal number \fInum\fR. +/* .IP \e\fIother\fR +/* The backslash character is discarded. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <ctype.h> + +/* Utility library. */ + +#include <vstring.h> +#include <stringops.h> + +/* unescape - process escape sequences */ + +VSTRING *unescape(VSTRING *result, const char *data) +{ + int ch; + int oval; + int i; + +#define UCHAR(cp) ((unsigned char *) (cp)) +#define ISOCTAL(ch) (ISDIGIT(ch) && (ch) != '8' && (ch) != '9') + + VSTRING_RESET(result); + + while ((ch = *UCHAR(data++)) != 0) { + if (ch == '\\') { + if ((ch = *UCHAR(data++)) == 0) + break; + switch (ch) { + case 'a': /* \a -> audible bell */ + ch = '\a'; + break; + case 'b': /* \b -> backspace */ + ch = '\b'; + break; + case 'f': /* \f -> formfeed */ + ch = '\f'; + break; + case 'n': /* \n -> newline */ + ch = '\n'; + break; + case 'r': /* \r -> carriagereturn */ + ch = '\r'; + break; + case 't': /* \t -> horizontal tab */ + ch = '\t'; + break; + case 'v': /* \v -> vertical tab */ + ch = '\v'; + break; + case '0': /* \nnn -> ASCII value */ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + for (oval = ch - '0', i = 0; + i < 2 && (ch = *UCHAR(data)) != 0 && ISOCTAL(ch); + i++, data++) { + oval = (oval << 3) | (ch - '0'); + } + ch = oval; + break; + default: /* \any -> any */ + break; + } + } + VSTRING_ADDCH(result, ch); + } + VSTRING_TERMINATE(result); + return (result); +} + +/* escape - reverse transformation */ + +VSTRING *escape(VSTRING *result, const char *data, ssize_t len) +{ + int ch; + + VSTRING_RESET(result); + while (len-- > 0) { + ch = *UCHAR(data++); + if (ISASCII(ch)) { + if (ISPRINT(ch)) { + if (ch == '\\') + VSTRING_ADDCH(result, ch); + VSTRING_ADDCH(result, ch); + continue; + } else if (ch == '\a') { /* \a -> audible bell */ + vstring_strcat(result, "\\a"); + continue; + } else if (ch == '\b') { /* \b -> backspace */ + vstring_strcat(result, "\\b"); + continue; + } else if (ch == '\f') { /* \f -> formfeed */ + vstring_strcat(result, "\\f"); + continue; + } else if (ch == '\n') { /* \n -> newline */ + vstring_strcat(result, "\\n"); + continue; + } else if (ch == '\r') { /* \r -> carriagereturn */ + vstring_strcat(result, "\\r"); + continue; + } else if (ch == '\t') { /* \t -> horizontal tab */ + vstring_strcat(result, "\\t"); + continue; + } else if (ch == '\v') { /* \v -> vertical tab */ + vstring_strcat(result, "\\v"); + continue; + } + } + vstring_sprintf_append(result, "\\%03o", ch); + } + VSTRING_TERMINATE(result); + return (result); +} + +#ifdef TEST + +#include <stdlib.h> +#include <string.h> +#include <msg.h> +#include <vstring_vstream.h> + +int main(int argc, char **argv) +{ + VSTRING *in = vstring_alloc(10); + VSTRING *out = vstring_alloc(10); + int un_escape = 1; + + if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0) + msg_fatal("usage: %s [-e (escape)]", argv[0]); + + if (un_escape) { + while (vstring_fgets_nonl(in, VSTREAM_IN)) { + unescape(out, vstring_str(in)); + vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out)); + VSTREAM_PUTC('\n', VSTREAM_OUT); + } + } else { + while (vstring_fgets_nonl(in, VSTREAM_IN)) { + escape(out, vstring_str(in), VSTRING_LEN(in)); + vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out)); + VSTREAM_PUTC('\n', VSTREAM_OUT); + } + } + vstream_fflush(VSTREAM_OUT); + exit(0); +} + +#endif |