aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libmdsclient/address.c94
-rw-r--r--src/libmdsclient/address.h5
-rw-r--r--src/libmdsclient/comm.c15
-rw-r--r--src/libmdsclient/comm.h16
4 files changed, 110 insertions, 20 deletions
diff --git a/src/libmdsclient/address.c b/src/libmdsclient/address.c
index 3a7aba3..0bb347a 100644
--- a/src/libmdsclient/address.c
+++ b/src/libmdsclient/address.c
@@ -17,9 +17,76 @@
*/
#include "address.h"
+#include <stddef.h>
+#include <sys/socket.h>
#include <sys/un.h>
#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <libmdsserver/config.h>
+
+
+
+/**
+ * Check whether a string is a radix-10 non-negative integer
+ *
+ * @param str The string
+ * @return Whether a string is a radix-10 non-negative integer
+ */
+__attribute__((nonnull))
+static int is_pzinteger(const char* restrict str)
+{
+ for (; *str; str++)
+ if (('0' > *str) || (*str > '9'))
+ return 0;
+ return 1;
+}
+
+
+/**
+ * Set the socket adress, with the address family `AF_UNIX`
+ *
+ * @param out_address Output paramter for the socket address
+ * @param pathlen Pointer to a variable where the length of the pathname will be stored
+ * @param format Formatting string for the pathname (should end with "%zn")
+ * @param ... Formatting arguments for the pathname (should end with `pathlen`)
+ * @return Zero on success, -1 on error, `errno`
+ * will have been set accordinly on error
+ *
+ * @throws ENOMEM Out of memory. Possibly, the application hit the
+ * RLIMIT_AS or RLIMIT_DATA limit described in getrlimit(2).
+ * @throws ENAMETOOLONG The filename of the target socket is too long
+ */
+__attribute__((nonnull, format(gnu_printf, 3, 4)))
+static int set_af_unix(struct sockaddr** restrict out_address, ssize_t* pathlen, const char* format, ...)
+#define set_af_unix(a, f, ...) ((set_af_unix)(a, &pathlen, f "%zn", __VA_ARGS__, &pathlen))
+{
+ struct sockaddr_un* address;
+ size_t maxlen;
+ va_list args;
+
+ address = malloc(sizeof(struct sockaddr_un));
+ *out_address = (struct sockaddr*)address;
+ if (address == NULL)
+ return -1;
+
+ maxlen = sizeof(address->sun_path) / sizeof(address->sun_path[0]);
+
+ va_start(args, format);
+
+ address->sun_family = AF_UNIX;
+ vsnprintf(address->sun_path, maxlen, format, args);
+
+ va_end(args);
+
+ if ((size_t)*pathlen > maxlen)
+ return errno = ENAMETOOLONG, -1;
+
+ return 0;
+}
/**
@@ -30,17 +97,38 @@
* @return Zero on success, even if parsing failed, -1 on error,
* `errno` will have been set accordinly on error
*
- * @throws ENOMEM Out of memory. Possibly, the application hit the
- * RLIMIT_AS or RLIMIT_DATA limit described in getrlimit(2).
+ * @throws ENOMEM Out of memory. Possibly, the application hit the
+ * RLIMIT_AS or RLIMIT_DATA limit described in getrlimit(2).
+ * @throws ENAMETOOLONG The filename of the target socket is too long
*/
int libmds_parse_display_adress(const char* restrict display, libmds_display_address_t* restrict address)
{
+ ssize_t pathlen;
+
address->domain = -1;
address->type = -1;
address->protocol = -1;
address->address = NULL;
address->address_len = 0;
- return (void) display, 0; /* TODO */
+ if (strchr(display, ':') == NULL)
+ return 0;
+
+ if (*display == ':')
+ {
+ address->domain = PF_UNIX;
+ address->type = SOCK_STREAM;
+ address->protocol = 0;
+ address->address_len = sizeof(struct sockaddr_un);
+
+ if (strstr(display, ":file:") == display)
+ return set_af_unix(&(address->address), "%s", display + 6);
+ else if (display[1] && is_pzinteger(display + 1))
+ return set_af_unix(&(address->address), "%s/%s.socket",
+ MDS_RUNTIME_ROOT_DIRECTORY, display + 1);
+ return 0;
+ }
+
+ return 0;
}
diff --git a/src/libmdsclient/address.h b/src/libmdsclient/address.h
index b094772..88ad4d3 100644
--- a/src/libmdsclient/address.h
+++ b/src/libmdsclient/address.h
@@ -74,8 +74,9 @@ typedef struct libmds_display_address
* @return Zero on success, even if parsing failed, -1 on error,
* `errno` will have been set accordinly on error
*
- * @throws ENOMEM Out of memory. Possibly, the application hit the
- * RLIMIT_AS or RLIMIT_DATA limit described in getrlimit(2).
+ * @throws ENOMEM Out of memory. Possibly, the application hit the
+ * RLIMIT_AS or RLIMIT_DATA limit described in getrlimit(2).
+ * @throws ENAMETOOLONG The filename of the target socket is too long
*/
__attribute__((nonnull))
int libmds_parse_display_adress(const char* restrict display, libmds_display_address_t* restrict address);
diff --git a/src/libmdsclient/comm.c b/src/libmdsclient/comm.c
index 11d03d4..a4c5fff 100644
--- a/src/libmdsclient/comm.c
+++ b/src/libmdsclient/comm.c
@@ -24,8 +24,6 @@
#include <sys/socket.h>
#include <string.h>
-#include <libmdsserver/config.h>
-
#define min(a, b) ((a) < (b) ? (a) : (b))
@@ -137,12 +135,13 @@ void libmds_connection_free(libmds_connection_t* restrict this)
* otherwise, `errno` will have been set to describe
* the error.
*
- * @throws EFAULT If the display server's address is not properly
- * formatted, or specifies an unsupported protocol,
- * `libmds_parse_display_adress` can be used to
- * figure out what is wrong.
- * @throws Any error specified for socket(2)
- * @throws Any error specified for connect(2), except EINTR
+ * @throws EFAULT If the display server's address is not properly
+ * formatted, or specifies an unsupported protocol,
+ * `libmds_parse_display_adress` can be used to
+ * figure out what is wrong.
+ * @throws ENAMETOOLONG The filename of the target socket is too long
+ * @throws Any error specified for socket(2)
+ * @throws Any error specified for connect(2), except EINTR
*/
int libmds_connection_establish(libmds_connection_t* restrict this, const char** restrict display)
{
diff --git a/src/libmdsclient/comm.h b/src/libmdsclient/comm.h
index b868e77..94dcc7a 100644
--- a/src/libmdsclient/comm.h
+++ b/src/libmdsclient/comm.h
@@ -124,13 +124,15 @@ void libmds_connection_free(libmds_connection_t* restrict this);
* otherwise, `errno` will have been set to describe
* the error.
*
- * @throws EFAULT If the display server's address is not properly
- * formatted, or specifies an unsupported protocol,
- * `libmds_parse_display_adress` can be used to
- * figure out what is wrong.
- * @throws Any error specified for socket(2)
- * @throws Any error specified for connect(2), except EINTR
- */__attribute__((nonnull))
+ * @throws EFAULT If the display server's address is not properly
+ * formatted, or specifies an unsupported protocol,
+ * `libmds_parse_display_adress` can be used to
+ * figure out what is wrong.
+ * @throws ENAMETOOLONG The filename of the target socket is too long
+ * @throws Any error specified for socket(2)
+ * @throws Any error specified for connect(2), except EINTR
+ */
+__attribute__((nonnull))
int libmds_connection_establish(libmds_connection_t* restrict this, const char** restrict display);
/**