diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2000-11-21 00:47:29 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2000-11-21 00:47:29 +0000 |
commit | f59583f0dd0bfa72fa781287133a9df5619c4d5b (patch) | |
tree | 19850a082855e8bb5c94d5ff0ba893272eea4580 /lib/libc | |
parent | da7ed5d122ce6e53ba6035162f80e4b3ea06db7c (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.3 | 58 | ||||
-rw-r--r-- | lib/libc/gen/vis.c | 64 |
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); } |