aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Makefile2
-rw-r--r--README4
-rw-r--r--bindtemp_un.c89
-rw-r--r--libsimple.h1
-rw-r--r--libsimple/net.h16
5 files changed, 110 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index 4a8a324..a66da02 100644
--- a/Makefile
+++ b/Makefile
@@ -39,6 +39,7 @@ SUBHDR =\
libsimple/memalloc.h\
libsimple/memdup.h\
libsimple/memelem.h\
+ libsimple/net.h\
libsimple/overflow.h\
libsimple/posix_memalign.h\
libsimple/posix_memalignz.h\
@@ -86,6 +87,7 @@ OBJ =\
asprintf.o\
bindex.o\
bindex_r.o\
+ bindtemp_un.o\
callocn.o\
close.o\
close_range.o\
diff --git a/README b/README
index 1de7b5c..d7aa9ea 100644
--- a/README
+++ b/README
@@ -5,8 +5,8 @@ values for integer data types.
All functions are namespaced with `libsimple_` and aliased with macro
definitions to unnamespaced names unless there already is a macro with that
-name. However, some functions are seen as libsimple specific and do not
-have unnamespaced.
+name. However, some functions are seen as libsimple specific and are not
+namespaced.
Programs using this library should define `char *argv0` and set it to
the 0:th command line argument.
diff --git a/bindtemp_un.c b/bindtemp_un.c
new file mode 100644
index 0000000..0362e47
--- /dev/null
+++ b/bindtemp_un.c
@@ -0,0 +1,89 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+/**
+ * Fill a buffer with random alphanumerical symbols, and '_' and '-'
+ *
+ * @param buf The buffer to fill
+ * @param n The size of the buffer
+ */
+static void
+random_alnum(char *buf, size_t n)
+{
+ size_t i;
+ int rnd;
+ double drnd;
+
+#if defined(__linux__) && defined(GRND_NONBLOCK)
+ ssize_t r = getrandom(buf, n, GRND_NONBLOCK);
+ i = r < 0 ? 0 : (size_t)r;
+#else
+ i = 0;
+#endif
+
+ for (; i < n; i++) {
+ rnd = rand();
+ drnd = (double)rnd / (double)RAND_MAX;
+ drnd *= 63;
+ rnd = (int)drnd;
+ buf[i] = (char)rnd;
+ }
+
+ for (i = 0; i < n; i++)
+ buf[i] = "0123456789_abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ"[buf[i] & 63];
+}
+
+
+int
+libsimple_bindtemp_un(int fd, int dir_fd, struct sockaddr_un *addr, socklen_t *addrlen)
+{
+ int len, saved_errno = errno;
+ size_t rem, try_limit = 1000;
+ struct sockaddr_un addr_;
+
+ if (!addr)
+ addr = &addr_;
+ if (addrlen)
+ *addrlen = sizeof(*addr);
+
+ memset(addr, 0, sizeof(*addr));
+ addr->sun_family = AF_UNIX;
+
+ if (dir_fd == AT_FDCWD)
+ len = snprintf(addr->sun_path, sizeof(addr->sun_path), "tmp");
+ else
+ len = snprintf(addr->sun_path, sizeof(addr->sun_path), "/dev/fd/%i/tmp", dir_fd);
+ if (len < 0 || (size_t)len >= sizeof(addr->sun_path) || sizeof(addr->sun_path) - (size_t)len < 6)
+ abort();
+ rem = sizeof(addr->sun_path) - 1 - len;
+ addr->sun_path[sizeof(addr->sun_path) - 1] = 0;
+
+ while (try_limit--) {
+ again:
+ random_alnum(&addr->sun_path[len], rem);
+ if (!bind(fd, (void *)&addr, (socklen_t)sizeof(*addr))) {
+ errno = saved_errno;
+ return 0;
+ } else if (errno == ENAMETOOLONG && rem > 5) {
+ addr->sun_path[len + --rem] = 0;
+ goto again;
+ } else if (errno != EEXIST && errno != EADDRINUSE) {
+ return -1;
+ }
+ }
+ return -1;
+}
+
+
+#else
+#include "test.h"
+
+int
+main(void) /* TODO add test */
+{
+ return 0;
+}
+
+#endif
diff --git a/libsimple.h b/libsimple.h
index bdfc7c7..1d72f46 100644
--- a/libsimple.h
+++ b/libsimple.h
@@ -167,6 +167,7 @@
#include "libsimple/search.h"
#include "libsimple/random.h"
#include "libsimple/abs.h"
+#include "libsimple/net.h"
/**
diff --git a/libsimple/net.h b/libsimple/net.h
new file mode 100644
index 0000000..c30020b
--- /dev/null
+++ b/libsimple/net.h
@@ -0,0 +1,16 @@
+/* See LICENSE file for copyright and license details. */
+
+
+/**
+ * Bind a unix(7) socket to a random file name in a specific directory
+ *
+ * @param fd The socket's file descriptor
+ * @param dir_fd File descriptor to the directory the socket shall be
+ * stored in (may be `AT_FDCWD`)
+ * @param addr_out Output parameter for the socket name (may be `NULL`);
+ * `&strrchr(addr_out->sun_path, '/')[1]` will be the
+ * name of the file the socket will be bound to
+ * @param addrlen_out Output parameter for the size of the socket name (may be `NULL`)
+ * @return 0 on success, -1 on failure
+ */
+int libsimple_bindtemp_un(int fd, int dir_fd, struct sockaddr_un *addr_out, socklen_t *addrlen_out); /* TODO man */