aboutsummaryrefslogtreecommitdiff
path: root/src/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils.c')
-rw-r--r--src/utils.c51
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;
+}