source: trunk/third/sendmail/src/snprintf.c @ 12554

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