vis.c revision 241236
1241236Sbrooks/* $NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 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) 60241236Sbrooks__RCSID("$NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $"); 61241236Sbrooks#endif /* LIBC_SCCS and not lint */ 62241236Sbrooks 63241236Sbrooks#include "namespace.h" 64241236Sbrooks#include <sys/types.h> 65241236Sbrooks 66241236Sbrooks#include <assert.h> 67241236Sbrooks#include <vis.h> 68241236Sbrooks#include <errno.h> 69241236Sbrooks#include <stdlib.h> 70241236Sbrooks 71241236Sbrooks#ifdef __weak_alias 72241236Sbrooks__weak_alias(strvisx,_strvisx) 73241236Sbrooks#endif 74241236Sbrooks 75241236Sbrooks#if !HAVE_VIS || !HAVE_SVIS 76241236Sbrooks#include <ctype.h> 77241236Sbrooks#include <limits.h> 78241236Sbrooks#include <stdio.h> 79241236Sbrooks#include <string.h> 80241236Sbrooks 81241236Sbrooksstatic char *do_svis(char *, size_t *, int, int, int, const char *); 82241236Sbrooks 83241236Sbrooks#undef BELL 84241236Sbrooks#define BELL '\a' 85241236Sbrooks 86241236Sbrooks#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') 87241236Sbrooks#define iswhite(c) (c == ' ' || c == '\t' || c == '\n') 88241236Sbrooks#define issafe(c) (c == '\b' || c == BELL || c == '\r') 89241236Sbrooks#define xtoa(c) "0123456789abcdef"[c] 90241236Sbrooks#define XTOA(c) "0123456789ABCDEF"[c] 91241236Sbrooks 92241236Sbrooks#define MAXEXTRAS 5 93241236Sbrooks 94241236Sbrooks#define MAKEEXTRALIST(flag, extra, orig_str) \ 95241236Sbrooksdo { \ 96241236Sbrooks const char *orig = orig_str; \ 97241236Sbrooks const char *o = orig; \ 98241236Sbrooks char *e; \ 99241236Sbrooks while (*o++) \ 100241236Sbrooks continue; \ 101241236Sbrooks extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \ 102241236Sbrooks if (!extra) break; \ 103241236Sbrooks for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ 104241236Sbrooks continue; \ 105241236Sbrooks e--; \ 106241236Sbrooks if (flag & VIS_SP) *e++ = ' '; \ 107241236Sbrooks if (flag & VIS_TAB) *e++ = '\t'; \ 108241236Sbrooks if (flag & VIS_NL) *e++ = '\n'; \ 109241236Sbrooks if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ 110241236Sbrooks *e = '\0'; \ 111241236Sbrooks} while (/*CONSTCOND*/0) 112241236Sbrooks 113241236Sbrooks/* 114241236Sbrooks * This is do_hvis, for HTTP style (RFC 1808) 115241236Sbrooks */ 116241236Sbrooksstatic char * 117241236Sbrooksdo_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) 118241236Sbrooks{ 119241236Sbrooks 120241236Sbrooks if ((isascii(c) && isalnum(c)) 121241236Sbrooks /* safe */ 122241236Sbrooks || c == '$' || c == '-' || c == '_' || c == '.' || c == '+' 123241236Sbrooks /* extra */ 124241236Sbrooks || c == '!' || c == '*' || c == '\'' || c == '(' || c == ')' 125241236Sbrooks || c == ',') { 126241236Sbrooks dst = do_svis(dst, dlen, c, flag, nextc, extra); 127241236Sbrooks } else { 128241236Sbrooks if (dlen) { 129241236Sbrooks if (*dlen < 3) 130241236Sbrooks return NULL; 131241236Sbrooks *dlen -= 3; 132241236Sbrooks } 133241236Sbrooks *dst++ = '%'; 134241236Sbrooks *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); 135241236Sbrooks *dst++ = xtoa((unsigned int)c & 0xf); 136241236Sbrooks } 137241236Sbrooks 138241236Sbrooks return dst; 139241236Sbrooks} 140241236Sbrooks 141241236Sbrooks/* 142241236Sbrooks * This is do_mvis, for Quoted-Printable MIME (RFC 2045) 143241236Sbrooks * NB: No handling of long lines or CRLF. 144241236Sbrooks */ 145241236Sbrooksstatic char * 146241236Sbrooksdo_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) 147241236Sbrooks{ 148241236Sbrooks if ((c != '\n') && 149241236Sbrooks /* Space at the end of the line */ 150241236Sbrooks ((isspace(c) && (nextc == '\r' || nextc == '\n')) || 151241236Sbrooks /* Out of range */ 152241236Sbrooks (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || 153241236Sbrooks /* Specific char to be escaped */ 154241236Sbrooks strchr("#$@[\\]^`{|}~", c) != NULL)) { 155241236Sbrooks if (dlen) { 156241236Sbrooks if (*dlen < 3) 157241236Sbrooks return NULL; 158241236Sbrooks *dlen -= 3; 159241236Sbrooks } 160241236Sbrooks *dst++ = '='; 161241236Sbrooks *dst++ = XTOA(((unsigned int)c >> 4) & 0xf); 162241236Sbrooks *dst++ = XTOA((unsigned int)c & 0xf); 163241236Sbrooks } else { 164241236Sbrooks dst = do_svis(dst, dlen, c, flag, nextc, extra); 165241236Sbrooks } 166241236Sbrooks return dst; 167241236Sbrooks} 168241236Sbrooks 169241236Sbrooks/* 170241236Sbrooks * This is do_vis, the central code of vis. 171241236Sbrooks * dst: Pointer to the destination buffer 172241236Sbrooks * c: Character to encode 173241236Sbrooks * flag: Flag word 174241236Sbrooks * nextc: The character following 'c' 175241236Sbrooks * extra: Pointer to the list of extra characters to be 176241236Sbrooks * backslash-protected. 177241236Sbrooks */ 178241236Sbrooksstatic char * 179241236Sbrooksdo_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) 180241236Sbrooks{ 181241236Sbrooks int isextra; 182241236Sbrooks size_t odlen = dlen ? *dlen : 0; 183241236Sbrooks 184241236Sbrooks isextra = strchr(extra, c) != NULL; 185241236Sbrooks#define HAVE(x) \ 186241236Sbrooks do { \ 187241236Sbrooks if (dlen) { \ 188241236Sbrooks if (*dlen < (x)) \ 189241236Sbrooks goto out; \ 190241236Sbrooks *dlen -= (x); \ 191241236Sbrooks } \ 192241236Sbrooks } while (/*CONSTCOND*/0) 193241236Sbrooks if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || 194241236Sbrooks ((flag & VIS_SAFE) && issafe(c)))) { 195241236Sbrooks HAVE(1); 196241236Sbrooks *dst++ = c; 197241236Sbrooks return dst; 198241236Sbrooks } 199241236Sbrooks if (flag & VIS_CSTYLE) { 200241236Sbrooks HAVE(2); 201241236Sbrooks switch (c) { 202241236Sbrooks case '\n': 203241236Sbrooks *dst++ = '\\'; *dst++ = 'n'; 204241236Sbrooks return dst; 205241236Sbrooks case '\r': 206241236Sbrooks *dst++ = '\\'; *dst++ = 'r'; 207241236Sbrooks return dst; 208241236Sbrooks case '\b': 209241236Sbrooks *dst++ = '\\'; *dst++ = 'b'; 210241236Sbrooks return dst; 211241236Sbrooks case BELL: 212241236Sbrooks *dst++ = '\\'; *dst++ = 'a'; 213241236Sbrooks return dst; 214241236Sbrooks case '\v': 215241236Sbrooks *dst++ = '\\'; *dst++ = 'v'; 216241236Sbrooks return dst; 217241236Sbrooks case '\t': 218241236Sbrooks *dst++ = '\\'; *dst++ = 't'; 219241236Sbrooks return dst; 220241236Sbrooks case '\f': 221241236Sbrooks *dst++ = '\\'; *dst++ = 'f'; 222241236Sbrooks return dst; 223241236Sbrooks case ' ': 224241236Sbrooks *dst++ = '\\'; *dst++ = 's'; 225241236Sbrooks return dst; 226241236Sbrooks case '\0': 227241236Sbrooks *dst++ = '\\'; *dst++ = '0'; 228241236Sbrooks if (isoctal(nextc)) { 229241236Sbrooks HAVE(2); 230241236Sbrooks *dst++ = '0'; 231241236Sbrooks *dst++ = '0'; 232241236Sbrooks } 233241236Sbrooks return dst; 234241236Sbrooks default: 235241236Sbrooks if (isgraph(c)) { 236241236Sbrooks *dst++ = '\\'; *dst++ = c; 237241236Sbrooks return dst; 238241236Sbrooks } 239241236Sbrooks if (dlen) 240241236Sbrooks *dlen = odlen; 241241236Sbrooks } 242241236Sbrooks } 243241236Sbrooks if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { 244241236Sbrooks HAVE(4); 245241236Sbrooks *dst++ = '\\'; 246241236Sbrooks *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; 247241236Sbrooks *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; 248241236Sbrooks *dst++ = (c & 07) + '0'; 249241236Sbrooks } else { 250241236Sbrooks if ((flag & VIS_NOSLASH) == 0) { 251241236Sbrooks HAVE(1); 252241236Sbrooks *dst++ = '\\'; 253241236Sbrooks } 254241236Sbrooks 255241236Sbrooks if (c & 0200) { 256241236Sbrooks HAVE(1); 257241236Sbrooks c &= 0177; *dst++ = 'M'; 258241236Sbrooks } 259241236Sbrooks 260241236Sbrooks if (iscntrl(c)) { 261241236Sbrooks HAVE(2); 262241236Sbrooks *dst++ = '^'; 263241236Sbrooks if (c == 0177) 264241236Sbrooks *dst++ = '?'; 265241236Sbrooks else 266241236Sbrooks *dst++ = c + '@'; 267241236Sbrooks } else { 268241236Sbrooks HAVE(2); 269241236Sbrooks *dst++ = '-'; *dst++ = c; 270241236Sbrooks } 271241236Sbrooks } 272241236Sbrooks return dst; 273241236Sbrooksout: 274241236Sbrooks *dlen = odlen; 275241236Sbrooks return NULL; 276241236Sbrooks} 277241236Sbrooks 278241236Sbrookstypedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *); 279241236Sbrooks 280241236Sbrooks/* 281241236Sbrooks * Return the appropriate encoding function depending on the flags given. 282241236Sbrooks */ 283241236Sbrooksstatic visfun_t 284241236Sbrooksgetvisfun(int flag) 285241236Sbrooks{ 286241236Sbrooks if (flag & VIS_HTTPSTYLE) 287241236Sbrooks return do_hvis; 288241236Sbrooks if (flag & VIS_MIMESTYLE) 289241236Sbrooks return do_mvis; 290241236Sbrooks return do_svis; 291241236Sbrooks} 292241236Sbrooks 293241236Sbrooks/* 294241236Sbrooks * isnvis - visually encode characters, also encoding the characters 295241236Sbrooks * pointed to by `extra' 296241236Sbrooks */ 297241236Sbrooksstatic char * 298241236Sbrooksisnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) 299241236Sbrooks{ 300241236Sbrooks char *nextra = NULL; 301241236Sbrooks visfun_t f; 302241236Sbrooks 303241236Sbrooks _DIAGASSERT(dst != NULL); 304241236Sbrooks _DIAGASSERT(extra != NULL); 305241236Sbrooks MAKEEXTRALIST(flag, nextra, extra); 306241236Sbrooks if (!nextra) { 307241236Sbrooks if (dlen && *dlen == 0) { 308241236Sbrooks errno = ENOSPC; 309241236Sbrooks return NULL; 310241236Sbrooks } 311241236Sbrooks *dst = '\0'; /* can't create nextra, return "" */ 312241236Sbrooks return dst; 313241236Sbrooks } 314241236Sbrooks f = getvisfun(flag); 315241236Sbrooks dst = (*f)(dst, dlen, c, flag, nextc, nextra); 316241236Sbrooks free(nextra); 317241236Sbrooks if (dst == NULL || (dlen && *dlen == 0)) { 318241236Sbrooks errno = ENOSPC; 319241236Sbrooks return NULL; 320241236Sbrooks } 321241236Sbrooks *dst = '\0'; 322241236Sbrooks return dst; 323241236Sbrooks} 324241236Sbrooks 325241236Sbrookschar * 326241236Sbrookssvis(char *dst, int c, int flag, int nextc, const char *extra) 327241236Sbrooks{ 328241236Sbrooks return isnvis(dst, NULL, c, flag, nextc, extra); 329241236Sbrooks} 330241236Sbrooks 331241236Sbrookschar * 332241236Sbrookssnvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra) 333241236Sbrooks{ 334241236Sbrooks return isnvis(dst, &dlen, c, flag, nextc, extra); 335241236Sbrooks} 336241236Sbrooks 337241236Sbrooks 338241236Sbrooks/* 339241236Sbrooks * strsvis, strsvisx - visually encode characters from src into dst 340241236Sbrooks * 341241236Sbrooks * Extra is a pointer to a \0-terminated list of characters to 342241236Sbrooks * be encoded, too. These functions are useful e. g. to 343241236Sbrooks * encode strings in such a way so that they are not interpreted 344241236Sbrooks * by a shell. 345241236Sbrooks * 346241236Sbrooks * Dst must be 4 times the size of src to account for possible 347241236Sbrooks * expansion. The length of dst, not including the trailing NULL, 348241236Sbrooks * is returned. 349241236Sbrooks * 350241236Sbrooks * Strsvisx encodes exactly len bytes from src into dst. 351241236Sbrooks * This is useful for encoding a block of data. 352241236Sbrooks */ 353241236Sbrooksstatic int 354241236Sbrooksistrsnvis(char *dst, size_t *dlen, const char *csrc, int flag, const char *extra) 355241236Sbrooks{ 356241236Sbrooks int c; 357241236Sbrooks char *start; 358241236Sbrooks char *nextra = NULL; 359241236Sbrooks const unsigned char *src = (const unsigned char *)csrc; 360241236Sbrooks visfun_t f; 361241236Sbrooks 362241236Sbrooks _DIAGASSERT(dst != NULL); 363241236Sbrooks _DIAGASSERT(src != NULL); 364241236Sbrooks _DIAGASSERT(extra != NULL); 365241236Sbrooks MAKEEXTRALIST(flag, nextra, extra); 366241236Sbrooks if (!nextra) { 367241236Sbrooks *dst = '\0'; /* can't create nextra, return "" */ 368241236Sbrooks return 0; 369241236Sbrooks } 370241236Sbrooks f = getvisfun(flag); 371241236Sbrooks for (start = dst; (c = *src++) != '\0'; /* empty */) { 372241236Sbrooks dst = (*f)(dst, dlen, c, flag, *src, nextra); 373241236Sbrooks if (dst == NULL) { 374241236Sbrooks errno = ENOSPC; 375241236Sbrooks return -1; 376241236Sbrooks } 377241236Sbrooks } 378241236Sbrooks free(nextra); 379241236Sbrooks if (dlen && *dlen == 0) { 380241236Sbrooks errno = ENOSPC; 381241236Sbrooks return -1; 382241236Sbrooks } 383241236Sbrooks *dst = '\0'; 384241236Sbrooks return (int)(dst - start); 385241236Sbrooks} 386241236Sbrooks 387241236Sbrooksint 388241236Sbrooksstrsvis(char *dst, const char *csrc, int flag, const char *extra) 389241236Sbrooks{ 390241236Sbrooks return istrsnvis(dst, NULL, csrc, flag, extra); 391241236Sbrooks} 392241236Sbrooks 393241236Sbrooksint 394241236Sbrooksstrsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra) 395241236Sbrooks{ 396241236Sbrooks return istrsnvis(dst, &dlen, csrc, flag, extra); 397241236Sbrooks} 398241236Sbrooks 399241236Sbrooksstatic int 400241236Sbrooksistrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag, 401241236Sbrooks const char *extra) 402241236Sbrooks{ 403241236Sbrooks unsigned char c; 404241236Sbrooks char *start; 405241236Sbrooks char *nextra = NULL; 406241236Sbrooks const unsigned char *src = (const unsigned char *)csrc; 407241236Sbrooks visfun_t f; 408241236Sbrooks 409241236Sbrooks _DIAGASSERT(dst != NULL); 410241236Sbrooks _DIAGASSERT(src != NULL); 411241236Sbrooks _DIAGASSERT(extra != NULL); 412241236Sbrooks MAKEEXTRALIST(flag, nextra, extra); 413241236Sbrooks if (! nextra) { 414241236Sbrooks if (dlen && *dlen == 0) { 415241236Sbrooks errno = ENOSPC; 416241236Sbrooks return -1; 417241236Sbrooks } 418241236Sbrooks *dst = '\0'; /* can't create nextra, return "" */ 419241236Sbrooks return 0; 420241236Sbrooks } 421241236Sbrooks 422241236Sbrooks f = getvisfun(flag); 423241236Sbrooks for (start = dst; len > 0; len--) { 424241236Sbrooks c = *src++; 425241236Sbrooks dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra); 426241236Sbrooks if (dst == NULL) { 427241236Sbrooks errno = ENOSPC; 428241236Sbrooks return -1; 429241236Sbrooks } 430241236Sbrooks } 431241236Sbrooks free(nextra); 432241236Sbrooks if (dlen && *dlen == 0) { 433241236Sbrooks errno = ENOSPC; 434241236Sbrooks return -1; 435241236Sbrooks } 436241236Sbrooks *dst = '\0'; 437241236Sbrooks return (int)(dst - start); 438241236Sbrooks} 439241236Sbrooks 440241236Sbrooksint 441241236Sbrooksstrsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) 442241236Sbrooks{ 443241236Sbrooks return istrsnvisx(dst, NULL, csrc, len, flag, extra); 444241236Sbrooks} 445241236Sbrooks 446241236Sbrooksint 447241236Sbrooksstrsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag, 448241236Sbrooks const char *extra) 449241236Sbrooks{ 450241236Sbrooks return istrsnvisx(dst, &dlen, csrc, len, flag, extra); 451241236Sbrooks} 452241236Sbrooks#endif 453241236Sbrooks 454241236Sbrooks#if !HAVE_VIS 455241236Sbrooks/* 456241236Sbrooks * vis - visually encode characters 457241236Sbrooks */ 458241236Sbrooksstatic char * 459241236Sbrooksinvis(char *dst, size_t *dlen, int c, int flag, int nextc) 460241236Sbrooks{ 461241236Sbrooks char *extra = NULL; 462241236Sbrooks unsigned char uc = (unsigned char)c; 463241236Sbrooks visfun_t f; 464241236Sbrooks 465241236Sbrooks _DIAGASSERT(dst != NULL); 466241236Sbrooks 467241236Sbrooks MAKEEXTRALIST(flag, extra, ""); 468241236Sbrooks if (! extra) { 469241236Sbrooks if (dlen && *dlen == 0) { 470241236Sbrooks errno = ENOSPC; 471241236Sbrooks return NULL; 472241236Sbrooks } 473241236Sbrooks *dst = '\0'; /* can't create extra, return "" */ 474241236Sbrooks return dst; 475241236Sbrooks } 476241236Sbrooks f = getvisfun(flag); 477241236Sbrooks dst = (*f)(dst, dlen, uc, flag, nextc, extra); 478241236Sbrooks free(extra); 479241236Sbrooks if (dst == NULL || (dlen && *dlen == 0)) { 480241236Sbrooks errno = ENOSPC; 481241236Sbrooks return NULL; 482241236Sbrooks } 483241236Sbrooks *dst = '\0'; 484241236Sbrooks return dst; 485241236Sbrooks} 486241236Sbrooks 487241236Sbrookschar * 488241236Sbrooksvis(char *dst, int c, int flag, int nextc) 489241236Sbrooks{ 490241236Sbrooks return invis(dst, NULL, c, flag, nextc); 491241236Sbrooks} 492241236Sbrooks 493241236Sbrookschar * 494241236Sbrooksnvis(char *dst, size_t dlen, int c, int flag, int nextc) 495241236Sbrooks{ 496241236Sbrooks return invis(dst, &dlen, c, flag, nextc); 497241236Sbrooks} 498241236Sbrooks 499241236Sbrooks 500241236Sbrooks/* 501241236Sbrooks * strvis, strvisx - visually encode characters from src into dst 502241236Sbrooks * 503241236Sbrooks * Dst must be 4 times the size of src to account for possible 504241236Sbrooks * expansion. The length of dst, not including the trailing NULL, 505241236Sbrooks * is returned. 506241236Sbrooks * 507241236Sbrooks * Strvisx encodes exactly len bytes from src into dst. 508241236Sbrooks * This is useful for encoding a block of data. 509241236Sbrooks */ 510241236Sbrooksstatic int 511241236Sbrooksistrnvis(char *dst, size_t *dlen, const char *src, int flag) 512241236Sbrooks{ 513241236Sbrooks char *extra = NULL; 514241236Sbrooks int rv; 515241236Sbrooks 516241236Sbrooks MAKEEXTRALIST(flag, extra, ""); 517241236Sbrooks if (!extra) { 518241236Sbrooks if (dlen && *dlen == 0) { 519241236Sbrooks errno = ENOSPC; 520241236Sbrooks return -1; 521241236Sbrooks } 522241236Sbrooks *dst = '\0'; /* can't create extra, return "" */ 523241236Sbrooks return 0; 524241236Sbrooks } 525241236Sbrooks rv = istrsnvis(dst, dlen, src, flag, extra); 526241236Sbrooks free(extra); 527241236Sbrooks return rv; 528241236Sbrooks} 529241236Sbrooks 530241236Sbrooksint 531241236Sbrooksstrvis(char *dst, const char *src, int flag) 532241236Sbrooks{ 533241236Sbrooks return istrnvis(dst, NULL, src, flag); 534241236Sbrooks} 535241236Sbrooks 536241236Sbrooksint 537241236Sbrooksstrnvis(char *dst, size_t dlen, const char *src, int flag) 538241236Sbrooks{ 539241236Sbrooks return istrnvis(dst, &dlen, src, flag); 540241236Sbrooks} 541241236Sbrooks 542241236Sbrooksstatic int 543241236Sbrooksistrnvisx(char *dst, size_t *dlen, const char *src, size_t len, int flag) 544241236Sbrooks{ 545241236Sbrooks char *extra = NULL; 546241236Sbrooks int rv; 547241236Sbrooks 548241236Sbrooks MAKEEXTRALIST(flag, extra, ""); 549241236Sbrooks if (!extra) { 550241236Sbrooks if (dlen && *dlen == 0) { 551241236Sbrooks errno = ENOSPC; 552241236Sbrooks return -1; 553241236Sbrooks } 554241236Sbrooks *dst = '\0'; /* can't create extra, return "" */ 555241236Sbrooks return 0; 556241236Sbrooks } 557241236Sbrooks rv = istrsnvisx(dst, dlen, src, len, flag, extra); 558241236Sbrooks free(extra); 559241236Sbrooks return rv; 560241236Sbrooks} 561241236Sbrooks 562241236Sbrooksint 563241236Sbrooksstrvisx(char *dst, const char *src, size_t len, int flag) 564241236Sbrooks{ 565241236Sbrooks return istrnvisx(dst, NULL, src, len, flag); 566241236Sbrooks} 567241236Sbrooks 568241236Sbrooksint 569241236Sbrooksstrnvisx(char *dst, size_t dlen, const char *src, size_t len, int flag) 570241236Sbrooks{ 571241236Sbrooks return istrnvisx(dst, &dlen, src, len, flag); 572241236Sbrooks} 573241236Sbrooks 574241236Sbrooks#endif 575