1 /* $NetBSD: vis.c,v 1.19 2000/01/22 22:42:45 mycroft Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 38 #include <sys/cdefs.h> 39 #if !defined(lint) 40 __RCSID("$NetBSD: vis.c,v 1.19 2000/01/22 22:42:45 mycroft Exp $"); 41 #endif /* not lint */ 42 43 #include "namespace.h" 44 #include <sys/types.h> 45 46 #include <assert.h> 47 #include <ctype.h> 48 #include <limits.h> 49 #include <stdio.h> 50 #include <string.h> 51 #include <vis.h> 52 53 #ifdef __weak_alias 54 __weak_alias(strsvis,_strsvis) 55 __weak_alias(strsvisx,_strsvisx) 56 __weak_alias(strvis,_strvis) 57 __weak_alias(strvisx,_strvisx) 58 __weak_alias(svis,_svis) 59 __weak_alias(vis,_vis) 60 #endif 61 62 #undef BELL 63 #if defined(__STDC__) 64 #define BELL '\a' 65 #else 66 #define BELL '\007' 67 #endif 68 69 #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 70 #define iswhite(c) (c == ' ' || c == '\t' || c == '\n') 71 #define issafe(c) (c == '\b' || c == BELL || c == '\r') 72 73 #define MAXEXTRAS 5 74 75 76 #define MAKEEXTRALIST(flag, extra) \ 77 do { \ 78 char *pextra = extra; \ 79 if (flag & VIS_SP) *pextra++ = ' '; \ 80 if (flag & VIS_TAB) *pextra++ = '\t'; \ 81 if (flag & VIS_NL) *pextra++ = '\n'; \ 82 if ((flag & VIS_NOSLASH) == 0) *pextra++ = '\\'; \ 83 *pextra = '\0'; \ 84 } while (/*CONSTCOND*/0) 85 86 /* 87 * This is SVIS, the central macro of vis. 88 * dst: Pointer to the destination buffer 89 * c: Character to encode 90 * flag: Flag word 91 * nextc: The character following 'c' 92 * extra: Pointer to the list of extra characters to be 93 * backslash-protected. 94 */ 95 #define SVIS(dst, c, flag, nextc, extra) \ 96 do { \ 97 int isextra, isc; \ 98 isextra = strchr(extra, c) != NULL; \ 99 if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \ 100 ((flag & VIS_SAFE) && issafe(c)))) { \ 101 *dst++ = c; \ 102 break; \ 103 } \ 104 isc = 0; \ 105 if (flag & VIS_CSTYLE) { \ 106 switch (c) { \ 107 case '\n': \ 108 isc = 1; *dst++ = '\\'; *dst++ = 'n'; \ 109 break; \ 110 case '\r': \ 111 isc = 1; *dst++ = '\\'; *dst++ = 'r'; \ 112 break; \ 113 case '\b': \ 114 isc = 1; *dst++ = '\\'; *dst++ = 'b'; \ 115 break; \ 116 case BELL: \ 117 isc = 1; *dst++ = '\\'; *dst++ = 'a'; \ 118 break; \ 119 case '\v': \ 120 isc = 1; *dst++ = '\\'; *dst++ = 'v'; \ 121 break; \ 122 case '\t': \ 123 isc = 1; *dst++ = '\\'; *dst++ = 't'; \ 124 break; \ 125 case '\f': \ 126 isc = 1; *dst++ = '\\'; *dst++ = 'f'; \ 127 break; \ 128 case ' ': \ 129 isc = 1; *dst++ = '\\'; *dst++ = 's'; \ 130 break; \ 131 case '\0': \ 132 isc = 1; *dst++ = '\\'; *dst++ = '0'; \ 133 if (isoctal(nextc)) { \ 134 *dst++ = '0'; \ 135 *dst++ = '0'; \ 136 } \ 137 } \ 138 } \ 139 if (isc) break; \ 140 if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \ 141 *dst++ = '\\'; \ 142 *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; \ 143 *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; \ 144 *dst++ = (c & 07) + '0'; \ 145 } else { \ 146 if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \ 147 if (c & 0200) { \ 148 c &= 0177; *dst++ = 'M'; \ 149 } \ 150 if (iscntrl(c)) { \ 151 *dst++ = '^'; \ 152 if (c == 0177) \ 153 *dst++ = '?'; \ 154 else \ 155 *dst++ = c + '@'; \ 156 } else { \ 157 *dst++ = '-'; *dst++ = c; \ 158 } \ 159 } \ 160 } while (/*CONSTCOND*/0) 161 162 163 /* 164 * svis - visually encode characters, also encoding the characters 165 * pointed to by `extra' 166 */ 167 char * 168 svis(dst, c, flag, nextc, extra) 169 char *dst; 170 int c, flag, nextc; 171 const char *extra; 172 { 173 _DIAGASSERT(dst != NULL); 174 _DIAGASSERT(extra != NULL); 175 176 SVIS(dst, c, flag, nextc, extra); 177 *dst = '\0'; 178 return(dst); 179 } 180 181 182 /* 183 * strsvis, strsvisx - visually encode characters from src into dst 184 * 185 * Extra is a pointer to a \0-terminated list of characters to 186 * be encoded, too. These functions are useful e. g. to 187 * encode strings in such a way so that they are not interpreted 188 * by a shell. 189 * 190 * Dst must be 4 times the size of src to account for possible 191 * expansion. The length of dst, not including the trailing NULL, 192 * is returned. 193 * 194 * Strsvisx encodes exactly len bytes from src into dst. 195 * This is useful for encoding a block of data. 196 */ 197 int 198 strsvis(dst, src, flag, extra) 199 char *dst; 200 const char *src; 201 int flag; 202 const char *extra; 203 { 204 char c; 205 char *start; 206 207 _DIAGASSERT(dst != NULL); 208 _DIAGASSERT(src != NULL); 209 _DIAGASSERT(extra != NULL); 210 211 for (start = dst; (c = *src++) != '\0'; /* empty */) 212 SVIS(dst, c, flag, *src, extra); 213 *dst = '\0'; 214 return (dst - start); 215 } 216 217 218 int 219 strsvisx(dst, src, len, flag, extra) 220 char *dst; 221 const char *src; 222 size_t len; 223 int flag; 224 const char *extra; 225 { 226 char c; 227 char *start; 228 229 _DIAGASSERT(dst != NULL); 230 _DIAGASSERT(src != NULL); 231 _DIAGASSERT(extra != NULL); 232 233 for (start = dst; len > 0; len--) { 234 c = *src++; 235 SVIS(dst, c, flag, len ? *src : '\0', extra); 236 } 237 *dst = '\0'; 238 return (dst - start); 239 } 240 241 242 /* 243 * vis - visually encode characters 244 */ 245 char * 246 vis(dst, c, flag, nextc) 247 char *dst; 248 int c, flag, nextc; 249 250 { 251 char extra[MAXEXTRAS]; 252 253 _DIAGASSERT(dst != NULL); 254 255 MAKEEXTRALIST(flag, extra); 256 SVIS(dst, c, flag, nextc, extra); 257 *dst = '\0'; 258 return (dst); 259 } 260 261 262 /* 263 * strvis, strvisx - visually encode characters from src into dst 264 * 265 * Dst must be 4 times the size of src to account for possible 266 * expansion. The length of dst, not including the trailing NULL, 267 * is returned. 268 * 269 * Strvisx encodes exactly len bytes from src into dst. 270 * This is useful for encoding a block of data. 271 */ 272 int 273 strvis(dst, src, flag) 274 char *dst; 275 const char *src; 276 int flag; 277 { 278 char extra[MAXEXTRAS]; 279 280 MAKEEXTRALIST(flag, extra); 281 return (strsvis(dst, src, flag, extra)); 282 } 283 284 285 int 286 strvisx(dst, src, len, flag) 287 char *dst; 288 const char *src; 289 size_t len; 290 int flag; 291 { 292 char extra[MAXEXTRAS]; 293 294 MAKEEXTRALIST(flag, extra); 295 return (strsvisx(dst, src, len, flag, extra)); 296 } 297