1 /* snprinterr.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 
4 /* a function similar to vsnprintf() but it just handles %m */
5 
6 #include "config.h"
7 
8 #include <stddef.h>	/* ptrdiff_t */
9 #include <ctype.h>	/* isdigit() */
10 #include <stdarg.h>
11 #include <stdlib.h>
12 #include <errno.h>
13 #if HAVE_SYSLOG_H
14 #include <syslog.h>
15 #endif
16 #include <sys/utsname.h>
17 #include <time.h>	/* time_t, strftime() */
18 #include <sys/time.h>	/* gettimeofday() */
19 #include <stdio.h>
20 #include <string.h>
21 #if HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24 
25 #include "snprinterr.h"
26 
27 #define HAVE_STRERROR_R 0
28 /* replace %m in format with actual strerror() message, write result to *str.
29    keep other % formats unchanged!
30    writes at most size chars including the terminating \0 to *str
31    returns the number of bytes in the output without terminating \0
32    result is always \0 terminated except when size==0
33  */
snprinterr(char * str,size_t size,const char * format)34 int snprinterr(char *str, size_t size, const char *format) {
35    char c;
36    int full = 0;	/* 1 means: there is no space left in * str for more data or \0 */
37    int count = 0;
38    if (size == 0)  return 0;
39    if (count >= size)  full = 1;
40    while (c = *format++) {
41       if (c == '%') {
42 	 c = *format++;
43 	 switch (c) {
44 	 case '\0':
45 	    ++count; if (!full) { (*str++ = '%'); if (count+1 >= size) full = 1; }
46 	    break;
47 	 default:
48 	    ++count; if (!full) { (*str++ = '%'); if (count+1 >= size) full = 1; }
49 	    ++count; if (!full) { (*str++ = c);   if (count+1 >= size) full = 1; }
50 	    break;
51 	 case 'm':
52 	    {
53 #if HAVE_STRERROR_R
54 #              define BUFLEN 64
55 	       char buf[BUFLEN] = "";
56 #endif /* HAVE_STRERROR_R */
57 	       char *bufp;
58 #if !HAVE_STRERROR_R
59 	       bufp = strerror(errno);
60 #else
61 	       /* there are two versions floating around... */
62 #  if 1	/* GNU version */
63 	       bufp = strerror_r(errno, buf, BUFLEN);
64 #  else	/* standard version */
65 	       strerror_r(errno, buf, BUFLEN);
66 	       bufp = buf;
67 #  endif
68 #endif /* HAVE_STRERROR_R */
69 	       while ((c = *bufp++) != '\0') {
70 		  ++count; if (!full) { (*str++ = c);   if (count+1 >= size) full = 1; }
71 	       }
72 	    }
73 	    c = ' ';	/* not \0 ! */
74 	    break;
75 	 }
76 	 if (c == '\0')  break;
77       } else {
78 	 ++count; if (!full) { (*str++ = c); if (count+1 >= size)  full = 1; }
79       }
80    }
81    *str++ = '\0';	/* always write terminating \0 */
82    return count;
83 #undef BUFLEN
84 }
85 
86