Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Start work on a pkg_printf.3 man page (adapted from printf.3)
Matthew Seaman committed 12 years ago
commit ce0d2e5d5b92ddca4b45731d27db34d2f8a4c446
parent 2d243b1
2 files changed +885 -0
modified libpkg/Makefile
@@ -44,6 +44,8 @@ SRCS= ${PC} \
		pkg_old.c \
		pkg.pc

+
MAN=		pkg_printf.3
+

CLEANFILES=	${PC} ${PKGH}

NEWVERS=	../newvers.sh
added libpkg/pkg_printf.3
@@ -0,0 +1,883 @@
+
.\" Copyright (c) 1990, 1991, 1993
+
.\"     The Regents of the University of California.  All rights reserved.
+
.\" Copyright (c) 2013 Matthew Seaman <matthew@FreeBSD.org>
+
.\"
+
.\" This code is derived from software contributed to Berkeley by
+
.\" Chris Torek and the American National Standards Committee X3,
+
.\" on Information Processing Systems.
+
.\"
+
.\" 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.
+
.\" 4. Neither the name of the University nor the names of its contributors
+
.\"    may be used to endorse or promote products derived from this software
+
.\"    without specific prior written permission.
+
.\"
+
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+
.\"
+
.Dd January 5, 2013
+
.Dt PKG_PRINTF 3
+
.Os
+
.Sh NAME
+
.Nm pkg_printf , pkg_fprintf , pkg_dprintf , pkg_snprintf , pkg_asprintf ,
+
.Nm pkg_sbuf_printf , pkg_sbuf_vprintf
+
.Nd formatted output of package data
+
.Sh LIBRARY
+
.Lb libpkg
+
.Sh SYNOPSIS
+
.In pkg.h
+
.Ft int
+
.Fn pkg_printf "const char * restrict format" ...
+
.Ft int
+
.Fn pkg_fprintf "FILE * restrict stream" "const char * restrict format" ...
+
.Ft int
+
.Fn pkg_dprintf "int fd" "const char * restrict format" ...
+
.Ft int
+
.Fn pkg_snprintf "char * restrict str" "size_t size" "const char * restrict format" ...
+
.Ft int
+
.Fn pkg_asprintf "char **ret" "const char * restrict format" ...
+
.Ft struct sbuf *
+
.Fn pkg_sbuf_printf "struct sbuf * restrict sbuf" "const char * restrict format" ...
+
.Ft struct sbuf *
+
.Fn pkg_sbuf_vprintf "struct sbuf * restrict sbuf" "const char * restrict format" "va_list ap"
+
.Sh DESCRIPTION
+
The
+
.Fn pkg_printf
+
family of functions produces output of package data according to a
+
.Fa format
+
as described below, analogously to the similarly named
+
.Xr printf 3
+
family of functions.
+
The
+
.Fn pkg_printf
+
function
+
writes output to
+
.Dv stdout ,
+
the standard output stream;
+
.Fn pkg_fprintf
+
writes output to the given output
+
.Fa stream ;
+
.Fn pkg_dprintf
+
writes output to the given file descriptor;
+
.Fn pkg_snprintf ,
+
writes to the character string
+
.Fa str ;
+
.Fn pkg_asprintf
+
dynamically allocates a new string with
+
.Xr malloc 3 ;
+
.Fn pkg_sbuf_printf
+
and
+
.Fn pkg_sbuf_vprint
+
write to the given sbuf structure.
+
.Pp
+
These functions write the output under the control of a
+
.Fa format
+
string that specifies how subsequent arguments
+
(or arguments accessed via the variable-length argument facilities of
+
.Xr stdarg 3 )
+
are converted for output.
+
.Pp
+
These functions return the number of characters printed
+
(not including the trailing
+
.Ql \e0
+
used to end output to strings) or a negative value if an output error occurs,
+
except for
+
.Fn pkg_snprintf
+
which returns the number of characters that would have been printed if the
+
.Fa size
+
were unlimited
+
(again, not including the final
+
.Ql \e0 ) 
+
and the two functions
+
.Fn pkg_sbuf_printf
+
and
+
.Fn pkg_sbuf_vprintf
+
which return the given sbuf pointer, or
+
.Dv NULL
+
in the case of errors. 
+
.Pp
+
The
+
.Fn pkg_asprintf
+
function
+
sets
+
.Fa *ret
+
to be a pointer to a buffer sufficiently large to hold the formatted string.
+
This pointer should be passed to
+
.Xr free 3
+
to release the allocated storage when it is no longer needed.
+
If sufficient space cannot be allocated,
+
.Fn pkg_asprintf
+
will return \-1 and set
+
.Fa ret
+
to be a
+
.Dv NULL
+
pointer.
+
.Pp
+
The
+
.Fn pkg_snprintf
+
function
+
will write at most
+
.Fa size Ns \-1
+
of the characters printed into the output string
+
(the
+
.Fa size Ns 'th
+
character then gets the terminating
+
.Ql \e0 ) ;
+
if the return value is greater than or equal to the
+
.Fa size
+
argument, the string was too short
+
and some of the printed characters were discarded.
+
The output is always null-terminated.
+
.Pp
+
The format string is composed of zero or more directives:
+
ordinary
+
.\" multibyte
+
characters (not
+
.Cm % ) ,
+
which are copied unchanged to the output stream;
+
and conversion specifications, each of which results
+
in fetching zero or more subsequent arguments.
+
Each conversion specification is introduced by
+
the
+
.Cm %
+
character.
+
The arguments must correspond properly (after type promotion)
+
with the conversion specifier.
+
After the
+
.Cm % ,
+
the following appear in sequence:
+
.Bl -bullet
+
.It
+
Zero or more of the following flags:
+
.Bl -tag -width ".So \  Sc (space)"
+
.It Sq Cm ?
+
The value should be converted to the
+
.Dq first alternate form .
+
For integer valued conversions
+
.Cm ( I s t )
+
this is a
+
.Dq humanized
+
form as a floating point value scaled to the range 0 \- 1000
+
followed by a SI power-of-10 scale factor.
+
.It Sq Cm #
+
The value should be converted to the
+
.Dq second alternate form .
+
For integer valued conversions
+
.Cm ( I s t )
+
this is a
+
.Dq humanized
+
form as a floating point value scaled to the range 0 \- 1024
+
followed by a SI power-of-2 scale factor.
+
For
+
.Cm c , d , i , n , p , s ,
+
and
+
.Cm u
+
conversions, this option has no effect.
+
For
+
.Cm o
+
conversions, the precision of the number is increased to force the first
+
character of the output string to a zero.
+
For
+
.Cm x
+
and
+
.Cm X
+
conversions, a non-zero result has the string
+
.Ql 0x
+
(Or
+
.Ql 0X
+
for
+
.Cm X
+
conversions) prepended to it.
+
For
+
.Cm a , A , e , E , f , F , g ,
+
and
+
.Cm G
+
conversions, the result will always contain a decimal point, even if no
+
digits follow it (normally, a decimal point appears in the results of
+
those conversions only if a digit follows).
+
For
+
.Cm g
+
and
+
.Cm G
+
conversions, trailing zeros are not removed from the result as they
+
would otherwise be.
+
.It So Cm 0 Sc (zero)
+
Zero padding.
+
For all conversions except
+
.Cm n ,
+
the converted value is padded on the left with zeros rather than blanks.
+
If a precision is given with a numeric conversion
+
.Cm ( d , i , o , u , i , x ,
+
and
+
.Cm X ) ,
+
the
+
.Cm 0
+
flag is ignored.
+
.It Sq Cm \-
+
A negative field width flag;
+
the converted value is to be left adjusted on the field boundary.
+
Except for
+
.Cm n
+
conversions, the converted value is padded on the right with blanks,
+
rather than on the left with blanks or zeros.
+
A
+
.Cm \-
+
overrides a
+
.Cm 0
+
if both are given.
+
.It So "\ " Sc (space)
+
A blank should be left before a positive number
+
produced by a signed conversion
+
.Cm ( a , A , d , e , E , f , F , g , G ,
+
or
+
.Cm i ) .
+
.It Sq Cm +
+
A sign must always be placed before a
+
number produced by a signed conversion.
+
A
+
.Cm +
+
overrides a space if both are used.
+
.It Sq Cm '
+
Decimal conversions
+
.Cm ( d , u ,
+
or
+
.Cm i )
+
or the integral portion of a floating point conversion
+
.Cm ( f
+
or
+
.Cm F )
+
should be grouped and separated by thousands using
+
the non-monetary separator returned by
+
.Xr localeconv 3 .
+
.El
+
.It
+
An optional decimal digit string specifying a minimum field width.
+
If the converted value has fewer characters than the field width, it will
+
be padded with spaces on the left (or right, if the left-adjustment
+
flag has been given) to fill out
+
the field width.
+
.It
+
An optional precision, in the form of a period
+
.Cm \&.
+
followed by an
+
optional digit string.
+
If the digit string is omitted, the precision is taken as zero.
+
This gives the minimum number of digits to appear for
+
.Cm d , i , o , u , x ,
+
and
+
.Cm X
+
conversions, the number of digits to appear after the decimal-point for
+
.Cm a , A , e , E , f ,
+
and
+
.Cm F
+
conversions, the maximum number of significant digits for
+
.Cm g
+
and
+
.Cm G
+
conversions, or the maximum number of characters to be printed from a
+
string for
+
.Cm s
+
conversions.
+
.It
+
An optional length modifier, that specifies the size of the argument.
+
The following length modifiers are valid for the
+
.Cm d , i , n , o , u , x ,
+
or
+
.Cm X
+
conversion:
+
.Bl -column ".Cm q Em (deprecated)" ".Vt signed char" ".Vt unsigned long long" ".Vt long long *"
+
.It Sy Modifier Ta Cm d , i Ta Cm o , u , x , X Ta Cm n
+
.It Cm hh Ta Vt "signed char" Ta Vt "unsigned char" Ta Vt "signed char *"
+
.It Cm h Ta Vt short Ta Vt "unsigned short" Ta Vt "short *"
+
.It Cm l No (ell) Ta Vt long Ta Vt "unsigned long" Ta Vt "long *"
+
.It Cm ll No (ell ell) Ta Vt "long long" Ta Vt "unsigned long long" Ta Vt "long long *"
+
.It Cm j Ta Vt intmax_t Ta Vt uintmax_t Ta Vt "intmax_t *"
+
.It Cm t Ta Vt ptrdiff_t Ta (see note) Ta Vt "ptrdiff_t *"
+
.It Cm z Ta (see note) Ta Vt size_t Ta (see note)
+
.It Cm q Em (deprecated) Ta Vt quad_t Ta Vt u_quad_t Ta Vt "quad_t *"
+
.El
+
.Pp
+
Note:
+
the
+
.Cm t
+
modifier, when applied to a
+
.Cm o , u , x ,
+
or
+
.Cm X
+
conversion, indicates that the argument is of an unsigned type
+
equivalent in size to a
+
.Vt ptrdiff_t .
+
The
+
.Cm z
+
modifier, when applied to a
+
.Cm d
+
or
+
.Cm i
+
conversion, indicates that the argument is of a signed type equivalent in
+
size to a
+
.Vt size_t .
+
Similarly, when applied to an
+
.Cm n
+
conversion, it indicates that the argument is a pointer to a signed type
+
equivalent in size to a
+
.Vt size_t .
+
.Pp
+
The following length modifier is valid for the
+
.Cm a , A , e , E , f , F , g ,
+
or
+
.Cm G
+
conversion:
+
.Bl -column ".Sy Modifier" ".Cm a , A , e , E , f , F , g , G"
+
.It Sy Modifier Ta Cm a , A , e , E , f , F , g , G
+
.It Cm l No (ell) Ta Vt double
+
(ignored, same behavior as without it)
+
.It Cm L Ta Vt "long double"
+
.El
+
.Pp
+
The following length modifier is valid for the
+
.Cm c
+
or
+
.Cm s
+
conversion:
+
.Bl -column ".Sy Modifier" ".Vt wint_t" ".Vt wchar_t *"
+
.It Sy Modifier Ta Cm c Ta Cm s
+
.It Cm l No (ell) Ta Vt wint_t Ta Vt "wchar_t *"
+
.El
+
.It
+
A character that specifies the type of conversion to be applied.
+
.El
+
.Pp
+
A field width or precision, or both, may be indicated by
+
an asterisk
+
.Ql *
+
or an asterisk followed by one or more decimal digits and a
+
.Ql $
+
instead of a
+
digit string.
+
In this case, an
+
.Vt int
+
argument supplies the field width or precision.
+
A negative field width is treated as a left adjustment flag followed by a
+
positive field width; a negative precision is treated as though it were
+
missing.
+
If a single format directive mixes positional
+
.Pq Li nn$
+
and non-positional arguments, the results are undefined.
+
.Pp
+
The conversion specifiers and their meanings are:
+
.Bl -tag -width ".Cm diouxX"
+
.It Cm diouxX
+
The
+
.Vt int
+
(or appropriate variant) argument is converted to signed decimal
+
.Cm ( d
+
and
+
.Cm i ) ,
+
unsigned octal
+
.Pq Cm o ,
+
unsigned decimal
+
.Pq Cm u ,
+
or unsigned hexadecimal
+
.Cm ( x
+
and
+
.Cm X )
+
notation.
+
The letters
+
.Dq Li abcdef
+
are used for
+
.Cm x
+
conversions; the letters
+
.Dq Li ABCDEF
+
are used for
+
.Cm X
+
conversions.
+
The precision, if any, gives the minimum number of digits that must
+
appear; if the converted value requires fewer digits, it is padded on
+
the left with zeros.
+
.It Cm DOU
+
The
+
.Vt "long int"
+
argument is converted to signed decimal, unsigned octal, or unsigned
+
decimal, as if the format had been
+
.Cm ld , lo ,
+
or
+
.Cm lu
+
respectively.
+
These conversion characters are deprecated, and will eventually disappear.
+
.It Cm eE
+
The
+
.Vt double
+
argument is rounded and converted in the style
+
.Sm off
+
.Oo \- Oc Ar d Li \&. Ar ddd Li e \(+- Ar dd
+
.Sm on
+
where there is one digit before the
+
decimal-point character
+
and the number of digits after it is equal to the precision;
+
if the precision is missing,
+
it is taken as 6; if the precision is
+
zero, no decimal-point character appears.
+
An
+
.Cm E
+
conversion uses the letter
+
.Ql E
+
(rather than
+
.Ql e )
+
to introduce the exponent.
+
The exponent always contains at least two digits; if the value is zero,
+
the exponent is 00.
+
.Pp
+
For
+
.Cm a , A , e , E , f , F , g ,
+
and
+
.Cm G
+
conversions, positive and negative infinity are represented as
+
.Li inf
+
and
+
.Li -inf
+
respectively when using the lowercase conversion character, and
+
.Li INF
+
and
+
.Li -INF
+
respectively when using the uppercase conversion character.
+
Similarly, NaN is represented as
+
.Li nan
+
when using the lowercase conversion, and
+
.Li NAN
+
when using the uppercase conversion.
+
.It Cm fF
+
The
+
.Vt double
+
argument is rounded and converted to decimal notation in the style
+
.Sm off
+
.Oo \- Oc Ar ddd Li \&. Ar ddd ,
+
.Sm on
+
where the number of digits after the decimal-point character
+
is equal to the precision specification.
+
If the precision is missing, it is taken as 6; if the precision is
+
explicitly zero, no decimal-point character appears.
+
If a decimal point appears, at least one digit appears before it.
+
.It Cm gG
+
The
+
.Vt double
+
argument is converted in style
+
.Cm f
+
or
+
.Cm e
+
(or
+
.Cm F
+
or
+
.Cm E
+
for
+
.Cm G
+
conversions).
+
The precision specifies the number of significant digits.
+
If the precision is missing, 6 digits are given; if the precision is zero,
+
it is treated as 1.
+
Style
+
.Cm e
+
is used if the exponent from its conversion is less than \-4 or greater than
+
or equal to the precision.
+
Trailing zeros are removed from the fractional part of the result; a
+
decimal point appears only if it is followed by at least one digit.
+
.It Cm aA
+
The
+
.Vt double
+
argument is rounded and converted to hexadecimal notation in the style
+
.Sm off
+
.Oo \- Oc Li 0x Ar h Li \&. Ar hhhp Oo \(+- Oc Ar d ,
+
.Sm on
+
where the number of digits after the hexadecimal-point character
+
is equal to the precision specification.
+
If the precision is missing, it is taken as enough to represent
+
the floating-point number exactly, and no rounding occurs.
+
If the precision is zero, no hexadecimal-point character appears.
+
The
+
.Cm p
+
is a literal character
+
.Ql p ,
+
and the exponent consists of a positive or negative sign
+
followed by a decimal number representing an exponent of 2.
+
The
+
.Cm A
+
conversion uses the prefix
+
.Dq Li 0X
+
(rather than
+
.Dq Li 0x ) ,
+
the letters
+
.Dq Li ABCDEF
+
(rather than
+
.Dq Li abcdef )
+
to represent the hex digits, and the letter
+
.Ql P
+
(rather than
+
.Ql p )
+
to separate the mantissa and exponent.
+
.Pp
+
Note that there may be multiple valid ways to represent floating-point
+
numbers in this hexadecimal format.
+
For example,
+
.Li 0x1.92p+1 , 0x3.24p+0 , 0x6.48p-1 ,
+
and
+
.Li 0xc.9p-2
+
are all equivalent.
+
.Fx 8.0
+
and later always prints finite non-zero numbers using
+
.Ql 1
+
as the digit before the hexadecimal point.
+
Zeroes are always represented with a mantissa of 0 (preceded by a
+
.Ql -
+
if appropriate) and an exponent of
+
.Li +0 .
+
.It Cm C
+
Treated as
+
.Cm c
+
with the
+
.Cm l
+
(ell) modifier.
+
.It Cm c
+
The
+
.Vt int
+
argument is converted to an
+
.Vt "unsigned char" ,
+
and the resulting character is written.
+
.Pp
+
If the
+
.Cm l
+
(ell) modifier is used, the
+
.Vt wint_t
+
argument shall be converted to a
+
.Vt wchar_t ,
+
and the (potentially multi-byte) sequence representing the
+
single wide character is written, including any shift sequences.
+
If a shift sequence is used, the shift state is also restored
+
to the original state after the character.
+
.It Cm S
+
Treated as
+
.Cm s
+
with the
+
.Cm l
+
(ell) modifier.
+
.It Cm s
+
The
+
.Vt "char *"
+
argument is expected to be a pointer to an array of character type (pointer
+
to a string).
+
Characters from the array are written up to (but not including)
+
a terminating
+
.Dv NUL
+
character;
+
if a precision is specified, no more than the number specified are
+
written.
+
If a precision is given, no null character
+
need be present; if the precision is not specified, or is greater than
+
the size of the array, the array must contain a terminating
+
.Dv NUL
+
character.
+
.Pp
+
If the
+
.Cm l
+
(ell) modifier is used, the
+
.Vt "wchar_t *"
+
argument is expected to be a pointer to an array of wide characters
+
(pointer to a wide string).
+
For each wide character in the string, the (potentially multi-byte)
+
sequence representing the
+
wide character is written, including any shift sequences.
+
If any shift sequence is used, the shift state is also restored
+
to the original state after the string.
+
Wide characters from the array are written up to (but not including)
+
a terminating wide
+
.Dv NUL
+
character;
+
if a precision is specified, no more than the number of bytes specified are
+
written (including shift sequences).
+
Partial characters are never written.
+
If a precision is given, no null character
+
need be present; if the precision is not specified, or is greater than
+
the number of bytes required to render the multibyte representation of
+
the string, the array must contain a terminating wide
+
.Dv NUL
+
character.
+
.It Cm p
+
The
+
.Vt "void *"
+
pointer argument is printed in hexadecimal (as if by
+
.Ql %#x
+
or
+
.Ql %#lx ) .
+
.It Cm n
+
The number of characters written so far is stored into the
+
integer indicated by the
+
.Vt "int *"
+
(or variant) pointer argument.
+
No argument is converted.
+
.It Cm %
+
A
+
.Ql %
+
is written.
+
No argument is converted.
+
The complete conversion specification
+
is
+
.Ql %% .
+
.El
+
.Pp
+
The decimal point
+
character is defined in the program's locale (category
+
.Dv LC_NUMERIC ) .
+
.Pp
+
In no case does a non-existent or small field width cause truncation of
+
a numeric field; if the result of a conversion is wider than the field
+
width, the
+
field is expanded to contain the conversion result.
+
.Sh EXAMPLES
+
To print a date and time in the form
+
.Dq Li "Sunday, July 3, 10:02" ,
+
where
+
.Fa weekday
+
and
+
.Fa month
+
are pointers to strings:
+
.Bd -literal -offset indent
+
#include <stdio.h>
+
fprintf(stdout, "%s, %s %d, %.2d:%.2d\en",
+
	weekday, month, day, hour, min);
+
.Ed
+
.Pp
+
To print \*(Pi
+
to five decimal places:
+
.Bd -literal -offset indent
+
#include <math.h>
+
#include <stdio.h>
+
fprintf(stdout, "pi = %.5f\en", 4 * atan(1.0));
+
.Ed
+
.Pp
+
To allocate a 128 byte string and print into it:
+
.Bd -literal -offset indent
+
#include <stdio.h>
+
#include <stdlib.h>
+
#include <stdarg.h>
+
char *newfmt(const char *fmt, ...)
+
{
+
	char *p;
+
	va_list ap;
+
	if ((p = malloc(128)) == NULL)
+
		return (NULL);
+
	va_start(ap, fmt);
+
	(void) vsnprintf(p, 128, fmt, ap);
+
	va_end(ap);
+
	return (p);
+
}
+
.Ed
+
.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
+
system call, the
+
.Fn printf
+
family of functions may fail if:
+
.Bl -tag -width Er
+
.It Bq Er EILSEQ
+
An invalid wide character code was encountered.
+
.It Bq Er ENOMEM
+
Insufficient storage space is available.
+
.El
+
.Sh SEE ALSO
+
.Xr printf 1 ,
+
.Xr fmtcheck 3 ,
+
.Xr scanf 3 ,
+
.Xr setlocale 3 ,
+
.Xr wprintf 3
+
.Sh STANDARDS
+
Subject to the caveats noted in the
+
.Sx BUGS
+
section below, the
+
.Fn fprintf ,
+
.Fn printf ,
+
.Fn sprintf ,
+
.Fn vprintf ,
+
.Fn vfprintf ,
+
and
+
.Fn vsprintf
+
functions
+
conform to
+
.St -ansiC
+
and
+
.St -isoC-99 .
+
With the same reservation, the
+
.Fn snprintf
+
and
+
.Fn vsnprintf
+
functions conform to
+
.St -isoC-99 ,
+
while
+
.Fn dprintf
+
and
+
.Fn vdprintf
+
conform to
+
.St -p1003.1-2008 .
+
.Sh HISTORY
+
The functions
+
.Fn asprintf
+
and
+
.Fn vasprintf
+
first appeared in the
+
.Tn GNU C
+
library.
+
These were implemented by
+
.An Peter Wemm Aq peter@FreeBSD.org
+
in
+
.Fx 2.2 ,
+
but were later replaced with a different implementation
+
from
+
.Ox 2.3
+
by
+
.An Todd C. Miller Aq Todd.Miller@courtesan.com .
+
The
+
.Fn dprintf
+
and
+
.Fn vdprintf
+
functions were added in
+
.Fx 8.0 .
+
.Sh BUGS
+
The
+
.Nm
+
family of functions do not correctly handle multibyte characters in the
+
.Fa format
+
argument.
+
.Sh SECURITY CONSIDERATIONS
+
The
+
.Fn sprintf
+
and
+
.Fn vsprintf
+
functions are easily misused in a manner which enables malicious users
+
to arbitrarily change a running program's functionality through
+
a buffer overflow attack.
+
Because
+
.Fn sprintf
+
and
+
.Fn vsprintf
+
assume an infinitely long string,
+
callers must be careful not to overflow the actual space;
+
this is often hard to assure.
+
For safety, programmers should use the
+
.Fn snprintf
+
interface instead.
+
For example:
+
.Bd -literal
+
void
+
foo(const char *arbitrary_string, const char *and_another)
+
{
+
	char onstack[8];
+

+
#ifdef BAD
+
	/*
+
	 * This first sprintf is bad behavior.  Do not use sprintf!
+
	 */
+
	sprintf(onstack, "%s, %s", arbitrary_string, and_another);
+
#else
+
	/*
+
	 * The following two lines demonstrate better use of
+
	 * snprintf().
+
	 */
+
	snprintf(onstack, sizeof(onstack), "%s, %s", arbitrary_string,
+
	    and_another);
+
#endif
+
}
+
.Ed
+
.Pp
+
The
+
.Fn printf
+
and
+
.Fn sprintf
+
family of functions are also easily misused in a manner
+
allowing malicious users to arbitrarily change a running program's
+
functionality by either causing the program
+
to print potentially sensitive data
+
.Dq "left on the stack" ,
+
or causing it to generate a memory fault or bus error
+
by dereferencing an invalid pointer.
+
.Pp
+
.Cm %n
+
can be used to write arbitrary data to potentially carefully-selected
+
addresses.
+
Programmers are therefore strongly advised to never pass untrusted strings
+
as the
+
.Fa format
+
argument, as an attacker can put format specifiers in the string
+
to mangle your stack,
+
leading to a possible security hole.
+
This holds true even if the string was built using a function like
+
.Fn snprintf ,
+
as the resulting string may still contain user-supplied conversion specifiers
+
for later interpolation by
+
.Fn printf .
+
.Pp
+
Always use the proper secure idiom:
+
.Pp
+
.Dl "snprintf(buffer, sizeof(buffer), \*q%s\*q, string);"