Code

fixes for using POSIX return codes
[nagiosplug.git] / plugins / snprintf.c
1 /*
2  * Copyright (c) 1983, 1995, 1996 Eric P. Allman
3  * Copyright (c) 1988, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by the University of
17  *      California, Berkeley and its contributors.
18  * 4. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
35 /* Some changes made by bbraun@synack.net for use with xinetd */
37 #if !defined(HAVE_SNPRINTF)
39 /* Extracted from sendmail 8.8.5 */
40 #ifndef lint
41 static char sccsid[] = "@(#)$Id$ excerpted from conf.c 8.333 (Berkeley) 1/21/97";
42 #endif /* not lint */
43 # ifdef __STDC__
44 #include <stdio.h>
45 #include <stdlib.h>
47 #ifndef __P
48 #define __P(p)  p
49 #endif
51 #include <stdarg.h>
52 #define VA_LOCAL_DECL   va_list ap;
53 #define VA_START(f)     va_start(ap, f)
54 #define VA_END          va_end(ap)
56 #else
58 #include <sys/types.h>
59 #include <stdio.h>
61 #ifndef __P
62 #define __P(p)  ()
63 #endif
65 #include <varargs.h>
66 #define VA_LOCAL_DECL   va_list ap;
67 #define VA_START(f)     va_start(ap)
68 #define VA_END          va_end(ap)
70 #endif
71 /*
72 **  SNPRINTF, VSNPRINT -- counted versions of printf
73 **
74 **      These versions have been grabbed off the net.  They have been
75 **      cleaned up to compile properly and support for .precision and
76 **      %lx has been added.
77 */
79 /**************************************************************
80  * Original:
81  * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
82  * A bombproof version of doprnt (dopr) included.
83  * Sigh.  This sort of thing is always nasty do deal with.  Note that
84  * the version here does not include floating point...
85  *
86  * snprintf() is used instead of sprintf() as it does limit checks
87  * for string length.  This covers a nasty loophole.
88  *
89  * The other functions are there to prevent NULL pointers from
90  * causing nast effects.
91  **************************************************************/
93 /*static char _id[] = "$Id$";*/
94 static void dopr();
95 static char *end;
96 #ifndef _SCO_DS
97 /* VARARGS3 */
98 int
99 # ifdef __STDC__
100 snprintf(char *str, size_t count, const char *fmt, ...)
101 # else
102 snprintf(str, count, fmt, va_alist)
103         char *str;
104         size_t count;
105         char *fmt;
106         va_dcl
107 #endif
109         int len;
110         VA_LOCAL_DECL
112         VA_START(fmt);
113         len = vsnprintf(str, count, fmt, ap);
114         VA_END;
115         return len;
117 #endif 
119 # ifndef luna2
120 int
121 # ifdef __STDC__
122 vsnprintf(char *str, size_t count, const char *fmt, va_list args)
123 #else
124 vsnprintf(str, count, fmt, args)
125         char *str;
126         int count;
127         char *fmt;
128         va_list args;
129 #endif
131         str[0] = 0;
132         end = str + count - 1;
133         dopr( str, fmt, args );
134         if (count > 0)
135                 end[0] = 0;
136         return strlen(str);
139 /*
140  * dopr(): poor man's version of doprintf
141  */
143 static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
144 static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
145 static void dostr __P(( char * , int ));
146 static char *output;
147 static void dopr_outch __P(( int c ));
149 static void
150 # ifdef __STDC__
151 dopr(char  * buffer, const char * format, va_list args )
152 #else
153 dopr( buffer, format, args )
154        char *buffer;
155        char *format;
156        va_list args;
157 #endif
159        int ch;
160        long value;
161        int longflag  = 0;
162        int pointflag = 0;
163        int maxwidth  = 0;
164        char *strvalue;
165        int ljust;
166        int len;
167        int zpad;
169        output = buffer;
170        while( (ch = *format++) ){
171                switch( ch ){
172                case '%':
173                        ljust = len = zpad = maxwidth = 0;
174                        longflag = pointflag = 0;
175                nextch:
176                        ch = *format++;
177                        switch( ch ){
178                        case 0:
179                                dostr( "**end of format**" , 0);
180                                return;
181                        case '-': ljust = 1; goto nextch;
182                        case '0': /* set zero padding if len not set */
183                                if(len==0 && !pointflag) zpad = '0';
184                        case '1': case '2': case '3':
185                        case '4': case '5': case '6':
186                        case '7': case '8': case '9':
187                                if (pointflag)
188                                  maxwidth = maxwidth*10 + ch - '0';
189                                else
190                                  len = len*10 + ch - '0';
191                                goto nextch;
192                        case '*': 
193                                if (pointflag)
194                                  maxwidth = va_arg( args, int );
195                                else
196                                  len = va_arg( args, int );
197                                goto nextch;
198                        case '.': pointflag = 1; goto nextch;
199                        case 'l': longflag = 1; goto nextch;
200                        case 'u': case 'U':
201                                /*fmtnum(value,base,dosign,ljust,len,zpad) */
202                                if( longflag ){
203                                        value = va_arg( args, long );
204                                } else {
205                                        value = va_arg( args, int );
206                                }
207                                fmtnum( value, 10,0, ljust, len, zpad ); break;
208                        case 'o': case 'O':
209                                /*fmtnum(value,base,dosign,ljust,len,zpad) */
210                                if( longflag ){
211                                        value = va_arg( args, long );
212                                } else {
213                                        value = va_arg( args, int );
214                                }
215                                fmtnum( value, 8,0, ljust, len, zpad ); break;
216                        case 'd': case 'D':
217                                if( longflag ){
218                                        value = va_arg( args, long );
219                                } else {
220                                        value = va_arg( args, int );
221                                }
222                                fmtnum( value, 10,1, ljust, len, zpad ); break;
223                        case 'x':
224                                if( longflag ){
225                                        value = va_arg( args, long );
226                                } else {
227                                        value = va_arg( args, int );
228                                }
229                                fmtnum( value, 16,0, ljust, len, zpad ); break;
230                        case 'X':
231                                if( longflag ){
232                                        value = va_arg( args, long );
233                                } else {
234                                        value = va_arg( args, int );
235                                }
236                                fmtnum( value,-16,0, ljust, len, zpad ); break;
237                        case 's':
238                                strvalue = va_arg( args, char *);
239                                if (maxwidth > 0 || !pointflag) {
240                                  if (pointflag && len > maxwidth)
241                                    len = maxwidth; /* Adjust padding */
242                                  fmtstr( strvalue,ljust,len,zpad, maxwidth);
243                                }
244                                break;
245                        case 'c':
246                                ch = va_arg( args, int );
247                                dopr_outch( ch ); break;
248                        case '%': dopr_outch( ch ); continue;
249                        default:
250                                dostr(  "???????" , 0);
251                        }
252                        break;
253                default:
254                        dopr_outch( ch );
255                        break;
256                }
257        }
258        *output = 0;
261 static void
262 fmtstr(  value, ljust, len, zpad, maxwidth )
263        char *value;
264        int ljust, len, zpad, maxwidth;
266        int padlen, strlen;     /* amount to pad */
268        if( value == 0 ){
269                value = "<NULL>";
270        }
271        for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */
272        if (strlen > maxwidth && maxwidth)
273          strlen = maxwidth;
274        padlen = len - strlen;
275        if( padlen < 0 ) padlen = 0;
276        if( ljust ) padlen = -padlen;
277        while( padlen > 0 ) {
278                dopr_outch( ' ' );
279                --padlen;
280        }
281        dostr( value, maxwidth );
282        while( padlen < 0 ) {
283                dopr_outch( ' ' );
284                ++padlen;
285        }
288 static void
289 fmtnum(  value, base, dosign, ljust, len, zpad )
290        long value;
291        int base, dosign, ljust, len, zpad;
293        int signvalue = 0;
294        unsigned long uvalue;
295        char convert[20];
296        int place = 0;
297        int padlen = 0; /* amount to pad */
298        int caps = 0;
300        /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
301                value, base, dosign, ljust, len, zpad )); */
302        uvalue = value;
303        if( dosign ){
304                if( value < 0 ) {
305                        signvalue = '-';
306                        uvalue = -value;
307                }
308        }
309        if( base < 0 ){
310                caps = 1;
311                base = -base;
312        }
313        do{
314                convert[place++] =
315                        (caps? "0123456789ABCDEF":"0123456789abcdef")
316                         [uvalue % (unsigned)base  ];
317                uvalue = (uvalue / (unsigned)base );
318        }while(uvalue);
319        convert[place] = 0;
320        padlen = len - place;
321        if( padlen < 0 ) padlen = 0;
322        if( ljust ) padlen = -padlen;
323        /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
324                convert,place,signvalue,padlen)); */
325        if( zpad && padlen > 0 ){
326                if( signvalue ){
327                        dopr_outch( signvalue );
328                        --padlen;
329                        signvalue = 0;
330                }
331                while( padlen > 0 ){
332                        dopr_outch( zpad );
333                        --padlen;
334                }
335        }
336        while( padlen > 0 ) {
337                dopr_outch( ' ' );
338                --padlen;
339        }
340        if( signvalue ) dopr_outch( signvalue );
341        while( place > 0 ) dopr_outch( convert[--place] );
342        while( padlen < 0 ){
343                dopr_outch( ' ' );
344                ++padlen;
345        }
348 static void
349 dostr( str , cut)
350      char *str;
351      int cut;
353   if (cut) {
354     while(*str && cut-- > 0) dopr_outch(*str++);
355   } else {
356     while(*str) dopr_outch(*str++);
357   }
360 static void
361 dopr_outch( c )
362        int c;
364 #if 0
365        if( iscntrl(c) && c != '\n' && c != '\t' ){
366                c = '@' + (c & 0x1F);
367                if( end == 0 || output < end )
368                        *output++ = '^';
369        }
370 #endif
371        if( end == 0 || output < end )
372                *output++ = c;
375 # endif /* !luna2 */
377 #endif /* HAVE_SNPRINTF */