summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2000-11-21 00:47:29 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2000-11-21 00:47:29 +0000
commitf59583f0dd0bfa72fa781287133a9df5619c4d5b (patch)
tree19850a082855e8bb5c94d5ff0ba893272eea4580 /lib/libc
parentda7ed5d122ce6e53ba6035162f80e4b3ea06db7c (diff)
Add strnvis(3) -- a length-bounded version of strvis(3) with a return
value similar to snprintf(3) and strlcpy(3).
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/vis.358
-rw-r--r--lib/libc/gen/vis.c64
2 files changed, 104 insertions, 18 deletions
diff --git a/lib/libc/gen/vis.3 b/lib/libc/gen/vis.3
index 6ca6afd7c1d..96b6996c290 100644
--- a/lib/libc/gen/vis.3
+++ b/lib/libc/gen/vis.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: vis.3,v 1.12 2000/09/14 17:47:09 aaron Exp $
+.\" $OpenBSD: vis.3,v 1.13 2000/11/21 00:47:28 millert Exp $
.\"
.\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -37,6 +37,7 @@
.Sh NAME
.Nm vis ,
.Nm strvis ,
+.Nm strnvis ,
.Nm strvisx
.Nd visually encode characters
.Sh SYNOPSIS
@@ -46,7 +47,9 @@
.Ft int
.Fn strvis "char *dst" "char *src" "int flag"
.Ft int
-.Fn strvisx "char *dst" "char *src" "int len" "int flag"
+.Fn strnvis "char *dst" "char *src" "size_t size" "int flag"
+.Ft int
+.Fn strvisx "char *dst" "char *src" "size_t len" "int flag"
.Sh DESCRIPTION
The
.Fn vis
@@ -78,7 +81,8 @@ is only used when selecting the
encoding format (explained below).
.Pp
The
-.Fn strvis
+.Fn strvis ,
+.Fn strnvis
and
.Fn strvisx
functions copy into
@@ -92,6 +96,14 @@ function encodes characters from
.Fa src
up to the first NUL.
The
+.Fn strnvis
+function encodes characters from
+.Fa src
+up to the first NUL or the end of
+.Fa dst ,
+as indicated by
+.Fa siz .
+The
.Fn strvisx
function encodes exactly
.Fa len
@@ -99,18 +111,36 @@ characters from
.Fa src
(this
is useful for encoding a block of data that may contain NULs).
-Both forms null terminate
+All three forms NUL terminate
.Fa dst .
-The size of
+For
+.Fn strvis
+and
+.Fn strvisx ,
+the size of
.Fa dst
must be four times the number
of characters encoded from
.Fa src
(plus one for the NUL).
-Both
-forms return the number of characters in
+.Fn strvis
+and
+.Fn strvisx
+return the number of characters in
.Fa dst
(not including the trailing NUL).
+.Fn strnvis
+returns the length that
+.Fa dst
+would become if it were of unlimited size (similar to
+.Xr snprintf 3
+or
+.Xr strlcpy 3 ) .
+This can be used to detect truncation but it also means that
+the return value of
+.Fn strnvis
+must not be used without checking it against
+.Fa siz .
.Pp
The encoding is a unique, invertible representation composed entirely of
graphic characters; it can be decoded back into the original form using
@@ -259,7 +289,19 @@ ambiguous and non-invertible.
.Sh SEE ALSO
.Xr unvis 1 ,
.Xr vis 1 ,
+.Xr snprintf 3 ,
+.Xr strlcpy 3 ,
.Xr unvis 3
.Sh HISTORY
-These functions first appeared in
+The
+.Fn vis ,
+.Fn strvis
+and
+.Fn strvisx
+functions first appeared in
.Bx 4.4 .
+.br
+The
+.Fn strnvis
+function first appeared in
+.Ox 2.9 .
diff --git a/lib/libc/gen/vis.c b/lib/libc/gen/vis.c
index 1c8028fb9b6..e15a7427d11 100644
--- a/lib/libc/gen/vis.c
+++ b/lib/libc/gen/vis.c
@@ -32,7 +32,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: vis.c,v 1.5 2000/07/19 15:25:13 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: vis.c,v 1.6 2000/11/21 00:47:28 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -41,6 +41,13 @@ static char rcsid[] = "$OpenBSD: vis.c,v 1.5 2000/07/19 15:25:13 deraadt Exp $";
#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)) && \
+ 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')))
/*
* vis - visually encode characters
@@ -51,12 +58,7 @@ vis(dst, c, flag, nextc)
int c, nextc;
register int flag;
{
- if (((u_int)c <= UCHAR_MAX && isascii((u_char)c) &&
- 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'))) {
+ if (isvisible(c)) {
*dst++ = c;
if (c == '\\' && (flag & VIS_NOSLASH) == 0)
*dst++ = '\\';
@@ -141,12 +143,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 NULL,
* 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.
*/
@@ -161,7 +166,48 @@ strvis(dst, src, flag)
for (start = dst; (c = *src);)
dst = vis(dst, c, flag, *++src);
+ return (dst - start);
+}
+
+int
+strnvis(dst, src, siz, flag)
+ register char *dst;
+ register const char *src;
+ size_t siz;
+ int flag;
+{
+ register char c;
+ char *start, *end;
+
+ for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) {
+ if (isvisible(c)) {
+ *dst++ = c;
+ if (c == '\\' && (flag & VIS_NOSLASH) == 0) {
+ /* need space for the extra '\\' */
+ if (dst < end)
+ *dst++ = '\\';
+ else {
+ dst--;
+ break;
+ }
+ }
+ src++;
+ } else {
+ /* vis(3) requires up to 4 chars */
+ if (dst + 3 < end)
+ dst = vis(dst, c, flag, *++src);
+ else
+ break;
+ }
+ }
*dst = '\0';
+ if (dst >= end) {
+ char tbuf[5];
+
+ /* adjust return value for truncation */
+ while ((c = *src))
+ dst += vis(tbuf, c, flag, *++src) - tbuf;
+ }
return (dst - start);
}
@@ -181,7 +227,5 @@ strvisx(dst, src, len, flag)
}
if (len)
dst = vis(dst, *src, flag, '\0');
- *dst = '\0';
-
return (dst - start);
}