]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Add vis and unvis
authorRobert Millan <rmh@aybabtu.com>
Sun, 19 Mar 2006 10:25:49 +0000 (10:25 +0000)
committerGuillem Jover <guillem@hadrons.org>
Tue, 6 May 2008 05:52:46 +0000 (08:52 +0300)
ChangeLog
Makefile
Versions
include/vis.h [new file with mode: 0644]
src/unvis.c [new file with mode: 0644]
src/vis.c [new file with mode: 0644]

index 814f0413cbf3c93611d063a370d7ac4030ec8529..0408ecc33858a0022a531d5b50ca2a1dd01c5e96 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2006-03-19  Robert Millan  <rmh@aybabtu.com>
+
+       * src/vis.c: New file.
+       * src/unvis.c: Ditto.
+       * include/vis.h: Add vis/unvis declarations.
+       * Makefile (LIB_SRCS): Add vis.c/unvis.c.
+       * Versions: Add vis/unvis functions.
+
 2006-03-17  Robert Millan  <rmh@aybabtu.com>
 
        * src/progname.c: New file.
index e84f4549aed8b0832b757481ec10a9269547d0b9..89276f34412bb54b771158c481d3726e377b6124 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -5,12 +5,12 @@
 #
 
 LIB_SRCS := arc4random.c bsd_getopt.c err.c fgetln.c inet_net_pton.c \
-           strlcat.c strlcpy.c md5c.c fmtcheck.c progname.c
+           strlcat.c strlcpy.c md5c.c fmtcheck.c progname.c vis.c unvis.c
 LIB_SRCS := $(patsubst %,src/%,$(LIB_SRCS))
 
-LIB_INCLUDES := err.h getopt.h ip_icmp.h random.h queue.h md5.h string.h \
-               bsd.h cdefs.h stdlib.h
-LIB_INCLUDES := $(patsubst %,include/bsd/%,$(LIB_INCLUDES))
+LIB_INCLUDES := bsd/err.h bsd/getopt.h bsd/ip_icmp.h bsd/random.h bsd/queue.h bsd/md5.h bsd/string.h \
+               bsd/bsd.h bsd/cdefs.h bsd/stdlib.h vis.h
+LIB_INCLUDES := $(patsubst %,include/%,$(LIB_INCLUDES))
 
 LIB_MANS := arc4random.3 strlcpy.3 fgetln.3 fmtcheck.3
 LIB_MANS := $(patsubst %,man/%,$(LIB_MANS))
index 77d3f29679645f0f09d2c11293c83a749c6d0a2d..0724ffbe356f6b7d99e4f2fd2e239f0ff6e840f1 100644 (file)
--- a/Versions
+++ b/Versions
@@ -10,6 +10,8 @@ LIBBSD_0.0 {
     getprogname; setprogname;
     strlcpy;
     strlcat;
+    vis; strvis; strvisx;
+    unvis; strunvis; strunvisx;
     MD5Init;
     MD5Update;
     MD5Pad;
diff --git a/include/vis.h b/include/vis.h
new file mode 100644 (file)
index 0000000..329481b
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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
+ * $FreeBSD: src/include/vis.h,v 1.11 2003/10/30 10:40:49 phk Exp $
+ */
+
+#ifndef _VIS_H_
+#define        _VIS_H_
+
+#include <sys/types.h>
+
+/*
+ * to select alternate encoding format
+ */
+#define        VIS_OCTAL       0x01    /* use octal \ddd format */
+#define        VIS_CSTYLE      0x02    /* use \[nrft0..] where appropriate */
+
+/*
+ * to alter set of characters encoded (default is to encode all
+ * non-graphic except space, tab, and newline).
+ */
+#define        VIS_SP          0x04    /* also encode space */
+#define        VIS_TAB         0x08    /* also encode tab */
+#define        VIS_NL          0x10    /* also encode newline */
+#define        VIS_WHITE       (VIS_SP | VIS_TAB | VIS_NL)
+#define        VIS_SAFE        0x20    /* only encode "unsafe" characters */
+
+/*
+ * other
+ */
+#define        VIS_NOSLASH     0x40    /* inhibit printing '\' */
+#define        VIS_HTTPSTYLE   0x80    /* http-style escape % HEX HEX */
+#define        VIS_GLOB        0x100   /* encode glob(3) magics */
+
+/*
+ * 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       1       /* no more characters */
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+char   *vis(char *, int, int, int);
+int    strvis(char *, const char *, int);
+int    strvisx(char *, const char *, size_t, int);
+int    strunvis(char *, const char *);
+int    strunvisx(char *, const char *, int);
+int    unvis(char *, int, int *, int);
+__END_DECLS
+
+#endif /* !_VIS_H_ */
diff --git a/src/unvis.c b/src/unvis.c
new file mode 100644 (file)
index 0000000..b567136
--- /dev/null
@@ -0,0 +1,291 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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 <sys/types.h>
+#include <ctype.h>
+#include <vis.h>
+
+/*
+ * 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_HEX2          7       /* hex digit 2 */
+
+#define        S_HTTP          0x080   /* %HEXHEX escape */
+
+#define        isoctal(c)      (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define        ishex(c)        ((((u_char)(c)) >= '0' && ((u_char)(c)) <= '9') || (((u_char)(c)) >= 'a' && ((u_char)(c)) <= 'f'))
+
+/*
+ * unvis - decode characters previously encoded by vis
+ */
+int
+unvis(char *cp, int c, int *astate, int flag)
+{
+
+       if (flag & UNVIS_END) {
+               if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               }
+               return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
+       }
+
+       switch (*astate & ~S_HTTP) {
+
+       case S_GROUND:
+               *cp = 0;
+               if (c == '\\') {
+                       *astate = S_START;
+                       return (0);
+               }
+               if (flag & VIS_HTTPSTYLE && c == '%') {
+                       *astate = S_START | S_HTTP;
+                       return (0);
+               }
+               *cp = c;
+               return (UNVIS_VALID);
+
+       case S_START:
+               if (*astate & S_HTTP) {
+                   if (ishex(tolower(c))) {
+                       *cp = isdigit(c) ? (c - '0') : (tolower(c) - 'a');
+                       *astate = S_HEX2;
+                       return (0);
+                   }
+               }
+               switch(c) {
+               case '\\':
+                       *cp = c;
+                       *astate = 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 = S_OCTAL2;
+                       return (0);
+               case 'M':
+                       *cp = 0200;
+                       *astate = S_META;
+                       return (0);
+               case '^':
+                       *astate = S_CTRL;
+                       return (0);
+               case 'n':
+                       *cp = '\n';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'r':
+                       *cp = '\r';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'b':
+                       *cp = '\b';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'a':
+                       *cp = '\007';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'v':
+                       *cp = '\v';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 't':
+                       *cp = '\t';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'f':
+                       *cp = '\f';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 's':
+                       *cp = ' ';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'E':
+                       *cp = '\033';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case '\n':
+                       /*
+                        * hidden newline
+                        */
+                       *astate = S_GROUND;
+                       return (UNVIS_NOCHAR);
+               case '$':
+                       /*
+                        * hidden marker
+                        */
+                       *astate = S_GROUND;
+                       return (UNVIS_NOCHAR);
+               }
+               *astate = S_GROUND;
+               return (UNVIS_SYNBAD);
+
+       case S_META:
+               if (c == '-')
+                       *astate = S_META1;
+               else if (c == '^')
+                       *astate = S_CTRL;
+               else {
+                       *astate = S_GROUND;
+                       return (UNVIS_SYNBAD);
+               }
+               return (0);
+
+       case S_META1:
+               *astate = S_GROUND;
+               *cp |= c;
+               return (UNVIS_VALID);
+
+       case S_CTRL:
+               if (c == '?')
+                       *cp |= 0177;
+               else
+                       *cp |= c & 037;
+               *astate = S_GROUND;
+               return (UNVIS_VALID);
+
+       case S_OCTAL2:  /* second possible octal digit */
+               if (isoctal(c)) {
+                       /*
+                        * yes - and maybe a third
+                        */
+                       *cp = (*cp << 3) + (c - '0');
+                       *astate = S_OCTAL3;
+                       return (0);
+               }
+               /*
+                * no - done with current sequence, push back passed char
+                */
+               *astate = S_GROUND;
+               return (UNVIS_VALIDPUSH);
+
+       case S_OCTAL3:  /* third possible octal digit */
+               *astate = S_GROUND;
+               if (isoctal(c)) {
+                       *cp = (*cp << 3) + (c - '0');
+                       return (UNVIS_VALID);
+               }
+               /*
+                * we were done, push back passed char
+                */
+               return (UNVIS_VALIDPUSH);
+
+       case S_HEX2:    /* second mandatory hex digit */
+               if (ishex(tolower(c))) {
+                       *cp = (isdigit(c) ? (*cp << 4) + (c - '0') : (*cp << 4) + (tolower(c) - 'a' + 10));
+               }
+               *astate = S_GROUND;
+               return (UNVIS_VALID);
+
+       default:
+               /*
+                * decoder in unknown state - (probably uninitialized)
+                */
+               *astate = S_GROUND;
+               return (UNVIS_SYNBAD);
+       }
+}
+
+/*
+ * strunvis - decode src into dst
+ *
+ *     Number of chars decoded into dst is returned, -1 on error.
+ *     Dst is null terminated.
+ */
+
+int
+strunvis(char *dst, const char *src)
+{
+       char c;
+       char *start = dst;
+       int state = 0;
+
+       while ( (c = *src++) ) {
+       again:
+               switch (unvis(dst, c, &state, 0)) {
+               case UNVIS_VALID:
+                       dst++;
+                       break;
+               case UNVIS_VALIDPUSH:
+                       dst++;
+                       goto again;
+               case 0:
+               case UNVIS_NOCHAR:
+                       break;
+               default:
+                       return (-1);
+               }
+       }
+       if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
+               dst++;
+       *dst = '\0';
+       return (dst - start);
+}
+
+int
+strunvisx(char *dst, const char *src, int flag)
+{
+       char c;
+       char *start = dst;
+       int state = 0;
+    
+       while ( (c = *src++) ) {
+       again:
+               switch (unvis(dst, c, &state, flag)) {
+               case UNVIS_VALID:
+                       dst++;
+                       break;
+               case UNVIS_VALIDPUSH:
+                       dst++;
+                       goto again;
+               case 0:
+               case UNVIS_NOCHAR:
+                       break;
+               default:
+                       return (-1);
+               }
+       }
+       if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
+               dst++;
+       *dst = '\0';
+       return (dst - start);
+}
diff --git a/src/vis.c b/src/vis.c
new file mode 100644 (file)
index 0000000..bd3f6f9
--- /dev/null
+++ b/src/vis.c
@@ -0,0 +1,199 @@
+/*-
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. 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 <sys/types.h>
+#include <limits.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <vis.h>
+
+#define        isoctal(c)      (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+
+/*
+ * vis - visually encode characters
+ */
+char *
+vis(dst, c, flag, nextc)
+       char *dst;
+       int c, nextc;
+       int flag;
+{
+       c = (unsigned char)c;
+
+       if (flag & VIS_HTTPSTYLE) {
+               /* Described in RFC 1808 */
+               if (!(isalnum(c) /* alpha-numeric */
+                   /* safe */
+                   || c == '$' || c == '-' || c == '_' || c == '.' || c == '+'
+                   /* extra */
+                   || c == '!' || c == '*' || c == '\'' || c == '('
+                   || c == ')' || c == ',')) {
+                       *dst++ = '%';
+                       snprintf(dst, 4, (c < 16 ? "0%X" : "%X"), c);
+                       dst += 2;
+                       goto done;
+               }
+       }
+
+       if ((flag & VIS_GLOB) &&
+           (c == '*' || c == '?' || c == '[' || c == '#'))
+               ;
+       else if (isgraph(c) ||
+          ((flag & VIS_SP) == 0 && c == ' ') ||
+          ((flag & VIS_TAB) == 0 && c == '\t') ||
+          ((flag & VIS_NL) == 0 && c == '\n') ||
+          ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) {
+               *dst++ = c;
+               if (c == '\\' && (flag & VIS_NOSLASH) == 0)
+                       *dst++ = '\\';
+               *dst = '\0';
+               return (dst);
+       }
+
+       if (flag & VIS_CSTYLE) {
+               switch(c) {
+               case '\n':
+                       *dst++ = '\\';
+                       *dst++ = 'n';
+                       goto done;
+               case '\r':
+                       *dst++ = '\\';
+                       *dst++ = 'r';
+                       goto done;
+               case '\b':
+                       *dst++ = '\\';
+                       *dst++ = 'b';
+                       goto done;
+               case '\a':
+                       *dst++ = '\\';
+                       *dst++ = 'a';
+                       goto done;
+               case '\v':
+                       *dst++ = '\\';
+                       *dst++ = 'v';
+                       goto done;
+               case '\t':
+                       *dst++ = '\\';
+                       *dst++ = 't';
+                       goto done;
+               case '\f':
+                       *dst++ = '\\';
+                       *dst++ = 'f';
+                       goto done;
+               case ' ':
+                       *dst++ = '\\';
+                       *dst++ = 's';
+                       goto done;
+               case '\0':
+                       *dst++ = '\\';
+                       *dst++ = '0';
+                       if (isoctal(nextc)) {
+                               *dst++ = '0';
+                               *dst++ = '0';
+                       }
+                       goto done;
+               }
+       }
+       if (((c & 0177) == ' ') || isgraph(c) || (flag & VIS_OCTAL)) {
+               *dst++ = '\\';
+               *dst++ = ((u_char)c >> 6 & 07) + '0';
+               *dst++ = ((u_char)c >> 3 & 07) + '0';
+               *dst++ = ((u_char)c & 07) + '0';
+               goto done;
+       }
+       if ((flag & VIS_NOSLASH) == 0)
+               *dst++ = '\\';
+       if (c & 0200) {
+               c &= 0177;
+               *dst++ = 'M';
+       }
+       if (iscntrl(c)) {
+               *dst++ = '^';
+               if (c == 0177)
+                       *dst++ = '?';
+               else
+                       *dst++ = c + '@';
+       } else {
+               *dst++ = '-';
+               *dst++ = c;
+       }
+done:
+       *dst = '\0';
+       return (dst);
+}
+
+/*
+ * 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 NUL,
+ *     is returned.
+ *
+ *     Strvisx encodes exactly len bytes from src into dst.
+ *     This is useful for encoding a block of data.
+ */
+int
+strvis(dst, src, flag)
+       char *dst;
+       const char *src;
+       int flag;
+{
+       char c;
+       char *start;
+
+       for (start = dst; (c = *src); )
+               dst = vis(dst, c, flag, *++src);
+       *dst = '\0';
+       return (dst - start);
+}
+
+int
+strvisx(dst, src, len, flag)
+       char *dst;
+       const char *src;
+       size_t len;
+       int flag;
+{
+       int c;
+       char *start;
+
+       for (start = dst; len > 1; len--) {
+               c = *src;
+               dst = vis(dst, c, flag, *++src);
+       }
+       if (len)
+               dst = vis(dst, *src, flag, '\0');
+       *dst = '\0';
+
+       return (dst - start);
+}