snprintf.c
上传用户:tjescc
上传日期:2021-02-23
资源大小:419k
文件大小:13k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /* taken from nmap -rd */
  2. /* Note -- this file was obtained from tcpdump-2000-9-17 CVS snapshot
  3.    ( www.tcpdump.org).  It has been modified slightly for compatability
  4.    with libnbase.  Modification etails may be in the nbase CHANGELOG 
  5.     - fyodor@insecure.org
  6.  */
  7. /*
  8.  * Copyright (c) 1995-1999 Kungliga Tekniska H鰃skolan
  9.  * (Royal Institute of Technology, Stockholm, Sweden).
  10.  * All rights reserved.
  11.  * 
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 
  16.  * 1. Redistributions of source code must retain the above copyright
  17.  *    notice, this list of conditions and the following disclaimer.
  18.  * 
  19.  * 2. Redistributions in binary form must reproduce the above copyright
  20.  *    notice, this list of conditions and the following disclaimer in the
  21.  *    documentation and/or other materials provided with the distribution.
  22.  * 
  23.  * 3. Neither the name of the Institute nor the names of its contributors
  24.  *    may be used to endorse or promote products derived from this software
  25.  *    without specific prior written permission.
  26.  * 
  27.  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  28.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  31.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  32.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  33.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  34.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  35.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  36.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  37.  * SUCH DAMAGE.
  38.  */
  39. /* $Id: snprintf.c,v 1.1 2003/01/27 10:49:59 renaud Exp $ */
  40. #include <includes.h>
  41. #ifndef HAVE_SNPRINTF
  42. #ifndef min
  43. #define min(a,b) ((a)>(b)?(b):(a))
  44. #endif
  45. #ifndef max
  46. #define max(a,b) ((b)>(a)?(b):(a))
  47. #endif
  48. enum format_flags {
  49.     minus_flag     =  1,
  50.     plus_flag      =  2,
  51.     space_flag     =  4,
  52.     alternate_flag =  8,
  53.     zero_flag      = 16
  54. };
  55. /*
  56.  * Common state
  57.  */
  58. struct state {
  59.   unsigned char *str;
  60.   unsigned char *s;
  61.   unsigned char *theend;
  62.   size_t sz;
  63.   size_t max_sz;
  64.   int (*append_char)(struct state *, unsigned char);
  65.   int (*reserve)(struct state *, size_t);
  66.   /* XXX - methods */
  67. };
  68. #ifndef HAVE_VSNPRINTF
  69. static int
  70. sn_reserve (struct state *state, size_t n)
  71. {
  72.   return state->s + n > state->theend;
  73. }
  74. static int
  75. sn_append_char (struct state *state, unsigned char c)
  76. {
  77.   if (sn_reserve (state, 1)) {
  78.     return 1;
  79.   } else {
  80.     *state->s++ = c;
  81.     return 0;
  82.   }
  83. }
  84. #endif
  85. static int
  86. as_reserve (struct state *state, size_t n)
  87. {
  88.   if (state->s + n > state->theend) {
  89.     int off = state->s - state->str;
  90.     unsigned char *tmp;
  91.     if (state->max_sz && state->sz >= state->max_sz)
  92.       return 1;
  93.     state->sz = max(state->sz * 2, state->sz + n);
  94.     if (state->max_sz)
  95.       state->sz = min(state->sz, state->max_sz);
  96.     tmp = realloc (state->str, state->sz);
  97.     if (tmp == NULL)
  98.       return 1;
  99.     state->str = tmp;
  100.     state->s = state->str + off;
  101.     state->theend = state->str + state->sz - 1;
  102.   }
  103.   return 0;
  104. }
  105. static int
  106. as_append_char (struct state *state, unsigned char c)
  107. {
  108.   if(as_reserve (state, 1))
  109.     return 1;
  110.   else {
  111.     *state->s++ = c;
  112.     return 0;
  113.   }
  114. }
  115. static int
  116. append_number(struct state *state,
  117.       unsigned long num, unsigned base, char *rep,
  118.       int width, int prec, int flags, int minusp)
  119. {
  120.   int len = 0;
  121.   int i;
  122.   /* given precision, ignore zero flag */
  123.   if(prec != -1)
  124.     flags &= ~zero_flag;
  125.   else
  126.     prec = 1;
  127.   /* zero value with zero precision -> "" */
  128.   if(prec == 0 && num == 0)
  129.     return 0;
  130.   do{
  131.     if((*state->append_char)(state, rep[num % base]))
  132.       return 1;
  133.     len++;
  134.     num /= base;
  135.   }while(num);
  136.   prec -= len;
  137.   /* pad with prec zeros */
  138.   while(prec-- > 0){
  139.     if((*state->append_char)(state, '0'))
  140.       return 1;
  141.     len++;
  142.   }
  143.   /* add length of alternate prefix (added later) to len */
  144.   if(flags & alternate_flag && (base == 16 || base == 8))
  145.     len += base / 8;
  146.   /* pad with zeros */
  147.   if(flags & zero_flag){
  148.     width -= len;
  149.     if(minusp || (flags & space_flag) || (flags & plus_flag))
  150.       width--;
  151.     while(width-- > 0){
  152.       if((*state->append_char)(state, '0'))
  153. return 1;
  154.       len++;
  155.     }
  156.   }
  157.   /* add alternate prefix */
  158.   if(flags & alternate_flag && (base == 16 || base == 8)){
  159.     if(base == 16)
  160.       if((*state->append_char)(state, rep[10] + 23)) /* XXX */
  161. return 1;
  162.     if((*state->append_char)(state, '0'))
  163.       return 1;
  164.   }
  165.   /* add sign */
  166.   if(minusp){
  167.     if((*state->append_char)(state, '-'))
  168.       return 1;
  169.     len++;
  170.   } else if(flags & plus_flag) {
  171.     if((*state->append_char)(state, '+'))
  172.       return 1;
  173.     len++;
  174.   } else if(flags & space_flag) {
  175.     if((*state->append_char)(state, ' '))
  176.       return 1;
  177.     len++;
  178.   }
  179.   if(flags & minus_flag)
  180.     /* swap before padding with spaces */
  181.     for(i = 0; i < len / 2; i++){
  182.       char c = state->s[-i-1];
  183.       state->s[-i-1] = state->s[-len+i];
  184.       state->s[-len+i] = c;
  185.     }
  186.   width -= len;
  187.   while(width-- > 0){
  188.     if((*state->append_char)(state,  ' '))
  189.       return 1;
  190.     len++;
  191.   }
  192.   if(!(flags & minus_flag))
  193.     /* swap after padding with spaces */
  194.     for(i = 0; i < len / 2; i++){
  195.       char c = state->s[-i-1];
  196.       state->s[-i-1] = state->s[-len+i];
  197.       state->s[-len+i] = c;
  198.     }
  199.     
  200.   return 0;
  201. }
  202. static int
  203. append_string (struct state *state,
  204.        unsigned char *arg,
  205.        int width,
  206.        int prec,
  207.        int flags)
  208. {
  209.   if(prec != -1)
  210.     width -= prec;
  211.   else
  212.     width -= strlen((char *)arg);
  213.   if(!(flags & minus_flag))
  214.     while(width-- > 0)
  215.       if((*state->append_char) (state, ' '))
  216. return 1;
  217.   if (prec != -1) {
  218.     while (*arg && prec--)
  219.       if ((*state->append_char) (state, *arg++))
  220. return 1;
  221.   } else {
  222.     while (*arg)
  223.       if ((*state->append_char) (state, *arg++))
  224. return 1;
  225.   }
  226.   if(flags & minus_flag)
  227.     while(width-- > 0)
  228.       if((*state->append_char) (state, ' '))
  229. return 1;
  230.   return 0;
  231. }
  232. static int
  233. append_char(struct state *state,
  234.     unsigned char arg,
  235.     int width,
  236.     int flags)
  237. {
  238.   while(!(flags & minus_flag) && --width > 0)
  239.     if((*state->append_char) (state, ' '))
  240.       return 1;
  241.     
  242.   if((*state->append_char) (state, arg))
  243.     return 1;
  244.   while((flags & minus_flag) && --width > 0)
  245.     if((*state->append_char) (state, ' '))
  246.       return 1;
  247.     
  248.   return 0;
  249. }
  250. /*
  251.  * This can't be made into a function...
  252.  */
  253. #define PARSE_INT_FORMAT(res, arg, unsig) 
  254. if (long_flag) 
  255.      res = (unsig long)va_arg(arg, unsig long); 
  256. else if (short_flag) 
  257.      res = (unsig short)va_arg(arg, unsig int); 
  258. else 
  259.      res = (unsig int)va_arg(arg, unsig int)
  260. /*
  261.  * zyxprintf - return 0 or -1
  262.  */
  263. static int
  264. xyzprintf (struct state *state, const char *char_format, va_list ap)
  265. {
  266.   const unsigned char *format = (const unsigned char *)char_format;
  267.   unsigned char c;
  268.   while((c = *format++)) {
  269.     if (c == '%') {
  270.       int flags      = 0;
  271.       int width      = 0;
  272.       int prec       = -1;
  273.       int long_flag  = 0;
  274.       int short_flag = 0;
  275.       /* flags */
  276.       while((c = *format++)){
  277. if(c == '-')
  278.   flags |= minus_flag;
  279. else if(c == '+')
  280.   flags |= plus_flag;
  281. else if(c == ' ')
  282.   flags |= space_flag;
  283. else if(c == '#')
  284.   flags |= alternate_flag;
  285. else if(c == '0')
  286.   flags |= zero_flag;
  287. else
  288.   break;
  289.       }
  290.       
  291.       if((flags & space_flag) && (flags & plus_flag))
  292. flags ^= space_flag;
  293.       if((flags & minus_flag) && (flags & zero_flag))
  294. flags ^= zero_flag;
  295.       /* width */
  296.       if (isdigit(c))
  297. do {
  298.   width = width * 10 + c - '0';
  299.   c = *format++;
  300. } while(isdigit(c));
  301.       else if(c == '*') {
  302. width = va_arg(ap, int);
  303. c = *format++;
  304.       }
  305.       /* precision */
  306.       if (c == '.') {
  307. prec = 0;
  308. c = *format++;
  309. if (isdigit(c))
  310.   do {
  311.     prec = prec * 10 + c - '0';
  312.     c = *format++;
  313.   } while(isdigit(c));
  314. else if (c == '*') {
  315.   prec = va_arg(ap, int);
  316.   c = *format++;
  317. }
  318.       }
  319.       /* size */
  320.       if (c == 'h') {
  321. short_flag = 1;
  322. c = *format++;
  323.       } else if (c == 'l') {
  324. long_flag = 1;
  325. c = *format++;
  326.       }
  327.       switch (c) {
  328.       case 'c' :
  329. if(append_char(state, va_arg(ap, int), width, flags))
  330.   return -1;
  331. break;
  332.       case 's' :
  333. if (append_string(state,
  334.   va_arg(ap, unsigned char*),
  335.   width,
  336.   prec, 
  337.   flags))
  338.   return -1;
  339. break;
  340.       case 'd' :
  341.       case 'i' : {
  342. long arg;
  343. unsigned long num;
  344. int minusp = 0;
  345. PARSE_INT_FORMAT(arg, ap, signed);
  346. if (arg < 0) {
  347.   minusp = 1;
  348.   num = -arg;
  349. } else
  350.   num = arg;
  351. if (append_number (state, num, 10, "0123456789",
  352.    width, prec, flags, minusp))
  353.   return -1;
  354. break;
  355.       }
  356.       case 'u' : {
  357. unsigned long arg;
  358. PARSE_INT_FORMAT(arg, ap, unsigned);
  359. if (append_number (state, arg, 10, "0123456789",
  360.    width, prec, flags, 0))
  361.   return -1;
  362. break;
  363.       }
  364.       case 'o' : {
  365. unsigned long arg;
  366. PARSE_INT_FORMAT(arg, ap, unsigned);
  367. if (append_number (state, arg, 010, "01234567",
  368.    width, prec, flags, 0))
  369.   return -1;
  370. break;
  371.       }
  372.       case 'x' : {
  373. unsigned long arg;
  374. PARSE_INT_FORMAT(arg, ap, unsigned);
  375. if (append_number (state, arg, 0x10, "0123456789abcdef",
  376.    width, prec, flags, 0))
  377.   return -1;
  378. break;
  379.       }
  380.       case 'X' :{
  381. unsigned long arg;
  382. PARSE_INT_FORMAT(arg, ap, unsigned);
  383. if (append_number (state, arg, 0x10, "0123456789ABCDEF",
  384.    width, prec, flags, 0))
  385.   return -1;
  386. break;
  387.       }
  388.       case 'p' : {
  389. unsigned long arg = (unsigned long)va_arg(ap, void*);
  390. if (append_number (state, arg, 0x10, "0123456789ABCDEF",
  391.    width, prec, flags, 0))
  392.   return -1;
  393. break;
  394.       }
  395.       case 'n' : {
  396. int *arg = va_arg(ap, int*);
  397. *arg = state->s - state->str;
  398. break;
  399.       }
  400.       case '' :
  401.   --format;
  402.   /* FALLTHROUGH */
  403.       case '%' :
  404. if ((*state->append_char)(state, c))
  405.   return -1;
  406. break;
  407.       default :
  408. if (   (*state->append_char)(state, '%')
  409.     || (*state->append_char)(state, c))
  410.   return -1;
  411. break;
  412.       }
  413.     } else
  414.       if ((*state->append_char) (state, c))
  415. return -1;
  416.   }
  417.   return 0;
  418. }
  419. #ifndef HAVE_SNPRINTF
  420. int
  421. snprintf (char *str, size_t sz, const char *format, ...)
  422. {
  423.   va_list args;
  424.   int ret;
  425.   va_start(args, format);
  426.   ret = vsnprintf (str, sz, format, args);
  427. #ifdef PARANOIA
  428.   {
  429.     int ret2;
  430.     char *tmp;
  431.     tmp = malloc (sz);
  432.     if (tmp == NULL)
  433.       abort ();
  434.     ret2 = vsprintf (tmp, format, args);
  435.     if (ret != ret2 || strcmp(str, tmp))
  436.       abort ();
  437.     free (tmp);
  438.   }
  439. #endif
  440.   va_end(args);
  441.   return ret;
  442. }
  443. #endif
  444. #ifndef HAVE_VASNPRINTF
  445. int
  446. vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
  447. {
  448.   int st;
  449.   size_t len;
  450.   struct state state;
  451.   state.max_sz = max_sz;
  452.   state.sz     = 1;
  453.   state.str    = malloc(state.sz);
  454.   if (state.str == NULL) {
  455.     *ret = NULL;
  456.     return -1;
  457.   }
  458.   state.s = state.str;
  459.   state.theend = state.s + state.sz - 1;
  460.   state.append_char = as_append_char;
  461.   state.reserve     = as_reserve;
  462.   st = xyzprintf (&state, format, args);
  463.   if (st) {
  464.     free (state.str);
  465.     *ret = NULL;
  466.     return -1;
  467.   } else {
  468.     char *tmp;
  469.     *state.s = '';
  470.     len = state.s - state.str;
  471.     tmp = realloc (state.str, len+1);
  472.     if (tmp == NULL) {
  473.       free (state.str);
  474.       *ret = NULL;
  475.       return -1;
  476.     }
  477.     *ret = tmp;
  478.     return len;
  479.   }
  480. }
  481. #endif
  482. #ifndef HAVE_VASPRINTF
  483. int
  484. vasprintf (char **ret, const char *format, va_list args)
  485. {
  486.   return vasnprintf (ret, 0, format, args);
  487. }
  488. #endif
  489. #ifndef HAVE_ASPRINTF
  490. int
  491. asprintf (char **ret, const char *format, ...)
  492. {
  493.   va_list args;
  494.   int val;
  495.   va_start(args, format);
  496.   val = vasprintf (ret, format, args);
  497. #ifdef PARANOIA
  498.   {
  499.     int ret2;
  500.     char *tmp;
  501.     tmp = malloc (val + 1);
  502.     if (tmp == NULL)
  503.       abort ();
  504.     ret2 = vsprintf (tmp, format, args);
  505.     if (val != ret2 || strcmp(*ret, tmp))
  506.       abort ();
  507.     free (tmp);
  508.   }
  509. #endif
  510.   va_end(args);
  511.   return val;
  512. }
  513. #endif
  514. #ifndef HAVE_ASNPRINTF
  515. int
  516. asnprintf (char **ret, size_t max_sz, const char *format, ...)
  517. {
  518.   va_list args;
  519.   int val;
  520.   va_start(args, format);
  521.   val = vasnprintf (ret, max_sz, format, args);
  522. #ifdef PARANOIA
  523.   {
  524.     int ret2;
  525.     char *tmp;
  526.     tmp = malloc (val + 1);
  527.     if (tmp == NULL)
  528.       abort ();
  529.     ret2 = vsprintf (tmp, format, args);
  530.     if (val != ret2 || strcmp(*ret, tmp))
  531.       abort ();
  532.     free (tmp);
  533.   }
  534. #endif
  535.   va_end(args);
  536.   return val;
  537. }
  538. #endif
  539. #ifndef HAVE_VSNPRINTF
  540. int
  541. vsnprintf (char *str, size_t sz, const char *format, va_list args)
  542. {
  543.   struct state state;
  544.   int ret;
  545.   unsigned char *ustr = (unsigned char *)str;
  546.   state.max_sz = 0;
  547.   state.sz     = sz;
  548.   state.str    = ustr;
  549.   state.s      = ustr;
  550.   state.theend = ustr + sz - 1;
  551.   state.append_char = sn_append_char;
  552.   state.reserve     = sn_reserve;
  553.   ret = xyzprintf (&state, format, args);
  554.   *state.s = '';
  555.   if (ret)
  556.     return sz;
  557.   else
  558.     return state.s - state.str;
  559. }
  560. #endif
  561. #endif