1 /* $NetBSD: vis.c,v 1.21 2002/01/31 22:43:39 tv 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 #include <sys/cdefs.h> 38 #if defined(LIBC_SCCS) && !defined(lint) 39 __RCSID("$NetBSD: vis.c,v 1.21 2002/01/31 22:43:39 tv Exp $"); 40 #endif /* LIBC_SCCS and not lint */ 41 42 #include "namespace.h" 43 #include <sys/types.h> 44 45 #include <assert.h> 46 #include <vis.h> 47 48 #ifdef __weak_alias 49 __weak_alias(strsvis,_strsvis) 50 __weak_alias(strsvisx,_strsvisx) 51 __weak_alias(strvis,_strvis) 52 __weak_alias(strvisx,_strvisx) 53 __weak_alias(svis,_svis) 54 __weak_alias(vis,_vis) 55 #endif 56 57 #if !HAVE_VIS_H 58 #include <ctype.h> 59 #include <limits.h> 60 #include <stdio.h> 61 #include <string.h> 62 63 #undef BELL 64 #if defined(__STDC__) 65 #define BELL '\a' 66 #else 67 #define BELL '\007' 68 #endif 69 70 #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 71 #define iswhite(c) (c == ' ' || c == '\t' || c == '\n') 72 #define issafe(c) (c == '\b' || c == BELL || c == '\r') 73 74 #define MAXEXTRAS 5 75 76 77 #define MAKEEXTRALIST(flag, extra) \ 78 do { \ 79 char *pextra = extra; \ 80 if (flag & VIS_SP) *pextra++ = ' '; \ 81 if (flag & VIS_TAB) *pextra++ = '\t'; \ 82 if (flag & VIS_NL) *pextra++ = '\n'; \ 83 if ((flag & VIS_NOSLASH) == 0) *pextra++ = '\\'; \ 84 *pextra = '\0'; \ 85 } while (/*CONSTCOND*/0) 86 87 /* 88 * This is SVIS, the central macro of vis. 89 * dst: Pointer to the destination buffer 90 * c: Character to encode 91 * flag: Flag word 92 * nextc: The character following 'c' 93 * extra: Pointer to the list of extra characters to be 94 * backslash-protected. 95 */ 96 #define SVIS(dst, c, flag, nextc, extra) \ 97 do { \ 98 int isextra, isc; \ 99 isextra = strchr(extra, c) != NULL; \ 100 if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \ 101 ((flag & VIS_SAFE) && issafe(c)))) { \ 102 *dst++ = c; \ 103 break; \ 104 } \ 105 isc = 0; \ 106 if (flag & VIS_CSTYLE) { \ 107 switch (c) { \ 108 case '\n': \ 109 isc = 1; *dst++ = '\\'; *dst++ = 'n'; \ 110 break; \ 111 case '\r': \ 112 isc = 1; *dst++ = '\\'; *dst++ = 'r'; \ 113 break; \ 114 case '\b': \ 115 isc = 1; *dst++ = '\\'; *dst++ = 'b'; \ 116 break; \ 117 case BELL: \ 118 isc = 1; *dst++ = '\\'; *dst++ = 'a'; \ 119 break; \ 120 case '\v': \ 121 isc = 1; *dst++ = '\\'; *dst++ = 'v'; \ 122 break; \ 123 case '\t': \ 124 isc = 1; *dst++ = '\\'; *dst++ = 't'; \ 125 break; \ 126 case '\f': \ 127 isc = 1; *dst++ = '\\'; *dst++ = 'f'; \ 128 break; \ 129 case ' ': \ 130 isc = 1; *dst++ = '\\'; *dst++ = 's'; \ 131 break; \ 132 case '\0': \ 133 isc = 1; *dst++ = '\\'; *dst++ = '0'; \ 134 if (isoctal(nextc)) { \ 135 *dst++ = '0'; \ 136 *dst++ = '0'; \ 137 } \ 138 } \ 139 } \ 140 if (isc) break; \ 141 if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \ 142 *dst++ = '\\'; \ 143 *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; \ 144 *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; \ 145 *dst++ = (c & 07) + '0'; \ 146 } else { \ 147 if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \ 148 if (c & 0200) { \ 149 c &= 0177; *dst++ = 'M'; \ 150 } \ 151 if (iscntrl(c)) { \ 152 *dst++ = '^'; \ 153 if (c == 0177) \ 154 *dst++ = '?'; \ 155 else \ 156 *dst++ = c + '@'; \ 157 } else { \ 158 *dst++ = '-'; *dst++ = c; \ 159 } \ 160 } \ 161 } while (/*CONSTCOND*/0) 162 163 164 /* 165 * svis - visually encode characters, also encoding the characters 166 * pointed to by `extra' 167 */ 168 char * 169 svis(dst, c, flag, nextc, extra) 170 char *dst; 171 int c, flag, nextc; 172 const char *extra; 173 { 174 _DIAGASSERT(dst != NULL); 175 _DIAGASSERT(extra != NULL); 176 177 SVIS(dst, c, flag, nextc, extra); 178 *dst = '\0'; 179 return(dst); 180 } 181 182 183 /* 184 * strsvis, strsvisx - visually encode characters from src into dst 185 * 186 * Extra is a pointer to a \0-terminated list of characters to 187 * be encoded, too. These functions are useful e. g. to 188 * encode strings in such a way so that they are not interpreted 189 * by a shell. 190 * 191 * Dst must be 4 times the size of src to account for possible 192 * expansion. The length of dst, not including the trailing NULL, 193 * is returned. 194 * 195 * Strsvisx encodes exactly len bytes from src into dst. 196 * This is useful for encoding a block of data. 197 */ 198 int 199 strsvis(dst, src, flag, extra) 200 char *dst; 201 const char *src; 202 int flag; 203 const char *extra; 204 { 205 char c; 206 char *start; 207 208 _DIAGASSERT(dst != NULL); 209 _DIAGASSERT(src != NULL); 210 _DIAGASSERT(extra != NULL); 211 212 for (start = dst; (c = *src++) != '\0'; /* empty */) 213 SVIS(dst, c, flag, *src, extra); 214 *dst = '\0'; 215 return (dst - start); 216 } 217 218 219 int 220 strsvisx(dst, src, len, flag, extra) 221 char *dst; 222 const char *src; 223 size_t len; 224 int flag; 225 const char *extra; 226 { 227 char c; 228 char *start; 229 230 _DIAGASSERT(dst != NULL); 231 _DIAGASSERT(src != NULL); 232 _DIAGASSERT(extra != NULL); 233 234 for (start = dst; len > 0; len--) { 235 c = *src++; 236 SVIS(dst, c, flag, len ? *src : '\0', extra); 237 } 238 *dst = '\0'; 239 return (dst - start); 240 } 241 242 243 /* 244 * vis - visually encode characters 245 */ 246 char * 247 vis(dst, c, flag, nextc) 248 char *dst; 249 int c, flag, nextc; 250 251 { 252 char extra[MAXEXTRAS]; 253 254 _DIAGASSERT(dst != NULL); 255 256 MAKEEXTRALIST(flag, extra); 257 SVIS(dst, c, flag, nextc, extra); 258 *dst = '\0'; 259 return (dst); 260 } 261 262 263 /* 264 * strvis, strvisx - visually encode characters from src into dst 265 * 266 * Dst must be 4 times the size of src to account for possible 267 * expansion. The length of dst, not including the trailing NULL, 268 * is returned. 269 * 270 * Strvisx encodes exactly len bytes from src into dst. 271 * This is useful for encoding a block of data. 272 */ 273 int 274 strvis(dst, src, flag) 275 char *dst; 276 const char *src; 277 int flag; 278 { 279 char extra[MAXEXTRAS]; 280 281 MAKEEXTRALIST(flag, extra); 282 return (strsvis(dst, src, flag, extra)); 283 } 284 285 286 int 287 strvisx(dst, src, len, flag) 288 char *dst; 289 const char *src; 290 size_t len; 291 int flag; 292 { 293 char extra[MAXEXTRAS]; 294 295 MAKEEXTRALIST(flag, extra); 296 return (strsvisx(dst, src, len, flag, extra)); 297 } 298 #endif 299