+ return *(int *) CMSG_DATA(cmsgptr);
+}
+
+static int receive_fd(struct unix_socket_addr socket_addr) {
+ int socketfd;
+ int ret;
+ int result;
+
+ if((socketfd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not open stream socket (error %d)!", socketfd);
+ return -1;
+ }
+
+ if((ret = connect(socketfd, (struct sockaddr *) &socket_addr.addr, socket_addr.size)) < 0) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Could not connect to Unix socket (error %d)!", ret);
+ result = -1;
+ goto end;
+ }
+
+ result = read_fd(socketfd);
+
+end:
+ close(socketfd);
+ return result;
+}
+
+static struct unix_socket_addr parse_socket_addr(const char *path) {
+ struct sockaddr_un socket_addr;
+ size_t path_length;
+
+ if(strlen(path) >= sizeof(socket_addr.sun_path)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Unix socket path too long!");
+ return (struct unix_socket_addr) {0};
+ }
+
+ socket_addr.sun_family = AF_UNIX;
+ strncpy(socket_addr.sun_path, path, sizeof(socket_addr.sun_path));
+
+ if(path[0] == '@') {
+ /* abstract namespace socket */
+ socket_addr.sun_path[0] = '\0';
+ path_length = strlen(path);
+ } else {
+ /* filesystem path with NUL terminator */
+ path_length = strlen(path) + 1;
+ }
+
+ return (struct unix_socket_addr) {
+ .size = offsetof(struct sockaddr_un, sun_path) + path_length,
+ .addr = socket_addr
+ };