Version 1.8.0.0
[socat.git] / utils.c
blob7243ca93d74798c6f1e4375af43ab80886f19c2e
1 /* source: utils.c */
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 */
7 #include "config.h"
9 #include "sysincludes.h"
11 #include "compat.h" /* socklen_t */
12 #include "mytypes.h"
13 #include "sycls.h"
14 #include "utils.h"
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) {
22 if (*t == c) break;
24 if (t < (unsigned char *)s)
25 return NULL;
26 return (void *)t;
28 #endif /* !HAVE_PROTOTYPE_LIB_memrchr */
30 void *memdup(const void *src, size_t n) {
31 void *dest;
33 if ((dest = Malloc(n)) == NULL) {
34 return NULL;
37 memcpy(dest, src, n);
38 return dest;
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
43 keyword was found. */
44 const struct wordent *keyw(const struct wordent *keywds, const char *name, unsigned int nkeys) {
45 unsigned int lower, upper, mid;
46 int r;
48 lower = 0;
49 upper = nkeys;
51 while (upper - lower > 1)
53 mid = (upper + lower) >> 1;
54 if (!(r = strcasecmp(keywds[mid].name, name)))
56 return &keywds[mid];
58 if (r < 0)
59 lower = mid;
60 else
61 upper = mid;
63 if (nkeys > 0 && !(strcasecmp(keywds[lower].name, name)))
65 return &keywds[lower];
67 return NULL;
70 /* Linux: setenv(), AIX (4.3?): putenv() */
71 #if !HAVE_SETENV
72 int setenv(const char *name, const char *value, int overwrite) {
73 int result;
74 char *env;
75 if (!overwrite) {
76 if (getenv(name)) return 0; /* already exists */
78 if ((env = Malloc(strlen(name)+strlen(value)+2)) == NULL) {
79 return -1;
81 sprintf(env, "%s=%s", name, value);
82 if ((result = putenv(env)) != 0) { /* AIX docu says "... nonzero ..." */
83 free(env);
84 result = -1;
86 /* linux "man putenv" says: ...this string becomes part of the environment*/
87 return result;
89 #endif /* !HAVE_SETENV */
92 /* sanitizes an "untrusted" character. output buffer must provide at least 4
93 characters space.
94 Does not append \0. returns length of output (currently: max 4) */
95 static size_t sanitize_char(char c, char *o, int style) {
96 int hn; /* high nibble */
97 int ln; /* low nibble */
98 int n; /* written chars */
99 if (isprint((unsigned char)c)) {
100 *o = c;
101 return 1;
103 *o++ = '\\';
104 n = 2;
105 switch (c) {
106 case '\0': *o++ = '0'; break;
107 case '\a': *o++ = 'a'; break;
108 case '\b': *o++ = 'b'; break;
109 case '\t': *o++ = 't'; break;
110 case '\n': *o++ = 'n'; break;
111 case '\v': *o++ = 'v'; break;
112 case '\f': *o++ = 'f'; break;
113 case '\r': *o++ = 'r'; break;
114 case '\'': *o++ = '\''; break;
115 case '\"': *o++ = '"'; break;
116 case '\\': *o++ = '\\'; break;
117 default:
118 *o++ = 'x';
119 hn = (c>>4)&0x0f;
120 ln = c&0x0f;
121 *o++ = (hn>=10 ? (('A'-1)+(hn-10)) : ('0'+hn));
122 *o++ = (ln>=10 ? (('A'-1)+(ln-10)) : ('0'+ln));
123 n = 4;
125 return n;
128 /* sanitizes "untrusted" text, replacing special control characters with the C
129 string version (eg."\n"), and replacing unprintable chars with hex
130 representation ("\xAB").
131 text can grow to four times of input, so keep output buffer long enough!
132 returns a pointer to the first untouched byte of the output buffer.
133 Output is not \0 terminated.
135 char *sanitize_string(const char *data, /* input data */
136 size_t bytes, /* length of input data, >=0 */
137 char *coded, /* output buffer, must be long enough */
138 int style
140 int c;
142 while (bytes > 0) {
143 c = *(unsigned char *)data++;
144 coded += sanitize_char(c, coded, style);
145 --bytes;
147 return coded;
150 /* copies a substring out of a given buff
151 returns scratch, \0 terminated; scratch must provide len+1 bytes
153 char *xiosubstr(char *scratch, const char *str, size_t from, size_t len) {
154 char *scratch0 = scratch;
155 str += from;
156 while (len--) {
157 *scratch++ = *str++;
159 *scratch = '\0';
160 return scratch0;
164 /* since version 1.7.2.4 socat supports C-99 behaviour of snprintf but still
165 can handle the old glibc case with -1 return on truncation.
166 Do not rely on exact return value in case of truncation
168 int xio_snprintf(char *str, size_t size, const char *format, ...) {
169 va_list ap;
170 int result;
172 va_start(ap, format);
173 result = vsnprintf(str, size, format, ap);
174 #if ! HAVE_C99_SNPRINTF
175 if (result < 0) {
176 result = size+63; /* indicate truncation with just some guess */
178 #endif /* !HAVE_C99_SNPRINTF */
179 va_end(ap);
180 return result;