forked from erluko/socat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
snprinterr.c
85 lines (79 loc) · 2.26 KB
/
snprinterr.c
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/* snprinterr.c */
/* Copyright Gerhard Rieger */
/* a function similar to vsnprintf() but it just handles %m */
#include "config.h"
#include <stddef.h> /* ptrdiff_t */
#include <ctype.h> /* isdigit() */
#include <stdarg.h>
#include <stdlib.h>
#include <errno.h>
#if HAVE_SYSLOG_H
#include <syslog.h>
#endif
#include <sys/utsname.h>
#include <time.h> /* time_t, strftime() */
#include <sys/time.h> /* gettimeofday() */
#include <stdio.h>
#include <string.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "snprinterr.h"
#define HAVE_STRERROR_R 0
/* replace %m in format with actual strerror() message, write result to *str.
keep other % formats unchanged!
writes at most size chars including the terminating \0 to *str
returns the number of bytes in the output without terminating \0
result is always \0 terminated except when size==0
*/
int snprinterr(char *str, size_t size, const char *format) {
char c;
int full = 0; /* 1 means: there is no space left in * str for more data or \0 */
int count = 0;
if (size == 0) return 0;
if (count >= size) full = 1;
while (c = *format++) {
if (c == '%') {
c = *format++;
switch (c) {
case '\0':
++count; if (!full) { (*str++ = '%'); if (count+1 >= size) full = 1; }
break;
default:
++count; if (!full) { (*str++ = '%'); if (count+1 >= size) full = 1; }
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
break;
case 'm':
{
#if HAVE_STRERROR_R
# define BUFLEN 64
char buf[BUFLEN] = "";
#endif /* HAVE_STRERROR_R */
char *bufp;
#if !HAVE_STRERROR_R
bufp = strerror(errno);
#else
/* there are two versions floating around... */
# if 1 /* GNU version */
bufp = strerror_r(errno, buf, BUFLEN);
# else /* standard version */
strerror_r(errno, buf, BUFLEN);
bufp = buf;
# endif
#endif /* HAVE_STRERROR_R */
while ((c = *bufp++) != '\0') {
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
}
}
c = ' '; /* not \0 ! */
break;
}
if (c == '\0') break;
} else {
++count; if (!full) { (*str++ = c); if (count+1 >= size) full = 1; }
}
}
*str++ = '\0'; /* always write terminating \0 */
return count;
#undef BUFLEN
}