1aa772005SRobert Watson /*-
2aa772005SRobert Watson * Copyright (c) 1989, 1993
3aa772005SRobert Watson * The Regents of the University of California. All rights reserved.
4aa772005SRobert Watson *
5aa772005SRobert Watson * Redistribution and use in source and binary forms, with or without
6aa772005SRobert Watson * modification, are permitted provided that the following conditions
7aa772005SRobert Watson * are met:
8aa772005SRobert Watson * 1. Redistributions of source code must retain the above copyright
9aa772005SRobert Watson * notice, this list of conditions and the following disclaimer.
10aa772005SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
11aa772005SRobert Watson * notice, this list of conditions and the following disclaimer in the
12aa772005SRobert Watson * documentation and/or other materials provided with the distribution.
13fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
14aa772005SRobert Watson * may be used to endorse or promote products derived from this software
15aa772005SRobert Watson * without specific prior written permission.
16aa772005SRobert Watson *
17aa772005SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18aa772005SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19aa772005SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20aa772005SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21aa772005SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22aa772005SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23aa772005SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24aa772005SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25aa772005SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26aa772005SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27aa772005SRobert Watson * SUCH DAMAGE.
28aa772005SRobert Watson *
29aa772005SRobert Watson * Defived from FreeBSD head/lib/libc/gen/vis.c 165903, head/include/vis.h
30aa772005SRobert Watson * 203964.
31aa772005SRobert Watson */
32aa772005SRobert Watson
33aa772005SRobert Watson #include <sys/types.h>
34aa772005SRobert Watson #include <limits.h>
35aa772005SRobert Watson #include <ctype.h>
36aa772005SRobert Watson #include <stdio.h>
37aa772005SRobert Watson
38aa772005SRobert Watson /*
39aa772005SRobert Watson * to select alternate encoding format
40aa772005SRobert Watson */
41aa772005SRobert Watson #define VIS_OCTAL 0x01 /* use octal \ddd format */
42aa772005SRobert Watson #define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */
43aa772005SRobert Watson
44aa772005SRobert Watson /*
45aa772005SRobert Watson * to alter set of characters encoded (default is to encode all
46aa772005SRobert Watson * non-graphic except space, tab, and newline).
47aa772005SRobert Watson */
48aa772005SRobert Watson #define VIS_SP 0x04 /* also encode space */
49aa772005SRobert Watson #define VIS_TAB 0x08 /* also encode tab */
50aa772005SRobert Watson #define VIS_NL 0x10 /* also encode newline */
51aa772005SRobert Watson #define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL)
52aa772005SRobert Watson #define VIS_SAFE 0x20 /* only encode "unsafe" characters */
53aa772005SRobert Watson
54aa772005SRobert Watson /*
55aa772005SRobert Watson * other
56aa772005SRobert Watson */
57aa772005SRobert Watson #define VIS_NOSLASH 0x40 /* inhibit printing '\' */
58aa772005SRobert Watson #define VIS_HTTPSTYLE 0x80 /* http-style escape % HEX HEX */
59aa772005SRobert Watson #define VIS_GLOB 0x100 /* encode glob(3) magics */
60aa772005SRobert Watson
61aa772005SRobert Watson /*
62aa772005SRobert Watson * unvis return codes
63aa772005SRobert Watson */
64aa772005SRobert Watson #define UNVIS_VALID 1 /* character valid */
65aa772005SRobert Watson #define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */
66aa772005SRobert Watson #define UNVIS_NOCHAR 3 /* valid sequence, no character produced */
67aa772005SRobert Watson #define UNVIS_SYNBAD -1 /* unrecognized escape sequence */
68aa772005SRobert Watson #define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */
69aa772005SRobert Watson
70aa772005SRobert Watson /*
71aa772005SRobert Watson * unvis flags
72aa772005SRobert Watson */
73aa772005SRobert Watson #define UNVIS_END 1 /* no more characters */
74aa772005SRobert Watson
75aa772005SRobert Watson #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
76aa772005SRobert Watson
77aa772005SRobert Watson /*
78aa772005SRobert Watson * vis - visually encode characters
79aa772005SRobert Watson */
80aa772005SRobert Watson char *
vis(dst,c,flag,nextc)81aa772005SRobert Watson vis(dst, c, flag, nextc)
82aa772005SRobert Watson char *dst;
83aa772005SRobert Watson int c, nextc;
84aa772005SRobert Watson int flag;
85aa772005SRobert Watson {
86aa772005SRobert Watson c = (unsigned char)c;
87aa772005SRobert Watson
88aa772005SRobert Watson if (flag & VIS_HTTPSTYLE) {
89aa772005SRobert Watson /* Described in RFC 1808 */
90aa772005SRobert Watson if (!(isalnum(c) /* alpha-numeric */
91aa772005SRobert Watson /* safe */
92aa772005SRobert Watson || c == '$' || c == '-' || c == '_' || c == '.' || c == '+'
93aa772005SRobert Watson /* extra */
94aa772005SRobert Watson || c == '!' || c == '*' || c == '\'' || c == '('
95aa772005SRobert Watson || c == ')' || c == ',')) {
96aa772005SRobert Watson *dst++ = '%';
97aa772005SRobert Watson snprintf(dst, 4, (c < 16 ? "0%X" : "%X"), c);
98aa772005SRobert Watson dst += 2;
99aa772005SRobert Watson goto done;
100aa772005SRobert Watson }
101aa772005SRobert Watson }
102aa772005SRobert Watson
103aa772005SRobert Watson if ((flag & VIS_GLOB) &&
104aa772005SRobert Watson (c == '*' || c == '?' || c == '[' || c == '#'))
105aa772005SRobert Watson ;
106aa772005SRobert Watson else if (isgraph(c) ||
107aa772005SRobert Watson ((flag & VIS_SP) == 0 && c == ' ') ||
108aa772005SRobert Watson ((flag & VIS_TAB) == 0 && c == '\t') ||
109aa772005SRobert Watson ((flag & VIS_NL) == 0 && c == '\n') ||
110aa772005SRobert Watson ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) {
111aa772005SRobert Watson *dst++ = c;
112aa772005SRobert Watson if (c == '\\' && (flag & VIS_NOSLASH) == 0)
113aa772005SRobert Watson *dst++ = '\\';
114aa772005SRobert Watson *dst = '\0';
115aa772005SRobert Watson return (dst);
116aa772005SRobert Watson }
117aa772005SRobert Watson
118aa772005SRobert Watson if (flag & VIS_CSTYLE) {
119aa772005SRobert Watson switch(c) {
120aa772005SRobert Watson case '\n':
121aa772005SRobert Watson *dst++ = '\\';
122aa772005SRobert Watson *dst++ = 'n';
123aa772005SRobert Watson goto done;
124aa772005SRobert Watson case '\r':
125aa772005SRobert Watson *dst++ = '\\';
126aa772005SRobert Watson *dst++ = 'r';
127aa772005SRobert Watson goto done;
128aa772005SRobert Watson case '\b':
129aa772005SRobert Watson *dst++ = '\\';
130aa772005SRobert Watson *dst++ = 'b';
131aa772005SRobert Watson goto done;
132aa772005SRobert Watson case '\a':
133aa772005SRobert Watson *dst++ = '\\';
134aa772005SRobert Watson *dst++ = 'a';
135aa772005SRobert Watson goto done;
136aa772005SRobert Watson case '\v':
137aa772005SRobert Watson *dst++ = '\\';
138aa772005SRobert Watson *dst++ = 'v';
139aa772005SRobert Watson goto done;
140aa772005SRobert Watson case '\t':
141aa772005SRobert Watson *dst++ = '\\';
142aa772005SRobert Watson *dst++ = 't';
143aa772005SRobert Watson goto done;
144aa772005SRobert Watson case '\f':
145aa772005SRobert Watson *dst++ = '\\';
146aa772005SRobert Watson *dst++ = 'f';
147aa772005SRobert Watson goto done;
148aa772005SRobert Watson case ' ':
149aa772005SRobert Watson *dst++ = '\\';
150aa772005SRobert Watson *dst++ = 's';
151aa772005SRobert Watson goto done;
152aa772005SRobert Watson case '\0':
153aa772005SRobert Watson *dst++ = '\\';
154aa772005SRobert Watson *dst++ = '0';
155aa772005SRobert Watson if (isoctal(nextc)) {
156aa772005SRobert Watson *dst++ = '0';
157aa772005SRobert Watson *dst++ = '0';
158aa772005SRobert Watson }
159aa772005SRobert Watson goto done;
160aa772005SRobert Watson }
161aa772005SRobert Watson }
162aa772005SRobert Watson if (((c & 0177) == ' ') || isgraph(c) || (flag & VIS_OCTAL)) {
163aa772005SRobert Watson *dst++ = '\\';
164aa772005SRobert Watson *dst++ = ((u_char)c >> 6 & 07) + '0';
165aa772005SRobert Watson *dst++ = ((u_char)c >> 3 & 07) + '0';
166aa772005SRobert Watson *dst++ = ((u_char)c & 07) + '0';
167aa772005SRobert Watson goto done;
168aa772005SRobert Watson }
169aa772005SRobert Watson if ((flag & VIS_NOSLASH) == 0)
170aa772005SRobert Watson *dst++ = '\\';
171aa772005SRobert Watson if (c & 0200) {
172aa772005SRobert Watson c &= 0177;
173aa772005SRobert Watson *dst++ = 'M';
174aa772005SRobert Watson }
175aa772005SRobert Watson if (iscntrl(c)) {
176aa772005SRobert Watson *dst++ = '^';
177aa772005SRobert Watson if (c == 0177)
178aa772005SRobert Watson *dst++ = '?';
179aa772005SRobert Watson else
180aa772005SRobert Watson *dst++ = c + '@';
181aa772005SRobert Watson } else {
182aa772005SRobert Watson *dst++ = '-';
183aa772005SRobert Watson *dst++ = c;
184aa772005SRobert Watson }
185aa772005SRobert Watson done:
186aa772005SRobert Watson *dst = '\0';
187aa772005SRobert Watson return (dst);
188aa772005SRobert Watson }
189