1 /* $NetBSD: vis.c,v 1.74 2017/11/27 16:37:21 christos Exp $ */ 2 /* $FreeBSD: head/contrib/libc-vis/vis.c 326307 2017-11-28 01:35:28Z brooks $ */ 3 4 /*- 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /*- 34 * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 47 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 48 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 49 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 50 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 56 * POSSIBILITY OF SUCH DAMAGE. 57 */ 58 59 #ifndef EMBED_LIB_SRC 60 #include "namespace.h" 61 #endif 62 #include <sys/types.h> 63 #include <sys/param.h> 64 65 #include <assert.h> 66 #include <vis.h> 67 #include <errno.h> 68 #include <stdlib.h> 69 #include <wchar.h> 70 #include <wctype.h> 71 #ifndef EMBED_LIB_SRC 72 #include "un-namespace.h" 73 #endif 74 75 #ifdef __weak_alias 76 __weak_alias(strvisx,_strvisx) 77 #endif 78 79 #if !HAVE_VIS || !HAVE_SVIS 80 #ifndef EMBED_LIB_SRC 81 #include "namespace.h" 82 #endif 83 #include <ctype.h> 84 #include <limits.h> 85 #include <stdio.h> 86 #include <string.h> 87 #ifndef EMBED_LIB_SRC 88 #include "un-namespace.h" 89 #endif 90 91 /* 92 * The reason for going through the trouble to deal with character encodings 93 * in vis(3), is that we use this to safe encode output of commands. This 94 * safe encoding varies depending on the character set. For example if we 95 * display ps output in French, we don't want to display French characters 96 * as M-foo. 97 */ 98 99 static wchar_t *do_svis(wchar_t *, wint_t, int, wint_t, const wchar_t *); 100 101 #undef BELL 102 #define BELL L'\a' 103 104 #if defined(LC_C_LOCALE) 105 #define iscgraph(c) isgraph_l(c, LC_C_LOCALE) 106 #else 107 /* Keep it simple for now, no locale stuff */ 108 #define iscgraph(c) isgraph(c) 109 #ifdef notyet 110 #include <locale.h> 111 static int 112 iscgraph(int c) { 113 int rv; 114 char *ol; 115 116 ol = setlocale(LC_CTYPE, "C"); 117 rv = isgraph(c); 118 if (ol) 119 setlocale(LC_CTYPE, ol); 120 return rv; 121 } 122 #endif 123 #endif 124 125 #define ISGRAPH(flags, c) \ 126 (((flags) & VIS_NOLOCALE) ? iscgraph(c) : iswgraph(c)) 127 128 #define iswoctal(c) (((u_char)(c)) >= L'0' && ((u_char)(c)) <= L'7') 129 #define iswwhite(c) (c == L' ' || c == L'\t' || c == L'\n') 130 #define iswsafe(c) (c == L'\b' || c == BELL || c == L'\r') 131 #define xtoa(c) L"0123456789abcdef"[c] 132 #define XTOA(c) L"0123456789ABCDEF"[c] 133 134 #define MAXEXTRAS 30 135 136 static const wchar_t char_shell[] = L"'`\";&<>()|{}]\\$!^~"; 137 static const wchar_t char_glob[] = L"*?[#"; 138 139 #if !HAVE_NBTOOL_CONFIG_H 140 #ifndef __NetBSD__ 141 /* 142 * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer 143 * integral type and it is probably wrong, since currently the maximum 144 * number of bytes and character needs is 6. Until this is fixed, the 145 * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and 146 * the assertion is commented out. 147 */ 148 #if defined(__FreeBSD__) || defined(__DragonFly__) 149 /* 150 * On FreeBSD and DragonFly, including <sys/systm.h> for CTASSERT only 151 * works in kernel mode. 152 */ 153 #ifndef CTASSERT 154 #define CTASSERT(x) _CTASSERT(x, __LINE__) 155 #define _CTASSERT(x, y) __CTASSERT(x, y) 156 #define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] 157 #endif 158 #endif /* __FreeBSD__ || __DragonFly__ */ 159 CTASSERT(MB_LEN_MAX <= sizeof(uint64_t)); 160 #endif /* !__NetBSD__ */ 161 #endif 162 163 /* 164 * This is do_hvis, for HTTP style (RFC 1808) 165 */ 166 static wchar_t * 167 do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) 168 { 169 if (iswalnum(c) 170 /* safe */ 171 || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+' 172 /* extra */ 173 || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')' 174 || c == L',') 175 dst = do_svis(dst, c, flags, nextc, extra); 176 else { 177 *dst++ = L'%'; 178 *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); 179 *dst++ = xtoa((unsigned int)c & 0xf); 180 } 181 182 return dst; 183 } 184 185 /* 186 * This is do_mvis, for Quoted-Printable MIME (RFC 2045) 187 * NB: No handling of long lines or CRLF. 188 */ 189 static wchar_t * 190 do_mvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) 191 { 192 if ((c != L'\n') && 193 /* Space at the end of the line */ 194 ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) || 195 /* Out of range */ 196 (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || 197 /* Specific char to be escaped */ 198 wcschr(L"#$@[\\]^`{|}~", c) != NULL)) { 199 *dst++ = L'='; 200 *dst++ = XTOA(((unsigned int)c >> 4) & 0xf); 201 *dst++ = XTOA((unsigned int)c & 0xf); 202 } else 203 dst = do_svis(dst, c, flags, nextc, extra); 204 return dst; 205 } 206 207 /* 208 * Output single byte of multibyte character. 209 */ 210 static wchar_t * 211 do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra) 212 { 213 if (flags & VIS_CSTYLE) { 214 switch (c) { 215 case L'\n': 216 *dst++ = L'\\'; *dst++ = L'n'; 217 return dst; 218 case L'\r': 219 *dst++ = L'\\'; *dst++ = L'r'; 220 return dst; 221 case L'\b': 222 *dst++ = L'\\'; *dst++ = L'b'; 223 return dst; 224 case BELL: 225 *dst++ = L'\\'; *dst++ = L'a'; 226 return dst; 227 case L'\v': 228 *dst++ = L'\\'; *dst++ = L'v'; 229 return dst; 230 case L'\t': 231 *dst++ = L'\\'; *dst++ = L't'; 232 return dst; 233 case L'\f': 234 *dst++ = L'\\'; *dst++ = L'f'; 235 return dst; 236 case L' ': 237 *dst++ = L'\\'; *dst++ = L's'; 238 return dst; 239 case L'\0': 240 *dst++ = L'\\'; *dst++ = L'0'; 241 if (iswoctal(nextc)) { 242 *dst++ = L'0'; 243 *dst++ = L'0'; 244 } 245 return dst; 246 /* We cannot encode these characters in VIS_CSTYLE 247 * because they special meaning */ 248 case L'n': 249 case L'r': 250 case L'b': 251 case L'a': 252 case L'v': 253 case L't': 254 case L'f': 255 case L's': 256 case L'x': 257 case L'0': 258 case L'E': 259 case L'F': 260 case L'M': 261 case L'-': 262 case L'^': 263 case L'$': /* vis(1) -l */ 264 break; 265 default: 266 if (ISGRAPH(flags, c) && !iswoctal(c)) { 267 *dst++ = L'\\'; 268 *dst++ = c; 269 return dst; 270 } 271 } 272 } 273 if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) { 274 *dst++ = L'\\'; 275 *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0'; 276 *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0'; 277 *dst++ = (c & 07) + L'0'; 278 } else { 279 if ((flags & VIS_NOSLASH) == 0) 280 *dst++ = L'\\'; 281 282 if (c & 0200) { 283 c &= 0177; 284 *dst++ = L'M'; 285 } 286 287 if (iswcntrl(c)) { 288 *dst++ = L'^'; 289 if (c == 0177) 290 *dst++ = L'?'; 291 else 292 *dst++ = c + L'@'; 293 } else { 294 *dst++ = L'-'; 295 *dst++ = c; 296 } 297 } 298 299 return dst; 300 } 301 302 /* 303 * This is do_vis, the central code of vis. 304 * dst: Pointer to the destination buffer 305 * c: Character to encode 306 * flags: Flags word 307 * nextc: The character following 'c' 308 * extra: Pointer to the list of extra characters to be 309 * backslash-protected. 310 */ 311 static wchar_t * 312 do_svis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) 313 { 314 int iswextra, i, shft; 315 uint64_t bmsk, wmsk; 316 317 iswextra = wcschr(extra, c) != NULL; 318 if (((flags & VIS_ALL) == 0) && 319 !iswextra && 320 (ISGRAPH(flags, c) || iswwhite(c) || 321 ((flags & VIS_SAFE) && iswsafe(c)))) { 322 *dst++ = c; 323 return dst; 324 } 325 326 /* See comment in istrsenvisx() output loop, below. */ 327 wmsk = 0; 328 for (i = sizeof(wmsk) - 1; i >= 0; i--) { 329 shft = i * NBBY; 330 bmsk = (uint64_t)0xffLL << shft; 331 wmsk |= bmsk; 332 if ((c & wmsk) || i == 0) 333 dst = do_mbyte(dst, (wint_t)( 334 (uint64_t)(c & bmsk) >> shft), 335 flags, nextc, iswextra); 336 } 337 338 return dst; 339 } 340 341 typedef wchar_t *(*visfun_t)(wchar_t *, wint_t, int, wint_t, const wchar_t *); 342 343 /* 344 * Return the appropriate encoding function depending on the flags given. 345 */ 346 static visfun_t 347 getvisfun(int flags) 348 { 349 if (flags & VIS_HTTPSTYLE) 350 return do_hvis; 351 if (flags & VIS_MIMESTYLE) 352 return do_mvis; 353 return do_svis; 354 } 355 356 /* 357 * Expand list of extra characters to not visually encode. 358 */ 359 static wchar_t * 360 makeextralist(int flags, const char *src) 361 { 362 wchar_t *dst, *d; 363 size_t len; 364 const wchar_t *s; 365 mbstate_t mbstate; 366 367 bzero(&mbstate, sizeof(mbstate)); 368 len = strlen(src); 369 if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL) 370 return NULL; 371 372 if ((flags & VIS_NOLOCALE) || mbsrtowcs(dst, &src, len, &mbstate) == (size_t)-1) { 373 size_t i; 374 for (i = 0; i < len; i++) 375 dst[i] = (wchar_t)(u_char)src[i]; 376 d = dst + len; 377 } else 378 d = dst + wcslen(dst); 379 380 if (flags & VIS_GLOB) 381 for (s = char_glob; *s; *d++ = *s++) 382 continue; 383 384 if (flags & VIS_SHELL) 385 for (s = char_shell; *s; *d++ = *s++) 386 continue; 387 388 if (flags & VIS_SP) *d++ = L' '; 389 if (flags & VIS_TAB) *d++ = L'\t'; 390 if (flags & VIS_NL) *d++ = L'\n'; 391 if (flags & VIS_DQ) *d++ = L'"'; 392 if ((flags & VIS_NOSLASH) == 0) *d++ = L'\\'; 393 *d = L'\0'; 394 395 return dst; 396 } 397 398 /* 399 * istrsenvisx() 400 * The main internal function. 401 * All user-visible functions call this one. 402 */ 403 static int 404 istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength, 405 int flags, const char *mbextra, int *cerr_ptr) 406 { 407 wchar_t *dst, *src, *pdst, *psrc, *start, *extra; 408 size_t len, olen; 409 uint64_t bmsk, wmsk; 410 wint_t c; 411 visfun_t f; 412 int clen = 0, cerr, error = -1, i, shft; 413 char *mbdst, *mdst; 414 ssize_t mbslength, maxolen; 415 mbstate_t mbstate; 416 417 _DIAGASSERT(mbdstp != NULL); 418 _DIAGASSERT(mbsrc != NULL || mblength == 0); 419 _DIAGASSERT(mbextra != NULL); 420 421 mbslength = (ssize_t)mblength; 422 /* 423 * When inputing a single character, must also read in the 424 * next character for nextc, the look-ahead character. 425 */ 426 if (mbslength == 1) 427 mbslength++; 428 429 /* 430 * Input (mbsrc) is a char string considered to be multibyte 431 * characters. The input loop will read this string pulling 432 * one character, possibly multiple bytes, from mbsrc and 433 * converting each to wchar_t in src. 434 * 435 * The vis conversion will be done using the wide char 436 * wchar_t string. 437 * 438 * This will then be converted back to a multibyte string to 439 * return to the caller. 440 */ 441 442 /* Allocate space for the wide char strings */ 443 psrc = pdst = extra = NULL; 444 mdst = NULL; 445 if ((psrc = calloc(mbslength + 1, sizeof(*psrc))) == NULL) 446 return -1; 447 if ((pdst = calloc((16 * mbslength) + 1, sizeof(*pdst))) == NULL) 448 goto out; 449 if (*mbdstp == NULL) { 450 if ((mdst = calloc((16 * mbslength) + 1, sizeof(*mdst))) == NULL) 451 goto out; 452 *mbdstp = mdst; 453 } 454 455 mbdst = *mbdstp; 456 dst = pdst; 457 src = psrc; 458 459 if (flags & VIS_NOLOCALE) { 460 /* Do one byte at a time conversion */ 461 cerr = 1; 462 } else { 463 /* Use caller's multibyte conversion error flag. */ 464 cerr = cerr_ptr ? *cerr_ptr : 0; 465 } 466 467 /* 468 * Input loop. 469 * Handle up to mblength characters (not bytes). We do not 470 * stop at NULs because we may be processing a block of data 471 * that includes NULs. 472 */ 473 bzero(&mbstate, sizeof(mbstate)); 474 while (mbslength > 0) { 475 /* Convert one multibyte character to wchar_t. */ 476 if (!cerr) 477 clen = mbrtowc(src, mbsrc, MB_LEN_MAX, &mbstate); 478 if (cerr || clen < 0) { 479 /* Conversion error, process as a byte instead. */ 480 *src = (wint_t)(u_char)*mbsrc; 481 clen = 1; 482 cerr = 1; 483 } 484 if (clen == 0) { 485 /* 486 * NUL in input gives 0 return value. process 487 * as single NUL byte and keep going. 488 */ 489 clen = 1; 490 } 491 /* Advance buffer character pointer. */ 492 src++; 493 /* Advance input pointer by number of bytes read. */ 494 mbsrc += clen; 495 /* Decrement input byte count. */ 496 mbslength -= clen; 497 } 498 len = src - psrc; 499 src = psrc; 500 501 /* 502 * In the single character input case, we will have actually 503 * processed two characters, c and nextc. Reset len back to 504 * just a single character. 505 */ 506 if (mblength < len) 507 len = mblength; 508 509 /* Convert extra argument to list of characters for this mode. */ 510 extra = makeextralist(flags, mbextra); 511 if (!extra) { 512 if (dlen && *dlen == 0) { 513 errno = ENOSPC; 514 goto out; 515 } 516 *mbdst = '\0'; /* can't create extra, return "" */ 517 error = 0; 518 goto out; 519 } 520 521 /* Look up which processing function to call. */ 522 f = getvisfun(flags); 523 524 /* 525 * Main processing loop. 526 * Call do_Xvis processing function one character at a time 527 * with next character available for look-ahead. 528 */ 529 for (start = dst; len > 0; len--) { 530 c = *src++; 531 dst = (*f)(dst, c, flags, len >= 1 ? *src : L'\0', extra); 532 if (dst == NULL) { 533 errno = ENOSPC; 534 goto out; 535 } 536 } 537 538 /* Terminate the string in the buffer. */ 539 *dst = L'\0'; 540 541 /* 542 * Output loop. 543 * Convert wchar_t string back to multibyte output string. 544 * If we have hit a multi-byte conversion error on input, 545 * output byte-by-byte here. Else use wctomb(). 546 */ 547 len = wcslen(start); 548 maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1); 549 olen = 0; 550 bzero(&mbstate, sizeof(mbstate)); 551 for (dst = start; len > 0; len--) { 552 if (!cerr) 553 clen = wcrtomb(mbdst, *dst, &mbstate); 554 if (cerr || clen < 0) { 555 /* 556 * Conversion error, process as a byte(s) instead. 557 * Examine each byte and higher-order bytes for 558 * data. E.g., 559 * 0x000000000000a264 -> a2 64 560 * 0x000000001f00a264 -> 1f 00 a2 64 561 */ 562 clen = 0; 563 wmsk = 0; 564 for (i = sizeof(wmsk) - 1; i >= 0; i--) { 565 shft = i * NBBY; 566 bmsk = (uint64_t)0xffLL << shft; 567 wmsk |= bmsk; 568 if ((*dst & wmsk) || i == 0) 569 mbdst[clen++] = (char)( 570 (uint64_t)(*dst & bmsk) >> 571 shft); 572 } 573 cerr = 1; 574 } 575 /* If this character would exceed our output limit, stop. */ 576 if (olen + clen > (size_t)maxolen) 577 break; 578 /* Advance output pointer by number of bytes written. */ 579 mbdst += clen; 580 /* Advance buffer character pointer. */ 581 dst++; 582 /* Incrment output character count. */ 583 olen += clen; 584 } 585 586 /* Terminate the output string. */ 587 *mbdst = '\0'; 588 589 if (flags & VIS_NOLOCALE) { 590 /* Pass conversion error flag out. */ 591 if (cerr_ptr) 592 *cerr_ptr = cerr; 593 } 594 595 free(extra); 596 free(pdst); 597 free(psrc); 598 599 return (int)olen; 600 out: 601 free(extra); 602 free(pdst); 603 free(psrc); 604 free(mdst); 605 return error; 606 } 607 608 static int 609 istrsenvisxl(char **mbdstp, size_t *dlen, const char *mbsrc, 610 int flags, const char *mbextra, int *cerr_ptr) 611 { 612 return istrsenvisx(mbdstp, dlen, mbsrc, 613 mbsrc != NULL ? strlen(mbsrc) : 0, flags, mbextra, cerr_ptr); 614 } 615 616 #endif 617 618 #if !HAVE_SVIS 619 /* 620 * The "svis" variants all take an "extra" arg that is a pointer 621 * to a NUL-terminated list of characters to be encoded, too. 622 * These functions are useful e. g. to encode strings in such a 623 * way so that they are not interpreted by a shell. 624 */ 625 626 char * 627 svis(char *mbdst, int c, int flags, int nextc, const char *mbextra) 628 { 629 char cc[2]; 630 int ret; 631 632 cc[0] = c; 633 cc[1] = nextc; 634 635 ret = istrsenvisx(&mbdst, NULL, cc, 1, flags, mbextra, NULL); 636 if (ret < 0) 637 return NULL; 638 return mbdst + ret; 639 } 640 641 char * 642 snvis(char *mbdst, size_t dlen, int c, int flags, int nextc, const char *mbextra) 643 { 644 char cc[2]; 645 int ret; 646 647 cc[0] = c; 648 cc[1] = nextc; 649 650 ret = istrsenvisx(&mbdst, &dlen, cc, 1, flags, mbextra, NULL); 651 if (ret < 0) 652 return NULL; 653 return mbdst + ret; 654 } 655 656 int 657 strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra) 658 { 659 return istrsenvisxl(&mbdst, NULL, mbsrc, flags, mbextra, NULL); 660 } 661 662 int 663 strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra) 664 { 665 return istrsenvisxl(&mbdst, &dlen, mbsrc, flags, mbextra, NULL); 666 } 667 668 int 669 strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra) 670 { 671 return istrsenvisx(&mbdst, NULL, mbsrc, len, flags, mbextra, NULL); 672 } 673 674 int 675 strsnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, 676 const char *mbextra) 677 { 678 return istrsenvisx(&mbdst, &dlen, mbsrc, len, flags, mbextra, NULL); 679 } 680 681 int 682 strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, 683 const char *mbextra, int *cerr_ptr) 684 { 685 return istrsenvisx(&mbdst, &dlen, mbsrc, len, flags, mbextra, cerr_ptr); 686 } 687 #endif 688 689 #if !HAVE_VIS 690 /* 691 * vis - visually encode characters 692 */ 693 char * 694 vis(char *mbdst, int c, int flags, int nextc) 695 { 696 char cc[2]; 697 int ret; 698 699 cc[0] = c; 700 cc[1] = nextc; 701 702 ret = istrsenvisx(&mbdst, NULL, cc, 1, flags, "", NULL); 703 if (ret < 0) 704 return NULL; 705 return mbdst + ret; 706 } 707 708 char * 709 nvis(char *mbdst, size_t dlen, int c, int flags, int nextc) 710 { 711 char cc[2]; 712 int ret; 713 714 cc[0] = c; 715 cc[1] = nextc; 716 717 ret = istrsenvisx(&mbdst, &dlen, cc, 1, flags, "", NULL); 718 if (ret < 0) 719 return NULL; 720 return mbdst + ret; 721 } 722 723 /* 724 * strvis - visually encode characters from src into dst 725 * 726 * Dst must be 4 times the size of src to account for possible 727 * expansion. The length of dst, not including the trailing NULL, 728 * is returned. 729 */ 730 731 int 732 strvis(char *mbdst, const char *mbsrc, int flags) 733 { 734 return istrsenvisxl(&mbdst, NULL, mbsrc, flags, "", NULL); 735 } 736 737 int 738 strnvis(char *dst, const char *src, size_t len, int flag) 739 { 740 return istrsenvisxl(&dst, &len, src, flag, "", NULL); 741 } 742 743 int 744 stravis(char **mbdstp, const char *mbsrc, int flags) 745 { 746 *mbdstp = NULL; 747 return istrsenvisxl(mbdstp, NULL, mbsrc, flags, "", NULL); 748 } 749 750 /* 751 * strvisx - visually encode characters from src into dst 752 * 753 * Dst must be 4 times the size of src to account for possible 754 * expansion. The length of dst, not including the trailing NULL, 755 * is returned. 756 * 757 * Strvisx encodes exactly len characters from src into dst. 758 * This is useful for encoding a block of data. 759 */ 760 761 int 762 strvisx(char *mbdst, const char *mbsrc, size_t len, int flags) 763 { 764 return istrsenvisx(&mbdst, NULL, mbsrc, len, flags, "", NULL); 765 } 766 767 int 768 strnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags) 769 { 770 return istrsenvisx(&mbdst, &dlen, mbsrc, len, flags, "", NULL); 771 } 772 773 int 774 strenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, 775 int *cerr_ptr) 776 { 777 return istrsenvisx(&mbdst, &dlen, mbsrc, len, flags, "", cerr_ptr); 778 } 779 #endif 780