aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2016-05-14 22:03:43 -0400
committerJesse Luehrs <doy@tozt.net>2016-05-14 22:03:43 -0400
commitd5b52a1302ef4409424ec0633ccf9bd72359ea32 (patch)
tree76d90c6b51f8bf234cc19cce75147d6089a1b808
parentbfe96a6aa5fa3ca9a05b658efbcaee9dc01b5235 (diff)
downloadrunes-d5b52a1302ef4409424ec0633ccf9bd72359ea32.tar.gz
runes-d5b52a1302ef4409424ec0633ccf9bd72359ea32.zip
refactor/rewrite the client/server protocol handling
also pass the environment and current directory over as well
-rw-r--r--Makefile8
-rw-r--r--src/daemon.c153
-rw-r--r--src/daemon.h1
-rw-r--r--src/protocol.c351
-rw-r--r--src/protocol.h23
-rw-r--r--src/runesc.c75
-rw-r--r--src/socket.c117
-rw-r--r--src/socket.h10
-rw-r--r--src/util.c14
-rw-r--r--src/util.h1
10 files changed, 566 insertions, 187 deletions
diff --git a/Makefile b/Makefile
index 001c0f7..b0e4eaa 100644
--- a/Makefile
+++ b/Makefile
@@ -21,9 +21,13 @@ DOBJ = $(BUILD)runesd.o \
$(BUILD)pty-unix.o \
$(BUILD)loop.o \
$(BUILD)util.o \
- $(BUILD)daemon.o
+ $(BUILD)daemon.o \
+ $(BUILD)socket.o \
+ $(BUILD)protocol.o
COBJ = $(BUILD)runesc.o \
- $(BUILD)util.o
+ $(BUILD)util.o \
+ $(BUILD)socket.o \
+ $(BUILD)protocol.o
LIBS = cairo cairo-xlib libevent pangocairo
OPT ?= -g
CFLAGS ?= $(OPT) -Wall -Wextra -Werror
diff --git a/src/daemon.c b/src/daemon.c
index 8c1269e..44c3c11 100644
--- a/src/daemon.c
+++ b/src/daemon.c
@@ -11,10 +11,10 @@
#include "daemon.h"
#include "loop.h"
+#include "protocol.h"
+#include "socket.h"
#include "term.h"
-static int runes_daemon_open_socket(char *sock_name);
-static void runes_daemon_close_socket(RunesDaemon *sock);
static int runes_daemon_handle_request(void *t);
RunesDaemon *runes_daemon_new(RunesLoop *loop, RunesWindowBackend *wb)
@@ -25,7 +25,7 @@ RunesDaemon *runes_daemon_new(RunesLoop *loop, RunesWindowBackend *wb)
daemon->loop = loop;
daemon->wb = wb;
daemon->sock_name = runes_get_daemon_socket_name();
- daemon->sock = runes_daemon_open_socket(daemon->sock_name);
+ daemon->sock = runes_socket_server_open(daemon->sock_name);
runes_daemon_init_loop(daemon, loop);
return daemon;
@@ -39,151 +39,42 @@ void runes_daemon_init_loop(RunesDaemon *daemon, RunesLoop *loop)
void runes_socket_delete(RunesDaemon *daemon)
{
- runes_daemon_close_socket(daemon);
+ runes_socket_server_close(daemon->sock, daemon->sock_name);
free(daemon->sock_name);
free(daemon);
}
-static int runes_daemon_open_socket(char *sock_name)
-{
- char *dir, *slash;
- int s;
- struct sockaddr_un server;
-
- if (strlen(sock_name) + 1 > MAX_SOCKET_PATH_LEN) {
- runes_die("socket path %s is too long", sock_name);
- }
-
- dir = strdup(sock_name);
- slash = strrchr(dir, '/');
- if (slash == NULL) {
- runes_die("socket path %s must be an absolute path", sock_name);
- }
- *slash = '\0';
- runes_mkdir_p(dir);
- free(dir);
-
- unlink(sock_name);
-
- s = socket(AF_UNIX, SOCK_STREAM, 0);
- if (s < 0) {
- runes_die("couldn't create socket: %s", strerror(errno));
- }
-
- server.sun_family = AF_UNIX;
- strcpy(server.sun_path, sock_name);
- if (bind(s, (struct sockaddr*)(&server), sizeof(struct sockaddr_un))) {
- runes_die("couldn't bind to socket %s: %s", sock_name,
- strerror(errno));
- }
-
- if (chmod(sock_name, S_IRUSR|S_IWUSR)) {
- runes_die("couldn't chmod socket %s: %s", sock_name,
- strerror(errno));
- }
-
- if (listen(s, 5)) {
- runes_die("couldn't listen on socket %s: %s", sock_name,
- strerror(errno));
- }
-
- return s;
-}
-
-static void runes_daemon_close_socket(RunesDaemon *daemon)
-{
- close(daemon->sock);
- unlink(daemon->sock_name);
-}
-
static int runes_daemon_handle_request(void *t)
{
RunesDaemon *daemon = (RunesDaemon *)t;
- struct sockaddr_un client;
- socklen_t len = sizeof(client);
- ssize_t bytes;
- uint32_t argc, argv_len;
- char **argv, *argv_buf;
-
- daemon->client_sock = accept(
- daemon->sock, (struct sockaddr*)(&client), &len);
- if (daemon->client_sock < 0) {
- runes_die("couldn't accept connection: %s", strerror(errno));
- }
+ int client_sock;
+ char *buf;
+ size_t len;
+ struct runes_protocol_message msg;
+ RunesTerm *new_term;
- bytes = recv(daemon->client_sock, (void*)(&argc), sizeof(argc), 0);
- if (bytes < (int)sizeof(argc)) {
- runes_warn("invalid message received: got %d bytes, expected 4",
- bytes);
- close(daemon->client_sock);
- return 1;
- }
+ client_sock = runes_socket_server_accept(daemon->sock);
- argc = ntohl(argc);
- if (argc > 1024) {
- runes_warn("invalid message received: argc = %d, must be < 1024",
- argc);
- close(daemon->client_sock);
- return 1;
- }
- argv = malloc(argc * sizeof(char*));
-
- bytes = recv(daemon->client_sock, (void*)(&argv_len), sizeof(argv_len), 0);
- if (bytes < (int)sizeof(argc)) {
- runes_warn("invalid message received: got %d bytes, expected 4",
- bytes);
- close(daemon->client_sock);
- free(argv);
+ if (!runes_protocol_read_packet(client_sock, &buf, &len)) {
+ runes_warn("invalid packet received");
return 1;
}
- argv_len = ntohl(argv_len);
- if (argv_len > 131072) {
- runes_warn("invalid message received: argv_len = %d, must be < %d",
- argv_len, 131072);
- close(daemon->client_sock);
- free(argv);
- return 1;
- }
- argv_buf = malloc(argv_len + 1);
-
- bytes = recv(daemon->client_sock, argv_buf, argv_len, 0);
- if (bytes < argv_len) {
- runes_warn("invalid message received: got %d bytes, expected %d",
- bytes, argv_len);
- close(daemon->client_sock);
- free(argv);
- free(argv_buf);
+ runes_socket_client_close(client_sock);
+
+ if (!runes_protocol_parse_message(buf, len, &msg)) {
+ runes_warn("couldn't parse message from client");
+ free(buf);
return 1;
}
- close(daemon->client_sock);
-
- if (argc > 0) {
- size_t offset = 0;
- int i;
-
- for (i = 0; i < (int)argc; ++i) {
- char *next_null;
-
- if (offset >= argv_len) {
- runes_die("args in argv_buf don't match argc of %d", argc);
- }
- argv[i] = argv_buf + offset;
- next_null = memchr(argv_buf + offset, '\0', argv_len - offset);
- if (!next_null) {
- runes_die("args in argv_buf don't match argc of %d", argc);
- }
- offset = next_null - argv_buf + 1;
- }
-
- runes_term_register_with_loop(
- runes_term_new(argc, argv, NULL, NULL, daemon->wb), daemon->loop);
- }
+ new_term = runes_term_new(
+ msg.argc, msg.argv, msg.envp, msg.cwd, daemon->wb);
+ runes_term_register_with_loop(new_term, daemon->loop);
- free(argv);
- free(argv_buf);
+ free(buf);
+ runes_protocol_free_message(&msg);
return 1;
}
diff --git a/src/daemon.h b/src/daemon.h
index 733e940..daf010e 100644
--- a/src/daemon.h
+++ b/src/daemon.h
@@ -8,7 +8,6 @@ struct runes_daemon {
RunesWindowBackend *wb;
char *sock_name;
int sock;
- int client_sock;
};
RunesDaemon *runes_daemon_new(RunesLoop *loop, RunesWindowBackend *wb);
diff --git a/src/protocol.c b/src/protocol.c
new file mode 100644
index 0000000..6451f63
--- /dev/null
+++ b/src/protocol.c
@@ -0,0 +1,351 @@
+#include <arpa/inet.h>
+#include <errno.h>
+#include <glib.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "runes.h"
+#include "protocol.h"
+
+#define RUNES_MAX_PACKET_SIZE (1024*1024)
+
+static int runes_protocol_store_u32(GArray *buf, uint32_t i);
+static int runes_protocol_store_strvec(GArray *buf, char *vec[]);
+static int runes_protocol_store_str(GArray *buf, char *str);
+static ssize_t runes_protocol_load_u32(char *buf, size_t len, uint32_t *i);
+static ssize_t runes_protocol_load_strvec(char *buf, size_t len, char ***vec);
+static ssize_t runes_protocol_load_str(char *buf, size_t len, char **str);
+static int runes_protocol_read_bytes(int sock, size_t len, char *outbuf);
+static int runes_protocol_write_bytes(int sock, char *buf, size_t len);
+
+int runes_protocol_parse_message(
+ char *buf, size_t len, struct runes_protocol_message *outmsg)
+{
+ uint32_t version;
+ size_t offset = 0;
+
+#define LOAD(type, var) \
+ do { \
+ ssize_t incr; \
+ incr = runes_protocol_load_##type(buf + offset, len - offset, &var); \
+ if (incr < 0) { \
+ free(outmsg); \
+ return 0; \
+ } \
+ offset += incr; \
+ } while (0)
+
+ LOAD(u32, version);
+ if (version != RUNES_PROTOCOL_MESSAGE_VERSION) {
+ /* backcompat code can go here eventually */
+ runes_warn("unknown protocol version %d", version);
+ free(outmsg);
+ return 0;
+ }
+
+ LOAD(u32, outmsg->argc);
+ LOAD(strvec, outmsg->argv);
+ LOAD(strvec, outmsg->envp);
+ LOAD(str, outmsg->cwd);
+
+#undef LOAD
+
+ return 1;
+}
+
+int runes_protocol_create_message(
+ struct runes_protocol_message *msg, char **outbuf, size_t *outlen)
+{
+ GArray *buf;
+
+ buf = g_array_new(FALSE, FALSE, 1);
+
+#define STORE(type, val) \
+ do { \
+ if (!runes_protocol_store_##type(buf, val)) { \
+ g_array_unref(buf); \
+ return 0; \
+ } \
+ } while (0)
+
+ STORE(u32, RUNES_PROTOCOL_MESSAGE_VERSION);
+
+ STORE(u32, msg->argc);
+ STORE(strvec, msg->argv);
+ STORE(strvec, msg->envp);
+ STORE(str, msg->cwd);
+
+#undef STORE
+
+ *outbuf = malloc(buf->len);
+ memcpy(*outbuf, buf->data, buf->len);
+ *outlen = buf->len;
+
+ g_array_unref(buf);
+
+ return 1;
+}
+
+void runes_protocol_free_message(struct runes_protocol_message *msg)
+{
+ char **p;
+
+ p = msg->argv;
+ while (*p) {
+ free(*p);
+ p++;
+ }
+ free(msg->argv);
+
+ p = msg->envp;
+ while (*p) {
+ free(*p);
+ p++;
+ }
+ free(msg->envp);
+
+ free(msg->cwd);
+}
+
+int runes_protocol_read_packet(int sock, char **outbuf, size_t *outlen)
+{
+ uint32_t len;
+ char *buf;
+
+ if (!runes_protocol_read_bytes(sock, sizeof(len), (char *)&len)) {
+ return 0;
+ }
+
+ len = ntohl(len);
+ if (len > RUNES_MAX_PACKET_SIZE) {
+ runes_warn("packet of size %d is too big", len);
+ return 0;
+ }
+ buf = malloc(len);
+
+ if (!runes_protocol_read_bytes(sock, len, buf)) {
+ free(buf);
+ return 0;
+ }
+
+ *outlen = len;
+ *outbuf = buf;
+
+ return 1;
+}
+
+int runes_protocol_send_packet(int sock, char *buf, size_t len)
+{
+ uint32_t len32 = len;
+
+ if (len > RUNES_MAX_PACKET_SIZE) {
+ runes_warn("packet of size %d is too big", len);
+ return 0;
+ }
+
+ len32 = htonl(len32);
+
+ if (!runes_protocol_write_bytes(sock, (char *)&len32, sizeof(len32))) {
+ runes_warn("failed to write packet to socket");
+ return 0;
+ }
+
+ if (!runes_protocol_write_bytes(sock, buf, len)) {
+ runes_warn("failed to write packet to socket");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int runes_protocol_store_u32(GArray *buf, uint32_t i)
+{
+ uint32_t ni = htonl(i);
+
+ g_array_append_vals(buf, (void *)&ni, sizeof(ni));
+
+ return 1;
+}
+
+static int runes_protocol_store_strvec(GArray *buf, char *vec[])
+{
+ size_t len, i;
+
+ for (len = 0; vec[len]; ++len);
+ if (len > RUNES_MAX_PACKET_SIZE) {
+ runes_warn("string vector of size %d is too big", len);
+ return 0;
+ }
+
+#define STORE(type, val) \
+ do { \
+ if (!runes_protocol_store_##type(buf, val)) { \
+ return 0; \
+ } \
+ } while (0)
+
+ STORE(u32, len);
+ for (i = 0; i < len; ++i) {
+ STORE(str, vec[i]);
+ }
+
+#undef STORE
+
+ return 1;
+}
+
+static int runes_protocol_store_str(GArray *buf, char *str)
+{
+ size_t len = strlen(str);
+
+ if (len > RUNES_MAX_PACKET_SIZE) {
+ runes_warn("string of size %d is too big", len);
+ return 0;
+ }
+
+#define STORE(type, val) \
+ do { \
+ if (!runes_protocol_store_##type(buf, val)) { \
+ return 0; \
+ } \
+ } while (0)
+
+ STORE(u32, len);
+
+ g_array_append_vals(buf, str, len);
+
+#undef STORE
+
+ return 1;
+}
+
+static ssize_t runes_protocol_load_u32(char *buf, size_t len, uint32_t *i)
+{
+ uint32_t hi;
+
+ if (len < sizeof(uint32_t)) {
+ return -1;
+ }
+
+ hi = ((uint32_t *)buf)[0];
+ *i = ntohl(hi);
+
+ return sizeof(uint32_t);
+}
+
+static ssize_t runes_protocol_load_strvec(char *buf, size_t len, char ***vec)
+{
+ ssize_t offset = 0;
+ uint32_t veclen = 0;
+ size_t i;
+
+ *vec = NULL;
+
+#define LOAD(type, var) \
+ do { \
+ ssize_t incr; \
+ incr = runes_protocol_load_##type(buf + offset, len - offset, &var); \
+ if (incr < 0) { \
+ free(*vec); \
+ for (i = 0; i < veclen; ++i) { \
+ free(*vec[i]); \
+ } \
+ return -1; \
+ } \
+ offset += incr; \
+ } while (0)
+
+ LOAD(u32, veclen);
+ if (veclen > len) {
+ runes_warn("string of size %d is too big", strlen);
+ return -1;
+ }
+
+ *vec = calloc(veclen + 1, sizeof(char *));
+
+ for (i = 0; i < veclen; ++i) {
+ LOAD(str, (*vec)[i]);
+ }
+ (*vec)[veclen] = NULL;
+
+#undef LOAD
+
+ return offset;
+}
+
+static ssize_t runes_protocol_load_str(char *buf, size_t len, char **str)
+{
+ ssize_t offset = 0;
+ uint32_t strlen;
+
+ *str = NULL;
+
+#define LOAD(type, var) \
+ do { \
+ ssize_t incr; \
+ incr = runes_protocol_load_##type(buf + offset, len - offset, &var); \
+ if (incr < 0) { \
+ free(*str); \
+ return -1; \
+ } \
+ offset += incr; \
+ } while (0)
+
+ LOAD(u32, strlen);
+ if (strlen > len) {
+ runes_warn("string of size %d is too big", strlen);
+ return -1;
+ }
+
+ *str = malloc(strlen + 1);
+
+ memcpy(*str, buf + offset, strlen);
+ (*str)[strlen] = '\0';
+ offset += strlen;
+
+#undef LOAD
+
+ return offset;
+}
+
+static int runes_protocol_write_bytes(int sock, char *buf, size_t len)
+{
+ size_t bytes = 0;
+
+ while (bytes < len) {
+ ssize_t sent;
+
+ sent = send(sock, buf + bytes, len - bytes, 0);
+ if (sent <= 0 && errno != EINTR) {
+ runes_warn(
+ "couldn't write %d bytes to socket: %s",
+ len, strerror(errno));
+ return 0;
+ }
+ bytes += sent;
+ }
+
+ return 1;
+}
+
+static int runes_protocol_read_bytes(int sock, size_t len, char *outbuf)
+{
+ size_t bytes = 0;
+
+ while (bytes < len) {
+ ssize_t got;
+
+ got = recv(sock, outbuf + bytes, len - bytes, 0);
+ if (got <= 0 && errno != EINTR) {
+ runes_warn(
+ "couldn't read %d bytes from socket: %s",
+ len, strerror(errno));
+ return 0;
+ }
+ bytes += got;
+ }
+
+ return 1;
+}
diff --git a/src/protocol.h b/src/protocol.h
new file mode 100644
index 0000000..fb3af96
--- /dev/null
+++ b/src/protocol.h
@@ -0,0 +1,23 @@
+#ifndef _RUNES_PROTOCOL_H
+#define _RUNES_PROTOCOL_H
+
+#include <stdint.h>
+
+#define RUNES_PROTOCOL_MESSAGE_VERSION 1
+
+struct runes_protocol_message {
+ uint32_t argc;
+ char **argv;
+ char **envp;
+ char *cwd;
+};
+
+int runes_protocol_parse_message(
+ char *buf, size_t len, struct runes_protocol_message *outmsg);
+int runes_protocol_create_message(
+ struct runes_protocol_message *msg, char **outbuf, size_t *outlen);
+void runes_protocol_free_message(struct runes_protocol_message *msg);
+int runes_protocol_read_packet(int sock, char **outbuf, size_t *outlen);
+int runes_protocol_send_packet(int s, char *buf, size_t len);
+
+#endif
diff --git a/src/runesc.c b/src/runesc.c
index 5046b98..88adec3 100644
--- a/src/runesc.c
+++ b/src/runesc.c
@@ -1,71 +1,40 @@
-#include <arpa/inet.h>
-#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
#include "runes.h"
-#define MAX_SOCKET_PATH_LEN \
- (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path))
+#include "protocol.h"
+#include "socket.h"
-static int runes_socket_open_client(char *name);
+extern char **environ;
int main (int argc, char *argv[])
{
char *name, *buf;
- int s, i;
- size_t len, offset;
- uint32_t argc32 = argc, argv_len;
+ int s;
+ size_t len;
+ struct runes_protocol_message msg;
- name = runes_get_daemon_socket_name();
- s = runes_socket_open_client(name);
+ msg.argc = argc;
+ msg.argv = argv;
+ msg.envp = environ;
+ msg.cwd = runes_getcwd();
- len = sizeof(argc32) + sizeof(argv_len);
- for (i = 0; i < argc; ++i) {
- len += strlen(argv[i]) + 1;
+ name = runes_get_daemon_socket_name();
+ s = runes_socket_client_open(name);
+ if (!runes_protocol_create_message(&msg, &buf, &len)) {
+ runes_warn("couldn't create message");
}
-
- buf = malloc(len);
- ((uint32_t*)buf)[0] = htonl(argc32);
- offset = sizeof(argc32) + sizeof(argv_len);
- ((uint32_t*)buf)[1] = htonl(len - offset);
-
- for (i = 0; i < argc; ++i) {
- size_t arg_len = strlen(argv[i]) + 1;
- memcpy(buf + offset, argv[i], arg_len);
- offset += arg_len;
+ else {
+ if (!runes_protocol_send_packet(s, buf, len)) {
+ runes_warn("couldn't send packet");
+ free(buf);
+ }
}
- send(s, buf, offset, 0);
free(buf);
- shutdown(s, SHUT_RDWR);
- return 0;
-}
+ free(msg.cwd);
+ runes_socket_client_close(s);
-static int runes_socket_open_client(char *name)
-{
- int s;
- struct sockaddr_un client;
-
- if (strlen(name) + 1 > MAX_SOCKET_PATH_LEN) {
- runes_die("socket path %s is too long", name);
- }
-
- s = socket(AF_UNIX, SOCK_STREAM, 0);
- if (s < 0) {
- runes_die("couldn't create socket: %s", strerror(errno));
- }
-
- client.sun_family = AF_UNIX;
- strcpy(client.sun_path, name);
- if (connect(s, (struct sockaddr*)(&client), sizeof(struct sockaddr_un))) {
- runes_die(
- "couldn't connect to socket at %s: %s", name, strerror(errno));
- }
-
- return s;
+ return 0;
}
diff --git a/src/socket.c b/src/socket.c
new file mode 100644
index 0000000..3d0a3ae
--- /dev/null
+++ b/src/socket.c
@@ -0,0 +1,117 @@
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "runes.h"
+#include "socket.h"
+
+#define MAX_SOCKET_PATH_LEN \
+ (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path))
+
+static void runes_socket_populate_sockaddr(
+ char *path, struct sockaddr_un *addr);
+
+int runes_socket_client_open(char *path)
+{
+ int s;
+ struct sockaddr_un client;
+
+ runes_socket_populate_sockaddr(path, &client);
+
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0) {
+ runes_die("couldn't create socket: %s", strerror(errno));
+ }
+
+ if (connect(s, (struct sockaddr*)(&client), sizeof(struct sockaddr_un))) {
+ runes_die(
+ "couldn't connect to socket at %s: %s", path, strerror(errno));
+ }
+
+ return s;
+}
+
+int runes_socket_server_open(char *path)
+{
+ char *dir, *slash;
+ int s;
+ struct sockaddr_un server;
+
+ runes_socket_populate_sockaddr(path, &server);
+
+ dir = strdup(path);
+ slash = strrchr(dir, '/');
+ if (slash == NULL) {
+ runes_die("socket path %s must be an absolute path", path);
+ }
+ *slash = '\0';
+ runes_mkdir_p(dir);
+ free(dir);
+
+ unlink(path);
+
+ s = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0) {
+ runes_die("couldn't create socket: %s", strerror(errno));
+ }
+
+ if (bind(s, (struct sockaddr*)(&server), sizeof(struct sockaddr_un))) {
+ runes_die(
+ "couldn't bind to socket %s: %s", path, strerror(errno));
+ }
+
+ if (chmod(path, S_IRUSR|S_IWUSR)) {
+ runes_die(
+ "couldn't chmod socket %s: %s", path, strerror(errno));
+ }
+
+ if (listen(s, 5)) {
+ runes_die(
+ "couldn't listen on socket %s: %s", path, strerror(errno));
+ }
+
+ return s;
+}
+
+int runes_socket_server_accept(int ss)
+{
+ struct sockaddr_un client;
+ socklen_t len = sizeof(client);
+ int cs;
+
+ cs = accept(ss, (struct sockaddr*)(&client), &len);
+ if (cs < 0) {
+ runes_die("couldn't accept connection: %s", strerror(errno));
+ }
+
+ return cs;
+}
+
+void runes_socket_client_close(int s)
+{
+ close(s);
+}
+
+void runes_socket_server_close(int s, char *path)
+{
+ close(s);
+ unlink(path);
+}
+
+static void runes_socket_populate_sockaddr(
+ char *path, struct sockaddr_un *addr)
+{
+ size_t name_len = strlen(path) + 1; // including the nul byte
+
+ if (name_len > MAX_SOCKET_PATH_LEN) {
+ runes_die("socket path %s is too long", path);
+ }
+
+ addr->sun_family = AF_UNIX;
+ strncpy(addr->sun_path, path, name_len);
+}
diff --git a/src/socket.h b/src/socket.h
new file mode 100644
index 0000000..85387c4
--- /dev/null
+++ b/src/socket.h
@@ -0,0 +1,10 @@
+#ifndef _RUNES_SOCKET_H
+#define _RUNES_SOCKET_H
+
+int runes_socket_client_open(char *path);
+int runes_socket_server_open(char *path);
+int runes_socket_server_accept(int s);
+void runes_socket_client_close(int s);
+void runes_socket_server_close(int s, char *path);
+
+#endif
diff --git a/src/util.c b/src/util.c
index 8737f11..c663710 100644
--- a/src/util.c
+++ b/src/util.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <unistd.h>
#include "runes.h"
@@ -103,6 +104,19 @@ void runes_mkdir_p(char *dir)
free(dir);
}
+char *runes_getcwd(void)
+{
+ char buf[4096];
+
+ if (getcwd(buf, 4096)) {
+ return strdup(buf);
+ }
+ else {
+ runes_die("getcwd: %s", strerror(errno));
+ return NULL;
+ }
+}
+
static void runes_vwarn(const char *fmt, va_list ap)
{
size_t fmt_len;
diff --git a/src/util.h b/src/util.h
index e4b9dcb..931cc0d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -8,5 +8,6 @@ void runes_die(const char *fmt, ...);
char *runes_get_daemon_socket_name(void);
int runes_sprintf_dup(char **out, const char *fmt, ...);
void runes_mkdir_p(char *dir);
+char *runes_getcwd(void);
#endif