1*0a6a1f1dSLionel Sambuc /* $NetBSD: vis.c,v 1.70 2015/05/26 21:42:46 christos Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras /*-
42fe8fb19SBen Gras * Copyright (c) 1989, 1993
52fe8fb19SBen Gras * The Regents of the University of California. All rights reserved.
62fe8fb19SBen Gras *
72fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without
82fe8fb19SBen Gras * modification, are permitted provided that the following conditions
92fe8fb19SBen Gras * are met:
102fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright
112fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer.
122fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
132fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the
142fe8fb19SBen Gras * documentation and/or other materials provided with the distribution.
152fe8fb19SBen Gras * 3. Neither the name of the University nor the names of its contributors
162fe8fb19SBen Gras * may be used to endorse or promote products derived from this software
172fe8fb19SBen Gras * without specific prior written permission.
182fe8fb19SBen Gras *
192fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
202fe8fb19SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
212fe8fb19SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
222fe8fb19SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
232fe8fb19SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
242fe8fb19SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
252fe8fb19SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
262fe8fb19SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
272fe8fb19SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
282fe8fb19SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
292fe8fb19SBen Gras * SUCH DAMAGE.
302fe8fb19SBen Gras */
312fe8fb19SBen Gras
322fe8fb19SBen Gras /*-
332fe8fb19SBen Gras * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
342fe8fb19SBen Gras * All rights reserved.
352fe8fb19SBen Gras *
362fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without
372fe8fb19SBen Gras * modification, are permitted provided that the following conditions
382fe8fb19SBen Gras * are met:
392fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright
402fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer.
412fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
422fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the
432fe8fb19SBen Gras * documentation and/or other materials provided with the distribution.
442fe8fb19SBen Gras *
452fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
462fe8fb19SBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
472fe8fb19SBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
482fe8fb19SBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
492fe8fb19SBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
502fe8fb19SBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
512fe8fb19SBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
522fe8fb19SBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
532fe8fb19SBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
542fe8fb19SBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
552fe8fb19SBen Gras * POSSIBILITY OF SUCH DAMAGE.
562fe8fb19SBen Gras */
572fe8fb19SBen Gras
582fe8fb19SBen Gras #include <sys/cdefs.h>
592fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
60*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: vis.c,v 1.70 2015/05/26 21:42:46 christos Exp $");
612fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
6284d9c625SLionel Sambuc #ifdef __FBSDID
6384d9c625SLionel Sambuc __FBSDID("$FreeBSD$");
6484d9c625SLionel Sambuc #define _DIAGASSERT(x) assert(x)
6584d9c625SLionel Sambuc #endif
662fe8fb19SBen Gras
672fe8fb19SBen Gras #include "namespace.h"
682fe8fb19SBen Gras #include <sys/types.h>
6984d9c625SLionel Sambuc #include <sys/param.h>
702fe8fb19SBen Gras
712fe8fb19SBen Gras #include <assert.h>
722fe8fb19SBen Gras #include <vis.h>
73f14fb602SLionel Sambuc #include <errno.h>
742fe8fb19SBen Gras #include <stdlib.h>
7584d9c625SLionel Sambuc #include <wchar.h>
7684d9c625SLionel Sambuc #include <wctype.h>
772fe8fb19SBen Gras
782fe8fb19SBen Gras #ifdef __weak_alias
792fe8fb19SBen Gras __weak_alias(strvisx,_strvisx)
802fe8fb19SBen Gras #endif
812fe8fb19SBen Gras
822fe8fb19SBen Gras #if !HAVE_VIS || !HAVE_SVIS
832fe8fb19SBen Gras #include <ctype.h>
842fe8fb19SBen Gras #include <limits.h>
852fe8fb19SBen Gras #include <stdio.h>
862fe8fb19SBen Gras #include <string.h>
872fe8fb19SBen Gras
8884d9c625SLionel Sambuc /*
8984d9c625SLionel Sambuc * The reason for going through the trouble to deal with character encodings
9084d9c625SLionel Sambuc * in vis(3), is that we use this to safe encode output of commands. This
9184d9c625SLionel Sambuc * safe encoding varies depending on the character set. For example if we
9284d9c625SLionel Sambuc * display ps output in French, we don't want to display French characters
9384d9c625SLionel Sambuc * as M-foo.
9484d9c625SLionel Sambuc */
9584d9c625SLionel Sambuc
9684d9c625SLionel Sambuc static wchar_t *do_svis(wchar_t *, wint_t, int, wint_t, const wchar_t *);
972fe8fb19SBen Gras
982fe8fb19SBen Gras #undef BELL
9984d9c625SLionel Sambuc #define BELL L'\a'
1002fe8fb19SBen Gras
101*0a6a1f1dSLionel Sambuc #if defined(LC_C_LOCALE)
102*0a6a1f1dSLionel Sambuc #define iscgraph(c) isgraph_l(c, LC_C_LOCALE)
103*0a6a1f1dSLionel Sambuc #else
104*0a6a1f1dSLionel Sambuc /* Keep it simple for now, no locale stuff */
105*0a6a1f1dSLionel Sambuc #define iscgraph(c) isgraph(c)
106*0a6a1f1dSLionel Sambuc #ifdef notyet
107*0a6a1f1dSLionel Sambuc #include <locale.h>
108*0a6a1f1dSLionel Sambuc static int
iscgraph(int c)109*0a6a1f1dSLionel Sambuc iscgraph(int c) {
110*0a6a1f1dSLionel Sambuc int rv;
111*0a6a1f1dSLionel Sambuc char *ol;
112*0a6a1f1dSLionel Sambuc
113*0a6a1f1dSLionel Sambuc ol = setlocale(LC_CTYPE, "C");
114*0a6a1f1dSLionel Sambuc rv = isgraph(c);
115*0a6a1f1dSLionel Sambuc if (ol)
116*0a6a1f1dSLionel Sambuc setlocale(LC_CTYPE, ol);
117*0a6a1f1dSLionel Sambuc return rv;
118*0a6a1f1dSLionel Sambuc }
119*0a6a1f1dSLionel Sambuc #endif
120*0a6a1f1dSLionel Sambuc #endif
121*0a6a1f1dSLionel Sambuc
122*0a6a1f1dSLionel Sambuc #define ISGRAPH(flags, c) \
123*0a6a1f1dSLionel Sambuc (((flags) & VIS_NOLOCALE) ? iscgraph(c) : iswgraph(c))
124*0a6a1f1dSLionel Sambuc
12584d9c625SLionel Sambuc #define iswoctal(c) (((u_char)(c)) >= L'0' && ((u_char)(c)) <= L'7')
12684d9c625SLionel Sambuc #define iswwhite(c) (c == L' ' || c == L'\t' || c == L'\n')
12784d9c625SLionel Sambuc #define iswsafe(c) (c == L'\b' || c == BELL || c == L'\r')
12884d9c625SLionel Sambuc #define xtoa(c) L"0123456789abcdef"[c]
12984d9c625SLionel Sambuc #define XTOA(c) L"0123456789ABCDEF"[c]
1302fe8fb19SBen Gras
131*0a6a1f1dSLionel Sambuc #define MAXEXTRAS 30
132*0a6a1f1dSLionel Sambuc
133*0a6a1f1dSLionel Sambuc static const wchar_t char_shell[] = L"'`\";&<>()|{}]\\$!^~";
134*0a6a1f1dSLionel Sambuc static const wchar_t char_glob[] = L"*?[#";
1352fe8fb19SBen Gras
13684d9c625SLionel Sambuc #if !HAVE_NBTOOL_CONFIG_H
13784d9c625SLionel Sambuc #if !defined(__NetBSD__) && ! defined(__minix)
13884d9c625SLionel Sambuc /*
13984d9c625SLionel Sambuc * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer
14084d9c625SLionel Sambuc * integral type and it is probably wrong, since currently the maximum
14184d9c625SLionel Sambuc * number of bytes and character needs is 6. Until this is fixed, the
14284d9c625SLionel Sambuc * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and
14384d9c625SLionel Sambuc * the assertion is commented out.
14484d9c625SLionel Sambuc */
14584d9c625SLionel Sambuc #ifdef __FreeBSD__
14684d9c625SLionel Sambuc /*
14784d9c625SLionel Sambuc * On FreeBSD including <sys/systm.h> for CTASSERT only works in kernel
14884d9c625SLionel Sambuc * mode.
14984d9c625SLionel Sambuc */
15084d9c625SLionel Sambuc #ifndef CTASSERT
15184d9c625SLionel Sambuc #define CTASSERT(x) _CTASSERT(x, __LINE__)
15284d9c625SLionel Sambuc #define _CTASSERT(x, y) __CTASSERT(x, y)
15384d9c625SLionel Sambuc #define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1]
15484d9c625SLionel Sambuc #endif
15584d9c625SLionel Sambuc #endif /* __FreeBSD__ */
15684d9c625SLionel Sambuc CTASSERT(MB_LEN_MAX <= sizeof(uint64_t));
15784d9c625SLionel Sambuc #endif /* !__NetBSD__ */
15884d9c625SLionel Sambuc #endif
1592fe8fb19SBen Gras
1602fe8fb19SBen Gras /*
1612fe8fb19SBen Gras * This is do_hvis, for HTTP style (RFC 1808)
1622fe8fb19SBen Gras */
16384d9c625SLionel Sambuc static wchar_t *
do_hvis(wchar_t * dst,wint_t c,int flags,wint_t nextc,const wchar_t * extra)16484d9c625SLionel Sambuc do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
1652fe8fb19SBen Gras {
16684d9c625SLionel Sambuc if (iswalnum(c)
1672fe8fb19SBen Gras /* safe */
16884d9c625SLionel Sambuc || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+'
1692fe8fb19SBen Gras /* extra */
17084d9c625SLionel Sambuc || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')'
17184d9c625SLionel Sambuc || c == L',')
17284d9c625SLionel Sambuc dst = do_svis(dst, c, flags, nextc, extra);
17384d9c625SLionel Sambuc else {
17484d9c625SLionel Sambuc *dst++ = L'%';
1752fe8fb19SBen Gras *dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
1762fe8fb19SBen Gras *dst++ = xtoa((unsigned int)c & 0xf);
1772fe8fb19SBen Gras }
1782fe8fb19SBen Gras
1792fe8fb19SBen Gras return dst;
1802fe8fb19SBen Gras }
1812fe8fb19SBen Gras
1822fe8fb19SBen Gras /*
1832fe8fb19SBen Gras * This is do_mvis, for Quoted-Printable MIME (RFC 2045)
1842fe8fb19SBen Gras * NB: No handling of long lines or CRLF.
1852fe8fb19SBen Gras */
18684d9c625SLionel Sambuc static wchar_t *
do_mvis(wchar_t * dst,wint_t c,int flags,wint_t nextc,const wchar_t * extra)18784d9c625SLionel Sambuc do_mvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
1882fe8fb19SBen Gras {
18984d9c625SLionel Sambuc if ((c != L'\n') &&
1902fe8fb19SBen Gras /* Space at the end of the line */
19184d9c625SLionel Sambuc ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) ||
1922fe8fb19SBen Gras /* Out of range */
19384d9c625SLionel Sambuc (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||
1942fe8fb19SBen Gras /* Specific char to be escaped */
19584d9c625SLionel Sambuc wcschr(L"#$@[\\]^`{|}~", c) != NULL)) {
19684d9c625SLionel Sambuc *dst++ = L'=';
1972fe8fb19SBen Gras *dst++ = XTOA(((unsigned int)c >> 4) & 0xf);
1982fe8fb19SBen Gras *dst++ = XTOA((unsigned int)c & 0xf);
19984d9c625SLionel Sambuc } else
20084d9c625SLionel Sambuc dst = do_svis(dst, c, flags, nextc, extra);
20184d9c625SLionel Sambuc return dst;
2022fe8fb19SBen Gras }
20384d9c625SLionel Sambuc
20484d9c625SLionel Sambuc /*
20584d9c625SLionel Sambuc * Output single byte of multibyte character.
20684d9c625SLionel Sambuc */
20784d9c625SLionel Sambuc static wchar_t *
do_mbyte(wchar_t * dst,wint_t c,int flags,wint_t nextc,int iswextra)20884d9c625SLionel Sambuc do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra)
20984d9c625SLionel Sambuc {
21084d9c625SLionel Sambuc if (flags & VIS_CSTYLE) {
21184d9c625SLionel Sambuc switch (c) {
21284d9c625SLionel Sambuc case L'\n':
21384d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L'n';
21484d9c625SLionel Sambuc return dst;
21584d9c625SLionel Sambuc case L'\r':
21684d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L'r';
21784d9c625SLionel Sambuc return dst;
21884d9c625SLionel Sambuc case L'\b':
21984d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L'b';
22084d9c625SLionel Sambuc return dst;
22184d9c625SLionel Sambuc case BELL:
22284d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L'a';
22384d9c625SLionel Sambuc return dst;
22484d9c625SLionel Sambuc case L'\v':
22584d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L'v';
22684d9c625SLionel Sambuc return dst;
22784d9c625SLionel Sambuc case L'\t':
22884d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L't';
22984d9c625SLionel Sambuc return dst;
23084d9c625SLionel Sambuc case L'\f':
23184d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L'f';
23284d9c625SLionel Sambuc return dst;
23384d9c625SLionel Sambuc case L' ':
23484d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L's';
23584d9c625SLionel Sambuc return dst;
23684d9c625SLionel Sambuc case L'\0':
23784d9c625SLionel Sambuc *dst++ = L'\\'; *dst++ = L'0';
23884d9c625SLionel Sambuc if (iswoctal(nextc)) {
23984d9c625SLionel Sambuc *dst++ = L'0';
24084d9c625SLionel Sambuc *dst++ = L'0';
24184d9c625SLionel Sambuc }
24284d9c625SLionel Sambuc return dst;
243*0a6a1f1dSLionel Sambuc /* We cannot encode these characters in VIS_CSTYLE
244*0a6a1f1dSLionel Sambuc * because they special meaning */
245*0a6a1f1dSLionel Sambuc case L'n':
246*0a6a1f1dSLionel Sambuc case L'r':
247*0a6a1f1dSLionel Sambuc case L'b':
248*0a6a1f1dSLionel Sambuc case L'a':
249*0a6a1f1dSLionel Sambuc case L'v':
250*0a6a1f1dSLionel Sambuc case L't':
251*0a6a1f1dSLionel Sambuc case L'f':
252*0a6a1f1dSLionel Sambuc case L's':
253*0a6a1f1dSLionel Sambuc case L'0':
254*0a6a1f1dSLionel Sambuc case L'M':
255*0a6a1f1dSLionel Sambuc case L'^':
256*0a6a1f1dSLionel Sambuc case L'$': /* vis(1) -l */
257*0a6a1f1dSLionel Sambuc break;
25884d9c625SLionel Sambuc default:
259*0a6a1f1dSLionel Sambuc if (ISGRAPH(flags, c) && !iswoctal(c)) {
26084d9c625SLionel Sambuc *dst++ = L'\\';
26184d9c625SLionel Sambuc *dst++ = c;
26284d9c625SLionel Sambuc return dst;
26384d9c625SLionel Sambuc }
26484d9c625SLionel Sambuc }
26584d9c625SLionel Sambuc }
26684d9c625SLionel Sambuc if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) {
26784d9c625SLionel Sambuc *dst++ = L'\\';
26884d9c625SLionel Sambuc *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0';
26984d9c625SLionel Sambuc *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0';
27084d9c625SLionel Sambuc *dst++ = (c & 07) + L'0';
27184d9c625SLionel Sambuc } else {
27284d9c625SLionel Sambuc if ((flags & VIS_NOSLASH) == 0)
27384d9c625SLionel Sambuc *dst++ = L'\\';
27484d9c625SLionel Sambuc
27584d9c625SLionel Sambuc if (c & 0200) {
27684d9c625SLionel Sambuc c &= 0177;
27784d9c625SLionel Sambuc *dst++ = L'M';
27884d9c625SLionel Sambuc }
27984d9c625SLionel Sambuc
28084d9c625SLionel Sambuc if (iswcntrl(c)) {
28184d9c625SLionel Sambuc *dst++ = L'^';
28284d9c625SLionel Sambuc if (c == 0177)
28384d9c625SLionel Sambuc *dst++ = L'?';
28484d9c625SLionel Sambuc else
28584d9c625SLionel Sambuc *dst++ = c + L'@';
28684d9c625SLionel Sambuc } else {
28784d9c625SLionel Sambuc *dst++ = L'-';
28884d9c625SLionel Sambuc *dst++ = c;
28984d9c625SLionel Sambuc }
29084d9c625SLionel Sambuc }
29184d9c625SLionel Sambuc
2922fe8fb19SBen Gras return dst;
2932fe8fb19SBen Gras }
2942fe8fb19SBen Gras
2952fe8fb19SBen Gras /*
2962fe8fb19SBen Gras * This is do_vis, the central code of vis.
2972fe8fb19SBen Gras * dst: Pointer to the destination buffer
2982fe8fb19SBen Gras * c: Character to encode
29984d9c625SLionel Sambuc * flags: Flags word
3002fe8fb19SBen Gras * nextc: The character following 'c'
3012fe8fb19SBen Gras * extra: Pointer to the list of extra characters to be
3022fe8fb19SBen Gras * backslash-protected.
3032fe8fb19SBen Gras */
30484d9c625SLionel Sambuc static wchar_t *
do_svis(wchar_t * dst,wint_t c,int flags,wint_t nextc,const wchar_t * extra)30584d9c625SLionel Sambuc do_svis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
3062fe8fb19SBen Gras {
30784d9c625SLionel Sambuc int iswextra, i, shft;
30884d9c625SLionel Sambuc uint64_t bmsk, wmsk;
309f14fb602SLionel Sambuc
31084d9c625SLionel Sambuc iswextra = wcschr(extra, c) != NULL;
311*0a6a1f1dSLionel Sambuc if (!iswextra && (ISGRAPH(flags, c) || iswwhite(c) ||
31284d9c625SLionel Sambuc ((flags & VIS_SAFE) && iswsafe(c)))) {
3132fe8fb19SBen Gras *dst++ = c;
3142fe8fb19SBen Gras return dst;
3152fe8fb19SBen Gras }
31684d9c625SLionel Sambuc
31784d9c625SLionel Sambuc /* See comment in istrsenvisx() output loop, below. */
31884d9c625SLionel Sambuc wmsk = 0;
31984d9c625SLionel Sambuc for (i = sizeof(wmsk) - 1; i >= 0; i--) {
32084d9c625SLionel Sambuc shft = i * NBBY;
32184d9c625SLionel Sambuc bmsk = (uint64_t)0xffLL << shft;
32284d9c625SLionel Sambuc wmsk |= bmsk;
32384d9c625SLionel Sambuc if ((c & wmsk) || i == 0)
32484d9c625SLionel Sambuc dst = do_mbyte(dst, (wint_t)(
32584d9c625SLionel Sambuc (uint64_t)(c & bmsk) >> shft),
32684d9c625SLionel Sambuc flags, nextc, iswextra);
327f14fb602SLionel Sambuc }
328f14fb602SLionel Sambuc
3292fe8fb19SBen Gras return dst;
3302fe8fb19SBen Gras }
3312fe8fb19SBen Gras
33284d9c625SLionel Sambuc typedef wchar_t *(*visfun_t)(wchar_t *, wint_t, int, wint_t, const wchar_t *);
3332fe8fb19SBen Gras
3342fe8fb19SBen Gras /*
3352fe8fb19SBen Gras * Return the appropriate encoding function depending on the flags given.
3362fe8fb19SBen Gras */
3372fe8fb19SBen Gras static visfun_t
getvisfun(int flags)33884d9c625SLionel Sambuc getvisfun(int flags)
3392fe8fb19SBen Gras {
34084d9c625SLionel Sambuc if (flags & VIS_HTTPSTYLE)
3412fe8fb19SBen Gras return do_hvis;
34284d9c625SLionel Sambuc if (flags & VIS_MIMESTYLE)
3432fe8fb19SBen Gras return do_mvis;
3442fe8fb19SBen Gras return do_svis;
3452fe8fb19SBen Gras }
3462fe8fb19SBen Gras
3472fe8fb19SBen Gras /*
34884d9c625SLionel Sambuc * Expand list of extra characters to not visually encode.
3492fe8fb19SBen Gras */
35084d9c625SLionel Sambuc static wchar_t *
makeextralist(int flags,const char * src)35184d9c625SLionel Sambuc makeextralist(int flags, const char *src)
3522fe8fb19SBen Gras {
35384d9c625SLionel Sambuc wchar_t *dst, *d;
35484d9c625SLionel Sambuc size_t len;
355*0a6a1f1dSLionel Sambuc const wchar_t *s;
3562fe8fb19SBen Gras
35784d9c625SLionel Sambuc len = strlen(src);
35884d9c625SLionel Sambuc if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL)
359f14fb602SLionel Sambuc return NULL;
36084d9c625SLionel Sambuc
361*0a6a1f1dSLionel Sambuc if ((flags & VIS_NOLOCALE) || mbstowcs(dst, src, len) == (size_t)-1) {
36284d9c625SLionel Sambuc size_t i;
36384d9c625SLionel Sambuc for (i = 0; i < len; i++)
364*0a6a1f1dSLionel Sambuc dst[i] = (wchar_t)(u_char)src[i];
36584d9c625SLionel Sambuc d = dst + len;
36684d9c625SLionel Sambuc } else
36784d9c625SLionel Sambuc d = dst + wcslen(dst);
36884d9c625SLionel Sambuc
369*0a6a1f1dSLionel Sambuc if (flags & VIS_GLOB)
370*0a6a1f1dSLionel Sambuc for (s = char_glob; *s; *d++ = *s++)
371*0a6a1f1dSLionel Sambuc continue;
372*0a6a1f1dSLionel Sambuc
373*0a6a1f1dSLionel Sambuc if (flags & VIS_SHELL)
374*0a6a1f1dSLionel Sambuc for (s = char_shell; *s; *d++ = *s++)
375*0a6a1f1dSLionel Sambuc continue;
37684d9c625SLionel Sambuc
37784d9c625SLionel Sambuc if (flags & VIS_SP) *d++ = L' ';
37884d9c625SLionel Sambuc if (flags & VIS_TAB) *d++ = L'\t';
37984d9c625SLionel Sambuc if (flags & VIS_NL) *d++ = L'\n';
38084d9c625SLionel Sambuc if ((flags & VIS_NOSLASH) == 0) *d++ = L'\\';
38184d9c625SLionel Sambuc *d = L'\0';
38284d9c625SLionel Sambuc
3832fe8fb19SBen Gras return dst;
3842fe8fb19SBen Gras }
3852fe8fb19SBen Gras
3862fe8fb19SBen Gras /*
38784d9c625SLionel Sambuc * istrsenvisx()
38884d9c625SLionel Sambuc * The main internal function.
38984d9c625SLionel Sambuc * All user-visible functions call this one.
3902fe8fb19SBen Gras */
391f14fb602SLionel Sambuc static int
istrsenvisx(char * mbdst,size_t * dlen,const char * mbsrc,size_t mblength,int flags,const char * mbextra,int * cerr_ptr)39284d9c625SLionel Sambuc istrsenvisx(char *mbdst, size_t *dlen, const char *mbsrc, size_t mblength,
39384d9c625SLionel Sambuc int flags, const char *mbextra, int *cerr_ptr)
3942fe8fb19SBen Gras {
39584d9c625SLionel Sambuc wchar_t *dst, *src, *pdst, *psrc, *start, *extra;
39684d9c625SLionel Sambuc size_t len, olen;
39784d9c625SLionel Sambuc uint64_t bmsk, wmsk;
39884d9c625SLionel Sambuc wint_t c;
3992fe8fb19SBen Gras visfun_t f;
400*0a6a1f1dSLionel Sambuc int clen = 0, cerr, error = -1, i, shft;
40184d9c625SLionel Sambuc ssize_t mbslength, maxolen;
4022fe8fb19SBen Gras
40384d9c625SLionel Sambuc _DIAGASSERT(mbdst != NULL);
404*0a6a1f1dSLionel Sambuc _DIAGASSERT(mbsrc != NULL || mblength == 0);
40584d9c625SLionel Sambuc _DIAGASSERT(mbextra != NULL);
40684d9c625SLionel Sambuc
40784d9c625SLionel Sambuc /*
40884d9c625SLionel Sambuc * Input (mbsrc) is a char string considered to be multibyte
40984d9c625SLionel Sambuc * characters. The input loop will read this string pulling
41084d9c625SLionel Sambuc * one character, possibly multiple bytes, from mbsrc and
41184d9c625SLionel Sambuc * converting each to wchar_t in src.
41284d9c625SLionel Sambuc *
41384d9c625SLionel Sambuc * The vis conversion will be done using the wide char
41484d9c625SLionel Sambuc * wchar_t string.
41584d9c625SLionel Sambuc *
41684d9c625SLionel Sambuc * This will then be converted back to a multibyte string to
41784d9c625SLionel Sambuc * return to the caller.
41884d9c625SLionel Sambuc */
41984d9c625SLionel Sambuc
42084d9c625SLionel Sambuc /* Allocate space for the wide char strings */
42184d9c625SLionel Sambuc psrc = pdst = extra = NULL;
42284d9c625SLionel Sambuc if ((psrc = calloc(mblength + 1, sizeof(*psrc))) == NULL)
423f14fb602SLionel Sambuc return -1;
42484d9c625SLionel Sambuc if ((pdst = calloc((4 * mblength) + 1, sizeof(*pdst))) == NULL)
42584d9c625SLionel Sambuc goto out;
42684d9c625SLionel Sambuc dst = pdst;
42784d9c625SLionel Sambuc src = psrc;
42884d9c625SLionel Sambuc
429*0a6a1f1dSLionel Sambuc if (flags & VIS_NOLOCALE) {
430*0a6a1f1dSLionel Sambuc /* Do one byte at a time conversion */
431*0a6a1f1dSLionel Sambuc cerr = 1;
432*0a6a1f1dSLionel Sambuc } else {
43384d9c625SLionel Sambuc /* Use caller's multibyte conversion error flag. */
434*0a6a1f1dSLionel Sambuc cerr = cerr_ptr ? *cerr_ptr : 0;
435*0a6a1f1dSLionel Sambuc }
43684d9c625SLionel Sambuc
43784d9c625SLionel Sambuc /*
43884d9c625SLionel Sambuc * Input loop.
43984d9c625SLionel Sambuc * Handle up to mblength characters (not bytes). We do not
44084d9c625SLionel Sambuc * stop at NULs because we may be processing a block of data
44184d9c625SLionel Sambuc * that includes NULs.
44284d9c625SLionel Sambuc */
44384d9c625SLionel Sambuc mbslength = (ssize_t)mblength;
44484d9c625SLionel Sambuc /*
44584d9c625SLionel Sambuc * When inputing a single character, must also read in the
44684d9c625SLionel Sambuc * next character for nextc, the look-ahead character.
44784d9c625SLionel Sambuc */
44884d9c625SLionel Sambuc if (mbslength == 1)
44984d9c625SLionel Sambuc mbslength++;
45084d9c625SLionel Sambuc while (mbslength > 0) {
45184d9c625SLionel Sambuc /* Convert one multibyte character to wchar_t. */
45284d9c625SLionel Sambuc if (!cerr)
45384d9c625SLionel Sambuc clen = mbtowc(src, mbsrc, MB_LEN_MAX);
45484d9c625SLionel Sambuc if (cerr || clen < 0) {
45584d9c625SLionel Sambuc /* Conversion error, process as a byte instead. */
45684d9c625SLionel Sambuc *src = (wint_t)(u_char)*mbsrc;
45784d9c625SLionel Sambuc clen = 1;
45884d9c625SLionel Sambuc cerr = 1;
459f14fb602SLionel Sambuc }
46084d9c625SLionel Sambuc if (clen == 0)
46184d9c625SLionel Sambuc /*
46284d9c625SLionel Sambuc * NUL in input gives 0 return value. process
46384d9c625SLionel Sambuc * as single NUL byte and keep going.
46484d9c625SLionel Sambuc */
46584d9c625SLionel Sambuc clen = 1;
46684d9c625SLionel Sambuc /* Advance buffer character pointer. */
46784d9c625SLionel Sambuc src++;
46884d9c625SLionel Sambuc /* Advance input pointer by number of bytes read. */
46984d9c625SLionel Sambuc mbsrc += clen;
47084d9c625SLionel Sambuc /* Decrement input byte count. */
47184d9c625SLionel Sambuc mbslength -= clen;
472f14fb602SLionel Sambuc }
47384d9c625SLionel Sambuc len = src - psrc;
47484d9c625SLionel Sambuc src = psrc;
47584d9c625SLionel Sambuc /*
47684d9c625SLionel Sambuc * In the single character input case, we will have actually
47784d9c625SLionel Sambuc * processed two characters, c and nextc. Reset len back to
47884d9c625SLionel Sambuc * just a single character.
47984d9c625SLionel Sambuc */
48084d9c625SLionel Sambuc if (mblength < len)
48184d9c625SLionel Sambuc len = mblength;
48284d9c625SLionel Sambuc
48384d9c625SLionel Sambuc /* Convert extra argument to list of characters for this mode. */
48484d9c625SLionel Sambuc extra = makeextralist(flags, mbextra);
48584d9c625SLionel Sambuc if (!extra) {
486f14fb602SLionel Sambuc if (dlen && *dlen == 0) {
487f14fb602SLionel Sambuc errno = ENOSPC;
48884d9c625SLionel Sambuc goto out;
489f14fb602SLionel Sambuc }
49084d9c625SLionel Sambuc *mbdst = '\0'; /* can't create extra, return "" */
49184d9c625SLionel Sambuc error = 0;
49284d9c625SLionel Sambuc goto out;
4932fe8fb19SBen Gras }
4942fe8fb19SBen Gras
49584d9c625SLionel Sambuc /* Look up which processing function to call. */
49684d9c625SLionel Sambuc f = getvisfun(flags);
4972fe8fb19SBen Gras
49884d9c625SLionel Sambuc /*
49984d9c625SLionel Sambuc * Main processing loop.
50084d9c625SLionel Sambuc * Call do_Xvis processing function one character at a time
50184d9c625SLionel Sambuc * with next character available for look-ahead.
50284d9c625SLionel Sambuc */
5032fe8fb19SBen Gras for (start = dst; len > 0; len--) {
5042fe8fb19SBen Gras c = *src++;
50584d9c625SLionel Sambuc dst = (*f)(dst, c, flags, len >= 1 ? *src : L'\0', extra);
506f14fb602SLionel Sambuc if (dst == NULL) {
507f14fb602SLionel Sambuc errno = ENOSPC;
50884d9c625SLionel Sambuc goto out;
509f14fb602SLionel Sambuc }
5102fe8fb19SBen Gras }
51184d9c625SLionel Sambuc
51284d9c625SLionel Sambuc /* Terminate the string in the buffer. */
51384d9c625SLionel Sambuc *dst = L'\0';
51484d9c625SLionel Sambuc
51584d9c625SLionel Sambuc /*
51684d9c625SLionel Sambuc * Output loop.
51784d9c625SLionel Sambuc * Convert wchar_t string back to multibyte output string.
51884d9c625SLionel Sambuc * If we have hit a multi-byte conversion error on input,
51984d9c625SLionel Sambuc * output byte-by-byte here. Else use wctomb().
52084d9c625SLionel Sambuc */
52184d9c625SLionel Sambuc len = wcslen(start);
52284d9c625SLionel Sambuc maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1);
52384d9c625SLionel Sambuc olen = 0;
52484d9c625SLionel Sambuc for (dst = start; len > 0; len--) {
52584d9c625SLionel Sambuc if (!cerr)
52684d9c625SLionel Sambuc clen = wctomb(mbdst, *dst);
52784d9c625SLionel Sambuc if (cerr || clen < 0) {
52884d9c625SLionel Sambuc /*
52984d9c625SLionel Sambuc * Conversion error, process as a byte(s) instead.
53084d9c625SLionel Sambuc * Examine each byte and higher-order bytes for
53184d9c625SLionel Sambuc * data. E.g.,
53284d9c625SLionel Sambuc * 0x000000000000a264 -> a2 64
53384d9c625SLionel Sambuc * 0x000000001f00a264 -> 1f 00 a2 64
53484d9c625SLionel Sambuc */
53584d9c625SLionel Sambuc clen = 0;
53684d9c625SLionel Sambuc wmsk = 0;
53784d9c625SLionel Sambuc for (i = sizeof(wmsk) - 1; i >= 0; i--) {
53884d9c625SLionel Sambuc shft = i * NBBY;
53984d9c625SLionel Sambuc bmsk = (uint64_t)0xffLL << shft;
54084d9c625SLionel Sambuc wmsk |= bmsk;
54184d9c625SLionel Sambuc if ((*dst & wmsk) || i == 0)
54284d9c625SLionel Sambuc mbdst[clen++] = (char)(
54384d9c625SLionel Sambuc (uint64_t)(*dst & bmsk) >>
54484d9c625SLionel Sambuc shft);
545f14fb602SLionel Sambuc }
54684d9c625SLionel Sambuc cerr = 1;
54784d9c625SLionel Sambuc }
54884d9c625SLionel Sambuc /* If this character would exceed our output limit, stop. */
54984d9c625SLionel Sambuc if (olen + clen > (size_t)maxolen)
55084d9c625SLionel Sambuc break;
55184d9c625SLionel Sambuc /* Advance output pointer by number of bytes written. */
55284d9c625SLionel Sambuc mbdst += clen;
55384d9c625SLionel Sambuc /* Advance buffer character pointer. */
55484d9c625SLionel Sambuc dst++;
55584d9c625SLionel Sambuc /* Incrment output character count. */
55684d9c625SLionel Sambuc olen += clen;
55784d9c625SLionel Sambuc }
55884d9c625SLionel Sambuc
55984d9c625SLionel Sambuc /* Terminate the output string. */
56084d9c625SLionel Sambuc *mbdst = '\0';
56184d9c625SLionel Sambuc
562*0a6a1f1dSLionel Sambuc if (flags & VIS_NOLOCALE) {
56384d9c625SLionel Sambuc /* Pass conversion error flag out. */
56484d9c625SLionel Sambuc if (cerr_ptr)
56584d9c625SLionel Sambuc *cerr_ptr = cerr;
566*0a6a1f1dSLionel Sambuc }
56784d9c625SLionel Sambuc
56884d9c625SLionel Sambuc free(extra);
56984d9c625SLionel Sambuc free(pdst);
57084d9c625SLionel Sambuc free(psrc);
57184d9c625SLionel Sambuc
57284d9c625SLionel Sambuc return (int)olen;
57384d9c625SLionel Sambuc out:
57484d9c625SLionel Sambuc free(extra);
57584d9c625SLionel Sambuc free(pdst);
57684d9c625SLionel Sambuc free(psrc);
57784d9c625SLionel Sambuc return error;
57884d9c625SLionel Sambuc }
579*0a6a1f1dSLionel Sambuc
580*0a6a1f1dSLionel Sambuc static int
istrsenvisxl(char * mbdst,size_t * dlen,const char * mbsrc,int flags,const char * mbextra,int * cerr_ptr)581*0a6a1f1dSLionel Sambuc istrsenvisxl(char *mbdst, size_t *dlen, const char *mbsrc,
582*0a6a1f1dSLionel Sambuc int flags, const char *mbextra, int *cerr_ptr)
583*0a6a1f1dSLionel Sambuc {
584*0a6a1f1dSLionel Sambuc return istrsenvisx(mbdst, dlen, mbsrc,
585*0a6a1f1dSLionel Sambuc mbsrc != NULL ? strlen(mbsrc) : 0, flags, mbextra, cerr_ptr);
586*0a6a1f1dSLionel Sambuc }
587*0a6a1f1dSLionel Sambuc
58884d9c625SLionel Sambuc #endif
58984d9c625SLionel Sambuc
59084d9c625SLionel Sambuc #if !HAVE_SVIS
59184d9c625SLionel Sambuc /*
59284d9c625SLionel Sambuc * The "svis" variants all take an "extra" arg that is a pointer
59384d9c625SLionel Sambuc * to a NUL-terminated list of characters to be encoded, too.
59484d9c625SLionel Sambuc * These functions are useful e. g. to encode strings in such a
59584d9c625SLionel Sambuc * way so that they are not interpreted by a shell.
59684d9c625SLionel Sambuc */
59784d9c625SLionel Sambuc
59884d9c625SLionel Sambuc char *
svis(char * mbdst,int c,int flags,int nextc,const char * mbextra)59984d9c625SLionel Sambuc svis(char *mbdst, int c, int flags, int nextc, const char *mbextra)
60084d9c625SLionel Sambuc {
60184d9c625SLionel Sambuc char cc[2];
60284d9c625SLionel Sambuc int ret;
60384d9c625SLionel Sambuc
60484d9c625SLionel Sambuc cc[0] = c;
60584d9c625SLionel Sambuc cc[1] = nextc;
60684d9c625SLionel Sambuc
60784d9c625SLionel Sambuc ret = istrsenvisx(mbdst, NULL, cc, 1, flags, mbextra, NULL);
60884d9c625SLionel Sambuc if (ret < 0)
60984d9c625SLionel Sambuc return NULL;
61084d9c625SLionel Sambuc return mbdst + ret;
61184d9c625SLionel Sambuc }
61284d9c625SLionel Sambuc
61384d9c625SLionel Sambuc char *
snvis(char * mbdst,size_t dlen,int c,int flags,int nextc,const char * mbextra)61484d9c625SLionel Sambuc snvis(char *mbdst, size_t dlen, int c, int flags, int nextc, const char *mbextra)
61584d9c625SLionel Sambuc {
61684d9c625SLionel Sambuc char cc[2];
61784d9c625SLionel Sambuc int ret;
61884d9c625SLionel Sambuc
61984d9c625SLionel Sambuc cc[0] = c;
62084d9c625SLionel Sambuc cc[1] = nextc;
62184d9c625SLionel Sambuc
62284d9c625SLionel Sambuc ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, mbextra, NULL);
62384d9c625SLionel Sambuc if (ret < 0)
62484d9c625SLionel Sambuc return NULL;
62584d9c625SLionel Sambuc return mbdst + ret;
6262fe8fb19SBen Gras }
627f14fb602SLionel Sambuc
628f14fb602SLionel Sambuc int
strsvis(char * mbdst,const char * mbsrc,int flags,const char * mbextra)62984d9c625SLionel Sambuc strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra)
630f14fb602SLionel Sambuc {
631*0a6a1f1dSLionel Sambuc return istrsenvisxl(mbdst, NULL, mbsrc, flags, mbextra, NULL);
632f14fb602SLionel Sambuc }
633f14fb602SLionel Sambuc
634f14fb602SLionel Sambuc int
strsnvis(char * mbdst,size_t dlen,const char * mbsrc,int flags,const char * mbextra)63584d9c625SLionel Sambuc strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra)
636f14fb602SLionel Sambuc {
637*0a6a1f1dSLionel Sambuc return istrsenvisxl(mbdst, &dlen, mbsrc, flags, mbextra, NULL);
63884d9c625SLionel Sambuc }
63984d9c625SLionel Sambuc
64084d9c625SLionel Sambuc int
strsvisx(char * mbdst,const char * mbsrc,size_t len,int flags,const char * mbextra)64184d9c625SLionel Sambuc strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra)
64284d9c625SLionel Sambuc {
64384d9c625SLionel Sambuc return istrsenvisx(mbdst, NULL, mbsrc, len, flags, mbextra, NULL);
64484d9c625SLionel Sambuc }
64584d9c625SLionel Sambuc
64684d9c625SLionel Sambuc int
strsnvisx(char * mbdst,size_t dlen,const char * mbsrc,size_t len,int flags,const char * mbextra)64784d9c625SLionel Sambuc strsnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
64884d9c625SLionel Sambuc const char *mbextra)
64984d9c625SLionel Sambuc {
65084d9c625SLionel Sambuc return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, NULL);
65184d9c625SLionel Sambuc }
65284d9c625SLionel Sambuc
65384d9c625SLionel Sambuc int
strsenvisx(char * mbdst,size_t dlen,const char * mbsrc,size_t len,int flags,const char * mbextra,int * cerr_ptr)65484d9c625SLionel Sambuc strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
65584d9c625SLionel Sambuc const char *mbextra, int *cerr_ptr)
65684d9c625SLionel Sambuc {
65784d9c625SLionel Sambuc return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, cerr_ptr);
658f14fb602SLionel Sambuc }
6592fe8fb19SBen Gras #endif
6602fe8fb19SBen Gras
6612fe8fb19SBen Gras #if !HAVE_VIS
6622fe8fb19SBen Gras /*
6632fe8fb19SBen Gras * vis - visually encode characters
6642fe8fb19SBen Gras */
66584d9c625SLionel Sambuc char *
vis(char * mbdst,int c,int flags,int nextc)66684d9c625SLionel Sambuc vis(char *mbdst, int c, int flags, int nextc)
6672fe8fb19SBen Gras {
66884d9c625SLionel Sambuc char cc[2];
66984d9c625SLionel Sambuc int ret;
6702fe8fb19SBen Gras
67184d9c625SLionel Sambuc cc[0] = c;
67284d9c625SLionel Sambuc cc[1] = nextc;
6732fe8fb19SBen Gras
67484d9c625SLionel Sambuc ret = istrsenvisx(mbdst, NULL, cc, 1, flags, "", NULL);
67584d9c625SLionel Sambuc if (ret < 0)
676f14fb602SLionel Sambuc return NULL;
67784d9c625SLionel Sambuc return mbdst + ret;
6782fe8fb19SBen Gras }
6792fe8fb19SBen Gras
680f14fb602SLionel Sambuc char *
nvis(char * mbdst,size_t dlen,int c,int flags,int nextc)68184d9c625SLionel Sambuc nvis(char *mbdst, size_t dlen, int c, int flags, int nextc)
682f14fb602SLionel Sambuc {
68384d9c625SLionel Sambuc char cc[2];
68484d9c625SLionel Sambuc int ret;
685f14fb602SLionel Sambuc
68684d9c625SLionel Sambuc cc[0] = c;
68784d9c625SLionel Sambuc cc[1] = nextc;
688f14fb602SLionel Sambuc
68984d9c625SLionel Sambuc ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, "", NULL);
69084d9c625SLionel Sambuc if (ret < 0)
69184d9c625SLionel Sambuc return NULL;
69284d9c625SLionel Sambuc return mbdst + ret;
69384d9c625SLionel Sambuc }
6942fe8fb19SBen Gras
6952fe8fb19SBen Gras /*
69684d9c625SLionel Sambuc * strvis - visually encode characters from src into dst
69784d9c625SLionel Sambuc *
69884d9c625SLionel Sambuc * Dst must be 4 times the size of src to account for possible
69984d9c625SLionel Sambuc * expansion. The length of dst, not including the trailing NULL,
70084d9c625SLionel Sambuc * is returned.
70184d9c625SLionel Sambuc */
70284d9c625SLionel Sambuc
70384d9c625SLionel Sambuc int
strvis(char * mbdst,const char * mbsrc,int flags)70484d9c625SLionel Sambuc strvis(char *mbdst, const char *mbsrc, int flags)
70584d9c625SLionel Sambuc {
706*0a6a1f1dSLionel Sambuc return istrsenvisxl(mbdst, NULL, mbsrc, flags, "", NULL);
70784d9c625SLionel Sambuc }
70884d9c625SLionel Sambuc
70984d9c625SLionel Sambuc int
strnvis(char * mbdst,size_t dlen,const char * mbsrc,int flags)71084d9c625SLionel Sambuc strnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags)
71184d9c625SLionel Sambuc {
712*0a6a1f1dSLionel Sambuc return istrsenvisxl(mbdst, &dlen, mbsrc, flags, "", NULL);
71384d9c625SLionel Sambuc }
71484d9c625SLionel Sambuc
71584d9c625SLionel Sambuc /*
71684d9c625SLionel Sambuc * strvisx - visually encode characters from src into dst
7172fe8fb19SBen Gras *
7182fe8fb19SBen Gras * Dst must be 4 times the size of src to account for possible
7192fe8fb19SBen Gras * expansion. The length of dst, not including the trailing NULL,
7202fe8fb19SBen Gras * is returned.
7212fe8fb19SBen Gras *
72284d9c625SLionel Sambuc * Strvisx encodes exactly len characters from src into dst.
7232fe8fb19SBen Gras * This is useful for encoding a block of data.
7242fe8fb19SBen Gras */
7252fe8fb19SBen Gras
72684d9c625SLionel Sambuc int
strvisx(char * mbdst,const char * mbsrc,size_t len,int flags)72784d9c625SLionel Sambuc strvisx(char *mbdst, const char *mbsrc, size_t len, int flags)
72884d9c625SLionel Sambuc {
72984d9c625SLionel Sambuc return istrsenvisx(mbdst, NULL, mbsrc, len, flags, "", NULL);
7302fe8fb19SBen Gras }
7312fe8fb19SBen Gras
732f14fb602SLionel Sambuc int
strnvisx(char * mbdst,size_t dlen,const char * mbsrc,size_t len,int flags)73384d9c625SLionel Sambuc strnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags)
734f14fb602SLionel Sambuc {
73584d9c625SLionel Sambuc return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", NULL);
736f14fb602SLionel Sambuc }
737f14fb602SLionel Sambuc
738f14fb602SLionel Sambuc int
strenvisx(char * mbdst,size_t dlen,const char * mbsrc,size_t len,int flags,int * cerr_ptr)73984d9c625SLionel Sambuc strenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
74084d9c625SLionel Sambuc int *cerr_ptr)
741f14fb602SLionel Sambuc {
74284d9c625SLionel Sambuc return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", cerr_ptr);
743f14fb602SLionel Sambuc }
7442fe8fb19SBen Gras #endif
745