aboutsummaryrefslogtreecommitdiffstats
path: root/libaxl_parse_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'libaxl_parse_display.c')
-rw-r--r--libaxl_parse_display.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/libaxl_parse_display.c b/libaxl_parse_display.c
new file mode 100644
index 0000000..1b304e3
--- /dev/null
+++ b/libaxl_parse_display.c
@@ -0,0 +1,154 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+int
+libaxl_parse_display(const char *name, char **hostp, char **protocolp, int *displayp, int *screenp)
+{
+ char *p;
+ size_t n;
+ unsigned long int ul;
+ int err;
+ int saved_errno = errno;
+ struct stat st;
+
+ *hostp = NULL;
+ *protocolp = NULL;
+ *displayp = 0;
+ *screenp = 0;
+
+ /* Get display server name string, if not specified */
+ if (!name || !*name) {
+ name = getenv("DISPLAY");
+ if (!name || !*name) {
+ liberror_save_backtrace(NULL);
+ liberror_set_error("No display server specified", "libaxl_parse_display", "libaxl",
+ LIBAXL_ERROR_NO_DISPLAY_SERVER_SPECIFIED);
+ err = LIBAXL_ERROR_NO_DISPLAY_SERVER_SPECIFIED;
+ goto fail;
+ }
+ }
+
+ /* Get path and test if protocol is "unix" */
+ p = strrchr(name, '.');
+ if (p && isdigit(*p)) {
+ errno = 0;
+ ul = strtoul(p, &p, 10);
+ if (errno || ul > (unsigned long int)INT_MAX)
+ p = NULL;
+ else
+ *screenp = (int)ul;
+ }
+ n = p ? (size_t)(p - name) : strlen(name);
+ if (n) {
+ *hostp = liberror_malloc(n + 1);
+ if (!*hostp)
+ goto errno_fail;
+ memcpy(*hostp, name, n);
+ (*hostp)[n] = '\0';
+ if (stat(*hostp, &st) || (st.st_mode & S_IFMT) != S_IFSOCK) {
+ free(*hostp);
+ *hostp = NULL;
+ goto normal;
+ }
+ *protocolp = liberror_malloc(sizeof("unix"));
+ if (!*protocolp)
+ goto errno_fail;
+ stpcpy(*protocolp, "unix");
+ goto done;
+ }
+
+normal:
+ /* Get protocol */
+ p = strrchr(name, '/');
+ if (p) {
+ n = (size_t)(p - name);
+ *protocolp = liberror_malloc(n + 1);
+ if (*protocolp)
+ goto errno_fail;
+ memcpy(*protocolp, name, n);
+ (*protocolp)[n] = '\0';
+ name = &p[1];
+ }
+
+ /* Get host */
+ p = strrchr(name, ':');
+ if (!p) {
+ liberror_save_backtrace(NULL);
+ liberror_set_error("Invalid display name: no display index", "libaxl_parse_display", "libaxl",
+ LIBAXL_ERROR_INVALID_DISPLAY_NAME_NO_DISPLAY_INDEX);
+ err = LIBAXL_ERROR_INVALID_DISPLAY_NAME_NO_DISPLAY_INDEX;
+ goto fail;
+ } else {
+ n = (size_t)(p - name);
+ *hostp = liberror_malloc(n + 1);
+ if (!*hostp)
+ goto errno_fail;
+ memcpy(*hostp, name, n);
+ (*hostp)[n] = '\0';
+ name = &p[1];
+ }
+
+ /* Get display */
+ if (!isdigit(*name)) {
+ liberror_save_backtrace(NULL);
+ liberror_set_error("Invalid display name: no display index", "libaxl_parse_display", "libaxl",
+ LIBAXL_ERROR_INVALID_DISPLAY_NAME_NO_DISPLAY_INDEX);
+ err = LIBAXL_ERROR_INVALID_DISPLAY_NAME_NO_DISPLAY_INDEX;
+ goto fail;
+ }
+ saved_errno = errno;
+ errno = 0;
+ ul = strtoul(name, (void *)&name, 10);
+ if (errno || ul > (unsigned long int)(*hostp ? 65535 - X_TCP_PORT : INT_MAX)) {
+ liberror_save_backtrace(NULL);
+ liberror_set_error("Invalid display name: display index is out of domain", "libaxl_parse_display", "libaxl",
+ LIBAXL_ERROR_INVALID_DISPLAY_NAME_DISPLAY_INDEX_OUT_OF_DOMAIN);
+ err = LIBAXL_ERROR_INVALID_DISPLAY_NAME_DISPLAY_INDEX_OUT_OF_DOMAIN;
+ goto fail;
+ }
+ *displayp = (int)ul;
+ errno = saved_errno;
+
+ /* Get screen */
+ if (*name)
+ goto done;
+ if (!isdigit(*name)) {
+ liberror_save_backtrace(NULL);
+ liberror_set_error("Invalid display name: invalid screen index", "libaxl_parse_display", "libaxl",
+ LIBAXL_ERROR_INVALID_DISPLAY_NAME_INVALID_SCREEN_INDEX);
+ err = LIBAXL_ERROR_INVALID_DISPLAY_NAME_INVALID_SCREEN_INDEX;
+ goto fail;
+ }
+ errno = 0;
+ ul = strtoul(name, (void *)&name, 10);
+ if (errno || ul > (unsigned long int)INT_MAX) {
+ liberror_save_backtrace(NULL);
+ liberror_set_error("Invalid display name: screen index is out of domain", "libaxl_parse_display", "libaxl",
+ LIBAXL_ERROR_INVALID_DISPLAY_NAME_SCREEN_INDEX_OUT_OF_DOMAIN);
+ err = LIBAXL_ERROR_INVALID_DISPLAY_NAME_SCREEN_INDEX_OUT_OF_DOMAIN;
+ goto fail;
+ }
+ *screenp = (int)ul;
+ if (*name) {
+ liberror_save_backtrace(NULL);
+ liberror_set_error("Invalid display name: invalid screen index", "libaxl_parse_display", "libaxl",
+ LIBAXL_ERROR_INVALID_DISPLAY_NAME_INVALID_SCREEN_INDEX);
+ err = LIBAXL_ERROR_INVALID_DISPLAY_NAME_INVALID_SCREEN_INDEX;
+ goto fail;
+ }
+
+done:
+ errno = saved_errno;
+ return 0;
+
+errno_fail:
+ err = LIBAXL_ERROR_SYSTEM;
+fail:
+ free(*protocolp);
+ *protocolp = NULL;
+ free(*hostp);
+ *hostp = NULL;
+ if (err != LIBAXL_ERROR_SYSTEM)
+ errno = EINVAL;
+ return err;
+}