#endif
#include "ecore_drm_private.h"
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <signal.h>
-
-#define RIGHTS_LEN CMSG_LEN(sizeof(int))
-
-#define IOVSET(_iov, _addr, _len) \
- (_iov)->iov_base = (void *)(_addr); \
- (_iov)->iov_len = (_len);
/* local variables */
static int _ecore_drm_init_count = 0;
-static int _ecore_drm_sockets[2] = { -1, -1 };
-static struct cmsghdr *cmsgptr = NULL;
+static char *sid;
/* external variables */
struct udev *udev;
int _ecore_drm_log_dom = -1;
-#ifdef LOG_TO_FILE
-FILE *lg;
-#endif
-
-static Eina_Bool
-_ecore_drm_sockets_create(void)
-{
- if (_ecore_drm_sockets[0] > -1) return EINA_TRUE;
-
- /* create a pair of sequenced sockets (fixed-length)
- * NB: when reading from one of these, it is required that we read
- * an entire packet with each read() call */
- if (socketpair(AF_LOCAL, SOCK_SEQPACKET | SOCK_NONBLOCK,
- 0, _ecore_drm_sockets) < 0)
- {
- ERR("Socketpair Failed: %m");
- return EINA_FALSE;
- }
-
- /* NB: We don't want cloexec for the sockets. That would cause them to be
- * closed when we exec the child process but we need them open so that
- * we can pass messages */
- /* if (fcntl(_ecore_drm_sockets[0], F_SETFD, FD_CLOEXEC) < 0) */
- /* { */
- /* ERR("Failed to set CLOEXEC: %m"); */
- /* return EINA_FALSE; */
- /* } */
-
- /* DBG("Parent Socket: %d", _ecore_drm_sockets[0]); */
- /* DBG("Child Socket: %d", _ecore_drm_sockets[1]); */
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_ecore_drm_launcher_spawn(void)
-{
- pid_t pid;
-
- if ((pid = fork()) < 0) return EINA_FALSE;
-
- if (pid == 0)
- {
- char renv[64], wenv[64], buff[PATH_MAX];
- char *args[1] = { NULL };
- sigset_t mask;
-
- /* read socket for slave is 1 */
- snprintf(renv, sizeof(renv), "ECORE_DRM_LAUNCHER_SOCKET_READ=%d",
- _ecore_drm_sockets[1]);
-
- /* write socket for slave is 0 */
- snprintf(wenv, sizeof(wenv), "ECORE_DRM_LAUNCHER_SOCKET_WRITE=%d",
- _ecore_drm_sockets[0]);
-
- /* assemble exec path */
- snprintf(buff, sizeof(buff),
- "%s/ecore_drm/bin/%s/ecore_drm_launch",
- PACKAGE_LIB_DIR, MODULE_ARCH);
-
- /* don't give our signal mask to the child */
- sigemptyset(&mask);
- sigaddset(&mask, SIGTERM);
- sigaddset(&mask, SIGCHLD);
- sigaddset(&mask, SIGINT);
- sigaddset(&mask, SIGTTIN);
- sigaddset(&mask, SIGTTOU);
- sigprocmask(SIG_UNBLOCK, &mask, NULL);
-
- /* NB: We need to use execve here so that capabilities are inherited.
- * Also, this should set Our (ecore_drm) effective uid to be the
- * owner of the launched process (setuid in this case) */
- char *ev[3] = { strdup(renv), strdup(wenv), NULL };
- execve(buff, args, ev);
- }
- else
- {
- int status;
-
- while (waitpid(pid, &status, WNOHANG) < 0)
- if (errno != EINTR) break;
-
- return EINA_TRUE;
- }
-
- return EINA_FALSE;
-}
-
-static ssize_t
-_ecore_drm_socket_send(int opcode, int fd, void *data, size_t bytes)
-{
- Ecore_Drm_Message dmsg;
- struct iovec iov[2];
- struct msghdr msg;
- ssize_t size;
- int *iptr;
-
- /* Simplified version of sending messages. We don't need to send any
- * 'credentials' with this as it is just basically an IPC to send over
- * our request to the slave process */
-
- /* NB: Hmm, don't think we need to set any socket options here */
-
- memset(&dmsg, 0, sizeof(dmsg));
-
- IOVSET(iov + 0, &dmsg, sizeof(dmsg));
- IOVSET(iov + 1, &data, bytes);
-
- dmsg.opcode = opcode;
- dmsg.size = bytes;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = iov;
- msg.msg_iovlen = 2;
- msg.msg_flags = 0;
-
- if ((!cmsgptr) && (!(cmsgptr = malloc(RIGHTS_LEN))))
- return -1;
-
- cmsgptr->cmsg_level = SOL_SOCKET;
- cmsgptr->cmsg_type = SCM_RIGHTS;
- cmsgptr->cmsg_len = RIGHTS_LEN;
-
- msg.msg_control = cmsgptr;
- msg.msg_controllen = RIGHTS_LEN;
-
- iptr = (int *)(CMSG_DATA(cmsgptr));
- if (fd > -1) *iptr = fd;
- else *iptr = _ecore_drm_sockets[1];
-
- errno = 0;
- size = sendmsg(_ecore_drm_sockets[1], &msg, MSG_EOR);
- if (errno != 0)
- {
- DBG("Error Sending Message: %m");
- }
-
- /* DBG("Sent %li bytes to Socket %d", size, _ecore_drm_sockets[1]); */
-
- return size;
-}
-
-static int
-_ecore_drm_socket_receive(int opcode EINA_UNUSED, int *fd, void **data, size_t bytes)
-{
- int ret = ECORE_DRM_OP_FAILURE;
- Ecore_Drm_Message dmsg;
- struct cmsghdr *cmsg;
- struct iovec iov[2];
- struct msghdr msg;
- char buff[CMSG_SPACE(sizeof(fd))];
- int *iptr;
- /* ssize_t size; */
-
- memset(&dmsg, 0, sizeof(dmsg));
- memset(&buff, 0, sizeof(buff));
-
- IOVSET(iov + 0, &dmsg, sizeof(dmsg));
- IOVSET(iov + 1, &buff, sizeof(buff));
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = iov;
- msg.msg_iovlen = 2;
- msg.msg_flags = 0;
-
- if ((!cmsgptr) && (!(cmsgptr = malloc(RIGHTS_LEN))))
- return -1;
-
- msg.msg_control = cmsgptr;
- msg.msg_controllen = RIGHTS_LEN;
-
- errno = 0;
- recvmsg(_ecore_drm_sockets[0], &msg, 0);
- if (errno != 0)
- {
- ERR("Failed to receive message: %m");
- return -1;
- }
-
- /* DBG("Received %li bytes from %d", size, _ecore_drm_sockets[0]); */
-
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg))
- {
- if (cmsg->cmsg_level != SOL_SOCKET)
- continue;
-
- switch (cmsg->cmsg_type)
- {
- case SCM_RIGHTS:
- iptr = (int *)(CMSG_DATA(cmsg));
- if (fd) *fd = *iptr;
- switch (dmsg.opcode)
- {
- case ECORE_DRM_OP_DEVICE_OPEN:
- case ECORE_DRM_OP_DEVICE_CLOSE:
- case ECORE_DRM_OP_TTY_OPEN:
- case ECORE_DRM_OP_DEVICE_MASTER_DROP:
- case ECORE_DRM_OP_DEVICE_MASTER_SET:
- if ((fd) && (*fd >= 0)) ret = ECORE_DRM_OP_SUCCESS;
- if (data) memcpy(*data, buff, bytes);
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
- }
-
- return ret;
-}
-
-void
-_ecore_drm_message_send(int opcode, int fd, void *data, size_t bytes)
-{
- _ecore_drm_socket_send(opcode, fd, data, bytes);
-}
-
-Eina_Bool
-_ecore_drm_message_receive(int opcode, int *fd, void **data, size_t bytes)
-{
- int ret = ECORE_DRM_OP_FAILURE;
-
- ret = _ecore_drm_socket_receive(opcode, fd, data, bytes);
- if (ret != ECORE_DRM_OP_SUCCESS) return EINA_FALSE;
-
- return EINA_TRUE;
-}
/**
* @defgroup Ecore_Drm_Init_Group Drm Library Init and Shutdown Functions
/* set logging level */
eina_log_level_set(EINA_LOG_LEVEL_DBG);
- setvbuf(stdout, NULL, _IONBF, 0);
- setvbuf(stderr, NULL, _IONBF, 0);
-
- /* optionally log output to a file */
-#ifdef LOG_TO_FILE
- int log_fd;
- char log_path[PATH_MAX];
- mode_t um;
-
- /* assemble logging file path */
- strcpy(log_path, "/tmp/ecore_drm_XXXXXX");
-
- /* create temporary logging file */
- um = umask(S_IRWXG | S_IRWXO);
- log_fd = mkstemp(log_path);
- umask(um);
-
- /* try to open logging file */
- if (!(lg = fdopen(log_fd, "w")))
- goto log_err;
-
- eina_log_print_cb_set(eina_log_print_cb_file, lg);
-#endif
-
/* try to create logging domain */
_ecore_drm_log_dom =
eina_log_domain_register("ecore_drm", ECORE_DRM_DEFAULT_LOG_COLOR);
if (!eina_log_domain_level_check(_ecore_drm_log_dom, EINA_LOG_LEVEL_DBG))
eina_log_domain_level_set("ecore_drm", EINA_LOG_LEVEL_DBG);
- /* try to init udev */
- if (!(udev = udev_new()))
- goto udev_err;
+ /* get sd-login properties we need */
+ if (sd_pid_get_session(getpid(), &sid) < 0) goto log_err;
- /* try to create the socketpair */
- if (!_ecore_drm_sockets_create())
- goto sock_err;
+ /* try to init dbus */
+ if (!_ecore_drm_dbus_init(sid)) goto dbus_err;
- /* try to run Spartacus */
- if (!_ecore_drm_launcher_spawn())
- goto spawn_err;
+ /* try to init udev */
+ if (!(udev = udev_new())) goto udev_err;
/* return init count */
return _ecore_drm_init_count;
-spawn_err:
- close(_ecore_drm_sockets[0]);
- close(_ecore_drm_sockets[1]);
-sock_err:
- if (udev) udev_unref(udev);
udev_err:
+ _ecore_drm_dbus_shutdown();
+dbus_err:
ecore_event_shutdown();
ecore_shutdown();
eina_log_domain_unregister(_ecore_drm_log_dom);
_ecore_drm_log_dom = -1;
+ free(sid);
log_err:
-#ifdef LOG_TO_FILE
- if (lg) fclose(lg);
-#endif
-
- /* shutdown eina */
eina_shutdown();
-
return --_ecore_drm_init_count;
}
/* close udev handle */
if (udev) udev_unref(udev);
- /* close sockets */
- close(_ecore_drm_sockets[0]);
- close(_ecore_drm_sockets[1]);
+ /* cleanup dbus */
+ _ecore_drm_dbus_shutdown();
/* shutdown ecore_event */
ecore_event_shutdown();
eina_log_domain_unregister(_ecore_drm_log_dom);
_ecore_drm_log_dom = -1;
-#ifdef LOG_TO_FILE
- if (lg) fclose(lg);
-#endif
-
/* shutdown eina */
eina_shutdown();
+ free(sid);
+
/* return init count */
return _ecore_drm_init_count;
}