1/*++ 2/* NAME 3/* unescape 3 4/* SUMMARY 5/* translate C-like escape sequences 6/* SYNOPSIS 7/* #include <stringops.h> 8/* 9/* VSTRING *unescape(result, input) 10/* VSTRING *result; 11/* const char *input; 12/* 13/* VSTRING *escape(result, input, len) 14/* VSTRING *result; 15/* const char *input; 16/* ssize_t len; 17/* DESCRIPTION 18/* unescape() translates C-like escape sequences in the null-terminated 19/* string \fIinput\fR and places the result in \fIresult\fR. The result 20/* is null-terminated, and is the function result value. 21/* 22/* escape() does the reverse transformation. 23/* 24/* Escape sequences and their translations: 25/* .IP \ea 26/* Bell character. 27/* .IP \eb 28/* Backspace character. 29/* .IP \ef 30/* formfeed character. 31/* .IP \en 32/* newline character 33/* .IP \er 34/* Carriage-return character. 35/* .IP \et 36/* Horizontal tab character. 37/* .IP \ev 38/* Vertical tab character. 39/* .IP \e\e 40/* Backslash character. 41/* .IP \e\fInum\fR 42/* 8-bit character whose ASCII value is the 1..3 digit 43/* octal number \fInum\fR. 44/* .IP \e\fIother\fR 45/* The backslash character is discarded. 46/* LICENSE 47/* .ad 48/* .fi 49/* The Secure Mailer license must be distributed with this software. 50/* AUTHOR(S) 51/* Wietse Venema 52/* IBM T.J. Watson Research 53/* P.O. Box 704 54/* Yorktown Heights, NY 10598, USA 55/*--*/ 56 57/* System library. */ 58 59#include <sys_defs.h> 60#include <ctype.h> 61 62/* Utility library. */ 63 64#include <vstring.h> 65#include <stringops.h> 66 67/* unescape - process escape sequences */ 68 69VSTRING *unescape(VSTRING *result, const char *data) 70{ 71 int ch; 72 int oval; 73 int i; 74 75#define UCHAR(cp) ((unsigned char *) (cp)) 76#define ISOCTAL(ch) (ISDIGIT(ch) && (ch) != '8' && (ch) != '9') 77 78 VSTRING_RESET(result); 79 80 while ((ch = *UCHAR(data++)) != 0) { 81 if (ch == '\\') { 82 if ((ch = *UCHAR(data++)) == 0) 83 break; 84 switch (ch) { 85 case 'a': /* \a -> audible bell */ 86 ch = '\a'; 87 break; 88 case 'b': /* \b -> backspace */ 89 ch = '\b'; 90 break; 91 case 'f': /* \f -> formfeed */ 92 ch = '\f'; 93 break; 94 case 'n': /* \n -> newline */ 95 ch = '\n'; 96 break; 97 case 'r': /* \r -> carriagereturn */ 98 ch = '\r'; 99 break; 100 case 't': /* \t -> horizontal tab */ 101 ch = '\t'; 102 break; 103 case 'v': /* \v -> vertical tab */ 104 ch = '\v'; 105 break; 106 case '0': /* \nnn -> ASCII value */ 107 case '1': 108 case '2': 109 case '3': 110 case '4': 111 case '5': 112 case '6': 113 case '7': 114 for (oval = ch - '0', i = 0; 115 i < 2 && (ch = *UCHAR(data)) != 0 && ISOCTAL(ch); 116 i++, data++) { 117 oval = (oval << 3) | (ch - '0'); 118 } 119 ch = oval; 120 break; 121 default: /* \any -> any */ 122 break; 123 } 124 } 125 VSTRING_ADDCH(result, ch); 126 } 127 VSTRING_TERMINATE(result); 128 return (result); 129} 130 131/* escape - reverse transformation */ 132 133VSTRING *escape(VSTRING *result, const char *data, ssize_t len) 134{ 135 int ch; 136 137 VSTRING_RESET(result); 138 while (len-- > 0) { 139 ch = *UCHAR(data++); 140 if (ISASCII(ch)) { 141 if (ISPRINT(ch)) { 142 if (ch == '\\') 143 VSTRING_ADDCH(result, ch); 144 VSTRING_ADDCH(result, ch); 145 continue; 146 } else if (ch == '\a') { /* \a -> audible bell */ 147 vstring_strcat(result, "\\a"); 148 continue; 149 } else if (ch == '\b') { /* \b -> backspace */ 150 vstring_strcat(result, "\\b"); 151 continue; 152 } else if (ch == '\f') { /* \f -> formfeed */ 153 vstring_strcat(result, "\\f"); 154 continue; 155 } else if (ch == '\n') { /* \n -> newline */ 156 vstring_strcat(result, "\\n"); 157 continue; 158 } else if (ch == '\r') { /* \r -> carriagereturn */ 159 vstring_strcat(result, "\\r"); 160 continue; 161 } else if (ch == '\t') { /* \t -> horizontal tab */ 162 vstring_strcat(result, "\\t"); 163 continue; 164 } else if (ch == '\v') { /* \v -> vertical tab */ 165 vstring_strcat(result, "\\v"); 166 continue; 167 } 168 } 169 if (ISDIGIT(*UCHAR(data))) 170 vstring_sprintf_append(result, "\\%03d", ch); 171 else 172 vstring_sprintf_append(result, "\\%d", ch); 173 } 174 VSTRING_TERMINATE(result); 175 return (result); 176} 177 178#ifdef TEST 179 180#include <stdlib.h> 181#include <string.h> 182#include <msg.h> 183#include <vstring_vstream.h> 184 185int main(int argc, char **argv) 186{ 187 VSTRING *in = vstring_alloc(10); 188 VSTRING *out = vstring_alloc(10); 189 int un_escape = 1; 190 191 if (argc > 2 || (argc > 1 && (un_escape = strcmp(argv[1], "-e"))) != 0) 192 msg_fatal("usage: %s [-e (escape)]", argv[0]); 193 194 if (un_escape) { 195 while (vstring_fgets_nonl(in, VSTREAM_IN)) { 196 unescape(out, vstring_str(in)); 197 vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out)); 198 } 199 } else { 200 while (vstring_fgets(in, VSTREAM_IN)) { 201 escape(out, vstring_str(in), VSTRING_LEN(in)); 202 vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out)); 203 } 204 } 205 vstream_fflush(VSTREAM_OUT); 206 exit(0); 207} 208 209#endif 210