diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/utils.c b/src/utils.c index d63edcc..4c6224d 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <ctype.h> #include <stdarg.h> #include <fcntl.h> #include <signal.h> @@ -25,6 +26,7 @@ char *arg0 = NULL; static int null_fd = -1; static void sighandler_child(int signo); +static inline void bin2hex_char(unsigned char c, char hexc[5]); int set_fd_nonblock(int fd) @@ -445,3 +447,52 @@ int update_setgroups_self(int allow) return 0; } #endif + +static inline void bin2hex_char(unsigned char c, char hexc[5]) +{ + static const char hexalnum[] = "0123456789ABCDEF"; + + hexc[0] = '\\'; + hexc[1] = 'x'; + hexc[2] = hexalnum[ (c >> 4)%16 ]; + hexc[3] = hexalnum[ (c & 0x0F)%16 ]; + hexc[4] = 0; +} + +void escape_ascii_string(const char ascii[], size_t siz, char **dest, size_t *newsiz) +{ + char hexbyte[5]; + const size_t binsiz = 4; + size_t i, j, ns; + + assert(ascii && dest && newsiz); + + ns = 0; + for (i = 0; i < siz; ++i) { + if (isprint(ascii[i])) + ns++; + else + ns += binsiz; + } + + if (ns > *newsiz) { + if (*dest) + free(*dest); + *dest = (char *) malloc(sizeof(char) * (ns+1)); + assert(*dest); + (*newsiz) = ns; + } + + for (i = 0, j = 0; i < siz && j < ns; ++i) { + if (isprint(ascii[i])) { + (*dest)[j] = ascii[i]; + j++; + } else { + bin2hex_char(ascii[i], hexbyte); + snprintf((*dest)+j, binsiz+1, "%s", hexbyte); + j += binsiz; + } + } + + (*dest)[ns] = 0; +} |