vis.c revision 244401
1244230Sbrooks/* $NetBSD: vis.c,v 1.45 2012/12/14 21:38:18 christos Exp $ */ 2241236Sbrooks 3241236Sbrooks/*- 4241236Sbrooks * Copyright (c) 1989, 1993 5241236Sbrooks * The Regents of the University of California. All rights reserved. 6241236Sbrooks * 7241236Sbrooks * Redistribution and use in source and binary forms, with or without 8241236Sbrooks * modification, are permitted provided that the following conditions 9241236Sbrooks * are met: 10241236Sbrooks * 1. Redistributions of source code must retain the above copyright 11241236Sbrooks * notice, this list of conditions and the following disclaimer. 12241236Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 13241236Sbrooks * notice, this list of conditions and the following disclaimer in the 14241236Sbrooks * documentation and/or other materials provided with the distribution. 15241236Sbrooks * 3. Neither the name of the University nor the names of its contributors 16241236Sbrooks * may be used to endorse or promote products derived from this software 17241236Sbrooks * without specific prior written permission. 18241236Sbrooks * 19241236Sbrooks * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20241236Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21241236Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22241236Sbrooks * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23241236Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24241236Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25241236Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26241236Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27241236Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28241236Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29241236Sbrooks * SUCH DAMAGE. 30241236Sbrooks */ 31241236Sbrooks 32241236Sbrooks/*- 33241236Sbrooks * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc. 34241236Sbrooks * All rights reserved. 35241236Sbrooks * 36241236Sbrooks * Redistribution and use in source and binary forms, with or without 37241236Sbrooks * modification, are permitted provided that the following conditions 38241236Sbrooks * are met: 39241236Sbrooks * 1. Redistributions of source code must retain the above copyright 40241236Sbrooks * notice, this list of conditions and the following disclaimer. 41241236Sbrooks * 2. Redistributions in binary form must reproduce the above copyright 42241236Sbrooks * notice, this list of conditions and the following disclaimer in the 43241236Sbrooks * documentation and/or other materials provided with the distribution. 44241236Sbrooks * 45241236Sbrooks * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 46241236Sbrooks * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 47241236Sbrooks * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48241236Sbrooks * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 49241236Sbrooks * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50241236Sbrooks * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 51241236Sbrooks * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 52241236Sbrooks * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 53241236Sbrooks * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54241236Sbrooks * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 55241236Sbrooks * POSSIBILITY OF SUCH DAMAGE. 56241236Sbrooks */ 57241236Sbrooks 58241236Sbrooks#include <sys/cdefs.h> 59241236Sbrooks#if defined(LIBC_SCCS) && !defined(lint) 60244230Sbrooks__RCSID("$NetBSD: vis.c,v 1.45 2012/12/14 21:38:18 christos Exp $"); 61241236Sbrooks#endif /* LIBC_SCCS and not lint */ 62244401Sbrooks__FBSDID("$FreeBSD: head/contrib/libc-vis/vis.c 244401 2012-12-18 16:37:24Z brooks $"); 63241236Sbrooks 64241236Sbrooks#include "namespace.h" 65241236Sbrooks#include <sys/types.h> 66241236Sbrooks 67241236Sbrooks#include <assert.h> 68241236Sbrooks#include <vis.h> 69241236Sbrooks#include <errno.h> 70241236Sbrooks#include <stdlib.h> 71241236Sbrooks 72244401Sbrooks#define _DIAGASSERT(x) assert(x) 73244401Sbrooks 74241236Sbrooks#ifdef __weak_alias 75241236Sbrooks__weak_alias(strvisx,_strvisx) 76241236Sbrooks#endif 77241236Sbrooks 78241236Sbrooks#if !HAVE_VIS || !HAVE_SVIS 79241236Sbrooks#include <ctype.h> 80241236Sbrooks#include <limits.h> 81241236Sbrooks#include <stdio.h> 82241236Sbrooks#include <string.h> 83241236Sbrooks 84241236Sbrooksstatic char *do_svis(char *, size_t *, int, int, int, const char *); 85241236Sbrooks 86241236Sbrooks#undef BELL 87241236Sbrooks#define BELL '\a' 88241236Sbrooks 89241236Sbrooks#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 90241236Sbrooks#define iswhite(c) (c == ' ' || c == '\t' || c == '\n') 91241236Sbrooks#define issafe(c) (c == '\b' || c == BELL || c == '\r') 92241236Sbrooks#define xtoa(c) "0123456789abcdef"[c] 93241236Sbrooks#define XTOA(c) "0123456789ABCDEF"[c] 94241236Sbrooks 95244230Sbrooks#define MAXEXTRAS 9 96241236Sbrooks 97241236Sbrooks#define MAKEEXTRALIST(flag, extra, orig_str) \ 98241236Sbrooksdo { \ 99241236Sbrooks const char *orig = orig_str; \ 100241236Sbrooks const char *o = orig; \ 101241236Sbrooks char *e; \ 102241236Sbrooks while (*o++) \ 103241236Sbrooks continue; \ 104241236Sbrooks extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \ 105241236Sbrooks if (!extra) break; \ 106241236Sbrooks for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ 107241236Sbrooks continue; \ 108241236Sbrooks e--; \ 109244230Sbrooks if (flag & VIS_GLOB) { \ 110244230Sbrooks *e++ = '*'; \ 111244230Sbrooks *e++ = '?'; \ 112244230Sbrooks *e++ = '['; \ 113244230Sbrooks *e++ = '#'; \ 114244230Sbrooks } \ 115241236Sbrooks if (flag & VIS_SP) *e++ = ' '; \ 116241236Sbrooks if (flag & VIS_TAB) *e++ = '\t'; \ 117241236Sbrooks if (flag & VIS_NL) *e++ = '\n'; \ 118241236Sbrooks if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ 119241236Sbrooks *e = '\0'; \ 120241236Sbrooks} while (/*CONSTCOND*/0) 121241236Sbrooks 122241236Sbrooks/* 123241236Sbrooks * This is do_hvis, for HTTP style (RFC 1808) 124241236Sbrooks */ 125241236Sbrooksstatic char * 126241236Sbrooksdo_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) 127241236Sbrooks{ 128241236Sbrooks 129241236Sbrooks if ((isascii(c) && isalnum(c)) 130241236Sbrooks /* safe */ 131241236Sbrooks || c == '$' || c == '-' || c == '_' || c == '.' || c == '+' 132241236Sbrooks /* extra */ 133241236Sbrooks || c == '!' || c == '*' || c == '\'' || c == '(' || c == ')' 134241236Sbrooks || c == ',') { 135241236Sbrooks dst = do_svis(dst, dlen, c, flag, nextc, extra); 136241236Sbrooks } else { 137241236Sbrooks if (dlen) { 138241236Sbrooks if (*dlen < 3) 139241236Sbrooks return NULL; 140241236Sbrooks *dlen -= 3; 141241236Sbrooks } 142241236Sbrooks *dst++ = '%'; 143241236Sbrooks *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); 144241236Sbrooks *dst++ = xtoa((unsigned int)c & 0xf); 145241236Sbrooks } 146241236Sbrooks 147241236Sbrooks return dst; 148241236Sbrooks} 149241236Sbrooks 150241236Sbrooks/* 151241236Sbrooks * This is do_mvis, for Quoted-Printable MIME (RFC 2045) 152241236Sbrooks * NB: No handling of long lines or CRLF. 153241236Sbrooks */ 154241236Sbrooksstatic char * 155241236Sbrooksdo_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) 156241236Sbrooks{ 157241236Sbrooks if ((c != '\n') && 158241236Sbrooks /* Space at the end of the line */ 159241236Sbrooks ((isspace(c) && (nextc == '\r' || nextc == '\n')) || 160241236Sbrooks /* Out of range */ 161241236Sbrooks (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || 162241236Sbrooks /* Specific char to be escaped */ 163241236Sbrooks strchr("#$@[\\]^`{|}~", c) != NULL)) { 164241236Sbrooks if (dlen) { 165241236Sbrooks if (*dlen < 3) 166241236Sbrooks return NULL; 167241236Sbrooks *dlen -= 3; 168241236Sbrooks } 169241236Sbrooks *dst++ = '='; 170241236Sbrooks *dst++ = XTOA(((unsigned int)c >> 4) & 0xf); 171241236Sbrooks *dst++ = XTOA((unsigned int)c & 0xf); 172241236Sbrooks } else { 173241236Sbrooks dst = do_svis(dst, dlen, c, flag, nextc, extra); 174241236Sbrooks } 175241236Sbrooks return dst; 176241236Sbrooks} 177241236Sbrooks 178241236Sbrooks/* 179241236Sbrooks * This is do_vis, the central code of vis. 180241236Sbrooks * dst: Pointer to the destination buffer 181241236Sbrooks * c: Character to encode 182241236Sbrooks * flag: Flag word 183241236Sbrooks * nextc: The character following 'c' 184241236Sbrooks * extra: Pointer to the list of extra characters to be 185241236Sbrooks * backslash-protected. 186241236Sbrooks */ 187241236Sbrooksstatic char * 188241236Sbrooksdo_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) 189241236Sbrooks{ 190241236Sbrooks int isextra; 191241236Sbrooks size_t odlen = dlen ? *dlen : 0; 192241236Sbrooks 193241236Sbrooks isextra = strchr(extra, c) != NULL; 194241236Sbrooks#define HAVE(x) \ 195241236Sbrooks do { \ 196241236Sbrooks if (dlen) { \ 197241236Sbrooks if (*dlen < (x)) \ 198241236Sbrooks goto out; \ 199241236Sbrooks *dlen -= (x); \ 200241236Sbrooks } \ 201241236Sbrooks } while (/*CONSTCOND*/0) 202241236Sbrooks if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || 203241236Sbrooks ((flag & VIS_SAFE) && issafe(c)))) { 204241236Sbrooks HAVE(1); 205241236Sbrooks *dst++ = c; 206241236Sbrooks return dst; 207241236Sbrooks } 208241236Sbrooks if (flag & VIS_CSTYLE) { 209241236Sbrooks HAVE(2); 210241236Sbrooks switch (c) { 211241236Sbrooks case '\n': 212241236Sbrooks *dst++ = '\\'; *dst++ = 'n'; 213241236Sbrooks return dst; 214241236Sbrooks case '\r': 215241236Sbrooks *dst++ = '\\'; *dst++ = 'r'; 216241236Sbrooks return dst; 217241236Sbrooks case '\b': 218241236Sbrooks *dst++ = '\\'; *dst++ = 'b'; 219241236Sbrooks return dst; 220241236Sbrooks case BELL: 221241236Sbrooks *dst++ = '\\'; *dst++ = 'a'; 222241236Sbrooks return dst; 223241236Sbrooks case '\v': 224241236Sbrooks *dst++ = '\\'; *dst++ = 'v'; 225241236Sbrooks return dst; 226241236Sbrooks case '\t': 227241236Sbrooks *dst++ = '\\'; *dst++ = 't'; 228241236Sbrooks return dst; 229241236Sbrooks case '\f': 230241236Sbrooks *dst++ = '\\'; *dst++ = 'f'; 231241236Sbrooks return dst; 232241236Sbrooks case ' ': 233241236Sbrooks *dst++ = '\\'; *dst++ = 's'; 234241236Sbrooks return dst; 235241236Sbrooks case '\0': 236241236Sbrooks *dst++ = '\\'; *dst++ = '0'; 237241236Sbrooks if (isoctal(nextc)) { 238241236Sbrooks HAVE(2); 239241236Sbrooks *dst++ = '0'; 240241236Sbrooks *dst++ = '0'; 241241236Sbrooks } 242241236Sbrooks return dst; 243241236Sbrooks default: 244241236Sbrooks if (isgraph(c)) { 245241236Sbrooks *dst++ = '\\'; *dst++ = c; 246241236Sbrooks return dst; 247241236Sbrooks } 248241236Sbrooks if (dlen) 249241236Sbrooks *dlen = odlen; 250241236Sbrooks } 251241236Sbrooks } 252241236Sbrooks if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { 253241236Sbrooks HAVE(4); 254241236Sbrooks *dst++ = '\\'; 255241236Sbrooks *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; 256241236Sbrooks *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; 257241236Sbrooks *dst++ = (c & 07) + '0'; 258241236Sbrooks } else { 259241236Sbrooks if ((flag & VIS_NOSLASH) == 0) { 260241236Sbrooks HAVE(1); 261241236Sbrooks *dst++ = '\\'; 262241236Sbrooks } 263241236Sbrooks 264241236Sbrooks if (c & 0200) { 265241236Sbrooks HAVE(1); 266241236Sbrooks c &= 0177; *dst++ = 'M'; 267241236Sbrooks } 268241236Sbrooks 269241236Sbrooks if (iscntrl(c)) { 270241236Sbrooks HAVE(2); 271241236Sbrooks *dst++ = '^'; 272241236Sbrooks if (c == 0177) 273241236Sbrooks *dst++ = '?'; 274241236Sbrooks else 275241236Sbrooks *dst++ = c + '@'; 276241236Sbrooks } else { 277241236Sbrooks HAVE(2); 278241236Sbrooks *dst++ = '-'; *dst++ = c; 279241236Sbrooks } 280241236Sbrooks } 281241236Sbrooks return dst; 282241236Sbrooksout: 283241236Sbrooks *dlen = odlen; 284241236Sbrooks return NULL; 285241236Sbrooks} 286241236Sbrooks 287241236Sbrookstypedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *); 288241236Sbrooks 289241236Sbrooks/* 290241236Sbrooks * Return the appropriate encoding function depending on the flags given. 291241236Sbrooks */ 292241236Sbrooksstatic visfun_t 293241236Sbrooksgetvisfun(int flag) 294241236Sbrooks{ 295241236Sbrooks if (flag & VIS_HTTPSTYLE) 296241236Sbrooks return do_hvis; 297241236Sbrooks if (flag & VIS_MIMESTYLE) 298241236Sbrooks return do_mvis; 299241236Sbrooks return do_svis; 300241236Sbrooks} 301241236Sbrooks 302241236Sbrooks/* 303241236Sbrooks * isnvis - visually encode characters, also encoding the characters 304241236Sbrooks * pointed to by `extra' 305241236Sbrooks */ 306241236Sbrooksstatic char * 307241236Sbrooksisnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) 308241236Sbrooks{ 309241236Sbrooks char *nextra = NULL; 310241236Sbrooks visfun_t f; 311241236Sbrooks 312241236Sbrooks _DIAGASSERT(dst != NULL); 313241236Sbrooks _DIAGASSERT(extra != NULL); 314241236Sbrooks MAKEEXTRALIST(flag, nextra, extra); 315241236Sbrooks if (!nextra) { 316241236Sbrooks if (dlen && *dlen == 0) { 317241236Sbrooks errno = ENOSPC; 318241236Sbrooks return NULL; 319241236Sbrooks } 320241236Sbrooks *dst = '\0'; /* can't create nextra, return "" */ 321241236Sbrooks return dst; 322241236Sbrooks } 323241236Sbrooks f = getvisfun(flag); 324241236Sbrooks dst = (*f)(dst, dlen, c, flag, nextc, nextra); 325241236Sbrooks free(nextra); 326241236Sbrooks if (dst == NULL || (dlen && *dlen == 0)) { 327241236Sbrooks errno = ENOSPC; 328241236Sbrooks return NULL; 329241236Sbrooks } 330241236Sbrooks *dst = '\0'; 331241236Sbrooks return dst; 332241236Sbrooks} 333241236Sbrooks 334241236Sbrookschar * 335241236Sbrookssvis(char *dst, int c, int flag, int nextc, const char *extra) 336241236Sbrooks{ 337241236Sbrooks return isnvis(dst, NULL, c, flag, nextc, extra); 338241236Sbrooks} 339241236Sbrooks 340241236Sbrookschar * 341241236Sbrookssnvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra) 342241236Sbrooks{ 343241236Sbrooks return isnvis(dst, &dlen, c, flag, nextc, extra); 344241236Sbrooks} 345241236Sbrooks 346241236Sbrooks 347241236Sbrooks/* 348241236Sbrooks * strsvis, strsvisx - visually encode characters from src into dst 349241236Sbrooks * 350241236Sbrooks * Extra is a pointer to a \0-terminated list of characters to 351241236Sbrooks * be encoded, too. These functions are useful e. g. to 352241236Sbrooks * encode strings in such a way so that they are not interpreted 353241236Sbrooks * by a shell. 354241236Sbrooks * 355241236Sbrooks * Dst must be 4 times the size of src to account for possible 356241236Sbrooks * expansion. The length of dst, not including the trailing NULL, 357241236Sbrooks * is returned. 358241236Sbrooks * 359241236Sbrooks * Strsvisx encodes exactly len bytes from src into dst. 360241236Sbrooks * This is useful for encoding a block of data. 361241236Sbrooks */ 362241236Sbrooksstatic int 363241236Sbrooksistrsnvis(char *dst, size_t *dlen, const char *csrc, int flag, const char *extra) 364241236Sbrooks{ 365241236Sbrooks int c; 366241236Sbrooks char *start; 367241236Sbrooks char *nextra = NULL; 368241236Sbrooks const unsigned char *src = (const unsigned char *)csrc; 369241236Sbrooks visfun_t f; 370241236Sbrooks 371241236Sbrooks _DIAGASSERT(dst != NULL); 372241236Sbrooks _DIAGASSERT(src != NULL); 373241236Sbrooks _DIAGASSERT(extra != NULL); 374241236Sbrooks MAKEEXTRALIST(flag, nextra, extra); 375241236Sbrooks if (!nextra) { 376241236Sbrooks *dst = '\0'; /* can't create nextra, return "" */ 377241236Sbrooks return 0; 378241236Sbrooks } 379241236Sbrooks f = getvisfun(flag); 380241236Sbrooks for (start = dst; (c = *src++) != '\0'; /* empty */) { 381241236Sbrooks dst = (*f)(dst, dlen, c, flag, *src, nextra); 382241236Sbrooks if (dst == NULL) { 383241236Sbrooks errno = ENOSPC; 384241236Sbrooks return -1; 385241236Sbrooks } 386241236Sbrooks } 387241236Sbrooks free(nextra); 388241236Sbrooks if (dlen && *dlen == 0) { 389241236Sbrooks errno = ENOSPC; 390241236Sbrooks return -1; 391241236Sbrooks } 392241236Sbrooks *dst = '\0'; 393241236Sbrooks return (int)(dst - start); 394241236Sbrooks} 395241236Sbrooks 396241236Sbrooksint 397241236Sbrooksstrsvis(char *dst, const char *csrc, int flag, const char *extra) 398241236Sbrooks{ 399241236Sbrooks return istrsnvis(dst, NULL, csrc, flag, extra); 400241236Sbrooks} 401241236Sbrooks 402241236Sbrooksint 403241236Sbrooksstrsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra) 404241236Sbrooks{ 405241236Sbrooks return istrsnvis(dst, &dlen, csrc, flag, extra); 406241236Sbrooks} 407241236Sbrooks 408241236Sbrooksstatic int 409241236Sbrooksistrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag, 410241236Sbrooks const char *extra) 411241236Sbrooks{ 412241236Sbrooks unsigned char c; 413241236Sbrooks char *start; 414241236Sbrooks char *nextra = NULL; 415241236Sbrooks const unsigned char *src = (const unsigned char *)csrc; 416241236Sbrooks visfun_t f; 417241236Sbrooks 418241236Sbrooks _DIAGASSERT(dst != NULL); 419241236Sbrooks _DIAGASSERT(src != NULL); 420241236Sbrooks _DIAGASSERT(extra != NULL); 421241236Sbrooks MAKEEXTRALIST(flag, nextra, extra); 422241236Sbrooks if (! nextra) { 423241236Sbrooks if (dlen && *dlen == 0) { 424241236Sbrooks errno = ENOSPC; 425241236Sbrooks return -1; 426241236Sbrooks } 427241236Sbrooks *dst = '\0'; /* can't create nextra, return "" */ 428241236Sbrooks return 0; 429241236Sbrooks } 430241236Sbrooks 431241236Sbrooks f = getvisfun(flag); 432241236Sbrooks for (start = dst; len > 0; len--) { 433241236Sbrooks c = *src++; 434241236Sbrooks dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra); 435241236Sbrooks if (dst == NULL) { 436241236Sbrooks errno = ENOSPC; 437241236Sbrooks return -1; 438241236Sbrooks } 439241236Sbrooks } 440241236Sbrooks free(nextra); 441241236Sbrooks if (dlen && *dlen == 0) { 442241236Sbrooks errno = ENOSPC; 443241236Sbrooks return -1; 444241236Sbrooks } 445241236Sbrooks *dst = '\0'; 446241236Sbrooks return (int)(dst - start); 447241236Sbrooks} 448241236Sbrooks 449241236Sbrooksint 450241236Sbrooksstrsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) 451241236Sbrooks{ 452241236Sbrooks return istrsnvisx(dst, NULL, csrc, len, flag, extra); 453241236Sbrooks} 454241236Sbrooks 455241236Sbrooksint 456241236Sbrooksstrsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag, 457241236Sbrooks const char *extra) 458241236Sbrooks{ 459241236Sbrooks return istrsnvisx(dst, &dlen, csrc, len, flag, extra); 460241236Sbrooks} 461241236Sbrooks#endif 462241236Sbrooks 463241236Sbrooks#if !HAVE_VIS 464241236Sbrooks/* 465241236Sbrooks * vis - visually encode characters 466241236Sbrooks */ 467241236Sbrooksstatic char * 468241236Sbrooksinvis(char *dst, size_t *dlen, int c, int flag, int nextc) 469241236Sbrooks{ 470241236Sbrooks char *extra = NULL; 471241236Sbrooks unsigned char uc = (unsigned char)c; 472241236Sbrooks visfun_t f; 473241236Sbrooks 474241236Sbrooks _DIAGASSERT(dst != NULL); 475241236Sbrooks 476241236Sbrooks MAKEEXTRALIST(flag, extra, ""); 477241236Sbrooks if (! extra) { 478241236Sbrooks if (dlen && *dlen == 0) { 479241236Sbrooks errno = ENOSPC; 480241236Sbrooks return NULL; 481241236Sbrooks } 482241236Sbrooks *dst = '\0'; /* can't create extra, return "" */ 483241236Sbrooks return dst; 484241236Sbrooks } 485241236Sbrooks f = getvisfun(flag); 486241236Sbrooks dst = (*f)(dst, dlen, uc, flag, nextc, extra); 487241236Sbrooks free(extra); 488241236Sbrooks if (dst == NULL || (dlen && *dlen == 0)) { 489241236Sbrooks errno = ENOSPC; 490241236Sbrooks return NULL; 491241236Sbrooks } 492241236Sbrooks *dst = '\0'; 493241236Sbrooks return dst; 494241236Sbrooks} 495241236Sbrooks 496241236Sbrookschar * 497241236Sbrooksvis(char *dst, int c, int flag, int nextc) 498241236Sbrooks{ 499241236Sbrooks return invis(dst, NULL, c, flag, nextc); 500241236Sbrooks} 501241236Sbrooks 502241236Sbrookschar * 503241236Sbrooksnvis(char *dst, size_t dlen, int c, int flag, int nextc) 504241236Sbrooks{ 505241236Sbrooks return invis(dst, &dlen, c, flag, nextc); 506241236Sbrooks} 507241236Sbrooks 508241236Sbrooks 509241236Sbrooks/* 510241236Sbrooks * strvis, strvisx - visually encode characters from src into dst 511241236Sbrooks * 512241236Sbrooks * Dst must be 4 times the size of src to account for possible 513241236Sbrooks * expansion. The length of dst, not including the trailing NULL, 514241236Sbrooks * is returned. 515241236Sbrooks * 516241236Sbrooks * Strvisx encodes exactly len bytes from src into dst. 517241236Sbrooks * This is useful for encoding a block of data. 518241236Sbrooks */ 519241236Sbrooksstatic int 520241236Sbrooksistrnvis(char *dst, size_t *dlen, const char *src, int flag) 521241236Sbrooks{ 522241236Sbrooks char *extra = NULL; 523241236Sbrooks int rv; 524241236Sbrooks 525241236Sbrooks MAKEEXTRALIST(flag, extra, ""); 526241236Sbrooks if (!extra) { 527241236Sbrooks if (dlen && *dlen == 0) { 528241236Sbrooks errno = ENOSPC; 529241236Sbrooks return -1; 530241236Sbrooks } 531241236Sbrooks *dst = '\0'; /* can't create extra, return "" */ 532241236Sbrooks return 0; 533241236Sbrooks } 534241236Sbrooks rv = istrsnvis(dst, dlen, src, flag, extra); 535241236Sbrooks free(extra); 536241236Sbrooks return rv; 537241236Sbrooks} 538241236Sbrooks 539241236Sbrooksint 540241236Sbrooksstrvis(char *dst, const char *src, int flag) 541241236Sbrooks{ 542241236Sbrooks return istrnvis(dst, NULL, src, flag); 543241236Sbrooks} 544241236Sbrooks 545241236Sbrooksint 546241236Sbrooksstrnvis(char *dst, size_t dlen, const char *src, int flag) 547241236Sbrooks{ 548241236Sbrooks return istrnvis(dst, &dlen, src, flag); 549241236Sbrooks} 550241236Sbrooks 551241236Sbrooksstatic int 552241236Sbrooksistrnvisx(char *dst, size_t *dlen, const char *src, size_t len, int flag) 553241236Sbrooks{ 554241236Sbrooks char *extra = NULL; 555241236Sbrooks int rv; 556241236Sbrooks 557241236Sbrooks MAKEEXTRALIST(flag, extra, ""); 558241236Sbrooks if (!extra) { 559241236Sbrooks if (dlen && *dlen == 0) { 560241236Sbrooks errno = ENOSPC; 561241236Sbrooks return -1; 562241236Sbrooks } 563241236Sbrooks *dst = '\0'; /* can't create extra, return "" */ 564241236Sbrooks return 0; 565241236Sbrooks } 566241236Sbrooks rv = istrsnvisx(dst, dlen, src, len, flag, extra); 567241236Sbrooks free(extra); 568241236Sbrooks return rv; 569241236Sbrooks} 570241236Sbrooks 571241236Sbrooksint 572241236Sbrooksstrvisx(char *dst, const char *src, size_t len, int flag) 573241236Sbrooks{ 574241236Sbrooks return istrnvisx(dst, NULL, src, len, flag); 575241236Sbrooks} 576241236Sbrooks 577241236Sbrooksint 578241236Sbrooksstrnvisx(char *dst, size_t dlen, const char *src, size_t len, int flag) 579241236Sbrooks{ 580241236Sbrooks return istrnvisx(dst, &dlen, src, len, flag); 581241236Sbrooks} 582241236Sbrooks 583241236Sbrooks#endif 584