diff --git a/include/stdio.h b/include/stdio.h index 1de521e76e38..78c62e824f1d 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -345,12 +345,14 @@ char *tempnam(const char *, const char *); ssize_t getdelim(char ** __restrict, size_t * __restrict, int, FILE * __restrict); int renameat(int, const char *, int, const char *); +int vdprintf(int, const char * __restrict, __va_list); /* - * Every programmer and his dog wrote functions called getline() - * before POSIX.1-2008 came along and decided to usurp the name, so we - * don't prototype getline() by default unless one of the following is true: - * a) the app has requested it specifically by defining _WITH_GETLINE + * Every programmer and his dog wrote functions called getline() and dprintf() + * before POSIX.1-2008 came along and decided to usurp the names, so we + * don't prototype them by default unless one of the following is true: + * a) the app has requested them specifically by defining _WITH_GETLINE or + * _WITH_DPRINTF, respectively * b) the app has requested a POSIX.1-2008 environment via _POSIX_C_SOURCE * c) the app defines a GNUism such as _BSD_SOURCE or _GNU_SOURCE */ @@ -368,6 +370,20 @@ int renameat(int, const char *, int, const char *); ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict); #endif +#ifndef _WITH_DPRINTF +#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE) +#define _WITH_DPRINTF +#elif defined(_POSIX_C_SOURCE) +#if _POSIX_C_SOURCE > 200809 +#define _WITH_DPRINTF +#endif +#endif +#endif + +#ifdef _WITH_DPRINTF +int dprintf(int, const char * __restrict, ...); +#endif + #endif /* __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 */ /* diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc index 2ed62f521429..c3b60f64fbff 100644 --- a/lib/libc/stdio/Makefile.inc +++ b/lib/libc/stdio/Makefile.inc @@ -4,7 +4,8 @@ # stdio sources .PATH: ${.CURDIR}/stdio -SRCS+= _flock_stub.c asprintf.c clrerr.c fclose.c fcloseall.c fdopen.c \ +SRCS+= _flock_stub.c asprintf.c clrerr.c dprintf.c \ + fclose.c fcloseall.c fdopen.c \ feof.c ferror.c fflush.c fgetc.c fgetln.c fgetpos.c fgets.c fgetwc.c \ fgetwln.c fgetws.c \ fileno.c findfp.c flags.c fopen.c fprintf.c fpurge.c fputc.c fputs.c \ @@ -17,7 +18,7 @@ SRCS+= _flock_stub.c asprintf.c clrerr.c fclose.c fcloseall.c fdopen.c \ refill.c remove.c rewind.c rget.c scanf.c setbuf.c setbuffer.c \ setvbuf.c snprintf.c sprintf.c sscanf.c stdio.c swprintf.c swscanf.c \ tempnam.c tmpfile.c \ - tmpnam.c ungetc.c ungetwc.c vasprintf.c vfprintf.c \ + tmpnam.c ungetc.c ungetwc.c vasprintf.c vdprintf.c vfprintf.c \ vfscanf.c \ vfwprintf.c vfwscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c \ vsscanf.c \ @@ -57,9 +58,9 @@ MLINKS+=getc.3 fgetc.3 getc.3 getc_unlocked.3 getc.3 getchar.3 \ MLINKS+=getline.3 getdelim.3 MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3 MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3 -MLINKS+=printf.3 asprintf.3 printf.3 fprintf.3 \ +MLINKS+=printf.3 asprintf.3 printf.3 dprintf.3 printf.3 fprintf.3 \ printf.3 snprintf.3 printf.3 sprintf.3 \ - printf.3 vasprintf.3 \ + printf.3 vasprintf.3 printf.3 vdprintf.3 \ printf.3 vfprintf.3 printf.3 vprintf.3 printf.3 vsnprintf.3 \ printf.3 vsprintf.3 MLINKS+=putc.3 fputc.3 putc.3 putc_unlocked.3 putc.3 putchar.3 \ diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map index bf054b640ae6..df66ab3c2399 100644 --- a/lib/libc/stdio/Symbol.map +++ b/lib/libc/stdio/Symbol.map @@ -111,8 +111,10 @@ FBSD_1.0 { }; FBSD_1.1 { + dprintf; getdelim; getline; + vdprintf; }; FBSDprivate_1.0 { diff --git a/lib/libc/stdio/dprintf.c b/lib/libc/stdio/dprintf.c new file mode 100644 index 000000000000..7f883ddf3ba6 --- /dev/null +++ b/lib/libc/stdio/dprintf.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2009 David Schultz + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#define _WITH_DPRINTF +#include "namespace.h" +#include +#include +#include "un-namespace.h" + +int +dprintf(int fd, const char * __restrict fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = vdprintf(fd, fmt, ap); + va_end(ap); + return (ret); +} diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3 index 98e26dc87c6a..27d5bf0d7e05 100644 --- a/lib/libc/stdio/printf.3 +++ b/lib/libc/stdio/printf.3 @@ -32,16 +32,17 @@ .\" @(#)printf.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd October 16, 2004 +.Dd March 3, 2009 .Dt PRINTF 3 .Os .Sh NAME -.Nm printf , fprintf , sprintf , snprintf , asprintf , -.Nm vprintf , vfprintf, vsprintf , vsnprintf , vasprintf +.Nm printf , fprintf , sprintf , snprintf , asprintf , dprintf , +.Nm vprintf , vfprintf, vsprintf , vsnprintf , vasprintf, vdprintf .Nd formatted output conversion .Sh LIBRARY .Lb libc .Sh SYNOPSIS +.Fd "#define _WITH_DPRINTF" .In stdio.h .Ft int .Fn printf "const char * restrict format" ... @@ -53,6 +54,8 @@ .Fn snprintf "char * restrict str" "size_t size" "const char * restrict format" ... .Ft int .Fn asprintf "char **ret" "const char *format" ... +.Ft int +.Fn dprintf "int" "const char * restrict format" ... .In stdarg.h .Ft int .Fn vprintf "const char * restrict format" "va_list ap" @@ -64,6 +67,8 @@ .Fn vsnprintf "char * restrict str" "size_t size" "const char * restrict format" "va_list ap" .Ft int .Fn vasprintf "char **ret" "const char *format" "va_list ap" +.Ft int +.Fn vdprintf "int fd" "const char * restrict format" "va_list ap" .Sh DESCRIPTION The .Fn printf @@ -83,6 +88,10 @@ and .Fn vfprintf write output to the given output .Fa stream ; +.Fn dprintf +and +.Fn vdprintf +write output to the given file descriptor; .Fn sprintf , .Fn snprintf , .Fn vsprintf , @@ -771,6 +780,57 @@ for later interpolation by Always use the proper secure idiom: .Pp .Dl "snprintf(buffer, sizeof(buffer), \*q%s\*q, string);" +.Sh COMPATIBILITY +Many application writers used the name +.Va dprintf +before the +.Fn dprintf +function was introduced in +.St -p1003.1 , +so a prototype is not provided by default in order to avoid +compatibility problems. +Applications that wish to use the +.Fn dprintf +function described herein should either request a strict +.St -p1003.1-2008 +environment by defining the macro +.Dv _POSIX_C_SOURCE +to the value 200809 or greater, or by defining the macro +.Dv _WITH_DPRINTF , +prior to the inclusion of +.In stdio.h . +For compatibility with GNU libc, defining either +.Dv _BSD_SOURCE +or +.Dv _GNU_SOURCE +prior to the inclusion of +.In stdio.h +will also make +.Fn dprintf +available. +.Pp +The conversion formats +.Cm \&%D , \&%O , +and +.Cm %U +are not standard and +are provided only for backward compatibility. +The effect of padding the +.Cm %p +format with zeros (either by the +.Cm 0 +flag or by specifying a precision), and the benign effect (i.e., none) +of the +.Cm # +flag on +.Cm %n +and +.Cm %p +conversions, as well as other +nonsensical combinations such as +.Cm %Ld , +are not standard; such combinations +should be avoided. .Sh ERRORS In addition to the errors documented for the .Xr write 2 @@ -810,7 +870,13 @@ With the same reservation, the and .Fn vsnprintf functions conform to -.St -isoC-99 . +.St -isoC-99 , +while +.Fn dprintf +and +.Fn vdprintf +conform to +.St -p1003.1-2008 . .Sh HISTORY The functions .Fn asprintf @@ -828,30 +894,13 @@ from .An Todd C. Miller Aq Todd.Miller@courtesan.com for .Ox 2.3 . +The +.Fn dprintf +and +.Fn vdprintf +functions were added in +.Fx 8.0 . .Sh BUGS -The conversion formats -.Cm \&%D , \&%O , -and -.Cm %U -are not standard and -are provided only for backward compatibility. -The effect of padding the -.Cm %p -format with zeros (either by the -.Cm 0 -flag or by specifying a precision), and the benign effect (i.e., none) -of the -.Cm # -flag on -.Cm %n -and -.Cm %p -conversions, as well as other -nonsensical combinations such as -.Cm %Ld , -are not standard; such combinations -should be avoided. -.Pp The .Nm family of functions do not correctly handle multibyte characters in the diff --git a/lib/libc/stdio/stdio.3 b/lib/libc/stdio/stdio.3 index a4d1eb77318b..53320b5d7a25 100644 --- a/lib/libc/stdio/stdio.3 +++ b/lib/libc/stdio/stdio.3 @@ -28,7 +28,7 @@ .\" @(#)stdio.3 8.7 (Berkeley) 4/19/94 .\" $FreeBSD$ .\" -.Dd February 28, 2009 +.Dd March 3, 2009 .Dt STDIO 3 .Os .Sh NAME @@ -243,6 +243,7 @@ library conforms to .It Sy "Function Description" .It "asprintf formatted output conversion" .It "clearerr check and reset stream status" +.It "dprintf formatted output conversion" .It "fclose close a stream" .It "fdopen stream open functions" .It "feof check and reset stream status" @@ -313,6 +314,7 @@ library conforms to .It "ungetc un-get character from input stream" .It "ungetwc un-get wide character from input stream" .It "vasprintf formatted output conversion" +.It "vdprintf formatted output conversion" .It "vfprintf formatted output conversion" .It "vfscanf input format conversion" .It "vfwprintf formatted wide character output conversion" diff --git a/lib/libc/stdio/vdprintf.c b/lib/libc/stdio/vdprintf.c new file mode 100644 index 000000000000..27030224bfb0 --- /dev/null +++ b/lib/libc/stdio/vdprintf.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2009 David Schultz + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include "namespace.h" +#include +#include +#include +#include +#include "un-namespace.h" + +#include "local.h" + +int +vdprintf(int fd, const char * __restrict fmt, va_list ap) +{ + FILE f; + unsigned char buf[BUFSIZ]; + int ret; + + if (fd > SHRT_MAX) { + errno = EMFILE; + return (EOF); + } + + f._p = buf; + f._w = sizeof(buf); + f._flags = __SWR; + f._file = fd; + f._cookie = &f; + f._write = __swrite; + f._bf._base = buf; + f._bf._size = sizeof(buf); + f._orientation = 0; + bzero(&f._mbstate, sizeof(f._mbstate)); + + if ((ret = __vfprintf(&f, fmt, ap)) < 0) + return (ret); + + return (__fflush(&f) ? EOF : ret); +}