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