2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* useful additions to C library */
9 #include "sysincludes.h"
11 #include "compat.h" /* socklen_t */
17 #if !HAVE_PROTOTYPE_LIB_memrchr
18 /* GNU extension, available since glibc 2.1.91 */
19 void *memrchr(const void *s
, int c
, size_t n
) {
20 const unsigned char *t
= ((unsigned char *)s
)+n
;
21 while (--t
>= (unsigned char *)s
) {
24 if (t
< (unsigned char *)s
)
28 #endif /* !HAVE_PROTOTYPE_LIB_memrchr */
30 void *memdup(const void *src
, size_t n
) {
33 if ((dest
= Malloc(n
)) == NULL
) {
41 /* search the keyword-table for a match of the leading part of name. */
42 /* returns the pointer to the matching field of the keyword or NULL if no
44 const struct wordent
*keyw(const struct wordent
*keywds
, const char *name
, unsigned int nkeys
) {
45 unsigned int lower
, upper
, mid
;
51 while (upper
- lower
> 1)
53 mid
= (upper
+ lower
) >> 1;
54 if (!(r
= strcasecmp(keywds
[mid
].name
, name
)))
63 if (nkeys
> 0 && !(strcasecmp(keywds
[lower
].name
, name
)))
65 return &keywds
[lower
];
70 /* Linux: setenv(), AIX (4.3?): putenv() */
72 int setenv(const char *name
, const char *value
, int overwrite
) {
76 if (getenv(name
)) return 0; /* already exists */
78 if ((env
= Malloc(strlen(name
)+strlen(value
)+2)) == NULL
) {
81 sprintf(env
, "%s=%s", name
, value
);
82 if ((result
= putenv(env
)) != 0) { /* AIX docu says "... nonzero ..." */
86 /* linux "man putenv" says: ...this string becomes part of the environment*/
89 #endif /* !HAVE_SETENV */
93 /* sanitizes an "untrusted" character. output buffer must provide at least 4
95 Does not append \0. returns length of output (currently: max 4) */
96 static size_t sanitize_char(char c
, char *o
, int style
) {
97 int hn
; /* high nibble */
98 int ln
; /* low nibble */
99 int n
; /* written chars */
107 case '\0': *o
++ = '0'; break;
108 case '\a': *o
++ = 'a'; break;
109 case '\b': *o
++ = 'b'; break;
110 case '\t': *o
++ = 't'; break;
111 case '\n': *o
++ = 'n'; break;
112 case '\v': *o
++ = 'v'; break;
113 case '\f': *o
++ = 'f'; break;
114 case '\r': *o
++ = 'r'; break;
115 case '\'': *o
++ = '\''; break;
116 case '\"': *o
++ = '"'; break;
117 case '\\': *o
++ = '\\'; break;
122 *o
++ = (hn
>=10 ? (('A'-1)+(hn
-10)) : ('0'+hn
));
123 *o
++ = (ln
>=10 ? (('A'-1)+(ln
-10)) : ('0'+ln
));
129 /* sanitizes "untrusted" text, replacing special control characters with the C
130 string version (eg."\n"), and replacing unprintable chars with hex
131 representation ("\xAB").
132 text can grow to four times of input, so keep output buffer long enough!
133 returns a pointer to the first untouched byte of the output buffer.
134 Output is not \0 terminated.
136 char *sanitize_string(const char *data
, /* input data */
137 size_t bytes
, /* length of input data, >=0 */
138 char *coded
, /* output buffer, must be long enough */
144 c
= *(unsigned char *)data
++;
145 coded
+= sanitize_char(c
, coded
, style
);
151 /* copies a substring out of a given buff
152 returns scratch, \0 terminated; scratch must provide len+1 bytes
154 char *xiosubstr(char *scratch
, const char *str
, size_t from
, size_t len
) {
155 char *scratch0
= scratch
;
165 /* since version 1.7.2.4 socat supports C-99 behaviour of snprintf but still
166 can handle the old glibc case with -1 return on truncation.
167 Do not rely on exact return value in case of truncation
169 int xio_snprintf(char *str
, size_t size
, const char *format
, ...) {
173 va_start(ap
, format
);
174 result
= vsnprintf(str
, size
, format
, ap
);
175 #if ! HAVE_C99_SNPRINTF
177 result
= size
+63; /* indicate truncation with just some guess */
179 #endif /* !HAVE_C99_SNPRINTF */