honeyd/vasprintf.c

Mon, 28 Jan 2013 17:37:18 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 28 Jan 2013 17:37:18 +0100
changeset 758
a2c6460cfb16
permissions
-rw-r--r--

Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.

     1 /* Like vsprintf but provides a pointer to malloc'd storage, which must
     2    be freed by the caller.
     3    Copyright (C) 1994, 2003 Free Software Foundation, Inc.
     5 This file is part of the libiberty library.
     6 Libiberty is free software; you can redistribute it and/or
     7 modify it under the terms of the GNU Library General Public
     8 License as published by the Free Software Foundation; either
     9 version 2 of the License, or (at your option) any later version.
    11 Libiberty is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    14 Library General Public License for more details.
    16 You should have received a copy of the GNU Library General Public
    17 License along with libiberty; see the file COPYING.LIB.  If
    18 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    19 Boston, MA 02111-1307, USA.  */
    21 #include <stdarg.h>
    22 #include <stdio.h>
    23 #include <stdlib.h>
    24 #include <string.h>
    25 #include "vasprintf.h"
    27 /*
    29 @deftypefn Extension int vasprintf (char **@var{resptr}, const char *@var{format}, va_list @var{args})
    31 Like @code{vsprintf}, but instead of passing a pointer to a buffer,
    32 you pass a pointer to a pointer.  This function will compute the size
    33 of the buffer needed, allocate memory with @code{malloc}, and store a
    34 pointer to the allocated memory in @code{*@var{resptr}}.  The value
    35 returned is the same as @code{vsprintf} would return.  If memory could
    36 not be allocated, minus one is returned and @code{NULL} is stored in
    37 @code{*@var{resptr}}.
    39 @end deftypefn
    41 */
    43 static int int_vasprintf(char **, const char *, va_list);
    45 static int
    46 int_vasprintf (result, format, args)
    47      char **result;
    48      const char *format;
    49      va_list args;
    50 {
    51   const char *p = format;
    52   /* Add one to make sure that it is never zero, which might cause malloc
    53      to return NULL.  */
    54   int total_width = strlen (format) + 1;
    55   va_list ap;
    57   memcpy ((void *) &ap, (const void *) &args, sizeof (va_list));
    59   while (*p != '\0')
    60     {
    61       if (*p++ == '%')
    62 	{
    63 	  while (strchr ("-+ #0", *p))
    64 	    ++p;
    65 	  if (*p == '*')
    66 	    {
    67 	      ++p;
    68 	      total_width += abs (va_arg (ap, int));
    69 	    }
    70 	  else
    71 	    total_width += strtoul (p, (char **) &p, 10);
    72 	  if (*p == '.')
    73 	    {
    74 	      ++p;
    75 	      if (*p == '*')
    76 		{
    77 		  ++p;
    78 		  total_width += abs (va_arg (ap, int));
    79 		}
    80 	      else
    81 	      total_width += strtoul (p, (char **) &p, 10);
    82 	    }
    83 	  while (strchr ("hlL", *p))
    84 	    ++p;
    85 	  /* Should be big enough for any format specifier except %s and floats.  */
    86 	  total_width += 30;
    87 	  switch (*p)
    88 	    {
    89 	    case 'd':
    90 	    case 'i':
    91 	    case 'o':
    92 	    case 'u':
    93 	    case 'x':
    94 	    case 'X':
    95 	    case 'c':
    96 	      (void) va_arg (ap, int);
    97 	      break;
    98 	    case 'f':
    99 	    case 'e':
   100 	    case 'E':
   101 	    case 'g':
   102 	    case 'G':
   103 	      (void) va_arg (ap, double);
   104 	      /* Since an ieee double can have an exponent of 307, we'll
   105 		 make the buffer wide enough to cover the gross case. */
   106 	      total_width += 307;
   107 	      break;
   108 	    case 's':
   109 	      total_width += strlen (va_arg (ap, char *));
   110 	      break;
   111 	    case 'p':
   112 	    case 'n':
   113 	      (void) va_arg (ap, char *);
   114 	      break;
   115 	    }
   116 	  p++;
   117 	}
   118     }
   119   *result = (char *) malloc (total_width);
   120   if (*result != NULL)
   121     return vsprintf (*result, format, args);
   122   else
   123     return -1;
   124 }
   126 int
   127 vasprintf (result, format, args)
   128      char **result;
   129      const char *format;
   130      va_list args;
   131 {
   132   return int_vasprintf (result, format, args);
   133 }

mercurial