snprintf.c
Upload User: xu_441
Upload Date: 2007-01-04
Package Size: 1640k
Code Size: 10k
Category:

Email Client

Development Platform:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.
  3.  * All rights reserved.
  4.  * Copyright (c) 1997 Eric P. Allman.  All rights reserved.
  5.  * Copyright (c) 1988, 1993
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * By using this file, you agree to the terms and conditions set
  9.  * forth in the LICENSE file which can be found at the top level of
  10.  * the sendmail distribution.
  11.  *
  12.  */
  13. #ifndef lint
  14. static char id[] = "@(#)$Id: snprintf.c,v 8.27 1999/10/13 03:27:08 ca Exp $";
  15. #endif /* ! lint */
  16. #include <sendmail.h>
  17. /*
  18. **  SNPRINTF, VSNPRINT -- counted versions of printf
  19. **
  20. ** These versions have been grabbed off the net.  They have been
  21. ** cleaned up to compile properly and support for .precision and
  22. ** %lx has been added.
  23. */
  24. /**************************************************************
  25.  * Original:
  26.  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
  27.  * A bombproof version of doprnt (sm_dopr) included.
  28.  * Sigh.  This sort of thing is always nasty do deal with.  Note that
  29.  * the version here does not include floating point...
  30.  *
  31.  * snprintf() is used instead of sprintf() as it does limit checks
  32.  * for string length.  This covers a nasty loophole.
  33.  *
  34.  * The other functions are there to prevent NULL pointers from
  35.  * causing nast effects.
  36.  **************************************************************/
  37. /*static char _id[] = "$OrigId: snprintf.c,v 1.2 1995/10/09 11:19:47 roberto Exp $";*/
  38. void sm_dopr();
  39. char *DoprEnd;
  40. int SnprfOverflow;
  41. #if !HASSNPRINTF
  42. /* VARARGS3 */
  43. int
  44. # ifdef __STDC__
  45. snprintf(char *str, size_t count, const char *fmt, ...)
  46. # else /* __STDC__ */
  47. snprintf(str, count, fmt, va_alist)
  48. char *str;
  49. size_t count;
  50. const char *fmt;
  51. va_dcl
  52. # endif /* __STDC__ */
  53. {
  54. int len;
  55. VA_LOCAL_DECL
  56. VA_START(fmt);
  57. len = vsnprintf(str, count, fmt, ap);
  58. VA_END;
  59. return len;
  60. }
  61. # ifndef luna2
  62. int
  63. vsnprintf(str, count, fmt, args)
  64. char *str;
  65. size_t count;
  66. const char *fmt;
  67. va_list args;
  68. {
  69. str[0] = 0;
  70. DoprEnd = str + count - 1;
  71. SnprfOverflow = 0;
  72. sm_dopr( str, fmt, args );
  73. if (count > 0)
  74. DoprEnd[0] = 0;
  75. if (SnprfOverflow && tTd(57, 2))
  76. dprintf("nvsnprintf overflow, len = %ld, str = %s",
  77. (long) count, shortenstring(str, MAXSHORTSTR));
  78. return strlen(str);
  79. }
  80. # endif /* ! luna2 */
  81. #endif /* !HASSNPRINTF */
  82. /*
  83.  * sm_dopr(): poor man's version of doprintf
  84.  */
  85. void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
  86. void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
  87. void dostr __P(( char * , int ));
  88. char *output;
  89. void dopr_outch __P(( int c ));
  90. int SyslogErrno;
  91. void
  92. sm_dopr( buffer, format, args )
  93.        char *buffer;
  94.        const char *format;
  95.        va_list args;
  96. {
  97.        int ch;
  98.        long value;
  99.        int longflag  = 0;
  100.        int pointflag = 0;
  101.        int maxwidth  = 0;
  102.        char *strvalue;
  103.        int ljust;
  104.        int len;
  105.        int zpad;
  106. #if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
  107. extern char *sys_errlist[];
  108. extern int sys_nerr;
  109. #endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */
  110.        output = buffer;
  111.        while( (ch = *format++) != '' ){
  112.        switch( ch ){
  113.        case '%':
  114.        ljust = len = zpad = maxwidth = 0;
  115.        longflag = pointflag = 0;
  116.        nextch:
  117.        ch = *format++;
  118.        switch( ch ){
  119.        case 0:
  120.        dostr( "**end of format**" , 0);
  121.        return;
  122.        case '-': ljust = 1; goto nextch;
  123.        case '0': /* set zero padding if len not set */
  124.        if(len==0 && !pointflag) zpad = '0';
  125. /* FALLTHROUGH */
  126.        case '1': case '2': case '3':
  127.        case '4': case '5': case '6':
  128.        case '7': case '8': case '9':
  129.        if (pointflag)
  130.  maxwidth = maxwidth*10 + ch - '0';
  131.        else
  132.  len = len*10 + ch - '0';
  133.        goto nextch;
  134.        case '*':
  135.        if (pointflag)
  136.  maxwidth = va_arg( args, int );
  137.        else
  138.  len = va_arg( args, int );
  139.        goto nextch;
  140.        case '.': pointflag = 1; goto nextch;
  141.        case 'l': longflag = 1; goto nextch;
  142.        case 'u': case 'U':
  143.        /*fmtnum(value,base,dosign,ljust,len,zpad) */
  144.        if( longflag ){
  145.        value = va_arg( args, long );
  146.        } else {
  147.        value = va_arg( args, int );
  148.        }
  149.        fmtnum( value, 10,0, ljust, len, zpad ); break;
  150.        case 'o': case 'O':
  151.        /*fmtnum(value,base,dosign,ljust,len,zpad) */
  152.        if( longflag ){
  153.        value = va_arg( args, long );
  154.        } else {
  155.        value = va_arg( args, int );
  156.        }
  157.        fmtnum( value, 8,0, ljust, len, zpad ); break;
  158.        case 'd': case 'D':
  159.        if( longflag ){
  160.        value = va_arg( args, long );
  161.        } else {
  162.        value = va_arg( args, int );
  163.        }
  164.        fmtnum( value, 10,1, ljust, len, zpad ); break;
  165.        case 'x':
  166.        if( longflag ){
  167.        value = va_arg( args, long );
  168.        } else {
  169.        value = va_arg( args, int );
  170.        }
  171.        fmtnum( value, 16,0, ljust, len, zpad ); break;
  172.        case 'X':
  173.        if( longflag ){
  174.        value = va_arg( args, long );
  175.        } else {
  176.        value = va_arg( args, int );
  177.        }
  178.        fmtnum( value,-16,0, ljust, len, zpad ); break;
  179.        case 's':
  180.        strvalue = va_arg( args, char *);
  181.        if (maxwidth > 0 || !pointflag) {
  182.  if (pointflag && len > maxwidth)
  183.    len = maxwidth; /* Adjust padding */
  184.  fmtstr( strvalue,ljust,len,zpad, maxwidth);
  185.        }
  186.        break;
  187.        case 'c':
  188.        ch = va_arg( args, int );
  189.        dopr_outch( ch ); break;
  190.        case 'm':
  191. #if HASSTRERROR
  192.        dostr(strerror(SyslogErrno), 0);
  193. #else /* HASSTRERROR */
  194.        if (SyslogErrno < 0 || SyslogErrno >= sys_nerr)
  195.        {
  196.    dostr("Error ", 0);
  197.    fmtnum(SyslogErrno, 10, 0, 0, 0, 0);
  198.        }
  199.        else
  200.    dostr((char *)sys_errlist[SyslogErrno], 0);
  201. #endif /* HASSTRERROR */
  202.        break;
  203.        case '%': dopr_outch( ch ); continue;
  204.        default:
  205.        dostr(  "???????" , 0);
  206.        }
  207.        break;
  208.        default:
  209.        dopr_outch( ch );
  210.        break;
  211.        }
  212.        }
  213.        *output = 0;
  214. }
  215. void
  216. fmtstr(  value, ljust, len, zpad, maxwidth )
  217.        char *value;
  218.        int ljust, len, zpad, maxwidth;
  219. {
  220.        int padlen, strleng;     /* amount to pad */
  221.        if( value == 0 ){
  222.        value = "<NULL>";
  223.        }
  224.        for( strleng = 0; value[strleng]; ++ strleng ); /* strlen */
  225.        if (strleng > maxwidth && maxwidth)
  226.  strleng = maxwidth;
  227.        padlen = len - strleng;
  228.        if( padlen < 0 ) padlen = 0;
  229.        if( ljust ) padlen = -padlen;
  230.        while( padlen > 0 ) {
  231.        dopr_outch( ' ' );
  232.        --padlen;
  233.        }
  234.        dostr( value, maxwidth );
  235.        while( padlen < 0 ) {
  236.        dopr_outch( ' ' );
  237.        ++padlen;
  238.        }
  239. }
  240. void
  241. fmtnum(  value, base, dosign, ljust, len, zpad )
  242.        long value;
  243.        int base, dosign, ljust, len, zpad;
  244. {
  245.        int signvalue = 0;
  246.        unsigned long uvalue;
  247.        char convert[20];
  248.        int place = 0;
  249.        int padlen = 0; /* amount to pad */
  250.        int caps = 0;
  251.        /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %dn",
  252.        value, base, dosign, ljust, len, zpad )); */
  253.        uvalue = value;
  254.        if( dosign ){
  255.        if( value < 0 ) {
  256.        signvalue = '-';
  257.        uvalue = -value;
  258.        }
  259.        }
  260.        if( base < 0 ){
  261.        caps = 1;
  262.        base = -base;
  263.        }
  264.        do{
  265.        convert[place++] =
  266.        (caps? "0123456789ABCDEF":"0123456789abcdef")
  267. [uvalue % (unsigned)base  ];
  268.        uvalue = (uvalue / (unsigned)base );
  269.        }while(uvalue);
  270.        convert[place] = 0;
  271.        padlen = len - place;
  272.        if( padlen < 0 ) padlen = 0;
  273.        if( ljust ) padlen = -padlen;
  274.        /* DEBUGP(( "str '%s', place %d, sign %c, padlen %dn",
  275.        convert,place,signvalue,padlen)); */
  276.        if( zpad && padlen > 0 ){
  277.        if( signvalue ){
  278.        dopr_outch( signvalue );
  279.        --padlen;
  280.        signvalue = 0;
  281.        }
  282.        while( padlen > 0 ){
  283.        dopr_outch( zpad );
  284.        --padlen;
  285.        }
  286.        }
  287.        while( padlen > 0 ) {
  288.        dopr_outch( ' ' );
  289.        --padlen;
  290.        }
  291.        if( signvalue ) dopr_outch( signvalue );
  292.        while( place > 0 ) dopr_outch( convert[--place] );
  293.        while( padlen < 0 ){
  294.        dopr_outch( ' ' );
  295.        ++padlen;
  296.        }
  297. }
  298. void
  299. dostr( str , cut)
  300.      char *str;
  301.      int cut;
  302. {
  303.   if (cut) {
  304.     while(*str && cut-- > 0) dopr_outch(*str++);
  305.   } else {
  306.     while(*str) dopr_outch(*str++);
  307.   }
  308. }
  309. void
  310. dopr_outch( c )
  311.        int c;
  312. {
  313. #if 0
  314.        if( iscntrl(c) && c != 'n' && c != 't' ){
  315.        c = '@' + (c & 0x1F);
  316.        if( DoprEnd == 0 || output < DoprEnd )
  317.        *output++ = '^';
  318.        }
  319. #endif /* 0 */
  320.        if( DoprEnd == 0 || output < DoprEnd )
  321.        *output++ = c;
  322.        else
  323. SnprfOverflow++;
  324. }
  325. /*
  326. **  QUAD_TO_STRING -- Convert a quad type to a string.
  327. **
  328. ** Convert a quad type to a string.  This must be done
  329. ** separately as %lld/%qd are not supported by snprint()
  330. ** and adding support would slow down systems which only
  331. ** emulate the data type.
  332. **
  333. ** Parameters:
  334. ** value -- number to convert to a string.
  335. **
  336. ** Returns:
  337. ** pointer to a string.
  338. */
  339. char *
  340. quad_to_string(value)
  341. QUAD_T value;
  342. {
  343. char *formatstr;
  344. static char buf[64];
  345. /*
  346. **  Use sprintf() instead of snprintf() since snprintf()
  347. **  does not support %qu or %llu.  The buffer is large enough
  348. **  to hold the string so there is no danger of buffer
  349. **  overflow.
  350. */
  351. #if NEED_PERCENTQ
  352. formatstr = "%qu";
  353. #else /* NEED_PERCENTQ */
  354. formatstr = "%llu";
  355. #endif /* NEED_PERCENTQ */
  356. sprintf(buf, formatstr, value);
  357. return buf;
  358. }
  359. /*
  360. **  SHORTENSTRING -- return short version of a string
  361. **
  362. ** If the string is already short, just return it.  If it is too
  363. ** long, return the head and tail of the string.
  364. **
  365. ** Parameters:
  366. ** s -- the string to shorten.
  367. ** m -- the max length of the string (strlen()).
  368. **
  369. ** Returns:
  370. ** Either s or a short version of s.
  371. */
  372. char *
  373. shortenstring(s, m)
  374. register const char *s;
  375. int m;
  376. {
  377. int l;
  378. static char buf[MAXSHORTSTR + 1];
  379. l = strlen(s);
  380. if (l < m)
  381. return (char *) s;
  382. if (m > MAXSHORTSTR)
  383. m = MAXSHORTSTR;
  384. else if (m < 10)
  385. {
  386. if (m < 5)
  387. {
  388. (void) strlcpy(buf, s, m + 1);
  389. return buf;
  390. }
  391. (void) strlcpy(buf, s, m - 2);
  392. (void) strlcat(buf, "...", sizeof buf);
  393. return buf;
  394. }
  395. m = (m - 3) / 2;
  396. (void) strlcpy(buf, s, m + 1);
  397. (void) strlcat(buf, "...", sizeof buf);
  398. (void) strlcat(buf, s + l - m, sizeof buf);
  399. return buf;
  400. }