1 #ifndef INCLUDED_ircd_snprintf_h
2 #define INCLUDED_ircd_snprintf_h
4 * IRC - Internet Relay Chat, include/ircd_snprintf.h
5 * Copyright (C) 2000 Kevin L. Mitchell <klmitch@mit.edu>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #ifndef INCLUDED_sys_types_h
24 #include <sys/types.h>
25 #define INCLUDED_sys_types_h
27 #ifndef INCLUDED_stdarg_h
29 #define INCLUDED_stdarg_h
34 /* structure passed as argument for %v conversion */
36 size_t vd_chars; /* number of characters inserted */
37 size_t vd_overflow; /* number of characters that couldn't be */
38 const char *vd_format; /* format string */
39 va_list vd_args; /* arguments for %v */
44 #define va_copy(DEST, SRC) __va_copy(DEST, SRC)
46 #define va_copy(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof(DEST))
50 extern int ircd_snprintf(struct Client *dest, char *buf, size_t buf_len,
51 const char *format, ...);
52 extern int ircd_vsnprintf(struct Client *dest, char *buf, size_t buf_len,
53 const char *format, va_list args);
58 ** These functions are intended to be a complete replacement for
59 ** sprintf and sprintf_irc. They are a (nearly) complete
60 ** reimplementation, and of course they're snprintf clones, making it
61 ** more difficult for accidental buffer overflows to crop up.
63 ** First off, what's missing? These functions support all ANSI C
64 ** conversion specifiers and selected ones from ISO 9x, with the
65 ** exception of all floating-point conversions. The floating-point
66 ** conversions are tricky, and will likely be dependent on the
67 ** representation of a floating-point number on a particular
68 ** architecture. While that representation is likely to conform to
69 ** some standard, it is not currently used in ircu, so seemed like a
70 ** good thing to omit, given the difficulty of implementing it.
72 ** There are two more things missing from this implementation that
73 ** would be required by ANSI; the first is support for multibyte
74 ** character strings, and the second is support for locales, neither
75 ** of which have any relevance for ircu, so again omission seemed to
76 ** be a good policy. Additionally, %#x always causes '0x' (or '0X')
77 ** to be printed, even if the number is zero.
79 ** These functions also have some extensions not seen in a
80 ** standards-compliant implementation; technically, the ISO 9x
81 ** extensions fall into this category, for instance. The ISO 9x
82 ** extensions supported are type extensions--%ju, %tu, and %zu, for
83 ** instance; %qu and %hhu are also supported. The extensions added
84 ** for use in ircu are %Tu, which takes a time_t, and the new %C
85 ** conversion, which inserts either a numeric or a nick, dependant on
86 ** the <dest> parameter. The GNU %m extension, which inserts the
87 ** strerror() string corresponding to the current value of errno, is
88 ** also supported, as is a special %v extension, which essentially
89 ** does a recursive call to ircd_snprintf.
91 ** The following description is descended from the Linux manpage for
92 ** the printf family of functions.
94 ** The format string is composed of zero or more directives:
95 ** ordinary characters (not %), which are copied unchanged to the
96 ** output stream; and conversion specifications, each of which results
97 ** in fetching zero or more subsequent arguments. Each conversion
98 ** specification is introduced by the character %. The arguments must
99 ** correspond properly (after type promotion) with the conversion
100 ** specifier. After the %, the following appear in sequence:
102 ** * Zero or more of the following flags:
104 ** # specifying that the value should be converted to an
105 ** "alternate form." For c, d, i, n, p, s, and u conversions,
106 ** this option has no effect. For o conversions, the precision
107 ** of the number is increased to force the first character of the
108 ** output string to a zero (except if a zero value is printed
109 ** with an explicit precision of zero). For x and X conversions,
110 ** the string '0x' (or '0X' for X conversions) is prepended to
111 ** it. For e, E, f, g, and G conversions, the result will always
112 ** contain a decimal point, even if no digits follow it
113 ** (normally, a decimal point appears in the results of those
114 ** conversions only if a digit follows). For g and G
115 ** conversions, trailing zeros are not removed from the result as
116 ** they would otherwise be. For C conversions, if the
117 ** destination is local and the origin is a user, the
118 ** nick!user@host form is used.
120 ** 0 specifying zero padding. For all conversions except n, the
121 ** converted value is padded on the left with zeros rather than
122 ** blanks. If a precision is given with a numeric conversion (d,
123 ** i, o, u, i, x, and X), the 0 flag is ignored.
125 ** - (a negative field width flag) indicates the converted value is
126 ** to be left adjusted on the field boundary. Except for n
127 ** conversions, the converted value is padded on the right with
128 ** blanks, rather than on the left with blanks or zeros. A -
129 ** overrides a 0 if both are given.
131 ** ' ' (a space) specifying that a blank should be left before a
132 ** positive number produced by a signed conversion (d, e, E, f,
135 ** + specifying that a sign always be placed before a number
136 ** produced by a signed conversion. A + overrides a space if
139 ** : specifying that a struct Client name should be preceded by a
140 ** ':' character if the destination is a user
142 ** * An optional decimal digit string specifying a minimum field
143 ** width. If the converted value has fewer characters than the
144 ** field width, it will be padded with spaces on the left (or right,
145 ** if the left-adjustment flag has been given) to fill out the field
148 ** * An optional precision, in the form of a period (`.') followed by
149 ** an optional digit string. If the digit string is omitted, the
150 ** precision is taken as zero. This gives the minimum number of
151 ** digits to appear for d, i, o, u, x, and X conversions, the number
152 ** of digits to appear after the decimal-point for e, E, and f
153 ** conversions, the maximum number of significant digits for g and G
154 ** conversions, or the maximum number of characters to be printed
155 ** from a string for s conversions.
157 ** * The optional character h, specifying that a following d, i, o, u,
158 ** x, or X conversion corresponds to a short int or unsigned short
159 ** int argument, or that a following n conversion corresponds to a
160 ** pointer to a short int argument. If the h character is given
161 ** again, char is used instead of short int.
163 ** * The optional character l (ell) specifying that a following d, i,
164 ** o, u, x, or X conversion applies to a pointer to a long int or
165 ** unsigned long int argument, or that a following n conversion
166 ** corresponds to a pointer to a long int argument.
168 ** * The character L specifying that a following e, E, f, g, or G
169 ** conversion corresponds to a long double argument, or a following
170 ** d, i, o, u, x, or X conversion corresponds to a long long
171 ** argument. Note that long long is not specified in ANSI C and
172 ** therefore not portable to all architectures.
174 ** * The optional character q. This is equivalent to L.
176 ** * A j character specifying that the following integer (d, i, o, u,
177 ** x, or X) conversion corresponds to an intmax_t argument.
179 ** * A t character specifying that the following integer (d, i, o, u,
180 ** x, or X) conversion corresponds to a ptrdiff_t argument.
182 ** * A z character specifying that the following integer (d, i, o, u,
183 ** x, or X) conversion corresponds to a size_t argument.
185 ** * A T character specifying that the following integer (d, i, o, u,
186 ** x, or X) conversion corresponds to a time_t argument.
188 ** * A character that specifies the type of conversion to be applied.
190 ** A field width or precision, or both, may be indicated by an
191 ** asterisk `*' instead of a digit string. In this case, an int
192 ** argument supplies the field width or precision. A negative field
193 ** width is treated as a left adjustment flag followed by a positive
194 ** field width; a negative precision is treated as though it were
197 ** The conversion specifiers and their meanings are:
199 ** diouxX The int (or appropriate variant) argument is converted
200 ** to signed decimal (d and i), unsigned octal (o),
201 ** unsigned decimal (u), or unsigned hexadecimal (x and
202 ** X) notation. The letters abcdef are used for x
203 ** conversions; the letters ABCDEF are used for X
204 ** conversions. The precision, if any, gives the minimum
205 ** number of digits that must appear; if the converted
206 ** value requires fewer digits, it is padded on the left
209 ** eE [NOT IMPLEMENTED] The double argument is rounded and
210 ** converted in the style [-]d.dddedd where there is one
211 ** digit before the decimal-point character and the
212 ** number of digits after it is equal to the precision;
213 ** if the precision is missing, it is taken as 6; if the
214 ** precision is zero, no decimal-point character appears.
215 ** An E conversion uses the letter E (rather than e) to
216 ** introduce the exponent. The exponent always contains
217 ** at least two digits; if the value is zero, the
220 ** f [NOT IMPLEMENTED] The double argument is rounded and
221 ** converted to decimal notation in the style
222 ** [-]ddd.ddd, where the number of digits after the
223 ** decimal-point character is equal to the precision
224 ** specification. If the precision is missing, it is
225 ** taken as 6; if the precision is explicitly zero, no
226 ** decimal-point character appears. If a decimal point
227 ** appears, at least one digit appears before it.
229 ** g [NOT IMPLEMENTED] The double argument is converted in
230 ** style f or e (or E for G conversions). The precision
231 ** specifies the number of significant digits. If the
232 ** precision is missing, 6 digits are given; if the
233 ** precision is zero, it is treated as 1. Style e is
234 ** used if the exponent from its conversion is less than
235 ** -4 or greater than or equal to the precision.
236 ** Trailing zeros are removed from the fractional part of
237 ** the result; a decimal point appears only if it is
238 ** followed by at least one digit.
240 ** c The int argument is converted to an unsigned char, and
241 ** the resulting character is written.
243 ** s The "char *" argument is expected to be a pointer to
244 ** an array of character type (pointer to a string).
245 ** Characters from the array are written up to (but not
246 ** including) a terminating NUL character; if a precision
247 ** is specified, no more than the number specified are
248 ** written. If a precision is given, no null character
249 ** need be present; if the precision is not specified, or
250 ** is greater than the size of the array, the array must
251 ** contain a terminating NUL character.
253 ** p The "void *" pointer argument is printed in
254 ** hexadecimal (as if by %#x or %#lx).
256 ** n The number of characters written so far is stored into
257 ** the integer indicated by the ``int *'' (or variant)
258 ** pointer argument. No argument is converted.
260 ** m The error message associated with the current value of
261 ** errno is printed as if by %s.
263 ** C The client argument identifier is printed under the
264 ** control of the <dest> argument; if <dest> is NULL or
265 ** is a user, the client's name (nickname or server name)
266 ** is printed; otherwise, the client's network numeric is
269 ** H The channel argument identifier (channel name) is
272 ** v The argument given must be a pointer to a struct
273 ** VarData with vd_format and vd_args must be initialized
274 ** appropriately. On return, vd_chars will contain the
275 ** number of characters added to the buffer, and
276 ** vd_overflow will contain the number of characters that
277 ** could not be added due to buffer overflow or due to a
280 ** % A `%' is written. No argument is converted. The
281 ** complete conversion specification is `%%'.
283 ** In no case does a non-existent or small field width cause
284 ** truncation of a field; if the result of a conversion is wider than
285 ** the field width, the field is expanded to contain the conversion
289 #endif /* INCLUDED_ircd_snprintf_h */