a4bde71e9b160a91cf7d6727799b6ccead929bd2
[samba.git] / source4 / heimdal / lib / roken / vis.c
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,v 1.9 2005/04/12 11:29:15 lha Exp $");
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 #define isoctal(c)      (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
112 #define iswhite(c)      (c == ' ' || c == '\t' || c == '\n')
113 #define issafe(c)       (c == '\b' || c == BELL || c == '\r')
114
115 #define MAXEXTRAS       5
116
117
118 #define MAKEEXTRALIST(flag, extra)                                            \
119 do {                                                                          \
120         char *pextra = extra;                                                 \
121         if (flag & VIS_SP) *pextra++ = ' ';                                   \
122         if (flag & VIS_TAB) *pextra++ = '\t';                                 \
123         if (flag & VIS_NL) *pextra++ = '\n';                                  \
124         if ((flag & VIS_NOSLASH) == 0) *pextra++ = '\\';                      \
125         *pextra = '\0';                                                       \
126 } while (/*CONSTCOND*/0)
127
128 /*
129  * This is SVIS, the central macro of vis.
130  * dst:       Pointer to the destination buffer
131  * c:         Character to encode
132  * flag:      Flag word
133  * nextc:     The character following 'c'
134  * extra:     Pointer to the list of extra characters to be
135  *            backslash-protected.
136  */
137 #define SVIS(dst, c, flag, nextc, extra)                                   \
138 do {                                                                       \
139         int isextra, isc;                                                  \
140         isextra = strchr(extra, c) != NULL;                                \
141         if (!isextra &&                                                    \
142             isascii((unsigned char)c) &&                                   \
143             (isgraph((unsigned char)c) || iswhite(c) ||                    \
144             ((flag & VIS_SAFE) && issafe(c)))) {                           \
145                 *dst++ = c;                                                \
146                 break;                                                     \
147         }                                                                  \
148         isc = 0;                                                           \
149         if (flag & VIS_CSTYLE) {                                           \
150                 switch (c) {                                               \
151                 case '\n':                                                 \
152                         isc = 1; *dst++ = '\\'; *dst++ = 'n';              \
153                         break;                                             \
154                 case '\r':                                                 \
155                         isc = 1; *dst++ = '\\'; *dst++ = 'r';              \
156                         break;                                             \
157                 case '\b':                                                 \
158                         isc = 1; *dst++ = '\\'; *dst++ = 'b';              \
159                         break;                                             \
160                 case BELL:                                                 \
161                         isc = 1; *dst++ = '\\'; *dst++ = 'a';              \
162                         break;                                             \
163                 case '\v':                                                 \
164                         isc = 1; *dst++ = '\\'; *dst++ = 'v';              \
165                         break;                                             \
166                 case '\t':                                                 \
167                         isc = 1; *dst++ = '\\'; *dst++ = 't';              \
168                         break;                                             \
169                 case '\f':                                                 \
170                         isc = 1; *dst++ = '\\'; *dst++ = 'f';              \
171                         break;                                             \
172                 case ' ':                                                  \
173                         isc = 1; *dst++ = '\\'; *dst++ = 's';              \
174                         break;                                             \
175                 case '\0':                                                 \
176                         isc = 1; *dst++ = '\\'; *dst++ = '0';              \
177                         if (isoctal(nextc)) {                              \
178                                 *dst++ = '0';                              \
179                                 *dst++ = '0';                              \
180                         }                                                  \
181                 }                                                          \
182         }                                                                  \
183         if (isc) break;                                                    \
184         if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {        \
185                 *dst++ = '\\';                                             \
186                 *dst++ = (u_char)(((unsigned)(u_char)c >> 6) & 03) + '0';  \
187                 *dst++ = (u_char)(((unsigned)(u_char)c >> 3) & 07) + '0';  \
188                 *dst++ =                             (c       & 07) + '0'; \
189         } else {                                                           \
190                 if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\';              \
191                 if (c & 0200) {                                            \
192                         c &= 0177; *dst++ = 'M';                           \
193                 }                                                          \
194                 if (iscntrl((unsigned char)c)) {                           \
195                         *dst++ = '^';                                      \
196                         if (c == 0177)                                     \
197                                 *dst++ = '?';                              \
198                         else                                               \
199                                 *dst++ = c + '@';                          \
200                 } else {                                                   \
201                         *dst++ = '-'; *dst++ = c;                          \
202                 }                                                          \
203         }                                                                  \
204 } while (/*CONSTCOND*/0)
205
206
207 /*
208  * svis - visually encode characters, also encoding the characters
209  *        pointed to by `extra'
210  */
211 #ifndef HAVE_SVIS
212 char * ROKEN_LIB_FUNCTION
213 svis(char *dst, int c, int flag, int nextc, const char *extra)
214 {
215         _DIAGASSERT(dst != NULL);
216         _DIAGASSERT(extra != NULL);
217
218         SVIS(dst, c, flag, nextc, extra);
219         *dst = '\0';
220         return(dst);
221 }
222 #endif
223
224
225 /*
226  * strsvis, strsvisx - visually encode characters from src into dst
227  *
228  *      Extra is a pointer to a \0-terminated list of characters to
229  *      be encoded, too. These functions are useful e. g. to
230  *      encode strings in such a way so that they are not interpreted
231  *      by a shell.
232  *      
233  *      Dst must be 4 times the size of src to account for possible
234  *      expansion.  The length of dst, not including the trailing NULL,
235  *      is returned. 
236  *
237  *      Strsvisx encodes exactly len bytes from src into dst.
238  *      This is useful for encoding a block of data.
239  */
240 #ifndef HAVE_STRSVIS
241 int ROKEN_LIB_FUNCTION
242 strsvis(char *dst, const char *src, int flag, const char *extra)
243 {
244         char c;
245         char *start;
246
247         _DIAGASSERT(dst != NULL);
248         _DIAGASSERT(src != NULL);
249         _DIAGASSERT(extra != NULL);
250
251         for (start = dst; (c = *src++) != '\0'; /* empty */)
252             SVIS(dst, c, flag, *src, extra);
253         *dst = '\0';
254         return (dst - start);
255 }
256 #endif
257
258
259 #ifndef HAVE_STRVISX
260 int ROKEN_LIB_FUNCTION
261 strsvisx(char *dst, const char *src, size_t len, int flag, const char *extra)
262 {
263         char c;
264         char *start;
265
266         _DIAGASSERT(dst != NULL);
267         _DIAGASSERT(src != NULL);
268         _DIAGASSERT(extra != NULL);
269
270         for (start = dst; len > 0; len--) {
271                 c = *src++;
272                 SVIS(dst, c, flag, len ? *src : '\0', extra);
273         }
274         *dst = '\0';
275         return (dst - start);
276 }
277 #endif
278
279
280 /*
281  * vis - visually encode characters
282  */
283 #ifndef HAVE_VIS
284 char * ROKEN_LIB_FUNCTION
285 vis(char *dst, int c, int flag, int nextc)
286 {
287         char extra[MAXEXTRAS];
288
289         _DIAGASSERT(dst != NULL);
290
291         MAKEEXTRALIST(flag, extra);
292         SVIS(dst, c, flag, nextc, extra);
293         *dst = '\0';
294         return (dst);
295 }
296 #endif
297
298
299 /*
300  * strvis, strvisx - visually encode characters from src into dst
301  *      
302  *      Dst must be 4 times the size of src to account for possible
303  *      expansion.  The length of dst, not including the trailing NULL,
304  *      is returned. 
305  *
306  *      Strvisx encodes exactly len bytes from src into dst.
307  *      This is useful for encoding a block of data.
308  */
309 #ifndef HAVE_STRVIS
310 int ROKEN_LIB_FUNCTION
311 strvis(char *dst, const char *src, int flag)
312 {
313         char extra[MAXEXTRAS];
314
315         MAKEEXTRALIST(flag, extra);
316         return (strsvis(dst, src, flag, extra));
317 }
318 #endif
319
320
321 #ifndef HAVE_STRVISX
322 int ROKEN_LIB_FUNCTION
323 strvisx(char *dst, const char *src, size_t len, int flag)
324 {
325         char extra[MAXEXTRAS];
326
327         MAKEEXTRALIST(flag, extra);
328         return (strsvisx(dst, src, len, flag, extra));
329 }
330 #endif