File: vsnprintf.c

package info (click to toggle)
starplot 0.95.5-8.2%2Bdeb9u1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 3,476 kB
  • sloc: ansic: 11,296; cpp: 6,418; sh: 5,092; makefile: 613; yacc: 289; sed: 16
file content (54 lines) | stat: -rw-r--r-- 1,432 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include "compat.h"

#if ! HAVE_VSNPRINTF
#include <stdarg.h>
#include <stdio.h>

int
vsnprintf(char * string, size_t size, const char * format, va_list args)
{
  char * buffer;
  int length;
  FILE * devnull = fopen("/dev/null", "w");

  /* Apparently programs get mad and segfault if you try to use a va_list
   * twice without re-initializing it, so make a copy: */
  va_list copy;
#ifdef va_copy
  va_copy(copy, args);
#else
# ifdef __va_copy
  __va_copy(copy, args);
# else
  copy = args;
# endif
#endif

  /* There's no ANSI function to output the length of a printf-formatted
   * string without actually creating such output, so this is a kludge. */
  if (! devnull) {
    fprintf(stderr, _("Sorry, you don't have /dev/null.\n\
I can't emulate snprintf() or vsnprintf() for you.\n"));
    exit(EXIT_FAILURE);
  }
  length = vfprintf(devnull, format, args);

  buffer = malloc(length + 1);
  if (!buffer) {
    fprintf(stderr, _("Sorry, ran out of memory.\n"));
    exit(EXIT_FAILURE);
  }
  vsprintf(buffer, format, copy);
  strncpy(string, buffer, size);

  /* clean up */
  va_end(copy); /* the calling function should call va_end(args) */
  fclose(devnull);
  free(buffer);

  /* according to the Linux Programmer's Manual, the ISO C99 standard has
   * vsnprintf returning the same number for a given format string as would
   * any other member of the printf family, even if length > size. */
  return length;
}
#endif