LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/roken - vis.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 53 208 25.5 %
Date: 2024-04-21 15:09:00 Functions: 4 13 30.8 %

          Line data    Source code
       1             : /*      $NetBSD: vis.c,v 1.37 2008/07/25 22:29:23 dsl Exp $     */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 1989, 1993
       5             :  *      The Regents of the University of California.  All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in the
      14             :  *    documentation and/or other materials provided with the distribution.
      15             :  * 3. Neither the name of the University nor the names of its contributors
      16             :  *    may be used to endorse or promote products derived from this software
      17             :  *    without specific prior written permission.
      18             :  *
      19             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      20             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      21             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      22             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      23             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      24             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      25             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      26             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      27             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      28             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      29             :  * SUCH DAMAGE.
      30             :  */
      31             : 
      32             : /*-
      33             :  * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
      34             :  * All rights reserved.
      35             :  *
      36             :  * Redistribution and use in source and binary forms, with or without
      37             :  * modification, are permitted provided that the following conditions
      38             :  * are met:
      39             :  * 1. Redistributions of source code must retain the above copyright
      40             :  *    notice, this list of conditions and the following disclaimer.
      41             :  * 2. Redistributions in binary form must reproduce the above copyright
      42             :  *    notice, this list of conditions and the following disclaimer in the
      43             :  *    documentation and/or other materials provided with the distribution.
      44             :  *
      45             :  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
      46             :  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      47             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      48             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
      49             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      50             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      51             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      52             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      53             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      54             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      55             :  * POSSIBILITY OF SUCH DAMAGE.
      56             :  */
      57             : 
      58             : #define _DEFAULT_SOURCE
      59             : #include <config.h>
      60             : #include "roken.h"
      61             : #ifdef TEST
      62             : #include "getarg.h"
      63             : #endif
      64             : #ifndef _DIAGASSERT
      65             : #define _DIAGASSERT(X)
      66             : #endif
      67             : 
      68             : #include <sys/types.h>
      69             : #include <assert.h>
      70             : #include <ctype.h>
      71             : #ifdef TEST
      72             : #include <err.h>
      73             : #endif
      74             : #include <errno.h>
      75             : #include <limits.h>
      76             : #include <stdio.h>
      77             : #include <string.h>
      78             : #include <stdlib.h>
      79             : #include <vis.h>
      80             : 
      81             : #if !HAVE_VIS || !HAVE_SVIS
      82             : #include <ctype.h>
      83             : #include <limits.h>
      84             : #include <stdio.h>
      85             : #include <string.h>
      86             : #endif
      87             : 
      88             : #if !HAVE_VIS || !HAVE_SVIS || TEST
      89             : /*
      90             :  * We use makextralist() in main(), so we need it even if we have all the VIS
      91             :  * routines in the host's C libraries.
      92             :  */
      93             : 
      94             : /* 5 is for VIS_SP, VIS_TAB, VIS_NL, VIS_DQ, and VIS_NOSLASH */
      95             : #define MAXEXTRAS       (sizeof(char_glob) - 1 + sizeof(char_shell) - 1 + 5)
      96             : 
      97             : #ifndef VIS_SHELL
      98             : #define VIS_SHELL       0x2000
      99             : #endif
     100             : #ifndef VIS_GLOB
     101             : #define VIS_GLOB        0x0100
     102             : #endif
     103             : 
     104             : #ifndef VIS_SP
     105             : #define VIS_SP          0x0004  /* also encode space */
     106             : #endif
     107             : #ifndef VIS_TAB
     108             : #define VIS_TAB         0x0008  /* also encode tab */
     109             : #endif
     110             : #ifndef VIS_NL
     111             : #define VIS_NL          0x0010  /* also encode newline */
     112             : #endif
     113             : #ifndef VIS_WHITE
     114             : #define VIS_WHITE       (VIS_SP | VIS_TAB | VIS_NL)
     115             : #endif
     116             : #ifndef VIS_SAFE
     117             : #define VIS_SAFE        0x0020  /* only encode "unsafe" characters */
     118             : #endif
     119             : #ifndef VIS_DQ
     120             : #define VIS_DQ          0x8000  /* also encode double quotes */
     121             : #endif
     122             : 
     123             : 
     124             : /*
     125             :  * Expand list of extra characters to not visually encode.
     126             :  */
     127             : static char *
     128      126570 : makeextralist(int flags, const char *src)
     129             : {
     130        4680 :     static const char char_glob[] = "*?[#";
     131        4680 :     static const char char_shell[] = "'`\";&<>()|{}]\\$!^~";
     132        4680 :     char *dst, *d;
     133        4680 :     size_t len;
     134             : 
     135      126570 :     len = strlen(src);
     136      126570 :     if ((dst = d = calloc(1, len + MAXEXTRAS + 1)) == NULL)
     137           0 :         return NULL;
     138             : 
     139      126570 :     memcpy(dst, src, len);
     140      126570 :     d += len;
     141             : 
     142      126570 :     if (flags & VIS_GLOB) {
     143           0 :         memcpy(d, char_glob, sizeof(char_glob) - 1);
     144           0 :         d += sizeof(char_glob) - 1;
     145             :     }
     146      126570 :     if (flags & VIS_SHELL) {
     147           0 :         memcpy(d, char_shell, sizeof(char_shell) - 1);
     148           0 :         d += sizeof(char_shell) - 1;
     149             :     }
     150             : 
     151      126570 :     if (flags & VIS_SP) *d++ = ' ';
     152      126570 :     if (flags & VIS_TAB) *d++ = '\t';
     153      126570 :     if (flags & VIS_NL) *d++ = '\n';
     154      126570 :     if (flags & VIS_DQ) *d++ = '"';
     155      126570 :     if ((flags & VIS_NOSLASH) == 0) *d++ = '\\';
     156             : 
     157      121890 :     return dst;
     158             : }
     159             : #endif
     160             : 
     161             : #if !HAVE_VIS || !HAVE_SVIS
     162             : static char *do_svis(char *, int, int, int, const char *);
     163             : 
     164             : #undef BELL
     165             : #if defined(__STDC__)
     166             : #define BELL '\a'
     167             : #else
     168             : #define BELL '\007'
     169             : #endif
     170             : 
     171             : ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
     172             :         rk_vis (char *, int, int, int);
     173             : ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
     174             :         rk_svis (char *, int, int, int, const char *);
     175             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     176             :         rk_strvis (char *, const char *, int);
     177             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     178             :         rk_strsvis (char *, const char *, int, const char *);
     179             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     180             :         rk_strvisx (char *, const char *, size_t, int);
     181             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     182             :         rk_strsvisx (char *, const char *, size_t, int, const char *);
     183             : 
     184             : #define isoctal(c)      (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
     185             : #define iswhite(c)      (c == ' ' || c == '\t' || c == '\n')
     186             : #define issafe(c)       (c == '\b' || c == BELL || c == '\r')
     187             : #define xtoa(c)         "0123456789abcdef"[c]
     188             : 
     189             : /*
     190             :  * This is do_hvis, for HTTP style (RFC 1808)
     191             :  */
     192             : static char *
     193           0 : do_hvis(char *dst, int c, int flag, int nextc, const char *extra)
     194             : {
     195           0 :         if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL ||
     196           0 :             strchr(extra, c)) {
     197           0 :                 *dst++ = '%';
     198           0 :                 *dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
     199           0 :                 *dst++ = xtoa((unsigned int)c & 0xf);
     200             :         } else {
     201           0 :                 dst = do_svis(dst, c, flag, nextc, extra);
     202             :         }
     203           0 :         return dst;
     204             : }
     205             : 
     206             : /*
     207             :  * This is do_vis, the central code of vis.
     208             :  * dst:       Pointer to the destination buffer
     209             :  * c:         Character to encode
     210             :  * flag:      Flag word
     211             :  * nextc:     The character following 'c'
     212             :  * extra:     Pointer to the list of extra characters to be
     213             :  *            backslash-protected.
     214             :  */
     215             : static char *
     216     1251568 : do_svis(char *dst, int c, int flag, int nextc, const char *extra)
     217             : {
     218       43875 :         int isextra;
     219     1251568 :         isextra = strchr(extra, c) != NULL;
     220     1251568 :         if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) ||
     221           0 :             ((flag & VIS_SAFE) && issafe(c)))) {
     222     1159406 :                 *dst++ = c;
     223     1159406 :                 return dst;
     224             :         }
     225       92162 :         if (flag & VIS_CSTYLE) {
     226       92162 :                 switch (c) {
     227           0 :                 case '\n':
     228           0 :                         *dst++ = '\\'; *dst++ = 'n';
     229           0 :                         return dst;
     230           0 :                 case '\r':
     231           0 :                         *dst++ = '\\'; *dst++ = 'r';
     232           0 :                         return dst;
     233           0 :                 case '\b':
     234           0 :                         *dst++ = '\\'; *dst++ = 'b';
     235           0 :                         return dst;
     236           0 :                 case BELL:
     237           0 :                         *dst++ = '\\'; *dst++ = 'a';
     238           0 :                         return dst;
     239           0 :                 case '\v':
     240           0 :                         *dst++ = '\\'; *dst++ = 'v';
     241           0 :                         return dst;
     242           0 :                 case '\t':
     243           0 :                         *dst++ = '\\'; *dst++ = 't';
     244           0 :                         return dst;
     245           0 :                 case '\f':
     246           0 :                         *dst++ = '\\'; *dst++ = 'f';
     247           0 :                         return dst;
     248       92162 :                 case ' ':
     249       92162 :                         *dst++ = '\\'; *dst++ = 's';
     250       92162 :                         return dst;
     251           0 :                 case '\0':
     252           0 :                         *dst++ = '\\'; *dst++ = '0';
     253           0 :                         if (isoctal(nextc)) {
     254           0 :                                 *dst++ = '0';
     255           0 :                                 *dst++ = '0';
     256             :                         }
     257           0 :                         return dst;
     258           0 :                 default:
     259           0 :                         if (isgraph(c)) {
     260           0 :                                 *dst++ = '\\'; *dst++ = c;
     261           0 :                                 return dst;
     262             :                         }
     263             :                 }
     264             :         }
     265           0 :         if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
     266           0 :                 *dst++ = '\\';
     267           0 :                 *dst++ = (u_char)(((unsigned int)(u_char)c >> 6) & 03) + '0';
     268           0 :                 *dst++ = (u_char)(((unsigned int)(u_char)c >> 3) & 07) + '0';
     269           0 :                 *dst++ = (u_char)(                       c       & 07) + '0';
     270             :         } else {
     271           0 :                 if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\';
     272           0 :                 if (c & 0200) {
     273           0 :                         c &= 0177; *dst++ = 'M';
     274             :                 }
     275           0 :                 if (iscntrl(c)) {
     276           0 :                         *dst++ = '^';
     277           0 :                         if (c == 0177)
     278           0 :                                 *dst++ = '?';
     279             :                         else
     280           0 :                                 *dst++ = c + '@';
     281             :                 } else {
     282           0 :                         *dst++ = '-'; *dst++ = c;
     283             :                 }
     284             :         }
     285           0 :         return dst;
     286             : }
     287             : 
     288             : 
     289             : /*
     290             :  * svis - visually encode characters, also encoding the characters
     291             :  *        pointed to by `extra'
     292             :  */
     293             : ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
     294           0 : rk_svis(char *dst, int c, int flag, int nextc, const char *extra)
     295             : {
     296           0 :         char *nextra = NULL;
     297             : 
     298           0 :         _DIAGASSERT(dst != NULL);
     299           0 :         _DIAGASSERT(extra != NULL);
     300           0 :         nextra = makeextralist(flag, extra);
     301           0 :         if (!nextra) {
     302           0 :                 *dst = '\0';            /* can't create nextra, return "" */
     303           0 :                 return dst;
     304             :         }
     305           0 :         if (flag & VIS_HTTPSTYLE)
     306           0 :                 dst = do_hvis(dst, c, flag, nextc, nextra);
     307             :         else
     308           0 :                 dst = do_svis(dst, c, flag, nextc, nextra);
     309           0 :         free(nextra);
     310           0 :         *dst = '\0';
     311           0 :         return dst;
     312             : }
     313             : 
     314             : 
     315             : /*
     316             :  * strsvis, strsvisx - visually encode characters from src into dst
     317             :  *
     318             :  *      Extra is a pointer to a \0-terminated list of characters to
     319             :  *      be encoded, too. These functions are useful e. g. to
     320             :  *      encode strings in such a way so that they are not interpreted
     321             :  *      by a shell.
     322             :  *
     323             :  *      Dst must be 4 times the size of src to account for possible
     324             :  *      expansion.  The length of dst, not including the trailing NULL,
     325             :  *      is returned.
     326             :  *
     327             :  *      Strsvisx encodes exactly len bytes from src into dst.
     328             :  *      This is useful for encoding a block of data.
     329             :  */
     330             : 
     331             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     332           0 : rk_strsvis(char *dst, const char *csrc, int flag, const char *extra)
     333             : {
     334           0 :         int c;
     335           0 :         char *start;
     336           0 :         char *nextra = NULL;
     337           0 :         const unsigned char *src = (const unsigned char *)csrc;
     338             : 
     339           0 :         _DIAGASSERT(dst != NULL);
     340           0 :         _DIAGASSERT(src != NULL);
     341           0 :         _DIAGASSERT(extra != NULL);
     342           0 :         nextra = makeextralist(flag, extra);
     343           0 :         if (!nextra) {
     344           0 :                 *dst = '\0';            /* can't create nextra, return "" */
     345           0 :                 return 0;
     346             :         }
     347           0 :         if (flag & VIS_HTTPSTYLE) {
     348           0 :                 for (start = dst; (c = *src++) != '\0'; /* empty */)
     349           0 :                         dst = do_hvis(dst, c, flag, *src, nextra);
     350             :         } else {
     351           0 :                 for (start = dst; (c = *src++) != '\0'; /* empty */)
     352           0 :                         dst = do_svis(dst, c, flag, *src, nextra);
     353             :         }
     354           0 :         free(nextra);
     355           0 :         *dst = '\0';
     356           0 :         return (dst - start);
     357             : }
     358             : 
     359             : 
     360             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     361       63285 : rk_strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)
     362             : {
     363        2340 :         unsigned char c;
     364        2340 :         char *start;
     365       63285 :         char *nextra = NULL;
     366       63285 :         const unsigned char *src = (const unsigned char *)csrc;
     367             : 
     368        2340 :         _DIAGASSERT(dst != NULL);
     369        2340 :         _DIAGASSERT(src != NULL);
     370        2340 :         _DIAGASSERT(extra != NULL);
     371       63285 :         nextra = makeextralist(flag, extra);
     372       63285 :         if (! nextra) {
     373           0 :                 *dst = '\0';            /* can't create nextra, return "" */
     374           0 :                 return 0;
     375             :         }
     376             : 
     377       63285 :         if (flag & VIS_HTTPSTYLE) {
     378           0 :                 for (start = dst; len > 0; len--) {
     379           0 :                         c = *src++;
     380           0 :                         dst = do_hvis(dst, c, flag, *src, nextra);
     381             :                 }
     382             :         } else {
     383     1314853 :                 for (start = dst; len > 0; len--) {
     384     1251568 :                         c = *src++;
     385     1251568 :                         dst = do_svis(dst, c, flag, *src, nextra);
     386             :                 }
     387             :         }
     388       63285 :         free(nextra);
     389       63285 :         *dst = '\0';
     390       63285 :         return (dst - start);
     391             : }
     392             : #endif
     393             : 
     394             : /*
     395             :  * Heimdal innovations: functions that allocate or reallocate a destination
     396             :  * buffer as needed.  Based on OpenBSD's stravis().
     397             :  */
     398             : 
     399             : #include <vis-extras.h>
     400             : 
     401             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     402           0 : rk_strasvis(char **out, const char *csrc, int flag, const char *extra)
     403             : {
     404           0 :         return rk_strasvisx(out, csrc, strlen(csrc), flag, extra);
     405             : }
     406             : 
     407             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     408           0 : rk_strrasvis(char **out, size_t *outsz, const char *csrc, int flag, const char *extra)
     409             : {
     410           0 :         return rk_strrasvisx(out, outsz, csrc, strlen(csrc), flag, extra);
     411             : }
     412             : 
     413             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     414           0 : rk_strasvisx(char **out, const char *csrc, size_t len, int flag, const char *extra)
     415             : {
     416           0 :         size_t sz = 0;
     417             : 
     418           0 :         *out = NULL;
     419           0 :         return rk_strrasvisx(out, &sz, csrc, strlen(csrc), flag, extra);
     420             : }
     421             : 
     422             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     423           0 : rk_strrasvisx(char **out,
     424             :               size_t *outsz,
     425             :               const char *csrc,
     426             :               size_t len,
     427             :               int flag,
     428             :               const char *extra)
     429             : {
     430           0 :         size_t want = 4 * len + 4;
     431           0 :         size_t have = *outsz;
     432           0 :         char *s = *out;
     433           0 :         int r;
     434             : 
     435           0 :         _DIAGASSERT(dst != NULL);
     436           0 :         _DIAGASSERT(src != NULL);
     437           0 :         _DIAGASSERT(extra != NULL);
     438           0 :         if (want < len || want > INT_MAX) {
     439           0 :                 errno = EOVERFLOW;
     440           0 :                 return -1;
     441             :         }
     442           0 :         if (have < want) {
     443           0 :                 if ((s = realloc(s, want)) == NULL)
     444           0 :                         return -1;
     445           0 :                 *outsz = want;
     446           0 :                 *out = s;
     447             :         }
     448           0 :         if (*out == NULL) {
     449           0 :             errno = EINVAL;
     450           0 :             return -1;
     451             :         }
     452           0 :         **out = '\0'; /* Makes source debugging nicer, that's all */
     453           0 :         r = strsvisx(*out, csrc, len, flag, extra);
     454           0 :         return r;
     455             : }
     456             : 
     457             : #if !HAVE_VIS
     458             : /*
     459             :  * vis - visually encode characters
     460             :  */
     461             : ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
     462           0 : rk_vis(char *dst, int c, int flag, int nextc)
     463             : {
     464           0 :         char *extra = NULL;
     465           0 :         unsigned char uc = (unsigned char)c;
     466             : 
     467           0 :         _DIAGASSERT(dst != NULL);
     468             : 
     469           0 :         extra = makeextralist(flag, "");
     470           0 :         if (! extra) {
     471           0 :                 *dst = '\0';            /* can't create extra, return "" */
     472           0 :                 return dst;
     473             :         }
     474           0 :         if (flag & VIS_HTTPSTYLE)
     475           0 :                 dst = do_hvis(dst, uc, flag, nextc, extra);
     476             :         else
     477           0 :                 dst = do_svis(dst, uc, flag, nextc, extra);
     478           0 :         free(extra);
     479           0 :         *dst = '\0';
     480           0 :         return dst;
     481             : }
     482             : 
     483             : 
     484             : /*
     485             :  * strvis, strvisx - visually encode characters from src into dst
     486             :  *
     487             :  *      Dst must be 4 times the size of src to account for possible
     488             :  *      expansion.  The length of dst, not including the trailing NULL,
     489             :  *      is returned.
     490             :  *
     491             :  *      Strvisx encodes exactly len bytes from src into dst.
     492             :  *      This is useful for encoding a block of data.
     493             :  */
     494             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     495           0 : rk_strvis(char *dst, const char *src, int flag)
     496             : {
     497           0 :         char *extra = NULL;
     498           0 :         int rv;
     499             : 
     500           0 :         extra = makeextralist(flag, "");
     501           0 :         if (!extra) {
     502           0 :                 *dst = '\0';            /* can't create extra, return "" */
     503           0 :                 return 0;
     504             :         }
     505           0 :         rv = strsvis(dst, src, flag, extra);
     506           0 :         free(extra);
     507           0 :         return rv;
     508             : }
     509             : 
     510             : 
     511             : ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
     512       63285 : rk_strvisx(char *dst, const char *src, size_t len, int flag)
     513             : {
     514       63285 :         char *extra = NULL;
     515        2340 :         int rv;
     516             : 
     517       63285 :         extra = makeextralist(flag, "");
     518       63285 :         if (!extra) {
     519           0 :                 *dst = '\0';            /* can't create extra, return "" */
     520           0 :                 return 0;
     521             :         }
     522       63285 :         rv = strsvisx(dst, src, len, flag, extra);
     523       63285 :         free(extra);
     524       63285 :         return rv;
     525             : }
     526             : #endif
     527             : 
     528             : #ifdef TEST
     529             : static const char *extra_arg = "";
     530             : static int cstyle_flag;
     531             : static int glob_flag;
     532             : static int help_flag;
     533             : static int http_flag;
     534             : static int httponly_flag;
     535             : static int line_flag;
     536             : static int octal_flag;
     537             : static int safe_flag;
     538             : static int shell_flag;
     539             : static int stdin_flag;
     540             : static int tab_flag;
     541             : static int whitespace_flag;
     542             : 
     543             : /*
     544             :  * The short options are compatible with a subset of the FreeBSD contrib
     545             :  * vis(1).  Heimdal additions have long option names only.
     546             :  */
     547             : static struct getargs args[] = {
     548             :     { "c", 'C', arg_flag, &cstyle_flag, "C style", "C style" },
     549             :     { "extra", 'e', arg_string, &extra_arg, "also encode extra", "also encode extra"},
     550             :     { "glob", 'g', arg_flag, &glob_flag, "escape glob specials", "escape glob specials" },
     551             :     { "help", 0, arg_flag, &help_flag, "help", "help"},
     552             :     { "line", 0, arg_flag, &line_flag, "read and escape stdin without escaping newlines", NULL },
     553             :     { "octal", 'o', arg_flag, &octal_flag, "octal escape", "octal escape" },
     554             :     { "safe", 's', arg_flag, &safe_flag, "only encode \"unsafe\" characters", "only encode \"unsafe\" characters" },
     555             :     { "shell", 'S', arg_flag, &shell_flag, "encode shell meta-characters", "encode shell meta-characters" },
     556             :     { "stdin", 0, arg_flag, &stdin_flag, "read and escape stdin", NULL },
     557             :     { "tab", 't', arg_flag, &tab_flag, "encode tabs", "encode tabs" },
     558             :     { "url", 'h', arg_flag, &http_flag, "url escape", "url escape" },
     559             :     { "url-only", 0, arg_flag, &httponly_flag, "url escape", "url escape" },
     560             :     { "whitespace", 'w', arg_flag, &whitespace_flag, "encode whitespace", "encode whitespace" },
     561             :     { 0, 0, 0, 0, 0, 0}
     562             : };
     563             : static size_t num_args = sizeof(args)/sizeof(args[0]);
     564             : 
     565             : int
     566             : main(int argc, char **argv)
     567             : {
     568             :     size_t sz = 0;
     569             :     char *nextra = NULL;
     570             :     char *s = NULL;
     571             :     int goptind = 0;
     572             :     int flags = 0;
     573             : 
     574             :     setprogname("vis");
     575             :     if (getarg(args, num_args, argc, argv, &goptind) || help_flag) {
     576             :         arg_printusage(args, num_args, NULL, "strings...");
     577             :         return help_flag ? 0 : 1;
     578             :     }
     579             : 
     580             :     argc -= goptind;
     581             :     argv += goptind;
     582             : 
     583             :     if (argc == 0 && !stdin_flag && !line_flag) {
     584             :         arg_printusage(args, num_args, NULL, "strings...");
     585             :         return 1;
     586             :     }
     587             : 
     588             :     if (http_flag && cstyle_flag)
     589             :         errx(1, "--http and --cstyle are mutually exclusive");
     590             : 
     591             :     flags |= cstyle_flag ? VIS_CSTYLE : 0;
     592             :     flags |= http_flag ? VIS_HTTPSTYLE : 0;
     593             :     flags |= httponly_flag ? VIS_HTTPSTYLE | VIS_NOESCAPE : 0;
     594             :     flags |= octal_flag ? VIS_OCTAL : 0;
     595             :     flags |= safe_flag ? VIS_SAFE : 0;
     596             :     flags |= tab_flag ? VIS_TAB : 0;
     597             :     flags |= whitespace_flag ? VIS_WHITE : 0;
     598             : 
     599             :     if ((nextra = makeextralist(flags, extra_arg)) == NULL)
     600             :         err(1, "Out of memory");
     601             : 
     602             :     while (argc) {
     603             :         if (rk_strrasvis(&s, &sz, argv[0], flags, nextra) < 0)
     604             :                 err(2, "Out of memory");
     605             :         printf("%s\n", s);
     606             :         argc--;
     607             :     }
     608             :     if (line_flag) {
     609             :         ssize_t nbytes;
     610             :         size_t linesz = 0;
     611             :         char *line = NULL;
     612             : 
     613             :         while (!feof(stdin) &&
     614             :                (nbytes = getline(&line, &linesz, stdin)) > 0) {
     615             :             const char *nl = "";
     616             : 
     617             :             if (line[nbytes - 1] == '\n') {
     618             :                 line[--nbytes] = '\0';
     619             :                 nl = "\n";
     620             :             }
     621             : 
     622             :             if (rk_strrasvisx(&s, &sz, line, nbytes, flags, nextra) < 0)
     623             :                 err(2, "Out of memory");
     624             :             printf("%s%s", s, nl);
     625             :         }
     626             :         fflush(stdout);
     627             :         if (ferror(stdin))
     628             :             errx(2, "I/O error");
     629             :     } else if (stdin_flag) {
     630             :         size_t nbytes;
     631             :         char buf[2048 + 1];
     632             :         char vbuf[4 * (sizeof(buf) - 1) + 1];
     633             : 
     634             :         while (!feof(stdin) &&
     635             :                (nbytes = fread(buf, 1, sizeof(buf) - 1, stdin))) {
     636             :             buf[nbytes] = '\0';
     637             :             strsvis(vbuf, buf, flags, nextra);
     638             :             printf("%s", vbuf);
     639             :         }
     640             :         fflush(stdout);
     641             :         if (ferror(stdin))
     642             :             errx(2, "I/O error");
     643             :     }
     644             : 
     645             :     free(nextra);
     646             :     free(s);
     647             :     return 0;
     648             : }
     649             : #endif

Generated by: LCOV version 1.14