Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

snprintf.c

Go to the documentation of this file.
00001 /* $Id$ */
00002 /*
00003 ** Copyright (C) 1998-2002 Martin Roesch <roesch@sourcefire.com>
00004 **
00005 ** This program is free software; you can redistribute it and/or modify
00006 ** it under the terms of the GNU General Public License as published by
00007 ** the Free Software Foundation; either version 2 of the License, or
00008 ** (at your option) any later version.
00009 **
00010 ** This program is distributed in the hope that it will be useful,
00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 ** GNU General Public License for more details.
00014 **
00015 ** You should have received a copy of the GNU General Public License
00016 ** along with this program; if not, write to the Free Software
00017 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00018 */
00019 
00020 /*
00021 ** This file contains various routines which we shamelessly steal from other
00022 ** opensource products :-P (I love code reuseability idea) 
00023 **                      fygrave@tigerteam.net
00024 */
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include "config.h"
00028 #endif
00029 
00030 #ifndef HAVE_SNPRINTF
00031     #include "snprintf.h"
00032 
00033 /* snprintf() and all supporting routines were taken from sendmail, hence the 
00034  * copyleft message 
00035  */
00036 
00037 /*
00038  * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
00039  * Copyright (c) 1997 Eric P. Allman.  All rights reserved.
00040  * Copyright (c) 1988, 1993
00041  *      The Regents of the University of California.  All rights reserved.
00042  *
00043  * By using this file, you agree to the terms and conditions set
00044  * forth in the LICENSE file which can be found at the top level of
00045  * the sendmail distribution.
00046  *
00047  */
00048 
00049 /*
00050 **  SNPRINTF, VSNPRINT -- counted versions of printf
00051 **
00052 **      These versions have been grabbed off the net.  They have been
00053 **      cleaned up to compile properly and support for .precision and
00054 **      %lx has been added.
00055 */
00056 
00057 /**************************************************************
00058  * Original:
00059  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
00060  * A bombproof version of doprnt (sm_dopr) included.
00061  * Sigh.  This sort of thing is always nasty do deal with.  Note that
00062  * the version here does not include floating point...
00063  *
00064  * snprintf() is used instead of sprintf() as it does limit checks
00065  * for string length.  This covers a nasty loophole.
00066  *
00067  * The other functions are there to prevent NULL pointers from
00068  * causing nast effects.
00069  **************************************************************/
00070 
00071 void    sm_dopr();
00072 char    *DoprEnd;
00073 int SnprfOverflow;
00074 
00075     #ifndef HAVE_SNPRINTF
00076 
00077 /* VARARGS3 */
00078 int
00079         #ifdef __STDC__
00080 snprintf(char *str, size_t count, const char *fmt, ...)
00081         #else
00082 snprintf(str, count, fmt, va_alist)
00083 char *str;
00084 size_t count;
00085 const char *fmt;
00086 va_dcl
00087         #endif
00088 {
00089     int len;
00090     VA_LOCAL_DECL
00091 
00092     VA_START(fmt);
00093     len = vsnprintf(str, count, fmt, ap);
00094     VA_END;
00095     return len;
00096 }
00097 
00098 
00099         #ifndef luna2
00100 #ifndef HAVE_VSNPRINTF
00101                 
00102 int
00103 vsnprintf(str, count, fmt, args)
00104 char *str;
00105 size_t count;
00106 const char *fmt;
00107 va_list args;
00108 {
00109     str[0] = 0;
00110     DoprEnd = str + count - 1;
00111     SnprfOverflow = 0;
00112     sm_dopr( str, fmt, args );
00113     if(count > 0)
00114         DoprEnd[0] = 0;
00115     if(SnprfOverflow && tTd(57, 2))
00116         printf("\nvsnprintf overflow, len = %ld, str = %s",
00117                (long) count, shortenstring(str, MAXSHORTSTR));
00118     return strlen((const char *)str);
00119 }
00120 
00121 #endif /* !HAVE_VSNPRINTF */
00122         
00123         #endif /* !luna2 */
00124     #endif /* !HASSNPRINTF */
00125 
00126 /*
00127  * sm_dopr(): poor man's version of doprintf
00128  */
00129 
00130 void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
00131 void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
00132 void dostr __P(( char * , int ));
00133 char *output;
00134 void dopr_outch __P(( int c ));
00135 int SyslogErrno;
00136 
00137 void
00138 sm_dopr( buffer, format, args )
00139 char *buffer;
00140 const char *format;
00141 va_list args;
00142 {
00143     int ch;
00144     long value;
00145     int longflag  = 0;
00146     int pointflag = 0;
00147     int maxwidth  = 0;
00148     char *strvalue;
00149     int ljust;
00150     int len;
00151     int zpad;
00152 #if !HAVE_STRERROR && !defined(ERRLIST_PREDEFINED)
00153     extern char *sys_errlist[];
00154     extern int sys_nerr;
00155 #endif
00156 
00157 
00158     output = buffer;
00159     while((ch = *format++) != '\0')
00160     {
00161         switch(ch)
00162         {
00163             case '%':
00164                 ljust = len = zpad = maxwidth = 0;
00165                 longflag = pointflag = 0;
00166                 nextch:
00167                 ch = *format++;
00168                 switch(ch)
00169                 {
00170                     case 0:
00171                         dostr( "**end of format**" , 0);
00172                         return;
00173                     case '-': ljust = 1; goto nextch;
00174                     case '0': /* set zero padding if len not set */
00175                         if(len==0 && !pointflag) zpad = '0';
00176                     case '1':
00177                     case '2':
00178                     case '3':
00179                     case '4':
00180                     case '5':
00181                     case '6':
00182                     case '7':
00183                     case '8':
00184                     case '9':
00185                         if(pointflag)
00186                             maxwidth = maxwidth*10 + ch - '0';
00187                         else
00188                             len = len*10 + ch - '0';
00189                         goto nextch;
00190                     case '*': 
00191                         if(pointflag)
00192                             maxwidth = va_arg( args, int );
00193                         else
00194                             len = va_arg( args, int );
00195                         goto nextch;
00196                     case '.': pointflag = 1; goto nextch;
00197                     case 'l': longflag = 1; goto nextch;
00198                     case 'u':
00199                     case 'U':
00200                         /*fmtnum(value,base,dosign,ljust,len,zpad) */
00201                         if(longflag)
00202                         {
00203                             value = va_arg( args, long );
00204                         }
00205                         else
00206                         {
00207                             value = va_arg( args, int );
00208                         }
00209                         fmtnum( value, 10,0, ljust, len, zpad ); break;
00210                     case 'o':
00211                     case 'O':
00212                         /*fmtnum(value,base,dosign,ljust,len,zpad) */
00213                         if(longflag)
00214                         {
00215                             value = va_arg( args, long );
00216                         }
00217                         else
00218                         {
00219                             value = va_arg( args, int );
00220                         }
00221                         fmtnum( value, 8,0, ljust, len, zpad ); break;
00222                     case 'd':
00223                     case 'D':
00224                         if(longflag)
00225                         {
00226                             value = va_arg( args, long );
00227                         }
00228                         else
00229                         {
00230                             value = va_arg( args, int );
00231                         }
00232                         fmtnum( value, 10,1, ljust, len, zpad ); break;
00233                     case 'x':
00234                         if(longflag)
00235                         {
00236                             value = va_arg( args, long );
00237                         }
00238                         else
00239                         {
00240                             value = va_arg( args, int );
00241                         }
00242                         fmtnum( value, 16,0, ljust, len, zpad ); break;
00243                     case 'X':
00244                         if(longflag)
00245                         {
00246                             value = va_arg( args, long );
00247                         }
00248                         else
00249                         {
00250                             value = va_arg( args, int );
00251                         }
00252                         fmtnum( value,-16,0, ljust, len, zpad ); break;
00253                     case 's':
00254                         strvalue = va_arg( args, char *);
00255                         if(maxwidth > 0 || !pointflag)
00256                         {
00257                             if(pointflag && len > maxwidth)
00258                                 len = maxwidth; /* Adjust padding */
00259                             fmtstr( strvalue,ljust,len,zpad, maxwidth);
00260                         }
00261                         break;
00262                     case 'c':
00263                         ch = va_arg( args, int );
00264                         dopr_outch( ch ); break;
00265                     case 'm':
00266 #if HAVE_STRERROR 
00267                         dostr(strerror(SyslogErrno), 0);
00268 #else
00269                         if(SyslogErrno < 0 || SyslogErrno >= sys_nerr)
00270                         {
00271                             dostr("Error ", 0);
00272                             fmtnum(SyslogErrno, 10, 0, 0, 0, 0);
00273                         }
00274                         else
00275                             dostr((char *)sys_errlist[SyslogErrno], 0);
00276 #endif
00277                         break;
00278 
00279                     case '%': dopr_outch( ch ); continue;
00280                     default:
00281                         dostr(  "???????" , 0);
00282                 }
00283                 break;
00284             default:
00285                 dopr_outch( ch );
00286                 break;
00287         }
00288     }
00289     *output = 0;
00290 }
00291 
00292 void
00293 fmtstr(  value, ljust, len, zpad, maxwidth )
00294 char *value;
00295 int ljust, len, zpad, maxwidth;
00296 {
00297     int padlen, strlen;     /* amount to pad */
00298 
00299     if(value == 0)
00300     {
00301         value = "<NULL>";
00302     }
00303     for(strlen = 0; value[strlen]; ++ strlen); /* strlen */
00304     if(strlen > maxwidth && maxwidth)
00305         strlen = maxwidth;
00306     padlen = len - strlen;
00307     if(padlen < 0) padlen = 0;
00308     if(ljust) padlen = -padlen;
00309     while(padlen > 0)
00310     {
00311         dopr_outch( ' ' );
00312         --padlen;
00313     }
00314     dostr( value, maxwidth );
00315     while(padlen < 0)
00316     {
00317         dopr_outch( ' ' );
00318         ++padlen;
00319     }
00320 }
00321 
00322 void
00323 fmtnum(  value, base, dosign, ljust, len, zpad )
00324 long value;
00325 int base, dosign, ljust, len, zpad;
00326 {
00327     int signvalue = 0;
00328     unsigned long uvalue;
00329     char convert[20];
00330     int place = 0;
00331     int padlen = 0; /* amount to pad */
00332     int caps = 0;
00333 
00334     /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
00335         value, base, dosign, ljust, len, zpad )); */
00336     uvalue = value;
00337     if(dosign)
00338     {
00339         if(value < 0)
00340         {
00341             signvalue = '-';
00342             uvalue = -value;
00343         }
00344     }
00345     if(base < 0)
00346     {
00347         caps = 1;
00348         base = -base;
00349     }
00350     do
00351     {
00352         convert[place++] =
00353         (caps? "0123456789ABCDEF":"0123456789abcdef")
00354         [uvalue % (unsigned)base  ];
00355         uvalue = (uvalue / (unsigned)base );
00356     }while(uvalue);
00357     convert[place] = 0;
00358     padlen = len - place;
00359     if(padlen < 0) padlen = 0;
00360     if(ljust) padlen = -padlen;
00361     /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
00362         convert,place,signvalue,padlen)); */
00363     if(zpad && padlen > 0)
00364     {
00365         if(signvalue)
00366         {
00367             dopr_outch( signvalue );
00368             --padlen;
00369             signvalue = 0;
00370         }
00371         while(padlen > 0)
00372         {
00373             dopr_outch( zpad );
00374             --padlen;
00375         }
00376     }
00377     while(padlen > 0)
00378     {
00379         dopr_outch( ' ' );
00380         --padlen;
00381     }
00382     if(signvalue) dopr_outch( signvalue );
00383     while(place > 0) dopr_outch( convert[--place] );
00384     while(padlen < 0)
00385     {
00386         dopr_outch( ' ' );
00387         ++padlen;
00388     }
00389 }
00390 
00391 void
00392 dostr( str , cut)
00393 char *str;
00394 int cut;
00395 {
00396     if(cut)
00397     {
00398         while(*str && cut-- > 0) dopr_outch(*str++);
00399     }
00400     else
00401     {
00402         while(*str) dopr_outch(*str++);
00403     }
00404 }
00405 
00406 void
00407 dopr_outch( c )
00408 int c;
00409 {
00410 #if 0
00411     if(iscntrl(c) && c != '\n' && c != '\t')
00412     {
00413         c = '@' + (c & 0x1F);
00414         if(DoprEnd == 0 || output < DoprEnd)
00415             *output++ = '^';
00416     }
00417 #endif
00418     if(DoprEnd == 0 || output < DoprEnd)
00419         *output++ = c;
00420     else
00421         SnprfOverflow++;
00422 }
00423 
00424 /*
00425 **  QUAD_TO_STRING -- Convert a quad type to a string.
00426 **
00427 **      Convert a quad type to a string.  This must be done
00428 **      separately as %lld/%qd are not supported by snprint()
00429 **      and adding support would slow down systems which only
00430 **      emulate the data type.
00431 **
00432 **      Parameters:
00433 **              value -- number to convert to a string.
00434 **
00435 **      Returns:
00436 **              pointer to a string.
00437 */
00438 
00439 char *
00440 quad_to_string(value)
00441 QUAD_T value;
00442 {
00443     char *fmtstr;
00444     static char buf[64];
00445 
00446     /*
00447     **  Use sprintf() instead of snprintf() since snprintf()
00448     **  does not support %qu or %llu.  The buffer is large enough
00449     **  to hold the string so there is no danger of buffer
00450     **  overflow.
00451     */
00452 
00453 #if NEED_PERCENTQ
00454     fmtstr = "%qu";
00455 #else
00456     fmtstr = "%llu";
00457 #endif
00458     sprintf(buf, fmtstr, value);
00459     return buf;
00460 }
00461 /*
00462 **  SHORTENSTRING -- return short version of a string
00463 **
00464 **      If the string is already short, just return it.  If it is too
00465 **      long, return the head and tail of the string.
00466 **
00467 **      Parameters:
00468 **              s -- the string to shorten.
00469 **              m -- the max length of the string.
00470 **
00471 **      Returns:
00472 **              Either s or a short version of s.
00473 */
00474 
00475 char *
00476 shortenstring(s, m)
00477 register const char *s;
00478 int m;
00479 {
00480     int l;
00481     static char buf[MAXSHORTSTR + 1];
00482 
00483     l = strlen(s);
00484     if(l < m)
00485         return(char *) s;
00486     if(m > MAXSHORTSTR)
00487         m = MAXSHORTSTR;
00488     else if(m < 10)
00489     {
00490         if(m < 5)
00491         {
00492             strncpy(buf, s, m);
00493             buf[m] = '\0';
00494             return buf;
00495         }
00496         strncpy(buf, s, m - 3);
00497         strcpy(buf + m - 3, "...");
00498         return buf;
00499     }
00500     m = (m - 3) / 2;
00501     strncpy(buf, s, m);
00502     strcpy(buf + m, "...");
00503     strcpy(buf + m + 3, s + l - m);
00504     return buf;
00505 }
00506 
00507 #endif

Generated on Sun May 14 14:51:18 2006 by  doxygen 1.4.2