ssh-1.2.26 patch for log_msg() overflow

From: Dug Song (dugsongat_private)
Date: Sun Nov 01 1998 - 13:39:05 PST

  • Next message: Mitch Vincent: "Re: SSH Communications page on rootshell.com"

    here is a patch for ssh-1.2.26 to fix the overflow in log_msg(), as
    detailed in IBM's emergency response service bulletin
    ERS-SVA-E01-1998:005.1 (included in rootshell security bulletin #25).
    
    -d.
    
    ---
    http://www.monkey.org/~dugsong/
    
    diff -u -r ssh-1.2.26-orig/Makefile.in ssh-1.2.26/Makefile.in
    --- ssh-1.2.26-orig/Makefile.in Wed Jul  8 12:40:39 1998
    +++ ssh-1.2.26/Makefile.in      Sun Nov  1 16:11:44 1998
    @@ -315,7 +315,7 @@
            rsa.o randoms.o md5.o buffer.o emulate.o packet.o compress.o \
            xmalloc.o ttymodes.o newchannels.o bufaux.o authfd.o authfile.o \
            crc32.o rsaglue.o cipher.o des.o match.o arcfour.o mpaux.o \
    -       userfile.o signals.o blowfish.o deattack.o
    +       userfile.o signals.o blowfish.o deattack.o snprintf.o
     SSHD_OBJS = sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o \
            log-server.o login.o hostfile.o canohost.o servconf.o tildexpand.o \
            serverloop.o $(COMMON_OBJS) $(KERBEROS_OBJS) $(SSHDCONFOBJS)
    @@ -332,7 +332,7 @@
            xmalloc.o bufaux.o authfd.o authfile.o cipher.o blowfish.o \
            des.o arcfour.o mpaux.o userfile.o signals.o $(LIBOBJS) \
            $(CONFOBJS)
    -SCP_OBJS = scp.o xmalloc.o
    +SCP_OBJS = scp.o xmalloc.o snprintf.o
     #ifdef F_SECURE_COMMERCIAL
     #
     #
    @@ -359,7 +359,7 @@
            randoms.h ttymodes.h authfd.h crc32.h includes.h \
            readconf.h userfile.h blowfish.h des.h md5.h rsa.h version.h bufaux.h \
            mpaux.h servconf.h xmalloc.h buffer.h emulate.h packet.h ssh.h \
    -       deattack.h
    +       deattack.h snprintf.h
    
     DISTFILES = $(srcdir)/COPYING $(srcdir)/README $(srcdir)/README.SECURID \
            $(srcdir)/README.TIS $(srcdir)/README.SECURERPC \
    diff -u -r ssh-1.2.26-orig/log-server.c ssh-1.2.26/log-server.c
    --- ssh-1.2.26-orig/log-server.c        Wed Jul  8 12:40:36 1998
    +++ ssh-1.2.26/log-server.c     Sun Nov  1 16:14:23 1998
    @@ -60,6 +60,7 @@
     #include "packet.h"
     #include "xmalloc.h"
     #include "ssh.h"
    +#include "snprintf.h"
    
     static int log_debug = 0;
     static int log_quiet = 0;
    @@ -134,7 +135,7 @@
       if (log_quiet)
         return;
       va_start(args, fmt);
    -  vsprintf(buf, fmt, args);
    +  vsnprintf(buf, sizeof(buf), fmt, args);
       va_end(args);
       if (log_on_stderr)
         fprintf(stderr, "log: %s\n", buf);
    @@ -175,7 +176,7 @@
       if (log_quiet)
         return;
       va_start(args, fmt);
    -  vsprintf(buf, fmt, args);
    +  vsnprintf(buf, sizeof(buf), fmt, args);
       va_end(args);
       if (log_on_stderr)
         fprintf(stderr, "log: %s\n", buf);
    @@ -191,7 +192,7 @@
       if (!log_debug || log_quiet)
         return;
       va_start(args, fmt);
    -  vsprintf(buf, fmt, args);
    +  vsnprintf(buf, sizeof(buf), fmt, args);
       va_end(args);
       if (log_on_stderr)
         fprintf(stderr, "debug: %s\n", buf);
    @@ -207,7 +208,7 @@
       if (log_quiet)
         return;
       va_start(args, fmt);
    -  vsprintf(buf, fmt, args);
    +  vsnprintf(buf, sizeof(buf), fmt, args);
       va_end(args);
       if (log_on_stderr)
         fprintf(stderr, "error: %s\n", buf);
    @@ -302,7 +303,7 @@
       if (log_quiet)
         exit(1);
       va_start(args, fmt);
    -  vsprintf(buf, fmt, args);
    +  vsnprintf(buf, sizeof(buf), fmt, args);
       va_end(args);
       if (log_on_stderr)
         fprintf(stderr, "fatal: %s\n", buf);
    @@ -321,7 +322,7 @@
       if (log_quiet)
         exit(1);
       va_start(args, fmt);
    -  vsprintf(buf, fmt, args);
    +  vsnprintf(buf, sizeof(buf), fmt, args);
       va_end(args);
       if (log_on_stderr)
         fprintf(stderr, "fatal: %s\n", buf);
    diff -u -r ssh-1.2.26-orig/packet.c ssh-1.2.26/packet.c
    --- ssh-1.2.26-orig/packet.c    Wed Jul  8 12:40:37 1998
    +++ ssh-1.2.26/packet.c Sun Nov  1 16:15:26 1998
    @@ -90,6 +90,7 @@
     #include "getput.h"
     #include "compress.h"
     #include "deattack.h"
    +#include "snprintf.h"
    
     /* This variable contains the file descriptors used for communicating with
        the other side.  connection_in is used for reading; connection_out
    @@ -693,7 +694,7 @@
       va_list args;
    
       va_start(args, fmt);
    -  vsprintf(buf, fmt, args);
    +  vsnprintf(buf, sizeof(buf), fmt, args);
       va_end(args);
    
       packet_start(SSH_MSG_DEBUG);
    @@ -719,7 +720,7 @@
       /* Format the message.  Note that the caller must make sure the message
          is of limited size. */
       va_start(args, fmt);
    -  vsprintf(buf, fmt, args);
    +  vsnprintf(buf, sizeof(buf), fmt, args);
       va_end(args);
    
       /* Send the disconnect message to the other side, and wait for it to get
    diff -u -r ssh-1.2.26-orig/scp.c ssh-1.2.26/scp.c
    --- ssh-1.2.26-orig/scp.c       Wed Jul  8 12:40:38 1998
    +++ ssh-1.2.26/scp.c    Sun Nov  1 16:34:57 1998
    @@ -134,6 +134,7 @@
     #include "includes.h"
     #include "ssh.h"
     #include "xmalloc.h"
    +#include "snprintf.h"
     #ifdef HAVE_UTIME_H
     #include <utime.h>
     #if defined(_NEXT_SOURCE) && !defined(_POSIX_SOURCE)
    @@ -332,7 +333,7 @@
       char buf[1024];
    
       va_start(ap, fmt);
    -  vsprintf(buf, fmt, ap);
    +  vsnprintf(buf, sizeof(buf), fmt, ap);
       va_end(ap);
       fprintf(stderr, "%s\n", buf);
       exit(255);
    diff -u -r ssh-1.2.26-orig/snprintf.c ssh-1.2.26/snprintf.c
    --- ssh-1.2.26-orig/snprintf.c  Sun Nov  1 16:19:33 1998
    +++ ssh-1.2.26/snprintf.c       Sun Nov  1 16:24:37 1998
    @@ -0,0 +1,559 @@
    +/*
    +
    +  Author: Tomi Salo <ttsaloat_private>
    +
    +  Copyright (C) 1996 SSH Communications Security Oy, Espoo, Finland
    +  All rights reserved.
    +
    +  Implementation of functions snprintf() and vsnprintf()
    +
    +  */
    +
    +/*
    + * $Id: snprintf.c,v 1.19 1998/06/03 00:45:30 ylo Exp $
    + * $Log: snprintf.c,v $
    + * $EndLog$
    + */
    +
    +#include "includes.h"
    +#include "snprintf.h"
    +
    +#define MINUS_FLAG 0x1
    +#define PLUS_FLAG 0x2
    +#define SPACE_FLAG 0x4
    +#define HASH_FLAG 0x8
    +#define CONV_TO_SHORT 0x10
    +#define IS_LONG_INT 0x20
    +#define IS_LONG_DOUBLE 0x40
    +#define X_UPCASE 0x80
    +#define IS_NEGATIVE 0x100
    +#define UNSIGNED_DEC 0x200
    +#define ZERO_PADDING 0x400
    +
    +#undef sprintf
    +
    +/* Extract a formatting directive from str. Str must point to a '%'.
    +   Returns number of characters used or zero if extraction failed. */
    +
    +int
    +snprintf_get_directive(const char *str, int *flags, int *width,
    +                      int *precision, char *format_char, va_list *ap)
    +{
    +  int length, n;
    +  const char *orig_str = str;
    +
    +  *flags = 0;
    +  *width = 0;
    +  *precision = 0;
    +  *format_char = (char)0;
    +
    +  if (*str == '%')
    +    {
    +      /* Get the flags */
    +      str++;
    +      while (*str == '-' || *str == '+' || *str == ' '
    +            || *str == '#' || *str == '0')
    +       {
    +         switch (*str)
    +           {
    +           case '-':
    +             *flags |= MINUS_FLAG;
    +             break;
    +           case '+':
    +             *flags |= PLUS_FLAG;
    +             break;
    +           case ' ':
    +             *flags |= SPACE_FLAG;
    +             break;
    +           case '#':
    +             *flags |= HASH_FLAG;
    +             break;
    +           case '0':
    +             *flags |= ZERO_PADDING;
    +             break;
    +           }
    +         str++;
    +       }
    +
    +      /* Don't pad left-justified numbers withs zeros */
    +      if ((*flags & MINUS_FLAG) && (*flags & ZERO_PADDING))
    +       *flags &= ~ZERO_PADDING;
    +
    +      /* Is width field present? */
    +      if (isdigit(*str))
    +       {
    +         n = sscanf(str, "%d", width);
    +         if (n == 0)
    +           return 0;
    +
    +         /* Step through the field */
    +         while (isdigit(*str))
    +           str++;
    +       }
    +      else
    +       if (*str == '*')
    +         {
    +           *width = va_arg(*ap, int);
    +           str++;
    +         }
    +
    +      /* Is the precision field present? */
    +      if (*str == '.')
    +       {
    +         str++;
    +         if (isdigit(*str))
    +           {
    +             n = sscanf(str, "%d", precision);
    +             if (n == 0)
    +               return 0;
    +
    +             /* Step through the field */
    +             while (isdigit(*str))
    +               str++;
    +           }
    +         else
    +           if (*str == '*')
    +             {
    +               *precision = va_arg(*ap, int);
    +               str++;
    +             }
    +           else
    +             *precision = 0;
    +       }
    +
    +      /* Get the optional type character */
    +      if (*str == 'h')
    +       {
    +         *flags |= CONV_TO_SHORT;
    +         str++;
    +       }
    +      else
    +       {
    +         if (*str == 'l')
    +           {
    +             *flags |= IS_LONG_INT;
    +             str++;
    +           }
    +         else
    +           {
    +             if (*str == 'L')
    +               {
    +                 *flags |= IS_LONG_DOUBLE;
    +                 str++;
    +               }
    +           }
    +       }
    +
    +      /* Get and check the formatting character */
    +
    +      *format_char = *str;
    +      str++;
    +      length = str - orig_str;
    +
    +      switch (*format_char)
    +       {
    +       case 'i': case 'd': case 'o': case 'u': case 'x': case 'X':
    +       case 'f': case 'e': case 'E': case 'g': case 'G':
    +       case 'c': case 's': case 'p': case 'n':
    +         if (*format_char == 'X')
    +           *flags |= X_UPCASE;
    +         if (*format_char == 'o')
    +           *flags |= UNSIGNED_DEC;
    +         return length;
    +
    +       default:
    +         return 0;
    +       }
    +    }
    +  else
    +    {
    +      return 0;
    +    }
    +}
    +
    +/* Convert a integer from unsigned long int representation
    +   to string representation. This will insert prefixes if needed
    +   (leading zero for octal and 0x or 0X for hexadecimal) and
    +   will write at most buf_size characters to buffer.
    +   tmp_buf is used because we want to get correctly truncated
    +   results.
    +   */
    +
    +int
    +snprintf_convert_ulong(char *buffer, size_t buf_size, int base, char *digits,
    +                      unsigned long int ulong_val, int flags, int width,
    +                      int precision)
    +{
    +  int tmp_buf_len = 100 + width, len;
    +  char *tmp_buf, *tmp_buf_ptr, prefix[2];
    +  tmp_buf = xmalloc(tmp_buf_len);
    +
    +  prefix[0] = '\0';
    +  prefix[1] = '\0';
    +
    +  /* Make tmp_buf_ptr point just past the last char of buffer */
    +  tmp_buf_ptr = tmp_buf + tmp_buf_len;
    +
    +  /* Main conversion loop */
    +  do
    +    {
    +      *--tmp_buf_ptr = digits[ulong_val % base];
    +      ulong_val /= base;
    +      precision--;
    +    }
    +  while ((ulong_val != 0 || precision > 0) && tmp_buf_ptr > tmp_buf);
    +
    +  /* Get the prefix */
    +  if (!(flags & IS_NEGATIVE))
    +    {
    +      if (base == 16 && (flags & HASH_FLAG))
    +         if (flags && X_UPCASE)
    +           {
    +             prefix[0] = 'x';
    +             prefix[1] = '0';
    +           }
    +         else
    +           {
    +             prefix[0] = 'X';
    +             prefix[1] = '0';
    +           }
    +
    +      if (base == 8 && (flags & HASH_FLAG))
    +         prefix[0] = '0';
    +
    +      if (base == 10 && !(flags & UNSIGNED_DEC) && (flags & PLUS_FLAG))
    +         prefix[0] = '+';
    +      else
    +       if (base == 10 && !(flags & UNSIGNED_DEC) && (flags & SPACE_FLAG))
    +         prefix[0] = ' ';
    +    }
    +  else
    +      prefix[0] = '-';
    +
    +  if (prefix[0] != '\0' && tmp_buf_ptr > tmp_buf)
    +    {
    +      *--tmp_buf_ptr = prefix[0];
    +      if (prefix[1] != '\0' && tmp_buf_ptr > tmp_buf)
    +       *--tmp_buf_ptr = prefix[1];
    +    }
    +
    +  len = (tmp_buf + tmp_buf_len) - tmp_buf_ptr;
    +
    +  if (len <= buf_size)
    +    {
    +      if (len < width)
    +       {
    +         if (width > (tmp_buf_ptr - tmp_buf))
    +           width = (tmp_buf_ptr - tmp_buf);
    +         if (flags & MINUS_FLAG)
    +           {
    +             memcpy(buffer, tmp_buf_ptr, len);
    +             memset(buffer + len, (flags & ZERO_PADDING)?'0':' ',
    +                    width - len);
    +             len = width;
    +           }
    +         else
    +           {
    +             memset(buffer, (flags & ZERO_PADDING)?'0':' ',
    +                    width - len);
    +             memcpy(buffer + width - len, tmp_buf_ptr, len);
    +             len = width;
    +           }
    +       }
    +      else
    +       {
    +         memcpy(buffer, tmp_buf_ptr, len);
    +       }
    +      xfree(tmp_buf);
    +      return len;
    +    }
    +  else
    +    {
    +      memcpy(buffer, tmp_buf_ptr, buf_size);
    +      xfree(tmp_buf);
    +      return buf_size;
    +    }
    +}
    +
    +int
    +snprintf_convert_float(char *buffer, size_t buf_size,
    +                      double dbl_val, int flags, int width,
    +                      int precision, char format_char)
    +{
    +  char print_buf[160], print_buf_len = 0;
    +  char format_str[80], *format_str_ptr;
    +
    +  format_str_ptr = format_str;
    +
    +  if (width > 155) width = 155;
    +  if (precision <= 0)
    +    precision = 6;
    +  if (precision > 120)
    +    precision = 120;
    +
    +  /* Construct the formatting string and let system's sprintf
    +     do the real work. */
    +
    +  *format_str_ptr++ = '%';
    +
    +  if (flags & MINUS_FLAG)
    +    *format_str_ptr++ = '-';
    +  if (flags & PLUS_FLAG)
    +    *format_str_ptr++ = '+';
    +  if (flags & SPACE_FLAG)
    +    *format_str_ptr++ = ' ';
    +  if (flags & ZERO_PADDING)
    +    *format_str_ptr++ = '0';
    +  if (flags & HASH_FLAG)
    +    *format_str_ptr++ = '#';
    +
    +  format_str_ptr += sprintf(format_str_ptr, "%d.%d", width, precision);
    +  if (flags & IS_LONG_DOUBLE)
    +    *format_str_ptr++ = 'L';
    +  *format_str_ptr++ = format_char;
    +  *format_str_ptr++ = '\0';
    +
    +  print_buf_len = sprintf(print_buf, format_str, dbl_val);
    +
    +  if (print_buf_len > buf_size) print_buf_len = buf_size;
    +  strncpy(buffer, print_buf, print_buf_len);
    +  return print_buf_len;
    +}
    +
    +int
    +snprintf(char *str, size_t size, const char *format, ...)
    +{
    +  int ret;
    +  va_list ap;
    +  va_start(ap, format);
    +  ret = vsnprintf(str, size, format, ap);
    +  va_end(ap);
    +
    +  return ret;
    +}
    +
    +int
    +vsnprintf(char *str, size_t size, const char *format, va_list ap)
    +{
    +  int status, left = (int)size - 1;
    +  const char *format_ptr = format;
    +  int flags, width, precision, i;
    +  char format_char, *orig_str = str;
    +  int *int_ptr;
    +  long int long_val;
    +  unsigned long int ulong_val;
    +  char *str_val;
    +  double dbl_val;
    +
    +  flags = 0;
    +  while (format_ptr < format + strlen(format))
    +    {
    +      if (*format_ptr == '%')
    +       {
    +         if (format_ptr[1] == '%' && left > 0)
    +           {
    +             *str++ = '%';
    +             left--;
    +             format_ptr += 2;
    +           }
    +         else
    +           {
    +             if (left <= 0)
    +               {
    +                 *str = '\0';
    +                 return size;
    +               }
    +             else
    +               {
    +                 status = snprintf_get_directive(format_ptr, &flags, &width,
    +                                                 &precision, &format_char,
    +                                                 &ap);
    +                 if (status == 0)
    +                   {
    +                     *str = '\0';
    +                     return 0;
    +                   }
    +                 else
    +                   {
    +                     format_ptr += status;
    +                     /* Print a formatted argument */
    +                     switch (format_char)
    +                       {
    +                       case 'i': case 'd':
    +                         /* Convert to unsigned long int before
    +                            actual conversion to string */
    +                         if (flags & IS_LONG_INT)
    +                           long_val = va_arg(ap, long int);
    +                         else
    +                           long_val = (long int) va_arg(ap, int);
    +
    +                         if (long_val < 0)
    +                           {
    +                             ulong_val = (unsigned long int) -long_val;
    +                             flags |= IS_NEGATIVE;
    +                           }
    +                         else
    +                           {
    +                             ulong_val = (unsigned long int) long_val;
    +                           }
    +                         status = snprintf_convert_ulong(str, left, 10,
    +                                                         "0123456789",
    +                                                         ulong_val, flags,
    +                                                         width, precision);
    +                         str += status;
    +                         left -= status;
    +                         break;
    +
    +                       case 'x':
    +                         if (flags & IS_LONG_INT)
    +                           ulong_val = va_arg(ap, unsigned long int);
    +                         else
    +                           ulong_val =
    +                             (unsigned long int) va_arg(ap, unsigned int);
    +
    +                         status = snprintf_convert_ulong(str, left, 16,
    +                                                         "0123456789abcdef",
    +                                                         ulong_val, flags,
    +                                                         width, precision);
    +                         str += status;
    +                         left -= status;
    +                         break;
    +
    +                       case 'X':
    +                         if (flags & IS_LONG_INT)
    +                           ulong_val = va_arg(ap, unsigned long int);
    +                         else
    +                           ulong_val =
    +                             (unsigned long int) va_arg(ap, unsigned int);
    +
    +                         status = snprintf_convert_ulong(str, left, 16,
    +                                                         "0123456789ABCDEF",
    +                                                         ulong_val, flags,
    +                                                         width, precision);
    +                         str += status;
    +                         left -= status;
    +                         break;
    +
    +                       case 'o':
    +                         if (flags & IS_LONG_INT)
    +                           ulong_val = va_arg(ap, unsigned long int);
    +                         else
    +                           ulong_val =
    +                             (unsigned long int) va_arg(ap, unsigned int);
    +
    +                         status = snprintf_convert_ulong(str, left, 8,
    +                                                         "01234567",
    +                                                         ulong_val, flags,
    +                                                         width, precision);
    +                         str += status;
    +                         left -= status;
    +                         break;
    +
    +                       case 'u':
    +                         if (flags & IS_LONG_INT)
    +                           ulong_val = va_arg(ap, unsigned long int);
    +                         else
    +                           ulong_val =
    +                             (unsigned long int) va_arg(ap, unsigned int);
    +
    +                         status = snprintf_convert_ulong(str, left, 10,
    +                                                         "0123456789",
    +                                                         ulong_val, flags,
    +                                                         width, precision);
    +                         str += status;
    +                         left -= status;
    +                         break;
    +
    +                       case 'p':
    +                         break;
    +
    +                       case 'c':
    +                         if (flags & IS_LONG_INT)
    +                           ulong_val = va_arg(ap, unsigned long int);
    +                         else
    +                           ulong_val =
    +                             (unsigned long int) va_arg(ap, unsigned int);
    +                         *str++ = (unsigned char)ulong_val;
    +                         left--;
    +                         break;
    +
    +                       case 's':
    +                         str_val = va_arg(ap, char *);
    +
    +                         if (str_val == NULL)
    +                           str_val = "(null)";
    +
    +                         if (precision == 0)
    +                           precision = strlen(str_val);
    +                         else
    +                           {
    +                             if (memchr(str_val, 0, precision) != NULL)
    +                               precision = strlen(str_val);
    +                           }
    +                         if (precision > left)
    +                           precision = left;
    +
    +                         if (width > left)
    +                           width = left;
    +                         if (width < precision)
    +                           width = precision;
    +                         i = width - precision;
    +
    +                         if (flags & MINUS_FLAG)
    +                           {
    +                             strncpy(str, str_val, precision);
    +                             memset(str + precision,
    +                                    (flags & ZERO_PADDING)?'0':' ', i);
    +                           }
    +                         else
    +                           {
    +                             memset(str, (flags & ZERO_PADDING)?'0':' ', i);
    +                             strncpy(str + i, str_val, precision);
    +                           }
    +                         str += width;
    +                         left -= width;
    +                         break;
    +
    +                       case 'n':
    +                         int_ptr = va_arg(ap, int *);
    +                         *int_ptr = str - orig_str;
    +                         break;
    +
    +                       case 'f': case 'e': case 'E': case 'g': case 'G':
    +                         if (flags & IS_LONG_DOUBLE)
    +                           dbl_val = (double) va_arg(ap, long double);
    +                         else
    +                           dbl_val = va_arg(ap, double);
    +                         status =
    +                           snprintf_convert_float(str, left, dbl_val, flags,
    +                                                  width, precision,
    +                                                  format_char);
    +                         str += status;
    +                         left -= status;
    +                         break;
    +
    +                       default:
    +                         break;
    +                       }
    +                   }
    +               }
    +           }
    +       }
    +      else
    +       {
    +         if (left > 0)
    +           {
    +             *str++ = *format_ptr++;
    +             left--;
    +           }
    +         else
    +           {
    +             *str = '\0';
    +             return size;
    +           }
    +       }
    +    }
    +  *str = '\0';
    +  return size - left - 1;
    +}
    +
    diff -u -r ssh-1.2.26-orig/snprintf.h ssh-1.2.26/snprintf.h
    --- ssh-1.2.26-orig/snprintf.h  Sun Nov  1 16:19:25 1998
    +++ ssh-1.2.26/snprintf.h       Sun Nov  1 16:16:48 1998
    @@ -0,0 +1,46 @@
    +/*
    +
    +  Author: Tomi Salo <ttsaloat_private>
    +
    +  Copyright (C) 1996 SSH Communications Security Oy, Espoo, Finland
    +  All rights reserved.
    +
    +  Header file for snprintf.c
    +
    +  */
    +
    +/*
    + * $Id:
    + * $Log: snprintf.h,v $
    + * $EndLog$
    + */
    +
    +#ifndef SNPRINTF_H
    +#define SNPRINTF_H
    +
    +#include "includes.h"
    +
    +/* Write formatted text to buffer 'str', using format string 'format'.
    +   Returns number of characters written, or negative if error
    +   occurred. SshBuffer's size is given in 'size'. Format string is
    +   understood as defined in ANSI C.
    +
    +   NOTE: This does NOT work identically with BDS's snprintf.
    +
    +   Integers: Ansi C says that precision specifies the minimun
    +   number of digits to print. BSD's version however counts the
    +   prefixes (+, -, ' ', '0x', '0X', octal prefix '0'...) as
    +   'digits'.
    +
    +   Also, BSD implementation does not permit padding integers
    +   to specified width with zeros on left (in front of the prefixes),
    +   it uses spaces instead, even when Ansi C only forbids padding
    +   with zeros on the right side of numbers.
    +
    +   */
    +
    +int snprintf(char *str, size_t size, const char *format, ...);
    +
    +int vsnprintf(char *str, size_t size, const char *format, va_list ap);
    +
    +#endif /* SNPRINTF_H */
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:21:46 PDT