vis.c revision 124208
1241675Suqs/*- 2241675Suqs * Copyright (c) 1989, 1993 3241675Suqs * The Regents of the University of California. All rights reserved. 4241675Suqs * 5241675Suqs * Redistribution and use in source and binary forms, with or without 6241675Suqs * modification, are permitted provided that the following conditions 7241675Suqs * are met: 8241675Suqs * 1. Redistributions of source code must retain the above copyright 9241675Suqs * notice, this list of conditions and the following disclaimer. 10241675Suqs * 2. Redistributions in binary form must reproduce the above copyright 11241675Suqs * notice, this list of conditions and the following disclaimer in the 12241675Suqs * documentation and/or other materials provided with the distribution. 13241675Suqs * 3. Neither the name of the University nor the names of its contributors 14241675Suqs * may be used to endorse or promote products derived from this software 15241675Suqs * without specific prior written permission. 16241675Suqs * 17241675Suqs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18241675Suqs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19241675Suqs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20241675Suqs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21241675Suqs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22241675Suqs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23241675Suqs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24241675Suqs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25241675Suqs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26241675Suqs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27241675Suqs * SUCH DAMAGE. 28241675Suqs */ 29241675Suqs#include "includes.h" 30241675Suqs#if !defined(HAVE_STRNVIS) 31241675Suqs 32241675Suqs#if defined(LIBC_SCCS) && !defined(lint) 33241675Suqsstatic char rcsid[] = "$OpenBSD: vis.c,v 1.12 2003/06/02 20:18:35 millert Exp $"; 34241675Suqs#endif /* LIBC_SCCS and not lint */ 35241675Suqs 36241675Suqs#include <ctype.h> 37241675Suqs#include <string.h> 38241675Suqs 39241675Suqs#include "vis.h" 40241675Suqs 41241675Suqs#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 42241675Suqs#define isvisible(c) (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \ 43241675Suqs isgraph((u_char)(c))) || \ 44241675Suqs ((flag & VIS_SP) == 0 && (c) == ' ') || \ 45241675Suqs ((flag & VIS_TAB) == 0 && (c) == '\t') || \ 46241675Suqs ((flag & VIS_NL) == 0 && (c) == '\n') || \ 47241675Suqs ((flag & VIS_SAFE) && ((c) == '\b' || \ 48241675Suqs (c) == '\007' || (c) == '\r' || \ 49241675Suqs isgraph((u_char)(c))))) 50241675Suqs 51241675Suqs/* 52241675Suqs * vis - visually encode characters 53241675Suqs */ 54241675Suqschar * 55241675Suqsvis(dst, c, flag, nextc) 56241675Suqs register char *dst; 57241675Suqs int c, nextc; 58241675Suqs register int flag; 59241675Suqs{ 60241675Suqs if (isvisible(c)) { 61241675Suqs *dst++ = c; 62241675Suqs if (c == '\\' && (flag & VIS_NOSLASH) == 0) 63241675Suqs *dst++ = '\\'; 64241675Suqs *dst = '\0'; 65241675Suqs return (dst); 66241675Suqs } 67241675Suqs 68241675Suqs if (flag & VIS_CSTYLE) { 69241675Suqs switch(c) { 70241675Suqs case '\n': 71241675Suqs *dst++ = '\\'; 72241675Suqs *dst++ = 'n'; 73241675Suqs goto done; 74241675Suqs case '\r': 75241675Suqs *dst++ = '\\'; 76241675Suqs *dst++ = 'r'; 77241675Suqs goto done; 78241675Suqs case '\b': 79241675Suqs *dst++ = '\\'; 80241675Suqs *dst++ = 'b'; 81241675Suqs goto done; 82241675Suqs case '\a': 83241675Suqs *dst++ = '\\'; 84241675Suqs *dst++ = 'a'; 85241675Suqs goto done; 86241675Suqs case '\v': 87241675Suqs *dst++ = '\\'; 88241675Suqs *dst++ = 'v'; 89241675Suqs goto done; 90241675Suqs case '\t': 91241675Suqs *dst++ = '\\'; 92241675Suqs *dst++ = 't'; 93241675Suqs goto done; 94241675Suqs case '\f': 95241675Suqs *dst++ = '\\'; 96241675Suqs *dst++ = 'f'; 97241675Suqs goto done; 98241675Suqs case ' ': 99241675Suqs *dst++ = '\\'; 100241675Suqs *dst++ = 's'; 101241675Suqs goto done; 102241675Suqs case '\0': 103241675Suqs *dst++ = '\\'; 104241675Suqs *dst++ = '0'; 105241675Suqs if (isoctal(nextc)) { 106241675Suqs *dst++ = '0'; 107241675Suqs *dst++ = '0'; 108241675Suqs } 109241675Suqs goto done; 110241675Suqs } 111 } 112 if (((c & 0177) == ' ') || (flag & VIS_OCTAL)) { 113 *dst++ = '\\'; 114 *dst++ = ((u_char)c >> 6 & 07) + '0'; 115 *dst++ = ((u_char)c >> 3 & 07) + '0'; 116 *dst++ = ((u_char)c & 07) + '0'; 117 goto done; 118 } 119 if ((flag & VIS_NOSLASH) == 0) 120 *dst++ = '\\'; 121 if (c & 0200) { 122 c &= 0177; 123 *dst++ = 'M'; 124 } 125 if (iscntrl(c)) { 126 *dst++ = '^'; 127 if (c == 0177) 128 *dst++ = '?'; 129 else 130 *dst++ = c + '@'; 131 } else { 132 *dst++ = '-'; 133 *dst++ = c; 134 } 135done: 136 *dst = '\0'; 137 return (dst); 138} 139 140/* 141 * strvis, strnvis, strvisx - visually encode characters from src into dst 142 * 143 * Dst must be 4 times the size of src to account for possible 144 * expansion. The length of dst, not including the trailing NULL, 145 * is returned. 146 * 147 * Strnvis will write no more than siz-1 bytes (and will NULL terminate). 148 * The number of bytes needed to fully encode the string is returned. 149 * 150 * Strvisx encodes exactly len bytes from src into dst. 151 * This is useful for encoding a block of data. 152 */ 153int 154strvis(dst, src, flag) 155 register char *dst; 156 register const char *src; 157 int flag; 158{ 159 register char c; 160 char *start; 161 162 for (start = dst; (c = *src);) 163 dst = vis(dst, c, flag, *++src); 164 *dst = '\0'; 165 return (dst - start); 166} 167 168int 169strnvis(dst, src, siz, flag) 170 char *dst; 171 const char *src; 172 size_t siz; 173 int flag; 174{ 175 char c; 176 char *start, *end; 177 char tbuf[5]; 178 int i; 179 180 i = 0; 181 for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) { 182 if (isvisible(c)) { 183 i = 1; 184 *dst++ = c; 185 if (c == '\\' && (flag & VIS_NOSLASH) == 0) { 186 /* need space for the extra '\\' */ 187 if (dst < end) 188 *dst++ = '\\'; 189 else { 190 dst--; 191 i = 2; 192 break; 193 } 194 } 195 src++; 196 } else { 197 i = vis(tbuf, c, flag, *++src) - tbuf; 198 if (dst + i <= end) { 199 memcpy(dst, tbuf, i); 200 dst += i; 201 } else { 202 src--; 203 break; 204 } 205 } 206 } 207 if (siz > 0) 208 *dst = '\0'; 209 if (dst + i > end) { 210 /* adjust return value for truncation */ 211 while ((c = *src)) 212 dst += vis(tbuf, c, flag, *++src) - tbuf; 213 } 214 return (dst - start); 215} 216 217int 218strvisx(dst, src, len, flag) 219 register char *dst; 220 register const char *src; 221 register size_t len; 222 int flag; 223{ 224 register char c; 225 char *start; 226 227 for (start = dst; len > 1; len--) { 228 c = *src; 229 dst = vis(dst, c, flag, *++src); 230 } 231 if (len) 232 dst = vis(dst, *src, flag, '\0'); 233 *dst = '\0'; 234 return (dst - start); 235} 236 237#endif 238