summaryrefslogtreecommitdiff
path: root/lib/libc/gen
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2004-10-17 20:25:32 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2004-10-17 20:25:32 +0000
commit8566f00d2c81878ad985906994fedb6fbb16df24 (patch)
treec040b009eee232769227b6f430ef75ceb07ee082 /lib/libc/gen
parent6119135c871cdb14d2c537be99ec398e13edf027 (diff)
implement strnunvis(3), a bounded version of strunvis(3). ok millert@
Diffstat (limited to 'lib/libc/gen')
-rw-r--r--lib/libc/gen/unvis.338
-rw-r--r--lib/libc/gen/unvis.c45
2 files changed, 78 insertions, 5 deletions
diff --git a/lib/libc/gen/unvis.3 b/lib/libc/gen/unvis.3
index e7fe0c7cac6..de4fcff41d2 100644
--- a/lib/libc/gen/unvis.3
+++ b/lib/libc/gen/unvis.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: unvis.3,v 1.13 2003/06/02 20:18:35 millert Exp $
+.\" $OpenBSD: unvis.3,v 1.14 2004/10/17 20:25:31 otto Exp $
.\"
.\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -32,7 +32,8 @@
.Os
.Sh NAME
.Nm unvis ,
-.Nm strunvis
+.Nm strunvis ,
+.Nm strnunvis
.Nd decode a visual representation of characters
.Sh SYNOPSIS
.Fd #include <vis.h>
@@ -40,11 +41,14 @@
.Fn unvis "char *cp" "char c" "int *astate" "int flag"
.Ft int
.Fn strunvis "char *dst" "char *src"
+.Ft ssize_t
+.Fn strnunvis "char *dst" "char *src" "size_t size"
.Sh DESCRIPTION
The
-.Fn unvis
-and
+.Fn unvis ,
.Fn strunvis
+and
+.Fn strnunvis
functions are used to decode a visual representation of characters,
as produced by the
.Xr vis 3
@@ -63,6 +67,14 @@ decodes the characters pointed to by
into the buffer pointed to by
.Fa dst .
.Pp
+.Fn strnunvis
+decodes the characters pointed to by
+.Fa src
+into the buffer pointed to by
+.Fa dst ,
+writing a maximum of
+.Fa size
+bytes.
The
.Fn strunvis
function simply copies
@@ -80,6 +92,12 @@ should be
equal to the size of
.Fa src
(that is, no expansion takes place during decoding).
+.Fn strunvis
+terminates the destination string with a trailing NUL byte;
+.Fn strnunvis
+does so if
+.Fa size
+is larger than 0.
.Pp
The
.Fn unvis
@@ -95,6 +113,7 @@ Call
.Fn unvis
with each successive byte, along with a pointer
to this integer, and a pointer to a destination character.
+.Sh RETURN VALUES
The
.Fn unvis
function has several return codes that must be handled properly.
@@ -125,6 +144,17 @@ When all bytes in the stream have been processed, call
one more time with flag set to
.Dv UNVIS_END
to extract any remaining character (the character passed in is ignored).
+.Pp
+The
+.Fn strunvis
+function returns the number of bytes written (not counting
+the trailing NUL byte) or \-1 if an error occurred.
+.Pp
+The
+.Fn strnunvis
+function returns the number of bytes (not counting the trailing NUL byte),
+that would be needed to fully convert the input string, or \-1 if an
+error occurred.
.Sh EXAMPLES
The following code fragment illustrates a proper use of
.Fn unvis .
diff --git a/lib/libc/gen/unvis.c b/lib/libc/gen/unvis.c
index 52e204c4641..d0bc70d5af3 100644
--- a/lib/libc/gen/unvis.c
+++ b/lib/libc/gen/unvis.c
@@ -28,7 +28,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: unvis.c,v 1.9 2004/05/18 02:05:52 jfb Exp $";
+static char rcsid[] = "$OpenBSD: unvis.c,v 1.10 2004/10/17 20:25:31 otto Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -230,6 +230,7 @@ strunvis(char *dst, const char *src)
case UNVIS_NOCHAR:
break;
default:
+ *dst = '\0';
return (-1);
}
}
@@ -238,3 +239,45 @@ strunvis(char *dst, const char *src)
*dst = '\0';
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);
+}
+