aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/net.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.c')
-rw-r--r--src/net.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/net.c b/src/net.c
index 0a6ef85..c3a4b5e 100644
--- a/src/net.c
+++ b/src/net.c
@@ -247,6 +247,88 @@ void *buf_get_data(const struct buf *buf)
return buf->data;
}
+static size_t count_strings(const void *_data, size_t size)
+{
+ const unsigned char *data = (const unsigned char *)_data;
+ const unsigned char *it = memchr(data, '\0', size);
+
+ size_t numof_strings = 0;
+ while (it) {
+ it = memchr(it + 1, '\0', size - (it - data) - 1);
+ ++numof_strings;
+ }
+
+ return numof_strings;
+}
+
+int buf_pack_strings(struct buf **_buf, size_t argc, const char **argv)
+{
+ struct buf *buf = malloc(sizeof(struct buf));
+ if (!buf) {
+ log_errno("malloc");
+ return -1;
+ }
+
+ buf->size = 0;
+ for (size_t i = 0; i < argc; ++i)
+ buf->size += strlen(argv[i]) + 1;
+
+ buf->data = malloc(buf->size);
+ if (!buf->data) {
+ log_errno("malloc");
+ goto free_buf;
+ }
+
+ char *it = (char *)buf->data;
+ for (size_t i = 0; i < argc; ++i) {
+ it = stpcpy(it, argv[i]) + 1;
+ }
+
+ *_buf = buf;
+ return 0;
+
+free_buf:
+ free(buf);
+
+ return -1;
+}
+
+int buf_unpack_strings(const struct buf *buf, size_t *_argc, const char ***_argv)
+{
+ size_t argc = count_strings(buf->data, buf->size);
+ size_t copied = 0;
+
+ const char **argv = calloc(argc + 1, sizeof(const char *));
+ if (!argv) {
+ log_errno("calloc");
+ return -1;
+ }
+
+ const char *it = (const char *)buf->data;
+ for (copied = 0; copied < argc; ++copied) {
+ argv[copied] = strdup(it);
+ if (!argv[copied]) {
+ log_errno("strdup");
+ goto free;
+ }
+
+ it += strlen(argv[copied]) + 1;
+ }
+
+ *_argc = argc;
+ *_argv = argv;
+ return 0;
+
+free:
+ for (size_t i = 0; i < copied; ++i) {
+ free((char *)argv[i]);
+ }
+
+ free(argv);
+
+ return -1;
+}
+
int net_send_buf(int fd, const struct buf *buf)
{
int ret = 0;