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