/* * Saitek X52 Pro MFD & LED driver - Client communication library * * Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org) * * SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0 */ #include "config.h" #include #include #include #include #include "x52dcomm-internal.h" #include "x52d_const.h" const char * x52d_command_sock_path(const char *sock_path) { if (sock_path == NULL) { sock_path = X52D_SOCK_COMMAND; } return sock_path; } const char * x52d_notify_sock_path(const char *sock_path) { if (sock_path == NULL) { sock_path = X52D_SOCK_NOTIFY; } return sock_path; } static int _setup_sockaddr(struct sockaddr_un *remote, const char *sock_path) { int len; if (remote == NULL) { errno = EINVAL; return -1; } len = strlen(sock_path); if ((size_t)len >= sizeof(remote->sun_path)) { /* Socket path will not fit inside sun_path */ errno = E2BIG; return -1; } /* Setup the sockaddr structure */ memset(remote, 0, sizeof(*remote)); remote->sun_family = AF_UNIX; /* We've already verified that sock_path will fit, so we don't need strncpy */ strcpy(remote->sun_path, sock_path); len += sizeof(remote->sun_family); return len; } int x52d_setup_command_sock(const char *sock_path, struct sockaddr_un *remote) { return _setup_sockaddr(remote, x52d_command_sock_path(sock_path)); } int x52d_setup_notify_sock(const char *sock_path, struct sockaddr_un *remote) { return _setup_sockaddr(remote, x52d_notify_sock_path(sock_path)); } int x52d_set_socket_nonblocking(int sock_fd) { int flags; /* Mark the socket as non-blocking */ flags = fcntl(sock_fd, F_GETFL); if (flags < 0) { goto sock_failure; } if (fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK) < 0) { goto sock_failure; } return 0; sock_failure: close(sock_fd); return -1; } int x52d_listen_socket(struct sockaddr_un *local, int len, int sock_fd) { /* Cleanup any existing socket */ unlink(local->sun_path); if (bind(sock_fd, (struct sockaddr *)local, (socklen_t)len) < 0) { /* Failure binding socket */ return -1; } if (listen(sock_fd, X52D_MAX_CLIENTS) < 0) { return -1; } return 0; } void x52d_split_args(int *argc, char **argv, char *buffer, int buflen) { int i = 0; while (i < buflen) { if (buffer[i]) { argv[*argc] = buffer + i; (*argc)++; for (; i < buflen && buffer[i]; i++); // At this point, buffer[i] = '\0' // Skip to the next character. i++; } else { // We should never reach here, unless we have two NULs in a row argv[*argc] = buffer + i; (*argc)++; i++; } } }