2 * snpf.c -- snprintf() empulation functions for lsof library
5 * Purdue University Computing Center
9 * Copyright 2000 Purdue Research Foundation, West Lafayette, Indiana
10 * 47907. All rights reserved.
12 * Written by Victor A. Abell
14 * This software is not subject to any license of the American Telephone
15 * and Telegraph Company or the Regents of the University of California.
17 * This software has been adapted from snprintf.c in sendmail 8.9.3. It
18 * is subject to the sendmail copyright statements listed below, and the
19 * sendmail licensing terms stated in the sendmail LICENSE file comment
20 * section of this file.
22 * Permission is granted to anyone to use this software for any purpose on
23 * any computer system, and to alter it and redistribute it freely, subject
24 * to the following restrictions:
26 * 1. Neither the authors nor Purdue University are responsible for any
27 * consequences of the use of this software.
29 * 2. The origin of this software must not be misrepresented, either by
30 * explicit claim or by omission. Credit to the authors and Purdue
31 * University must appear in documentation and sources.
33 * 3. Altered versions must be plainly marked as such, and must not be
34 * misrepresented as being the original software.
36 * 4. This notice may not be removed or altered.
39 #include "../machine.h"
44 * Sendmail copyright statements:
46 * Copyright (c) 1998 Sendmail, Inc. All rights reserved.
47 * Copyright (c) 1997 Eric P. Allman. All rights reserved.
48 * Copyright (c) 1988, 1993
49 * The Regents of the University of California. All rights reserved.
51 * By using this file, you agree to the terms and conditions set
52 * forth in the LICENSE file which can be found at the top level of
53 * the sendmail distribution.
55 * The LICENSE file may be found in the following comment section.
60 * Begin endmail LICENSE file.
64 The following license terms and conditions apply, unless a different
65 license is obtained from Sendmail, Inc., 1401 Park Avenue, Emeryville, CA
66 94608, or by electronic mail at license@sendmail.com.
70 Use, Modification and Redistribution (including distribution of any
71 modified or derived work) in source and binary forms is permitted only if
72 each of the following conditions is met:
74 1. Redistributions qualify as "freeware" or "Open Source Software" under
75 one of the following terms:
77 (a) Redistributions are made at no charge beyond the reasonable cost of
78 materials and delivery.
80 (b) Redistributions are accompanied by a copy of the Source Code or by an
81 irrevocable offer to provide a copy of the Source Code for up to three
82 years at the cost of materials and delivery. Such redistributions
83 must allow further use, modification, and redistribution of the Source
84 Code under substantially the same terms as this license. For the
85 purposes of redistribution "Source Code" means the complete source
86 code of sendmail including all modifications.
88 Other forms of redistribution are allowed only under a separate royalty-
89 free agreement permitting such redistribution subject to standard
90 commercial terms and conditions. A copy of such agreement may be
91 obtained from Sendmail, Inc. at the above address.
93 2. Redistributions of source code must retain the copyright notices as they
94 appear in each source code file, these license terms, and the
95 disclaimer/limitation of liability set forth as paragraph 6 below.
97 3. Redistributions in binary form must reproduce the Copyright Notice,
98 these license terms, and the disclaimer/limitation of liability set
99 forth as paragraph 6 below, in the documentation and/or other materials
100 provided with the distribution. For the purposes of binary distribution
101 the "Copyright Notice" refers to the following language:
102 "Copyright (c) 1998 Sendmail, Inc. All rights reserved."
104 4. Neither the name of Sendmail, Inc. nor the University of California nor
105 the names of their contributors may be used to endorse or promote
106 products derived from this software without specific prior written
107 permission. The name "sendmail" is a trademark of Sendmail, Inc.
109 5. All redistributions must comply with the conditions imposed by the
110 University of California on certain embedded code, whose copyright
111 notice and conditions for redistribution are as follows:
113 (a) Copyright (c) 1988, 1993 The Regents of the University of
114 California. All rights reserved.
116 (b) Redistribution and use in source and binary forms, with or without
117 modification, are permitted provided that the following conditions
120 (i) Redistributions of source code must retain the above copyright
121 notice, this list of conditions and the following disclaimer.
123 (ii) Redistributions in binary form must reproduce the above
124 copyright notice, this list of conditions and the following
125 disclaimer in the documentation and/or other materials provided
126 with the distribution.
128 (iii) All advertising materials mentioning features or use of this
129 software must display the following acknowledgement: "This
130 product includes software developed by the University of
131 California, Berkeley and its contributors."
133 (iv) Neither the name of the University nor the names of its
134 contributors may be used to endorse or promote products derived
135 from this software without specific prior written permission.
137 6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY
138 SENDMAIL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
139 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
140 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
141 NO EVENT SHALL SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF
142 CALIFORNIA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
143 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
144 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
145 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
146 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
147 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
148 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
150 (Version 8.6, last updated 6/24/1998)
152 * End endmail LICENSE file.
157 * If "ll" format support is not possible -- e.g., the long long type isn't
158 * supported -- define HAS_NO_LONG_LONG.
162 static char copyright[] =
163 "@(#) Copyright 2000 Purdue Research Foundation.\nAll rights reserved.\n";
164 # endif /* !defined(lint) */
168 #if defined(__STDC__)
169 #define _PROTOTYPE(function, params) function params
170 #else /* !defined(__STDC__) */
171 #define _PROTOTYPE(function, params) function()
172 #endif /* defined(__STDC__) */
176 ** SNPRINTF, VSNPRINT -- counted versions of printf
178 ** These versions have been grabbed off the net. They have been
179 ** cleaned up to compile properly and support for .precision and
180 ** %lx has been added.
183 /**************************************************************
185 * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
186 * A bombproof version of doprnt (dopr) included.
187 * Sigh. This sort of thing is always nasty do deal with. Note that
188 * the version here does not include floating point...
190 * snprintf() is used instead of sprintf() as it does limit checks
191 * for string length. This covers a nasty loophole.
193 * The other functions are there to prevent NULL pointers from
194 * causing nast effects.
195 **************************************************************/
197 /*static char _id[] = "$Id: snpf.c,v 1.5 2008/10/21 16:13:23 abe Exp $";*/
201 * Local function prototypes
204 _PROTOTYPE(static void dopr,(char *bp, char *ep, char *fmt, va_list args));
205 _PROTOTYPE(static void dopr_outch,(char **bp, char *ep, int c));
206 _PROTOTYPE(static void dostr,(char **bp, char *ep, char *str, int));
208 # if !defined(HAS_NO_LONG_LONG)
209 _PROTOTYPE(static void fmtllnum,(char **bp, char *ep, long long value,
210 int base, int dosign, int ljust, int len,
212 # endif /* !defined(HAS_NO_LONG_LONG) */
214 _PROTOTYPE(static void fmtnum,(char **bp, char *ep, long value, int base,
215 int dosign, int ljust, int len, int zpad));
216 _PROTOTYPE(static void fmtstr,(char **bp, char *ep, char *value, int ljust,
229 * snpf() -- count-controlled sprintf()
234 va_dcl /* requires at least three arguments:
235 * bp = receiving buffer pointer
236 * ct = length of buffer
237 * fmt = format string
245 bp = va_arg(args, char *);
246 ct = va_arg(args, int);
247 fmt = va_arg(args, char *);
248 len = vsnpf(bp, ct, fmt, args);
255 * vsnpf() -- count-controlled vsprintf()
259 vsnpf(str, count, fmt, args)
260 char *str; /* result buffer */
261 int count; /* size of buffer */
262 char *fmt; /* format */
263 va_list args; /* variable length argument list */
265 char *ep = str + count - 1;
268 (void) dopr(str, ep, fmt, args);
276 * dopr() -- poor man's version of doprintf
281 dopr(bp, ep, fmt, args)
282 char *bp; /* buffer start */
283 char *ep; /* buffer end (start + length - 1) */
284 char *fmt; /* format */
285 va_list args; /* variable length argument list */
289 int ebufl = (int)(sizeof(ebuf) - 1);
292 int longlongflag = 0;
301 # if !defined(HAS_NO_LONG_LONG)
303 # endif /* !defined(HAS_NO_LONG_LONG) */
306 while((ch = *fmt++)) {
309 ljust = len = zpad = zxflag = maxwidth = 0;
310 longflag = longlongflag = pointflag = 0;
317 dostr(&bp, ep, "**end of format**" , 0);
322 case '0': /* set zero padding if len not set */
323 if ((len == 0) && !pointflag)
335 maxwidth = (maxwidth * 10) + (int)(ch - '0');
337 len = (len * 10) + (int)(ch - '0');
341 maxwidth = va_arg(args, int);
343 len = va_arg(args, int);
363 # if !defined(HAS_NO_LONG_LONG)
364 llvalue = va_arg(args, long long);
365 (void) fmtllnum(&bp,ep,llvalue,10,0,ljust,len,zpad);
366 # else /* defined(HAS_NO_LONG_LONG) */
367 (void) strncpy(ebuf, "ll is unsupported", ebufl);
368 ebuf[(int)ebufl] = '\0';
369 (void) dostr(&bp, ep, ebuf, 0);
370 # endif /* !defined(HAS_NO_LONG_LONG) */
375 value = va_arg(args, long);
377 value = va_arg(args, int);
378 (void) fmtnum(&bp, ep, value, 10,0, ljust, len, zpad);
384 # if !defined(HAS_NO_LONG_LONG)
385 llvalue = va_arg(args, long long);
386 (void) fmtllnum(&bp,ep,llvalue,8,0,ljust,len,zpad);
387 # else /* defined(HAS_NO_LONG_LONG) */
388 (void) strncpy(ebuf, "ll is unsupported", ebufl);
389 ebuf[(int)ebufl] = '\0';
390 (void) dostr(&bp, ep, ebuf, 0);
391 # endif /* !defined(HAS_NO_LONG_LONG) */
396 value = va_arg(args, long);
398 value = va_arg(args, int);
399 (void) fmtnum(&bp, ep, value, 8,0, ljust, len, zpad);
405 # if !defined(HAS_NO_LONG_LONG)
406 llvalue = va_arg(args, long long);
407 (void) fmtllnum(&bp,ep,llvalue,10,1,ljust,len,zpad);
408 # else /* defined(HAS_NO_LONG_LONG) */
409 (void) strncpy(ebuf, "ll is unsupported", ebufl);
410 ebuf[(int)ebufl] = '\0';
411 (void) dostr(&bp, ep, ebuf, 0);
412 # endif /* !defined(HAS_NO_LONG_LONG) */
417 value = va_arg(args, long);
419 value = va_arg(args, int);
420 (void) fmtnum(&bp, ep, value, 10,1, ljust, len, zpad);
425 # if !defined(HAS_NO_LONG_LONG)
426 llvalue = va_arg(args, long long);
427 if (zxflag && llvalue) {
428 (void) dostr(&bp, ep, "0x", 0);
432 (void) fmtllnum(&bp,ep,llvalue,16,0,ljust,len,zpad);
433 # else /* defined(HAS_NO_LONG_LONG) */
434 (void) strncpy(ebuf, "ll is unsupported", ebufl);
435 ebuf[(int)ebufl] = '\0';
436 (void) dostr(&bp, ep, ebuf, 0);
437 # endif /* !defined(HAS_NO_LONG_LONG) */
442 value = va_arg(args, long);
444 value = va_arg(args, int);
445 if (zxflag && value) {
446 (void) dostr(&bp, ep, "0x", 0);
450 (void) fmtnum(&bp, ep, value, 16,0, ljust, len, zpad);
455 # if !defined(HAS_NO_LONG_LONG)
456 llvalue = va_arg(args, long long);
457 if (zxflag && llvalue) {
458 (void) dostr(&bp, ep, "0x", 0);
462 (void) fmtllnum(&bp,ep,llvalue,-16,0,ljust,len,zpad);
463 # else /* defined(HAS_NO_LONG_LONG) */
464 (void) strncpy(ebuf, "ll is unsupported", ebufl);
465 ebuf[(int)ebufl] = '\0';
466 (void) dostr(&bp, ep, ebuf, 0);
467 # endif /* !defined(HAS_NO_LONG_LONG) */
472 value = va_arg(args, long);
474 value = va_arg(args, int);
475 if (zxflag && value) {
476 (void) dostr(&bp, ep, "0x", 0);
480 (void) fmtnum(&bp, ep, value,-16,0, ljust, len, zpad);
483 strvalue = va_arg(args, char *);
484 if (maxwidth > 0 || !pointflag) {
485 if (pointflag && len > maxwidth)
486 len = maxwidth; /* Adjust padding */
487 (void) fmtstr(&bp, ep, strvalue, ljust, len, zpad,
492 ch = va_arg(args, int);
493 dopr_outch(&bp, ep, ch);
496 (void) dopr_outch(&bp, ep, ch);
500 (void) strncpy(&ebuf[1], " is unsupported", ebufl);
501 ebuf[(int)ebufl] = '\0';
502 (void) dostr(&bp, ep, ebuf, 0);
506 (void) dopr_outch(&bp, ep, ch);
514 # if !defined(HAS_NO_LONG_LONG)
516 * fmtllnum() -- format long long number for output
520 fmtllnum(bp, ep, value, base, dosign, ljust, len, zpad)
521 char **bp; /* current buffer pointer */
522 char *ep; /* end of buffer (-1) */
523 long long value; /* number to format */
524 int base; /* number base */
525 int dosign; /* sign request */
526 int ljust; /* left justfication request */
527 int len; /* length request */
528 int zpad; /* zero padding request */
531 unsigned long long uvalue;
534 int padlen = 0; /* amount to pad */
550 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
551 [uvalue % (unsigned)base];
552 uvalue = (uvalue / (unsigned)base);
553 } while (uvalue && (place < (int)(sizeof(convert) - 1)));
555 padlen = len - place;
560 if (zpad && padlen > 0) {
562 (void) dopr_outch(bp, ep, signvalue);
567 (void) dopr_outch(bp, ep, zpad);
572 (void) dopr_outch(bp, ep, ' ');
576 (void) dopr_outch(bp, ep, signvalue);
578 (void) dopr_outch(bp, ep, convert[--place]);
580 (void) dopr_outch(bp, ep, ' ');
584 # endif /* !defined(HAS_NO_LONG_LONG) */
588 * fmtnum() -- format number for output
592 fmtnum(bp, ep, value, base, dosign, ljust, len, zpad)
593 char **bp; /* current buffer pointer */
594 char *ep; /* end of buffer (-1) */
595 long value; /* number to format */
596 int base; /* number base */
597 int dosign; /* sign request */
598 int ljust; /* left justfication request */
599 int len; /* length request */
600 int zpad; /* zero padding request */
603 unsigned long uvalue;
606 int padlen = 0; /* amount to pad */
622 (caps ? "0123456789ABCDEF" : "0123456789abcdef")
623 [uvalue % (unsigned)base];
624 uvalue = (uvalue / (unsigned)base);
625 } while (uvalue && (place < (int)(sizeof(convert) - 1)));
627 padlen = len - place;
632 if (zpad && padlen > 0) {
634 (void) dopr_outch(bp, ep, signvalue);
639 (void) dopr_outch(bp, ep, zpad);
644 (void) dopr_outch(bp, ep, ' ');
648 (void) dopr_outch(bp, ep, signvalue);
650 (void) dopr_outch(bp, ep, convert[--place]);
652 (void) dopr_outch(bp, ep, ' ');
659 * fmtstr() -- format string for output
663 fmtstr(bp, ep, value, ljust, len, zpad, maxwidth)
664 char **bp; /* current buffer pointer */
665 char *ep; /* end of buffer (-1) */
666 char *value; /* string to format */
667 int ljust; /* left justification request */
668 int len; /* length request */
669 int zpad; /* zero padding request */
670 int maxwidth; /* maximum width request */
672 int padlen, strlen; /* amount to pad */
676 for (strlen = 0; value[strlen]; ++ strlen) /* strlen() */
678 if ((strlen > maxwidth) && maxwidth)
680 padlen = len - strlen;
686 (void) dopr_outch(bp, ep, ' ');
689 (void) dostr(bp, ep, value, maxwidth);
691 (void) dopr_outch(bp, ep, ' ');
698 * dostr() -- do string output
702 dostr(bp, ep, str, cut)
703 char **bp; /* current buffer pointer */
704 char *ep; /* end of buffer (-1) */
705 char *str; /* string to output */
706 int cut; /* limit on amount of string to output:
715 (void) dopr_outch(bp, ep, *str);
717 (void) dopr_outch(bp, ep, *str);
724 * dopr_outch() -- output a character (or two)
728 dopr_outch(bp, ep, c)
729 char **bp; /* current buffer pointer */
730 char *ep; /* end of buffer (-1) */
731 int c; /* character to output */
733 register char *cp = *bp;
735 if (iscntrl(c) && c != '\n' && c != '\t') {
736 c = '@' + (c & 0x1F);
747 #else /* !defined(USE_LIB_SNPF) */
748 char snpf_d1[] = "d"; char *snpf_d2 = snpf_d1;
749 #endif /* defined(USE_LIB_SNPF) */