summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Versions3
-rw-r--r--include/vis.h2
-rw-r--r--src/unvis.c41
-rw-r--r--src/vis.c61
4 files changed, 105 insertions, 2 deletions
diff --git a/Versions b/Versions
index 271839d..3e99cf4 100644
--- a/Versions
+++ b/Versions
@@ -44,5 +44,8 @@ LIBBSD_0.1 {
LIBBSD_0.2 {
strtonum;
+
+ strnvis;
+ strnunvis;
} LIBBSD_0.1;
diff --git a/include/vis.h b/include/vis.h
index 84de6fc..835d2d6 100644
--- a/include/vis.h
+++ b/include/vis.h
@@ -78,8 +78,10 @@ __BEGIN_DECLS
char *vis(char *, int, int, int);
int strvis(char *, const char *, int);
int strvisx(char *, const char *, size_t, int);
+int strnvis(char *, const char *, size_t, int);
int strunvis(char *, const char *);
int strunvisx(char *, const char *, int);
+ssize_t strnunvis(char *, const char *, size_t);
int unvis(char *, int, int *, int);
__END_DECLS
diff --git a/src/unvis.c b/src/unvis.c
index 66d74a5..188edca 100644
--- a/src/unvis.c
+++ b/src/unvis.c
@@ -257,6 +257,47 @@ strunvis(char *dst, const char *src)
return (dst - start);
}
+ssize_t
+strnunvis(char *dst, const char *src, size_t sz)
+{
+ char c, p;
+ char *start = dst, *end = dst + sz - 1;
+ int state = 0;
+
+ if (sz > 0)
+ *end = '\0';
+ while ((c = *src++)) {
+ again:
+ switch (unvis(&p, c, &state, 0)) {
+ case UNVIS_VALID:
+ if (dst < end)
+ *dst = p;
+ dst++;
+ break;
+ case UNVIS_VALIDPUSH:
+ if (dst < end)
+ *dst = p;
+ dst++;
+ goto again;
+ case 0:
+ case UNVIS_NOCHAR:
+ break;
+ default:
+ if (dst <= end)
+ *dst = '\0';
+ return (-1);
+ }
+ }
+ if (unvis(&p, c, &state, UNVIS_END) == UNVIS_VALID) {
+ if (dst < end)
+ *dst = p;
+ dst++;
+ }
+ if (dst <= end)
+ *dst = '\0';
+ return (dst - start);
+}
+
int
strunvisx(char *dst, const char *src, int flag)
{
diff --git a/src/vis.c b/src/vis.c
index 4ad31d5..189fde8 100644
--- a/src/vis.c
+++ b/src/vis.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: vis.c,v 1.18 2005/08/29 18:38:41 otto Exp $ */
/*-
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,10 +31,20 @@
#include <sys/types.h>
#include <limits.h>
#include <ctype.h>
-#include <stdio.h>
+#include <string.h>
#include <vis.h>
#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define isvisible(c) \
+ (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \
+ (((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \
+ (flag & VIS_GLOB) == 0) && isgraph((u_char)(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' || \
+ isgraph((u_char)(c)))))
/*
* vis - visually encode characters
@@ -149,12 +160,15 @@ done:
}
/*
- * strvis, strvisx - visually encode characters from src into dst
+ * strvis, strnvis, 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.
*
+ * Strnvis will write no more than siz-1 bytes (and will NULL terminate).
+ * The number of bytes needed to fully encode the string is returned.
+ *
* Strvisx encodes exactly len bytes from src into dst.
* This is useful for encoding a block of data.
*/
@@ -174,6 +188,49 @@ strvis(dst, src, flag)
}
int
+strnvis(char *dst, const char *src, size_t siz, int flag)
+{
+ char *start, *end;
+ char tbuf[5];
+ int c, i;
+
+ i = 0;
+ for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
+ if (isvisible(c)) {
+ i = 1;
+ *dst++ = c;
+ if (c == '\\' && (flag & VIS_NOSLASH) == 0) {
+ /* need space for the extra '\\' */
+ if (dst < end)
+ *dst++ = '\\';
+ else {
+ dst--;
+ i = 2;
+ break;
+ }
+ }
+ src++;
+ } else {
+ i = vis(tbuf, c, flag, *++src) - tbuf;
+ if (dst + i <= end) {
+ memcpy(dst, tbuf, i);
+ dst += i;
+ } else {
+ src--;
+ break;
+ }
+ }
+ }
+ if (siz > 0)
+ *dst = '\0';
+ if (dst + i > end) {
+ /* adjust return value for truncation */
+ while ((c = *src))
+ dst += vis(tbuf, c, flag, *++src) - tbuf;
+ }
+ return (dst - start);
+}
+
strvisx(dst, src, len, flag)
char *dst;
const char *src;