ISC DHCP  4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
iscprint.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2017 Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003 Internet Software Consortium.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* $Id: iscprint.c,v 1.2 2005/03/17 20:30:41 dhankins Exp $ */
19 
20 #include "dhcpd.h"
21 
22 #ifdef NO_SNPRINTF
23 
24 #ifndef LINT
25 static char copyright[] =
26 "$Id: iscprint.c,v 1.2 2005/03/17 20:30:41 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium, Inc. All rights reserved.";
27 #endif
28 
29 #define INSIST(cond) REQUIRE(cond)
30 #define REQUIRE(cond) if (!(cond)) { return 0; }
31 
32 /*
33  * Return length of string that would have been written if not truncated.
34  */
35 
36 int
37 isc_print_snprintf(char *str, size_t size, const char *format, ...) {
38  va_list ap;
39  int ret;
40 
41  va_start(ap, format);
42  ret = vsnprintf(str, size, format, ap);
43  va_end(ap);
44  return (ret);
45 }
46 
47 /*
48  * Return length of string that would have been written if not truncated.
49  */
50 
51 int
52 isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
53  int h;
54  int l;
55  int q;
56  int alt;
57  int zero;
58  int left;
59  int plus;
60  int space;
61  int neg;
62  isc_int64_t tmpi;
63  isc_uint64_t tmpui;
64  unsigned long width;
65  unsigned long precision;
66  unsigned int length;
67  char buf[1024];
68  char c;
69  void *v;
70  char *save = str;
71  const char *cp;
72  const char *head;
73  int count = 0;
74  int pad;
75  int zeropad;
76  int dot;
77  double dbl;
78 #ifdef HAVE_LONG_DOUBLE
79  long double ldbl;
80 #endif
81  char fmt[32];
82 
83  INSIST(str != NULL);
84  INSIST(format != NULL);
85 
86  while (*format != '\0') {
87  if (*format != '%') {
88  if (size > 1) {
89  *str++ = *format;
90  size--;
91  }
92  count++;
93  format++;
94  continue;
95  }
96  format++;
97 
98  /*
99  * Reset flags.
100  */
101  dot = neg = space = plus = left = zero = alt = h = l = q = 0;
102  width = precision = 0;
103  head = "";
104  length = pad = zeropad = 0;
105 
106  do {
107  if (*format == '#') {
108  alt = 1;
109  format++;
110  } else if (*format == '-') {
111  left = 1;
112  zero = 0;
113  format++;
114  } else if (*format == ' ') {
115  if (!plus)
116  space = 1;
117  format++;
118  } else if (*format == '+') {
119  plus = 1;
120  space = 0;
121  format++;
122  } else if (*format == '0') {
123  if (!left)
124  zero = 1;
125  format++;
126  } else
127  break;
128  } while (1);
129 
130  /*
131  * Width.
132  */
133  if (*format == '*') {
134  width = va_arg(ap, int);
135  format++;
136  } else if (isdigit((unsigned char)*format)) {
137  char *e;
138  width = strtoul(format, &e, 10);
139  format = e;
140  }
141 
142  /*
143  * Precision.
144  */
145  if (*format == '.') {
146  format++;
147  dot = 1;
148  if (*format == '*') {
149  precision = va_arg(ap, int);
150  format++;
151  } else if (isdigit((unsigned char)*format)) {
152  char *e;
153  precision = strtoul(format, &e, 10);
154  format = e;
155  }
156  }
157 
158  switch (*format) {
159  case '\0':
160  continue;
161  case '%':
162  if (size > 1) {
163  *str++ = *format;
164  size--;
165  }
166  count++;
167  break;
168  case 'q':
169  q = 1;
170  format++;
171  goto doint;
172  case 'h':
173  h = 1;
174  format++;
175  goto doint;
176  case 'l':
177  l = 1;
178  format++;
179  if (*format == 'l') {
180  q = 1;
181  format++;
182  }
183  goto doint;
184  case 'n':
185  case 'i':
186  case 'd':
187  case 'o':
188  case 'u':
189  case 'x':
190  case 'X':
191  doint:
192  if (precision != 0)
193  zero = 0;
194  switch (*format) {
195  case 'n':
196  if (h) {
197  short int *p;
198  p = va_arg(ap, short *);
199  REQUIRE(p != NULL);
200  *p = str - save;
201  } else if (l) {
202  long int *p;
203  p = va_arg(ap, long *);
204  REQUIRE(p != NULL);
205  *p = str - save;
206  } else {
207  int *p;
208  p = va_arg(ap, int *);
209  REQUIRE(p != NULL);
210  *p = str - save;
211  }
212  break;
213  case 'i':
214  case 'd':
215  if (q)
216  tmpi = va_arg(ap, isc_int64_t);
217  else if (l)
218  tmpi = va_arg(ap, long int);
219  else
220  tmpi = va_arg(ap, int);
221  if (tmpi < 0) {
222  head = "-";
223  tmpui = -tmpi;
224  } else {
225  if (plus)
226  head = "+";
227  else if (space)
228  head = " ";
229  else
230  head = "";
231  tmpui = tmpi;
232  }
233  sprintf(buf, "%u", tmpui);
234  goto printint;
235  case 'o':
236  if (q)
237  tmpui = va_arg(ap, isc_uint64_t);
238  else if (l)
239  tmpui = va_arg(ap, long int);
240  else
241  tmpui = va_arg(ap, int);
242  sprintf(buf, alt ? "%#o"
243  : "%o", tmpui);
244  goto printint;
245  case 'u':
246  if (q)
247  tmpui = va_arg(ap, isc_uint64_t);
248  else if (l)
249  tmpui = va_arg(ap, unsigned long int);
250  else
251  tmpui = va_arg(ap, unsigned int);
252  sprintf(buf, "%u", tmpui);
253  goto printint;
254  case 'x':
255  if (q)
256  tmpui = va_arg(ap, isc_uint64_t);
257  else if (l)
258  tmpui = va_arg(ap, unsigned long int);
259  else
260  tmpui = va_arg(ap, unsigned int);
261  if (alt) {
262  head = "0x";
263  if (precision > 2)
264  precision -= 2;
265  }
266  sprintf(buf, "%x", tmpui);
267  goto printint;
268  case 'X':
269  if (q)
270  tmpui = va_arg(ap, isc_uint64_t);
271  else if (l)
272  tmpui = va_arg(ap, unsigned long int);
273  else
274  tmpui = va_arg(ap, unsigned int);
275  if (alt) {
276  head = "0X";
277  if (precision > 2)
278  precision -= 2;
279  }
280  sprintf(buf, "%X", tmpui);
281  goto printint;
282  printint:
283  if (precision != 0 || width != 0) {
284  length = strlen(buf);
285  if (length < precision)
286  zeropad = precision - length;
287  else if (length < width && zero)
288  zeropad = width - length;
289  if (width != 0) {
290  pad = width - length -
291  zeropad - strlen(head);
292  if (pad < 0)
293  pad = 0;
294  }
295  }
296  count += strlen(head) + strlen(buf) + pad +
297  zeropad;
298  if (!left) {
299  while (pad > 0 && size > 1) {
300  *str++ = ' ';
301  size--;
302  pad--;
303  }
304  }
305  cp = head;
306  while (*cp != '\0' && size > 1) {
307  *str++ = *cp++;
308  size--;
309  }
310  while (zeropad > 0 && size > 1) {
311  *str++ = '0';
312  size--;
313  zeropad--;
314  }
315  cp = buf;
316  while (*cp != '\0' && size > 1) {
317  *str++ = *cp++;
318  size--;
319  }
320  while (pad > 0 && size > 1) {
321  *str++ = ' ';
322  size--;
323  pad--;
324  }
325  break;
326  default:
327  break;
328  }
329  break;
330  case 's':
331  cp = va_arg(ap, char *);
332  REQUIRE(cp != NULL);
333 
334  if (precision != 0) {
335  /*
336  * cp need not be NULL terminated.
337  */
338  const char *tp;
339  unsigned long n;
340 
341  n = precision;
342  tp = cp;
343  while (n != 0 && *tp != '\0')
344  n--, tp++;
345  length = precision - n;
346  } else {
347  length = strlen(cp);
348  }
349  if (width != 0) {
350  pad = width - length;
351  if (pad < 0)
352  pad = 0;
353  }
354  count += pad + length;
355  if (!left)
356  while (pad > 0 && size > 1) {
357  *str++ = ' ';
358  size--;
359  pad--;
360  }
361  if (precision != 0)
362  while (precision > 0 && *cp != '\0' &&
363  size > 1) {
364  *str++ = *cp++;
365  size--;
366  precision--;
367  }
368  else
369  while (*cp != '\0' && size > 1) {
370  *str++ = *cp++;
371  size--;
372  }
373  while (pad > 0 && size > 1) {
374  *str++ = ' ';
375  size--;
376  pad--;
377  }
378  break;
379  case 'c':
380  c = va_arg(ap, int);
381  if (width > 0) {
382  count += width;
383  width--;
384  if (left) {
385  *str++ = c;
386  size--;
387  }
388  while (width-- > 0 && size > 1) {
389  *str++ = ' ';
390  size--;
391  }
392  if (!left && size > 1) {
393  *str++ = c;
394  size--;
395  }
396  } else {
397  count++;
398  if (size > 1) {
399  *str++ = c;
400  size--;
401  }
402  }
403  break;
404  case 'p':
405  v = va_arg(ap, void *);
406  sprintf(buf, "%p", v);
407  length = strlen(buf);
408  if (precision > length)
409  zeropad = precision - length;
410  if (width > 0) {
411  pad = width - length - zeropad;
412  if (pad < 0)
413  pad = 0;
414  }
415  count += length + pad + zeropad;
416  if (!left)
417  while (pad > 0 && size > 1) {
418  *str++ = ' ';
419  size--;
420  pad--;
421  }
422  cp = buf;
423  if (zeropad > 0 && buf[0] == '0' &&
424  (buf[1] == 'x' || buf[1] == 'X')) {
425  if (size > 1) {
426  *str++ = *cp++;
427  size--;
428  }
429  if (size > 1) {
430  *str++ = *cp++;
431  size--;
432  }
433  while (zeropad > 0 && size > 1) {
434  *str++ = '0';
435  size--;
436  zeropad--;
437  }
438  }
439  while (*cp != '\0' && size > 1) {
440  *str++ = *cp++;
441  size--;
442  }
443  while (pad > 0 && size > 1) {
444  *str++ = ' ';
445  size--;
446  pad--;
447  }
448  break;
449  case 'D': /*deprecated*/
450  INSIST("use %ld instead of %D" == NULL);
451  case 'O': /*deprecated*/
452  INSIST("use %lo instead of %O" == NULL);
453  case 'U': /*deprecated*/
454  INSIST("use %lu instead of %U" == NULL);
455 
456  case 'L':
457 #ifdef HAVE_LONG_DOUBLE
458  l = 1;
459 #else
460  INSIST("long doubles are not supported" == NULL);
461 #endif
462  /*FALLTHROUGH*/
463  case 'e':
464  case 'E':
465  case 'f':
466  case 'g':
467  case 'G':
468  if (!dot)
469  precision = 6;
470  /*
471  * IEEE floating point.
472  * MIN 2.2250738585072014E-308
473  * MAX 1.7976931348623157E+308
474  * VAX floating point has a smaller range than IEEE.
475  *
476  * precisions > 324 don't make much sense.
477  * if we cap the precision at 512 we will not
478  * overflow buf.
479  */
480  if (precision > 512)
481  precision = 512;
482  sprintf(fmt, "%%%s%s.%lu%s%c", alt ? "#" : "",
483  plus ? "+" : space ? " " : "",
484  precision, l ? "L" : "", *format);
485  switch (*format) {
486  case 'e':
487  case 'E':
488  case 'f':
489  case 'g':
490  case 'G':
491 #ifdef HAVE_LONG_DOUBLE
492  if (l) {
493  ldbl = va_arg(ap, long double);
494  sprintf(buf, fmt, ldbl);
495  } else
496 #endif
497  {
498  dbl = va_arg(ap, double);
499  sprintf(buf, fmt, dbl);
500  }
501  length = strlen(buf);
502  if (width > 0) {
503  pad = width - length;
504  if (pad < 0)
505  pad = 0;
506  }
507  count += length + pad;
508  if (!left)
509  while (pad > 0 && size > 1) {
510  *str++ = ' ';
511  size--;
512  pad--;
513  }
514  cp = buf;
515  while (*cp != ' ' && size > 1) {
516  *str++ = *cp++;
517  size--;
518  }
519  while (pad > 0 && size > 1) {
520  *str++ = ' ';
521  size--;
522  pad--;
523  }
524  break;
525  default:
526  continue;
527  }
528  break;
529  default:
530  continue;
531  }
532  format++;
533  }
534  if (size > 0)
535  *str = '\0';
536  return (count);
537 }
538 
539 #endif
dhcpd.h
space
Definition: keama.h:281
REQUIRE
Definition: dhctoken.h:104