rm lib/libc/gen/unvis.c \ lib/libc/gen/vis.3 \ lib/libc/gen/vis.c \ lib/libc/gen/unvis.3 \ include/vis.h Index: lib/libc/gen/Makefile.inc =================================================================== --- lib/libc/gen/Makefile.inc (revision 244091) +++ lib/libc/gen/Makefile.inc (working copy) @@ -32,13 +32,16 @@ sigsetops.c sleep.c srand48.c statvfs.c stringlist.c strtofflags.c \ sysconf.c sysctl.c sysctlbyname.c sysctlnametomib.c \ syslog.c telldir.c termios.c time.c times.c timezone.c tls.c \ - ttyname.c ttyslot.c ualarm.c ulimit.c uname.c unvis.c \ - usleep.c utime.c utxdb.c valloc.c vis.c wait.c wait3.c waitpid.c \ + ttyname.c ttyslot.c ualarm.c ulimit.c uname.c unvis-compat.c \ + usleep.c utime.c utxdb.c valloc.c wait.c wait3.c waitpid.c \ waitid.c wordexp.c .PATH: ${.CURDIR}/../../contrib/libc-pwcache SRCS+= pwcache.c pwcache.h +.PATH: ${.CURDIR}/../../contrib/libc-vis +SRCS+= unvis.c vis.c + MISRCS+=modf.c CANCELPOINTS_SRCS=sem.c sem_new.c Index: lib/libc/gen/unvis-compat.c =================================================================== --- lib/libc/gen/unvis-compat.c (revision 0) +++ lib/libc/gen/unvis-compat.c (working copy) @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2012 SRI International + * All rights reserved. + * + * This software was developed by SRI International and the University of + * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) + * ("CTSRD"), as part of the DARPA CRASH research programme. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include + +#define _UNVIS_END 1 + +int +__unvis_44bsd(char *cp, int c, int *astate, int flag) +{ + + if (flag & _UNVIS_END) + flag = (flag & ~_UNVIS_END) ^ UNVIS_END; + return unvis(cp, c, astate, flag); +} + +__sym_compat(unvis, __vis_44bsd, FBSD_1.0); Property changes on: lib/libc/gen/unvis-compat.c ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H Added: svn:eol-style ## -0,0 +1 ## +native Index: lib/libc/gen/Symbol.map =================================================================== --- lib/libc/gen/Symbol.map (revision 244091) +++ lib/libc/gen/Symbol.map (working copy) @@ -298,7 +298,6 @@ ualarm; ulimit; uname; - unvis; strunvis; strunvisx; usleep; @@ -388,9 +387,21 @@ __FreeBSD_libc_enter_restricted_mode; getcontextx; gid_from_group; + nvis; pwcache_userdb; pwcache_groupdb; + snvis; + strnunvis; + strnunvisx; + strnvis; + strnvisx; + strsnvis; + strsnvisx; + strsvis; + strsvisx; + svis; uid_from_user; + unvis; waitid; }; Index: include/Makefile =================================================================== --- include/Makefile (revision 244091) +++ include/Makefile (working copy) @@ -23,9 +23,12 @@ stdnoreturn.h stdio.h stdlib.h string.h stringlist.h \ strings.h sysexits.h tar.h termios.h tgmath.h \ time.h timeconv.h timers.h ttyent.h \ - ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h vis.h \ + ulimit.h unistd.h utime.h utmpx.h uuid.h varargs.h \ wchar.h wctype.h wordexp.h xlocale.h +.PATH: ${.CURDIR}/../contrib/libc-vis +INCS+= vis.h + MHDRS= float.h floatingpoint.h stdarg.h PHDRS= sched.h _semaphore.h diff -ruN contrib/libc-vis/unvis.3 contrib/libc-vis/unvis.3 --- contrib/libc-vis/unvis.3 1969-12-31 18:00:00.000000000 -0600 +++ contrib/libc-vis/unvis.3 2012-10-20 09:09:04.000000000 -0500 @@ -0,0 +1,247 @@ +.\" $NetBSD: unvis.3,v 1.23 2011/03/17 14:06:29 wiz Exp $ +.\" $FreeBSD$ +.\" +.\" Copyright (c) 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)unvis.3 8.2 (Berkeley) 12/11/93 +.\" +.Dd October 20, 2012 +.Dt UNVIS 3 +.Os +.Sh NAME +.Nm unvis , +.Nm strunvis +.Nd decode a visual representation of characters +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In vis.h +.Ft int +.Fn unvis "char *cp" "int c" "int *astate" "int flag" +.Ft int +.Fn strunvis "char *dst" "const char *src" +.Ft int +.Fn strnunvis "char *dst" "size_t dlen" "const char *src" +.Ft int +.Fn strunvisx "char *dst" "const char *src" "int flag" +.Ft int +.Fn strnunvisx "char *dst" "size_t dlen" "const char *src" "int flag" +.Sh DESCRIPTION +The +.Fn unvis , +.Fn strunvis +and +.Fn strunvisx +functions +are used to decode a visual representation of characters, as produced +by the +.Xr vis 3 +function, back into +the original form. +.Pp +The +.Fn unvis +function is called with successive characters in +.Ar c +until a valid sequence is recognized, at which time the decoded +character is available at the character pointed to by +.Ar cp . +.Pp +The +.Fn strunvis +function decodes the characters pointed to by +.Ar src +into the buffer pointed to by +.Ar dst . +The +.Fn strunvis +function simply copies +.Ar src +to +.Ar dst , +decoding any escape sequences along the way, +and returns the number of characters placed into +.Ar dst , +or \-1 if an +invalid escape sequence was detected. +The size of +.Ar dst +should be equal to the size of +.Ar src +(that is, no expansion takes place during decoding). +.Pp +The +.Fn strunvisx +function does the same as the +.Fn strunvis +function, +but it allows you to add a flag that specifies the style the string +.Ar src +is encoded with. +Currently, the supported flags are: +.Dv VIS_HTTPSTYLE +and +.Dv VIS_MIMESTYLE . +.Pp +The +.Fn unvis +function implements a state machine that can be used to decode an +arbitrary stream of bytes. +All state associated with the bytes being decoded is stored outside the +.Fn unvis +function (that is, a pointer to the state is passed in), so +calls decoding different streams can be freely intermixed. +To start decoding a stream of bytes, first initialize an integer to zero. +Call +.Fn unvis +with each successive byte, along with a pointer +to this integer, and a pointer to a destination character. +The +.Fn unvis +function has several return codes that must be handled properly. +They are: +.Bl -tag -width UNVIS_VALIDPUSH +.It Li \&0 (zero) +Another character is necessary; nothing has been recognized yet. +.It Dv UNVIS_VALID +A valid character has been recognized and is available at the location +pointed to by cp. +.It Dv UNVIS_VALIDPUSH +A valid character has been recognized and is available at the location +pointed to by cp; however, the character currently passed in should +be passed in again. +.It Dv UNVIS_NOCHAR +A valid sequence was detected, but no character was produced. +This return code is necessary to indicate a logical break between characters. +.It Dv UNVIS_SYNBAD +An invalid escape sequence was detected, or the decoder is in an unknown state. +The decoder is placed into the starting state. +.El +.Pp +When all bytes in the stream have been processed, call +.Fn unvis +one more time with flag set to +.Dv UNVIS_END +to extract any remaining character (the character passed in is ignored). +.Pp +The +.Ar flag +argument is also used to specify the encoding style of the source. +If set to +.Dv VIS_HTTPSTYLE +or +.Dv VIS_HTTP1808 , +.Fn unvis +will decode URI strings as specified in RFC 1808. +If set to +.Dv VIS_HTTP1866 , +.Fn unvis +will decode URI strings as specified in RFC 1866. +If set to +.Dv VIS_MIMESTYLE , +.Fn unvis +will decode MIME Quoted-Printable strings as specified in RFC 2045. +If set to +.Dv VIS_NOESCAPE , +.Fn unvis +will not decode \e quoted characters. +.Pp +The following code fragment illustrates a proper use of +.Fn unvis . +.Bd -literal -offset indent +int state = 0; +char out; + +while ((ch = getchar()) != EOF) { +again: + switch(unvis(\*[Am]out, ch, \*[Am]state, 0)) { + case 0: + case UNVIS_NOCHAR: + break; + case UNVIS_VALID: + (void)putchar(out); + break; + case UNVIS_VALIDPUSH: + (void)putchar(out); + goto again; + case UNVIS_SYNBAD: + errx(EXIT_FAILURE, "Bad character sequence!"); + } +} +if (unvis(\*[Am]out, '\e0', \*[Am]state, UNVIS_END) == UNVIS_VALID) + (void)putchar(out); +.Ed +.Sh ERRORS +The functions +.Fn strunvis , +.Fn strnunvis , +.Fn strunvisx , +and +.Fn strnunvisx +will return \-1 on error and set +.Va errno +to: +.Bl -tag -width Er +.It Bq Er EINVAL +An invalid escape sequence was detected, or the decoder is in an unknown state. +.El +.Pp +In addition the functions +.Fn strnunvis +and +.Fn strnunvisx +will can also set +.Va errno +on error to: +.Bl -tag -width Er +.It Bq Er ENOSPC +Not enough space to perform the conversion. +.El +.Sh SEE ALSO +.Xr unvis 1 , +.Xr vis 1 , +.Xr vis 3 +.Rs +.%A R. Fielding +.%T Relative Uniform Resource Locators +.%O RFC1808 +.Re +.Sh HISTORY +The +.Fn unvis +function +first appeared in +.Bx 4.4 . +The +.Fn strnunvis +and +.Fn strnunvisx +functions appeared in +.Nx 6.0 +and +.Fx 10.0 . diff -ruN contrib/libc-vis/unvis.c contrib/libc-vis/unvis.c --- contrib/libc-vis/unvis.c 1969-12-31 18:00:00.000000000 -0600 +++ contrib/libc-vis/unvis.c 2012-10-20 09:22:09.000000000 -0500 @@ -0,0 +1,562 @@ +/* $NetBSD: unvis.c,v 1.39 2012/03/13 21:13:37 christos Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: unvis.c,v 1.39 2012/03/13 21:13:37 christos Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include + +#include +#include +#include +#include +#include +#include + +#define _DIAGASSERT(x) assert(x) + +/* + * Return the number of elements in a statically-allocated array, + * __x. + */ +#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) + +#ifdef __weak_alias +__weak_alias(strnunvisx,_strnunvisx) +#endif + +#if !HAVE_VIS +/* + * decode driven by state machine + */ +#define S_GROUND 0 /* haven't seen escape char */ +#define S_START 1 /* start decoding special sequence */ +#define S_META 2 /* metachar started (M) */ +#define S_META1 3 /* metachar more, regular char (-) */ +#define S_CTRL 4 /* control char started (^) */ +#define S_OCTAL2 5 /* octal digit 2 */ +#define S_OCTAL3 6 /* octal digit 3 */ +#define S_HEX 7 /* mandatory hex digit */ +#define S_HEX1 8 /* http hex digit */ +#define S_HEX2 9 /* http hex digit 2 */ +#define S_MIME1 10 /* mime hex digit 1 */ +#define S_MIME2 11 /* mime hex digit 2 */ +#define S_EATCRNL 12 /* mime eating CRNL */ +#define S_AMP 13 /* seen & */ +#define S_NUMBER 14 /* collecting number */ +#define S_STRING 15 /* collecting string */ + +#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') +#define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10)) +#define XTOD(c) (isdigit(c) ? (c - '0') : ((c - 'A') + 10)) + +/* + * RFC 1866 + */ +static const struct nv { + const char *name; + uint8_t value; +} nv[] = { + { "AElig", 198 }, /* capital AE diphthong (ligature) */ + { "Aacute", 193 }, /* capital A, acute accent */ + { "Acirc", 194 }, /* capital A, circumflex accent */ + { "Agrave", 192 }, /* capital A, grave accent */ + { "Aring", 197 }, /* capital A, ring */ + { "Atilde", 195 }, /* capital A, tilde */ + { "Auml", 196 }, /* capital A, dieresis or umlaut mark */ + { "Ccedil", 199 }, /* capital C, cedilla */ + { "ETH", 208 }, /* capital Eth, Icelandic */ + { "Eacute", 201 }, /* capital E, acute accent */ + { "Ecirc", 202 }, /* capital E, circumflex accent */ + { "Egrave", 200 }, /* capital E, grave accent */ + { "Euml", 203 }, /* capital E, dieresis or umlaut mark */ + { "Iacute", 205 }, /* capital I, acute accent */ + { "Icirc", 206 }, /* capital I, circumflex accent */ + { "Igrave", 204 }, /* capital I, grave accent */ + { "Iuml", 207 }, /* capital I, dieresis or umlaut mark */ + { "Ntilde", 209 }, /* capital N, tilde */ + { "Oacute", 211 }, /* capital O, acute accent */ + { "Ocirc", 212 }, /* capital O, circumflex accent */ + { "Ograve", 210 }, /* capital O, grave accent */ + { "Oslash", 216 }, /* capital O, slash */ + { "Otilde", 213 }, /* capital O, tilde */ + { "Ouml", 214 }, /* capital O, dieresis or umlaut mark */ + { "THORN", 222 }, /* capital THORN, Icelandic */ + { "Uacute", 218 }, /* capital U, acute accent */ + { "Ucirc", 219 }, /* capital U, circumflex accent */ + { "Ugrave", 217 }, /* capital U, grave accent */ + { "Uuml", 220 }, /* capital U, dieresis or umlaut mark */ + { "Yacute", 221 }, /* capital Y, acute accent */ + { "aacute", 225 }, /* small a, acute accent */ + { "acirc", 226 }, /* small a, circumflex accent */ + { "acute", 180 }, /* acute accent */ + { "aelig", 230 }, /* small ae diphthong (ligature) */ + { "agrave", 224 }, /* small a, grave accent */ + { "amp", 38 }, /* ampersand */ + { "aring", 229 }, /* small a, ring */ + { "atilde", 227 }, /* small a, tilde */ + { "auml", 228 }, /* small a, dieresis or umlaut mark */ + { "brvbar", 166 }, /* broken (vertical) bar */ + { "ccedil", 231 }, /* small c, cedilla */ + { "cedil", 184 }, /* cedilla */ + { "cent", 162 }, /* cent sign */ + { "copy", 169 }, /* copyright sign */ + { "curren", 164 }, /* general currency sign */ + { "deg", 176 }, /* degree sign */ + { "divide", 247 }, /* divide sign */ + { "eacute", 233 }, /* small e, acute accent */ + { "ecirc", 234 }, /* small e, circumflex accent */ + { "egrave", 232 }, /* small e, grave accent */ + { "eth", 240 }, /* small eth, Icelandic */ + { "euml", 235 }, /* small e, dieresis or umlaut mark */ + { "frac12", 189 }, /* fraction one-half */ + { "frac14", 188 }, /* fraction one-quarter */ + { "frac34", 190 }, /* fraction three-quarters */ + { "gt", 62 }, /* greater than */ + { "iacute", 237 }, /* small i, acute accent */ + { "icirc", 238 }, /* small i, circumflex accent */ + { "iexcl", 161 }, /* inverted exclamation mark */ + { "igrave", 236 }, /* small i, grave accent */ + { "iquest", 191 }, /* inverted question mark */ + { "iuml", 239 }, /* small i, dieresis or umlaut mark */ + { "laquo", 171 }, /* angle quotation mark, left */ + { "lt", 60 }, /* less than */ + { "macr", 175 }, /* macron */ + { "micro", 181 }, /* micro sign */ + { "middot", 183 }, /* middle dot */ + { "nbsp", 160 }, /* no-break space */ + { "not", 172 }, /* not sign */ + { "ntilde", 241 }, /* small n, tilde */ + { "oacute", 243 }, /* small o, acute accent */ + { "ocirc", 244 }, /* small o, circumflex accent */ + { "ograve", 242 }, /* small o, grave accent */ + { "ordf", 170 }, /* ordinal indicator, feminine */ + { "ordm", 186 }, /* ordinal indicator, masculine */ + { "oslash", 248 }, /* small o, slash */ + { "otilde", 245 }, /* small o, tilde */ + { "ouml", 246 }, /* small o, dieresis or umlaut mark */ + { "para", 182 }, /* pilcrow (paragraph sign) */ + { "plusmn", 177 }, /* plus-or-minus sign */ + { "pound", 163 }, /* pound sterling sign */ + { "quot", 34 }, /* double quote */ + { "raquo", 187 }, /* angle quotation mark, right */ + { "reg", 174 }, /* registered sign */ + { "sect", 167 }, /* section sign */ + { "shy", 173 }, /* soft hyphen */ + { "sup1", 185 }, /* superscript one */ + { "sup2", 178 }, /* superscript two */ + { "sup3", 179 }, /* superscript three */ + { "szlig", 223 }, /* small sharp s, German (sz ligature) */ + { "thorn", 254 }, /* small thorn, Icelandic */ + { "times", 215 }, /* multiply sign */ + { "uacute", 250 }, /* small u, acute accent */ + { "ucirc", 251 }, /* small u, circumflex accent */ + { "ugrave", 249 }, /* small u, grave accent */ + { "uml", 168 }, /* umlaut (dieresis) */ + { "uuml", 252 }, /* small u, dieresis or umlaut mark */ + { "yacute", 253 }, /* small y, acute accent */ + { "yen", 165 }, /* yen sign */ + { "yuml", 255 }, /* small y, dieresis or umlaut mark */ +}; + +/* + * unvis - decode characters previously encoded by vis + */ +int +unvis(char *cp, int c, int *astate, int flag) +{ + unsigned char uc = (unsigned char)c; + unsigned char st, ia, is, lc; + +/* + * Bottom 8 bits of astate hold the state machine state. + * Top 8 bits hold the current character in the http 1866 nv string decoding + */ +#define GS(a) ((a) & 0xff) +#define SS(a, b) (((uint32_t)(a) << 24) | (b)) +#define GI(a) ((uint32_t)(a) >> 24) + + _DIAGASSERT(cp != NULL); + _DIAGASSERT(astate != NULL); + st = GS(*astate); + + if (flag & UNVIS_END) { + switch (st) { + case S_OCTAL2: + case S_OCTAL3: + case S_HEX2: + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case S_GROUND: + return UNVIS_NOCHAR; + default: + return UNVIS_SYNBAD; + } + } + + switch (st) { + + case S_GROUND: + *cp = 0; + if ((flag & VIS_NOESCAPE) == 0 && c == '\\') { + *astate = SS(0, S_START); + return UNVIS_NOCHAR; + } + if ((flag & VIS_HTTP1808) && c == '%') { + *astate = SS(0, S_HEX1); + return UNVIS_NOCHAR; + } + if ((flag & VIS_HTTP1866) && c == '&') { + *astate = SS(0, S_AMP); + return UNVIS_NOCHAR; + } + if ((flag & VIS_MIMESTYLE) && c == '=') { + *astate = SS(0, S_MIME1); + return UNVIS_NOCHAR; + } + *cp = c; + return UNVIS_VALID; + + case S_START: + switch(c) { + case '\\': + *cp = c; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + *cp = (c - '0'); + *astate = SS(0, S_OCTAL2); + return UNVIS_NOCHAR; + case 'M': + *cp = (char)0200; + *astate = SS(0, S_META); + return UNVIS_NOCHAR; + case '^': + *astate = SS(0, S_CTRL); + return UNVIS_NOCHAR; + case 'n': + *cp = '\n'; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 'r': + *cp = '\r'; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 'b': + *cp = '\b'; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 'a': + *cp = '\007'; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 'v': + *cp = '\v'; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 't': + *cp = '\t'; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 'f': + *cp = '\f'; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 's': + *cp = ' '; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 'E': + *cp = '\033'; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + case 'x': + *astate = SS(0, S_HEX); + return UNVIS_NOCHAR; + case '\n': + /* + * hidden newline + */ + *astate = SS(0, S_GROUND); + return UNVIS_NOCHAR; + case '$': + /* + * hidden marker + */ + *astate = SS(0, S_GROUND); + return UNVIS_NOCHAR; + } + goto bad; + + case S_META: + if (c == '-') + *astate = SS(0, S_META1); + else if (c == '^') + *astate = SS(0, S_CTRL); + else + goto bad; + return UNVIS_NOCHAR; + + case S_META1: + *astate = SS(0, S_GROUND); + *cp |= c; + return UNVIS_VALID; + + case S_CTRL: + if (c == '?') + *cp |= 0177; + else + *cp |= c & 037; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + + case S_OCTAL2: /* second possible octal digit */ + if (isoctal(uc)) { + /* + * yes - and maybe a third + */ + *cp = (*cp << 3) + (c - '0'); + *astate = SS(0, S_OCTAL3); + return UNVIS_NOCHAR; + } + /* + * no - done with current sequence, push back passed char + */ + *astate = SS(0, S_GROUND); + return UNVIS_VALIDPUSH; + + case S_OCTAL3: /* third possible octal digit */ + *astate = SS(0, S_GROUND); + if (isoctal(uc)) { + *cp = (*cp << 3) + (c - '0'); + return UNVIS_VALID; + } + /* + * we were done, push back passed char + */ + return UNVIS_VALIDPUSH; + + case S_HEX: + if (!isxdigit(uc)) + goto bad; + /*FALLTHROUGH*/ + case S_HEX1: + if (isxdigit(uc)) { + *cp = xtod(uc); + *astate = SS(0, S_HEX2); + return UNVIS_NOCHAR; + } + /* + * no - done with current sequence, push back passed char + */ + *astate = SS(0, S_GROUND); + return UNVIS_VALIDPUSH; + + case S_HEX2: + *astate = S_GROUND; + if (isxdigit(uc)) { + *cp = xtod(uc) | (*cp << 4); + return UNVIS_VALID; + } + return UNVIS_VALIDPUSH; + + case S_MIME1: + if (uc == '\n' || uc == '\r') { + *astate = SS(0, S_EATCRNL); + return UNVIS_NOCHAR; + } + if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) { + *cp = XTOD(uc); + *astate = SS(0, S_MIME2); + return UNVIS_NOCHAR; + } + goto bad; + + case S_MIME2: + if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) { + *astate = SS(0, S_GROUND); + *cp = XTOD(uc) | (*cp << 4); + return UNVIS_VALID; + } + goto bad; + + case S_EATCRNL: + switch (uc) { + case '\r': + case '\n': + return UNVIS_NOCHAR; + case '=': + *astate = SS(0, S_MIME1); + return UNVIS_NOCHAR; + default: + *cp = uc; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + } + + case S_AMP: + *cp = 0; + if (uc == '#') { + *astate = SS(0, S_NUMBER); + return UNVIS_NOCHAR; + } + *astate = SS(0, S_STRING); + /*FALLTHROUGH*/ + + case S_STRING: + ia = *cp; /* index in the array */ + is = GI(*astate); /* index in the string */ + lc = is == 0 ? 0 : nv[ia].name[is - 1]; /* last character */ + + if (uc == ';') + uc = '\0'; + + for (; ia < __arraycount(nv); ia++) { + if (is != 0 && nv[ia].name[is - 1] != lc) + goto bad; + if (nv[ia].name[is] == uc) + break; + } + + if (ia == __arraycount(nv)) + goto bad; + + if (uc != 0) { + *cp = ia; + *astate = SS(is + 1, S_STRING); + return UNVIS_NOCHAR; + } + + *cp = nv[ia].value; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + + case S_NUMBER: + if (uc == ';') + return UNVIS_VALID; + if (!isdigit(uc)) + goto bad; + *cp += (*cp * 10) + uc - '0'; + return UNVIS_NOCHAR; + + default: + bad: + /* + * decoder in unknown state - (probably uninitialized) + */ + *astate = SS(0, S_GROUND); + return UNVIS_SYNBAD; + } +} + +/* + * strnunvisx - decode src into dst + * + * Number of chars decoded into dst is returned, -1 on error. + * Dst is null terminated. + */ + +int +strnunvisx(char *dst, size_t dlen, const char *src, int flag) +{ + char c; + char t = '\0', *start = dst; + int state = 0; + + _DIAGASSERT(src != NULL); + _DIAGASSERT(dst != NULL); +#define CHECKSPACE() \ + do { \ + if (dlen-- == 0) { \ + errno = ENOSPC; \ + return -1; \ + } \ + } while (/*CONSTCOND*/0) + + while ((c = *src++) != '\0') { + again: + switch (unvis(&t, c, &state, flag)) { + case UNVIS_VALID: + CHECKSPACE(); + *dst++ = t; + break; + case UNVIS_VALIDPUSH: + CHECKSPACE(); + *dst++ = t; + goto again; + case 0: + case UNVIS_NOCHAR: + break; + case UNVIS_SYNBAD: + errno = EINVAL; + return -1; + default: + _DIAGASSERT(/*CONSTCOND*/0); + errno = EINVAL; + return -1; + } + } + if (unvis(&t, c, &state, UNVIS_END) == UNVIS_VALID) { + CHECKSPACE(); + *dst++ = t; + } + CHECKSPACE(); + *dst = '\0'; + return (int)(dst - start); +} + +int +strunvisx(char *dst, const char *src, int flag) +{ + return strnunvisx(dst, (size_t)~0, src, flag); +} + +int +strunvis(char *dst, const char *src) +{ + return strnunvisx(dst, (size_t)~0, src, 0); +} + +int +strnunvis(char *dst, size_t dlen, const char *src) +{ + return strnunvisx(dst, dlen, src, 0); +} +#endif diff -ruN contrib/libc-vis/vis.3 contrib/libc-vis/vis.3 --- contrib/libc-vis/vis.3 1969-12-31 18:00:00.000000000 -0600 +++ contrib/libc-vis/vis.3 2012-10-20 09:15:06.000000000 -0500 @@ -0,0 +1,456 @@ +.\" $NetBSD: vis.3,v 1.27 2011/05/17 07:10:39 joerg Exp $ +.\" $FreeBSD$ +.\" +.\" Copyright (c) 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)vis.3 8.1 (Berkeley) 6/9/93 +.\" +.Dd October 20, 2012 +.Dt VIS 3 +.Os +.Sh NAME +.Nm vis , +.Nm nvis , +.Nm strvis , +.Nm strnvis , +.Nm strvisx , +.Nm strnvisx , +.Nm svis , +.Nm snvis , +.Nm strsvis , +.Nm strsnvis , +.Nm strsvisx +.Nm strsnvisx +.Nd visually encode characters +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In vis.h +.Ft char * +.Fn vis "char *dst" "int c" "int flag" "int nextc" +.Ft char * +.Fn nvis "char *dst" "size_t dlen" "int c" "int flag" "int nextc" +.Ft int +.Fn strvis "char *dst" "const char *src" "int flag" +.Ft int +.Fn strnvis "char *dst" "size_t dlen" "const char *src" "int flag" +.Ft int +.Fn strvisx "char *dst" "const char *src" "size_t len" "int flag" +.Ft int +.Fn strnvisx "char *dst" "size_t dlen" "const char *src" "size_t len" "int flag" +.Ft char * +.Fn svis "char *dst" "int c" "int flag" "int nextc" "const char *extra" +.Ft char * +.Fn snvis "char *dst" "size_t dlen" "int c" "int flag" "int nextc" "const char *extra" +.Ft int +.Fn strsvis "char *dst" "const char *src" "int flag" "const char *extra" +.Ft int +.Fn strsnvis "char *dst" "size_t dlen" "const char *src" "int flag" "const char *extra" +.Ft int +.Fn strsvisx "char *dst" "const char *src" "size_t len" "int flag" "const char *extra" +.Ft int +.Fn strsnvisx "char *dst" "size_t dlen" "const char *src" "size_t len" "int flag" "const char *extra" +.Sh DESCRIPTION +The +.Fn vis +function +copies into +.Fa dst +a string which represents the character +.Fa c . +If +.Fa c +needs no encoding, it is copied in unaltered. +The string is null terminated, and a pointer to the end of the string is +returned. +The maximum length of any encoding is four +characters (not including the trailing +.Dv NUL ) ; +thus, when +encoding a set of characters into a buffer, the size of the buffer should +be four times the number of characters encoded, plus one for the trailing +.Dv NUL . +The flag parameter is used for altering the default range of +characters considered for encoding and for altering the visual +representation. +The additional character, +.Fa nextc , +is only used when selecting the +.Dv VIS_CSTYLE +encoding format (explained below). +.Pp +The +.Fn strvis , +.Fn strnvis , +.Fn strvisx , +and +.Fn strnvisx +functions copy into +.Fa dst +a visual representation of +the string +.Fa src . +The +.Fn strvis +and +.Fn strnvis +functions encode characters from +.Fa src +up to the +first +.Dv NUL . +The +.Fn strvisx +and +.Fn strnvisx +functions encode exactly +.Fa len +characters from +.Fa src +(this +is useful for encoding a block of data that may contain +.Dv NUL Ns 's ) . +Both forms +.Dv NUL +terminate +.Fa dst . +The size of +.Fa dst +must be four times the number +of characters encoded from +.Fa src +(plus one for the +.Dv NUL ) . +Both +forms return the number of characters in dst (not including +the trailing +.Dv NUL ) . +The +.Dq n +versions of the functions also take an additional argument +.Fa dlen +that indicates the length of the +.Fa dst +buffer. +If +.Fa dlen +is not large enough to fix the converted string then the +.Fn strnvis +and +.Fn strnvisx +functions return \-1 and set +.Va errno +to +.Dv ENOSPC . +.Pp +The functions +.Fn svis , +.Fn snvis , +.Fn strsvis , +.Fn strsnvis , +.Fn strsvisx , +and +.Fn strsnvisx +correspond to +.Fn vis , +.Fn nvis , +.Fn strvis , +.Fn strnvis , +.Fn strvisx , +and +.Fn strnvisx +but have an additional argument +.Fa extra , +pointing to a +.Dv NUL +terminated list of characters. +These characters will be copied encoded or backslash-escaped into +.Fa dst . +These functions are useful e.g. to remove the special meaning +of certain characters to shells. +.Pp +The encoding is a unique, invertible representation composed entirely of +graphic characters; it can be decoded back into the original form using +the +.Xr unvis 3 , +.Xr strunvis 3 +or +.Xr strnunvis 3 +functions. +.Pp +There are two parameters that can be controlled: the range of +characters that are encoded (applies only to +.Fn vis , +.Fn nvis , +.Fn strvis , +.Fn strnvis , +.Fn strvisx , +and +.Fn strnvisx ) , +and the type of representation used. +By default, all non-graphic characters, +except space, tab, and newline are encoded. +(See +.Xr isgraph 3 . ) +The following flags +alter this: +.Bl -tag -width VIS_WHITEX +.It Dv VIS_GLOB +Also encode magic characters +.Ql ( * , +.Ql \&? , +.Ql \&[ +and +.Ql # ) +recognized by +.Xr glob 3 . +.It Dv VIS_SP +Also encode space. +.It Dv VIS_TAB +Also encode tab. +.It Dv VIS_NL +Also encode newline. +.It Dv VIS_WHITE +Synonym for +.Dv VIS_SP +\&| +.Dv VIS_TAB +\&| +.Dv VIS_NL . +.It Dv VIS_SAFE +Only encode "unsafe" characters. +Unsafe means control characters which may cause common terminals to perform +unexpected functions. +Currently this form allows space, tab, newline, backspace, bell, and +return - in addition to all graphic characters - unencoded. +.El +.Pp +(The above flags have no effect for +.Fn svis , +.Fn snvis , +.Fn strsvis , +.Fn strsnvis , +.Fn strsvisx , +and +.Fn strsnvisx . +When using these functions, place all graphic characters to be +encoded in an array pointed to by +.Fa extra . +In general, the backslash character should be included in this array, see the +warning on the use of the +.Dv VIS_NOSLASH +flag below). +.Pp +There are four forms of encoding. +All forms use the backslash character +.Ql \e +to introduce a special +sequence; two backslashes are used to represent a real backslash, +except +.Dv VIS_HTTPSTYLE +that uses +.Ql % , +or +.Dv VIS_MIMESTYLE +that uses +.Ql = . +These are the visual formats: +.Bl -tag -width VIS_CSTYLE +.It (default) +Use an +.Ql M +to represent meta characters (characters with the 8th +bit set), and use caret +.Ql ^ +to represent control characters see +.Pf ( Xr iscntrl 3 ) . +The following formats are used: +.Bl -tag -width xxxxx +.It Dv \e^C +Represents the control character +.Ql C . +Spans characters +.Ql \e000 +through +.Ql \e037 , +and +.Ql \e177 +(as +.Ql \e^? ) . +.It Dv \eM-C +Represents character +.Ql C +with the 8th bit set. +Spans characters +.Ql \e241 +through +.Ql \e376 . +.It Dv \eM^C +Represents control character +.Ql C +with the 8th bit set. +Spans characters +.Ql \e200 +through +.Ql \e237 , +and +.Ql \e377 +(as +.Ql \eM^? ) . +.It Dv \e040 +Represents +.Tn ASCII +space. +.It Dv \e240 +Represents Meta-space. +.El +.Pp +.It Dv VIS_CSTYLE +Use C-style backslash sequences to represent standard non-printable +characters. +The following sequences are used to represent the indicated characters: +.Bd -unfilled -offset indent +.Li \ea Tn - BEL No (007) +.Li \eb Tn - BS No (010) +.Li \ef Tn - NP No (014) +.Li \en Tn - NL No (012) +.Li \er Tn - CR No (015) +.Li \es Tn - SP No (040) +.Li \et Tn - HT No (011) +.Li \ev Tn - VT No (013) +.Li \e0 Tn - NUL No (000) +.Ed +.Pp +When using this format, the nextc parameter is looked at to determine +if a +.Dv NUL +character can be encoded as +.Ql \e0 +instead of +.Ql \e000 . +If +.Fa nextc +is an octal digit, the latter representation is used to +avoid ambiguity. +.It Dv VIS_OCTAL +Use a three digit octal sequence. +The form is +.Ql \eddd +where +.Em d +represents an octal digit. +.It Dv VIS_HTTPSTYLE +Use URI encoding as described in RFC 1738. +The form is +.Ql %xx +where +.Em x +represents a lower case hexadecimal digit. +.It Dv VIS_MIMESTYLE +Use MIME Quoted-Printable encoding as described in RFC 2045, only don't +break lines and don't handle CRLF. +The form is: +.Ql %XX +where +.Em X +represents an upper case hexadecimal digit. +.El +.Pp +There is one additional flag, +.Dv VIS_NOSLASH , +which inhibits the +doubling of backslashes and the backslash before the default +format (that is, control characters are represented by +.Ql ^C +and +meta characters as +.Ql M-C ) . +With this flag set, the encoding is +ambiguous and non-invertible. +.Sh ERRORS +The functions +.Fn nvis +and +.Fn snvis +will return +.Dv NULL +and the functions +.Fn strnvis , +.Fn strnvisx , +.Fn strsnvis , +and +.Fn strsnvisx , +will return \-1 when the +.Fa dlen +destination buffer length size is not enough to perform the conversion while +setting +.Va errno +to: +.Bl -tag -width Er +.It Bq Er ENOSPC +The destination buffer size is not large enough to perform the conversion. +.El +.Sh SEE ALSO +.Xr unvis 1 , +.Xr vis 1 , +.Xr glob 3 , +.Xr unvis 3 +.Rs +.%A T. Berners-Lee +.%T Uniform Resource Locators (URL) +.%O RFC1738 +.Re +.Sh HISTORY +The +.Fn vis , +.Fn strvis , +and +.Fa strvisx +functions first appeared in +.Bx 4.4 . +The +.Fn svis , +.Fn strsvis , +and +.Fn strsvisx +functions appeared in +.Nx 1.5 +and +.Fx 10.0 . +The buffer size limited versions of the functions +.Po Fn nvis , +.Fn strnvis , +.Fn strnvisx , +.Fn snvis , +.Fn strsnvis , +and +.Fn strsnvisx Pc +appeared in +.Nx 6.0 +and +.Fx 10.0 . diff -ruN contrib/libc-vis/vis.c contrib/libc-vis/vis.c --- contrib/libc-vis/vis.c 1969-12-31 18:00:00.000000000 -0600 +++ contrib/libc-vis/vis.c 2012-10-20 09:18:00.000000000 -0500 @@ -0,0 +1,583 @@ +/* $NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $ */ + +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $"); +#endif /* LIBC_SCCS and not lint */ +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include + +#include +#include +#include +#include + +#ifdef __weak_alias +__weak_alias(strvisx,_strvisx) +#endif + +#if !HAVE_VIS || !HAVE_SVIS +#include +#include +#include +#include + +#define _DIAGASSERT(x) assert(x) + +static char *do_svis(char *, size_t *, int, int, int, const char *); + +#undef BELL +#define BELL '\a' + +#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') +#define iswhite(c) (c == ' ' || c == '\t' || c == '\n') +#define issafe(c) (c == '\b' || c == BELL || c == '\r') +#define xtoa(c) "0123456789abcdef"[c] +#define XTOA(c) "0123456789ABCDEF"[c] + +#define MAXEXTRAS 9 + +#define MAKEEXTRALIST(flag, extra, orig_str) \ +do { \ + const char *orig = orig_str; \ + const char *o = orig; \ + char *e; \ + while (*o++) \ + continue; \ + extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \ + if (!extra) break; \ + for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ + continue; \ + e--; \ + if (flag & VIS_GLOB) { \ + *e++ = '*'; \ + *e++ = '?'; \ + *e++ = '['; \ + *e++ = '#'; \ + } \ + if (flag & VIS_SP) *e++ = ' '; \ + if (flag & VIS_TAB) *e++ = '\t'; \ + if (flag & VIS_NL) *e++ = '\n'; \ + if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ + *e = '\0'; \ +} while (/*CONSTCOND*/0) + +/* + * This is do_hvis, for HTTP style (RFC 1808) + */ +static char * +do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +{ + + if ((isascii(c) && isalnum(c)) + /* safe */ + || c == '$' || c == '-' || c == '_' || c == '.' || c == '+' + /* extra */ + || c == '!' || c == '*' || c == '\'' || c == '(' || c == ')' + || c == ',') { + dst = do_svis(dst, dlen, c, flag, nextc, extra); + } else { + if (dlen) { + if (*dlen < 3) + return NULL; + *dlen -= 3; + } + *dst++ = '%'; + *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); + *dst++ = xtoa((unsigned int)c & 0xf); + } + + return dst; +} + +/* + * This is do_mvis, for Quoted-Printable MIME (RFC 2045) + * NB: No handling of long lines or CRLF. + */ +static char * +do_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +{ + if ((c != '\n') && + /* Space at the end of the line */ + ((isspace(c) && (nextc == '\r' || nextc == '\n')) || + /* Out of range */ + (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || + /* Specific char to be escaped */ + strchr("#$@[\\]^`{|}~", c) != NULL)) { + if (dlen) { + if (*dlen < 3) + return NULL; + *dlen -= 3; + } + *dst++ = '='; + *dst++ = XTOA(((unsigned int)c >> 4) & 0xf); + *dst++ = XTOA((unsigned int)c & 0xf); + } else { + dst = do_svis(dst, dlen, c, flag, nextc, extra); + } + return dst; +} + +/* + * This is do_vis, the central code of vis. + * dst: Pointer to the destination buffer + * c: Character to encode + * flag: Flag word + * nextc: The character following 'c' + * extra: Pointer to the list of extra characters to be + * backslash-protected. + */ +static char * +do_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +{ + int isextra; + size_t odlen = dlen ? *dlen : 0; + + isextra = strchr(extra, c) != NULL; +#define HAVE(x) \ + do { \ + if (dlen) { \ + if (*dlen < (x)) \ + goto out; \ + *dlen -= (x); \ + } \ + } while (/*CONSTCOND*/0) + if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || + ((flag & VIS_SAFE) && issafe(c)))) { + HAVE(1); + *dst++ = c; + return dst; + } + if (flag & VIS_CSTYLE) { + HAVE(2); + switch (c) { + case '\n': + *dst++ = '\\'; *dst++ = 'n'; + return dst; + case '\r': + *dst++ = '\\'; *dst++ = 'r'; + return dst; + case '\b': + *dst++ = '\\'; *dst++ = 'b'; + return dst; + case BELL: + *dst++ = '\\'; *dst++ = 'a'; + return dst; + case '\v': + *dst++ = '\\'; *dst++ = 'v'; + return dst; + case '\t': + *dst++ = '\\'; *dst++ = 't'; + return dst; + case '\f': + *dst++ = '\\'; *dst++ = 'f'; + return dst; + case ' ': + *dst++ = '\\'; *dst++ = 's'; + return dst; + case '\0': + *dst++ = '\\'; *dst++ = '0'; + if (isoctal(nextc)) { + HAVE(2); + *dst++ = '0'; + *dst++ = '0'; + } + return dst; + default: + if (isgraph(c)) { + *dst++ = '\\'; *dst++ = c; + return dst; + } + if (dlen) + *dlen = odlen; + } + } + if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { + HAVE(4); + *dst++ = '\\'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; + *dst++ = (c & 07) + '0'; + } else { + if ((flag & VIS_NOSLASH) == 0) { + HAVE(1); + *dst++ = '\\'; + } + + if (c & 0200) { + HAVE(1); + c &= 0177; *dst++ = 'M'; + } + + if (iscntrl(c)) { + HAVE(2); + *dst++ = '^'; + if (c == 0177) + *dst++ = '?'; + else + *dst++ = c + '@'; + } else { + HAVE(2); + *dst++ = '-'; *dst++ = c; + } + } + return dst; +out: + *dlen = odlen; + return NULL; +} + +typedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *); + +/* + * Return the appropriate encoding function depending on the flags given. + */ +static visfun_t +getvisfun(int flag) +{ + if (flag & VIS_HTTPSTYLE) + return do_hvis; + if (flag & VIS_MIMESTYLE) + return do_mvis; + return do_svis; +} + +/* + * isnvis - visually encode characters, also encoding the characters + * pointed to by `extra' + */ +static char * +isnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra) +{ + char *nextra = NULL; + visfun_t f; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(extra != NULL); + MAKEEXTRALIST(flag, nextra, extra); + if (!nextra) { + if (dlen && *dlen == 0) { + errno = ENOSPC; + return NULL; + } + *dst = '\0'; /* can't create nextra, return "" */ + return dst; + } + f = getvisfun(flag); + dst = (*f)(dst, dlen, c, flag, nextc, nextra); + free(nextra); + if (dst == NULL || (dlen && *dlen == 0)) { + errno = ENOSPC; + return NULL; + } + *dst = '\0'; + return dst; +} + +char * +svis(char *dst, int c, int flag, int nextc, const char *extra) +{ + return isnvis(dst, NULL, c, flag, nextc, extra); +} + +char * +snvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra) +{ + return isnvis(dst, &dlen, c, flag, nextc, extra); +} + + +/* + * strsvis, strsvisx - visually encode characters from src into dst + * + * Extra is a pointer to a \0-terminated list of characters to + * be encoded, too. These functions are useful e. g. to + * encode strings in such a way so that they are not interpreted + * by a shell. + * + * Dst must be 4 times the size of src to account for possible + * expansion. The length of dst, not including the trailing NULL, + * is returned. + * + * Strsvisx encodes exactly len bytes from src into dst. + * This is useful for encoding a block of data. + */ +static int +istrsnvis(char *dst, size_t *dlen, const char *csrc, int flag, const char *extra) +{ + int c; + char *start; + char *nextra = NULL; + const unsigned char *src = (const unsigned char *)csrc; + visfun_t f; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + _DIAGASSERT(extra != NULL); + MAKEEXTRALIST(flag, nextra, extra); + if (!nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return 0; + } + f = getvisfun(flag); + for (start = dst; (c = *src++) != '\0'; /* empty */) { + dst = (*f)(dst, dlen, c, flag, *src, nextra); + if (dst == NULL) { + errno = ENOSPC; + return -1; + } + } + free(nextra); + if (dlen && *dlen == 0) { + errno = ENOSPC; + return -1; + } + *dst = '\0'; + return (int)(dst - start); +} + +int +strsvis(char *dst, const char *csrc, int flag, const char *extra) +{ + return istrsnvis(dst, NULL, csrc, flag, extra); +} + +int +strsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra) +{ + return istrsnvis(dst, &dlen, csrc, flag, extra); +} + +static int +istrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag, + const char *extra) +{ + unsigned char c; + char *start; + char *nextra = NULL; + const unsigned char *src = (const unsigned char *)csrc; + visfun_t f; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + _DIAGASSERT(extra != NULL); + MAKEEXTRALIST(flag, nextra, extra); + if (! nextra) { + if (dlen && *dlen == 0) { + errno = ENOSPC; + return -1; + } + *dst = '\0'; /* can't create nextra, return "" */ + return 0; + } + + f = getvisfun(flag); + for (start = dst; len > 0; len--) { + c = *src++; + dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra); + if (dst == NULL) { + errno = ENOSPC; + return -1; + } + } + free(nextra); + if (dlen && *dlen == 0) { + errno = ENOSPC; + return -1; + } + *dst = '\0'; + return (int)(dst - start); +} + +int +strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) +{ + return istrsnvisx(dst, NULL, csrc, len, flag, extra); +} + +int +strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag, + const char *extra) +{ + return istrsnvisx(dst, &dlen, csrc, len, flag, extra); +} +#endif + +#if !HAVE_VIS +/* + * vis - visually encode characters + */ +static char * +invis(char *dst, size_t *dlen, int c, int flag, int nextc) +{ + char *extra = NULL; + unsigned char uc = (unsigned char)c; + visfun_t f; + + _DIAGASSERT(dst != NULL); + + MAKEEXTRALIST(flag, extra, ""); + if (! extra) { + if (dlen && *dlen == 0) { + errno = ENOSPC; + return NULL; + } + *dst = '\0'; /* can't create extra, return "" */ + return dst; + } + f = getvisfun(flag); + dst = (*f)(dst, dlen, uc, flag, nextc, extra); + free(extra); + if (dst == NULL || (dlen && *dlen == 0)) { + errno = ENOSPC; + return NULL; + } + *dst = '\0'; + return dst; +} + +char * +vis(char *dst, int c, int flag, int nextc) +{ + return invis(dst, NULL, c, flag, nextc); +} + +char * +nvis(char *dst, size_t dlen, int c, int flag, int nextc) +{ + return invis(dst, &dlen, c, flag, nextc); +} + + +/* + * strvis, strvisx - visually encode characters from src into dst + * + * Dst must be 4 times the size of src to account for possible + * expansion. The length of dst, not including the trailing NULL, + * is returned. + * + * Strvisx encodes exactly len bytes from src into dst. + * This is useful for encoding a block of data. + */ +static int +istrnvis(char *dst, size_t *dlen, const char *src, int flag) +{ + char *extra = NULL; + int rv; + + MAKEEXTRALIST(flag, extra, ""); + if (!extra) { + if (dlen && *dlen == 0) { + errno = ENOSPC; + return -1; + } + *dst = '\0'; /* can't create extra, return "" */ + return 0; + } + rv = istrsnvis(dst, dlen, src, flag, extra); + free(extra); + return rv; +} + +int +strvis(char *dst, const char *src, int flag) +{ + return istrnvis(dst, NULL, src, flag); +} + +int +strnvis(char *dst, size_t dlen, const char *src, int flag) +{ + return istrnvis(dst, &dlen, src, flag); +} + +static int +istrnvisx(char *dst, size_t *dlen, const char *src, size_t len, int flag) +{ + char *extra = NULL; + int rv; + + MAKEEXTRALIST(flag, extra, ""); + if (!extra) { + if (dlen && *dlen == 0) { + errno = ENOSPC; + return -1; + } + *dst = '\0'; /* can't create extra, return "" */ + return 0; + } + rv = istrsnvisx(dst, dlen, src, len, flag, extra); + free(extra); + return rv; +} + +int +strvisx(char *dst, const char *src, size_t len, int flag) +{ + return istrnvisx(dst, NULL, src, len, flag); +} + +int +strnvisx(char *dst, size_t dlen, const char *src, size_t len, int flag) +{ + return istrnvisx(dst, &dlen, src, len, flag); +} + +#endif diff -ruN contrib/libc-vis/vis.h contrib/libc-vis/vis.h --- contrib/libc-vis/vis.h 1969-12-31 18:00:00.000000000 -0600 +++ contrib/libc-vis/vis.h 2012-10-20 09:20:17.000000000 -0500 @@ -0,0 +1,114 @@ +/* $NetBSD: vis.h,v 1.19 2011/03/12 19:52:45 christos Exp $ */ +/* $FreeBSD$ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)vis.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _VIS_H_ +#define _VIS_H_ + +#include + +/* + * to select alternate encoding format + */ +#define VIS_OCTAL 0x001 /* use octal \ddd format */ +#define VIS_CSTYLE 0x002 /* use \[nrft0..] where appropiate */ + +/* + * to alter set of characters encoded (default is to encode all + * non-graphic except space, tab, and newline). + */ +#define VIS_SP 0x004 /* also encode space */ +#define VIS_TAB 0x008 /* also encode tab */ +#define VIS_NL 0x010 /* also encode newline */ +#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) +#define VIS_SAFE 0x020 /* only encode "unsafe" characters */ + +/* + * other + */ +#define VIS_NOSLASH 0x0040 /* inhibit printing '\' */ +#define VIS_HTTP1808 0x0080 /* http-style escape % hex hex */ +#define VIS_HTTPSTYLE 0x0080 /* http-style escape % hex hex */ +#define VIS_GLOB 0x0100 /* encode glob(3) magics */ +#define VIS_MIMESTYLE 0x0200 /* mime-style escape = HEX HEX */ +#define VIS_HTTP1866 0x0400 /* http-style &#num; or &string; */ +#define VIS_NOESCAPE 0x0800 /* don't decode `\' */ +#define _VIS_END 0x1000 /* for unvis */ + +/* + * unvis return codes + */ +#define UNVIS_VALID 1 /* character valid */ +#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */ +#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */ +#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */ +#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */ + +/* + * unvis flags + */ +#define UNVIS_END _VIS_END /* no more characters */ + +#include + +__BEGIN_DECLS +char *vis(char *, int, int, int); +char *nvis(char *, size_t, int, int, int); + +char *svis(char *, int, int, int, const char *); +char *snvis(char *, size_t, int, int, int, const char *); + +int strvis(char *, const char *, int); +int strnvis(char *, size_t, const char *, int); + +int strsvis(char *, const char *, int, const char *); +int strsnvis(char *, size_t, const char *, int, const char *); + +int strvisx(char *, const char *, size_t, int); +int strnvisx(char *, size_t, const char *, size_t, int); + +int strsvisx(char *, const char *, size_t, int, const char *); +int strsnvisx(char *, size_t, const char *, size_t, int, const char *); + +int strunvis(char *, const char *); +int strnunvis(char *, size_t, const char *); + +int strunvisx(char *, const char *, int); +int strnunvisx(char *, size_t, const char *, int); + +#ifndef __LIBC12_SOURCE__ +int unvis(char *, int, int *, int); +#endif +__END_DECLS + +#endif /* !_VIS_H_ */