From: Kevin L. Mitchell Date: Thu, 13 Apr 2000 19:20:53 +0000 (+0000) Subject: Author: Kev X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=4b1176eea672c03083572a0ac5b92e21cf31d923;p=ircu2.10.12-pk.git Author: Kev Log message: * config/aclocal.m4 (unet_CHECK_TYPE_SIZES): check size of void *, too, for ircd_snprintf.c * include/ircd_snprintf.h: documentation for ircd_(v)snprintf, in comments; mostly descended from the Linux manpage for printf, but also documenting the extensions. * ircd/ircd_snprintf.c: NULL dest is equivalent to going to a client; make 'q' be the same as 'L'; remove __inline__; only define EXTENSION if HAVE_LONG_LONG is defined git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@161 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/ChangeLog b/ChangeLog index 4dc058b..f54b16e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2000-04-13 Kevin L. Mitchell + * config/aclocal.m4 (unet_CHECK_TYPE_SIZES): check size of void *, + too, for ircd_snprintf.c + + * include/ircd_snprintf.h: documentation for ircd_(v)snprintf, in + comments; mostly descended from the Linux manpage for printf, but + also documenting the extensions. + + * ircd/ircd_snprintf.c: NULL dest is equivalent to going to a + client; make 'q' be the same as 'L'; remove __inline__; only + define EXTENSION if HAVE_LONG_LONG is defined + * include/handlers.h: declare m_gline() * ircd/parse.c: gline can be called by users, but it only lists @@ -422,7 +433,7 @@ # # ChangeLog for ircu2.10.11 # -# $Id: ChangeLog,v 1.78 2000-04-13 15:58:22 kev Exp $ +# $Id: ChangeLog,v 1.79 2000-04-13 19:20:52 kev Exp $ # # Insert new changes at beginning of the change list. # diff --git a/config/aclocal.m4 b/config/aclocal.m4 index 8cd8680..875251f 100644 --- a/config/aclocal.m4 +++ b/config/aclocal.m4 @@ -234,6 +234,7 @@ AC_DEFUN(unet_CHECK_TYPE_SIZES, AC_CHECK_SIZEOF(short) AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(void *) if test "$ac_cv_sizeof_int" = 2 ; then AC_CHECK_TYPE(int16_t, int) AC_CHECK_TYPE(u_int16_t, unsigned int) diff --git a/include/ircd_snprintf.h b/include/ircd_snprintf.h index 824c594..28bcc5c 100644 --- a/include/ircd_snprintf.h +++ b/include/ircd_snprintf.h @@ -47,4 +47,230 @@ extern int ircd_snprintf(struct Client *dest, char *buf, size_t buf_len, extern int ircd_vsnprintf(struct Client *dest, char *buf, size_t buf_len, const char *format, va_list args); +/* +** ircd_(v)snprintf +** +** These functions are intended to be a complete replacement for +** sprintf and sprintf_irc. They are a (nearly) complete +** reimplementation, and of course they're snprintf clones, making it +** more difficult for accidental buffer overflows to crop up. +** +** First off, what's missing? These functions support all ANSI C +** conversion specifiers and selected ones from ISO 9x, with the +** exception of all floating-point conversions. The floating-point +** conversions are tricky, and will likely be dependent on the +** representation of a floating-point number on a particular +** architecture. While that representation is likely to conform to +** some standard, it is not currently used in ircu, so seemed like a +** good thing to omit, given the difficulty of implementing it. +** +** There are two more things missing from this implementation that +** would be required by ANSI; the first is support for multibyte +** character strings, and the second is support for locales, neither +** of which have any relevance for ircu, so again omission seemed to +** be a good policy. Additionally, %#x always causes '0x' (or '0X') +** to be printed, even if the number is zero. +** +** These functions also have some extensions not seen in a +** standards-compliant implementation; technically, the ISO 9x +** extensions fall into this category, for instance. The ISO 9x +** extensions supported are type extensions--%ju, %tu, and %zu, for +** instance; %qu and %hhu are also supported. The extensions added +** for use in ircu are %Tu, which takes a time_t, and the new %C +** conversion, which inserts either a numeric or a nick, dependant on +** the parameter. The GNU %m extension, which inserts the +** strerror() string corresponding to the current value of errno, is +** also supported, as is a special %v extension, which essentially +** does a recursive call to ircd_snprintf. +** +** The following description is descended from the Linux manpage for +** the printf family of functions. +** +** The format string is composed of zero or more directives: +** ordinary characters (not %), 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 character %. The arguments must +** correspond properly (after type promotion) with the conversion +** specifier. After the %, the following appear in sequence: +** +** * Zero or more of the following flags: +** +** # specifying that the value should be converted to an +** "alternate form." For c, d, i, n, p, s, and u conversions, +** this option has no effect. For o conversions, the precision +** of the number is increased to force the first character of the +** output string to a zero (except if a zero value is printed +** with an explicit precision of zero). For x and X conversions, +** the string '0x' (or '0X' for X conversions) is prepended to +** it. For e, E, f, g, and 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 g and G +** conversions, trailing zeros are not removed from the result as +** they would otherwise be. +** +** 0 specifying zero padding. For all conversions except n, the +** converted value is padded on the left with zeros rather than +** blanks. If a precision is given with a numeric conversion (d, +** i, o, u, i, x, and X), the 0 flag is ignored. +** +** - (a negative field width flag) indicates the converted value is +** to be left adjusted on the field boundary. Except for n +** conversions, the converted value is padded on the right with +** blanks, rather than on the left with blanks or zeros. A - +** overrides a 0 if both are given. +** +** ' ' (a space) specifying that a blank should be left before a +** positive number produced by a signed conversion (d, e, E, f, +** g, G, or i). +** +** + specifying that a sign always be placed before a number +** produced by a signed conversion. A + overrides a space if +** both are used. +** +** * 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. +** +** * An optional precision, in the form of a period (`.') 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 d, i, o, u, x, and X conversions, the number +** of digits to appear after the decimal-point for e, E, and f +** conversions, the maximum number of significant digits for g and G +** conversions, or the maximum number of characters to be printed +** from a string for s conversions. +** +** * The optional character h, specifying that a following d, i, o, u, +** x, or X conversion corresponds to a short int or unsigned short +** int argument, or that a following n conversion corresponds to a +** pointer to a short int argument. If the h character is given +** again, char is used instead of short int. +** +** * The optional character l (ell) specifying that a following d, i, +** o, u, x, or X conversion applies to a pointer to a long int or +** unsigned long int argument, or that a following n conversion +** corresponds to a pointer to a long int argument. +** +** * The character L specifying that a following e, E, f, g, or G +** conversion corresponds to a long double argument, or a following +** d, i, o, u, x, or X conversion corresponds to a long long +** argument. Note that long long is not specified in ANSI C and +** therefore not portable to all architectures. +** +** * The optional character q. This is equivalent to L. +** +** * A j character specifying that the following integer (d, i, o, u, +** x, or X) conversion corresponds to an intmax_t argument. +** +** * A t character specifying that the following integer (d, i, o, u, +** x, or X) conversion corresponds to a ptrdiff_t argument. +** +** * A z character specifying that the following integer (d, i, o, u, +** x, or X) conversion corresponds to a size_t argument. +** +** * A T character specifying that the following integer (d, i, o, u, +** x, or X) conversion corresponds to a time_t argument. +** +** * A character that specifies the type of conversion to be applied. +** +** A field width or precision, or both, may be indicated by an +** asterisk `*' instead of a digit string. In this case, an 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. +** +** The conversion specifiers and their meanings are: +** +** diouxX The int (or appropriate variant) argument is converted +** to signed decimal (d and i), unsigned octal (o), +** unsigned decimal (u), or unsigned hexadecimal (x and +** X) notation. The letters abcdef are used for x +** conversions; the letters ABCDEF are used for 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. +** +** eE [NOT IMPLEMENTED] The double argument is rounded and +** converted in the style [-]d.dddedd 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 E conversion uses the letter E (rather than e) to +** introduce the exponent. The exponent always contains +** at least two digits; if the value is zero, the +** exponent is 00. +** +** f [NOT IMPLEMENTED] The double argument is rounded and +** converted to decimal notation in the style +** [-]ddd.ddd, 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. +** +** g [NOT IMPLEMENTED] The double argument is converted in +** style f or e (or E for 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 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. +** +** c The int argument is converted to an unsigned char, and +** the resulting character is written. +** +** s The "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 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 NUL character. +** +** p The "void *" pointer argument is printed in +** hexadecimal (as if by %#x or %#lx). +** +** n The number of characters written so far is stored into +** the integer indicated by the ``int *'' (or variant) +** pointer argument. No argument is converted. +** +** m The error message associated with the current value of +** errno is printed as if by %s. +** +** C The client argument identifier is printed under the +** control of the argument; if is NULL or +** is a user, the client's name (nickname or server name) +** is printed; otherwise, the client's network numeric is +** printed. +** +** v The argument given must be a pointer to a struct +** VarData with vd_format and vd_args must be initialized +** appropriately. On return, vd_chars will contain the +** number of characters added to the buffer, and +** vd_overflow will contain the number of characters that +** could not be added due to buffer overflow or due to a +** precision. +** +** % A `%' is written. No argument is converted. The +** complete conversion specification is `%%'. +** +** In no case does a non-existent or small field width cause +** truncation of a field; if the result of a conversion is wider than +** the field width, the field is expanded to contain the conversion +** result. +*/ + #endif /* INCLUDED_ircd_snprintf_h */ diff --git a/ircd/ircd_snprintf.c b/ircd/ircd_snprintf.c index 646dc16..6c9e43d 100644 --- a/ircd/ircd_snprintf.c +++ b/ircd/ircd_snprintf.c @@ -28,15 +28,8 @@ #include #include -/* for testing purposes */ -#ifndef SIZEOF_VOID_P -# warning SIZEOF_VOID_P not defined yet! -# define SIZEOF_VOID_P 4 -# define SIZEOF_LONG 4 -#endif - /* Inhibit complaints when we use GCC extensions */ -#ifdef __GNUC__ +#if defined(__GNUC__) && defined(HAVE_LONG_LONG) # define EXTENSION __extension__ #else # define EXTENSION @@ -1411,7 +1404,7 @@ static char *HEX[] = { }; /* Add a character to the buffer */ -static __inline__ void +static void addc(struct BufData *buf_p, int c) { int overflow = 0; @@ -1432,7 +1425,7 @@ addc(struct BufData *buf_p, int c) } /* Add a string to the buffer */ -static __inline__ void +static void adds(struct BufData *buf_p, int s_len, const char *s) { int overflow = 0; @@ -1460,7 +1453,7 @@ adds(struct BufData *buf_p, int s_len, const char *s) } /* Add padding */ -static __inline__ void +static void do_pad(struct BufData *buf_p, int padlen, char *pad) { /* do chunks of PAD_LENGTH first */ @@ -1472,7 +1465,7 @@ do_pad(struct BufData *buf_p, int padlen, char *pad) } /* Find string length up to maxlen */ -static __inline__ int +static int my_strnlen(const char *str, int maxlen) { int len = 0; @@ -1604,21 +1597,13 @@ doprintf(struct Client *dest, struct BufData *buf_p, const char *fmt, if (state <= OPT) { state = OPT; if (fld_s.flags & TYPE_LONG) /* We support 'll' */ - fld_s.flags |= TYPE_QUAD; + fld_s.flags |= TYPE_QUAD | TYPE_LONGDOUBLE; else if (!(fld_s.flags & TYPE_MASK)) fld_s.flags |= TYPE_LONG; } continue; - case 'q': /* it's a quad */ - if (state <= OPT) { - state = OPT; - if (!(fld_s.flags & TYPE_MASK)) - fld_s.flags |= TYPE_QUAD; - } - continue; - - case 'L': /* it's a quad or long double */ + case 'q': case 'L': /* it's a quad or long double */ if (state <= OPT) { state = OPT; if (!(fld_s.flags & TYPE_MASK)) @@ -2005,7 +1990,7 @@ doprintf(struct Client *dest, struct BufData *buf_p, const char *fmt, char *str1 = 0, *str2 = 0; int slen1 = 0, slen2 = 0, plen = 0; - if (IsServer(dest)) { + if (dest && IsServer(dest)) { if (IsServer(cptr)) str1 = cptr->yxx; else {