initial
This commit is contained in:
commit
2a453f362d
26
Makefile
Normal file
26
Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -Wall -W
|
||||
CFLAGS += `pkg-config --cflags libdrm`
|
||||
LDFLAGS = `pkg-config --libs libdrm`
|
||||
PROGRAM = drm_master_util
|
||||
INSTALL = /usr/bin/install
|
||||
PREFIX = /usr
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
$(PROGRAM): drm_master_util.o
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
install: $(PROGRAM)
|
||||
$(INSTALL) $(PROGRAM) $(PREFIX)/bin
|
||||
chmod u+s $(PREFIX)/bin/${PROGRAM}
|
||||
|
||||
clean:
|
||||
rm -f *.o $(PROGRAM)
|
||||
|
||||
distclean: clean
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $^ -I. -o $@
|
||||
|
||||
.PHONY: all install clean distclean
|
151
drm_master_util.c
Normal file
151
drm_master_util.c
Normal file
@ -0,0 +1,151 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <xf86drm.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define DRM_HACK_SOCKET_NAME "xorg_drm_master_util"
|
||||
|
||||
int recv_fd(int sock)
|
||||
{
|
||||
// This function does the arcane magic recving
|
||||
// file descriptors over unix domain sockets
|
||||
struct msghdr msg;
|
||||
struct iovec iov[1];
|
||||
struct cmsghdr *cmsg = NULL;
|
||||
char ctrl_buf[CMSG_SPACE(sizeof(int))];
|
||||
char data[1];
|
||||
|
||||
memset(&msg, 0, sizeof(struct msghdr));
|
||||
memset(ctrl_buf, 0, CMSG_SPACE(sizeof(int)));
|
||||
|
||||
iov[0].iov_base = data;
|
||||
iov[0].iov_len = sizeof(data);
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_control = ctrl_buf;
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(int));
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
recvmsg(sock, &msg, 0);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
|
||||
return *((int *) CMSG_DATA(cmsg));
|
||||
}
|
||||
|
||||
void usage(const char *name)
|
||||
{
|
||||
printf("usage: %s\n", name);
|
||||
printf("\n"
|
||||
"-h, --help: print this help\n"
|
||||
"-s, --set: drmSetMaster\n"
|
||||
"-d, --drop: drmDropMaster\n"
|
||||
"-t, --test: test\n"
|
||||
"-r, --root: ensure i'm root\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
void check_error(char *prog, int err)
|
||||
{
|
||||
if (err) {
|
||||
fprintf(stderr, "%s: %s\n", prog, strerror(errno));
|
||||
exit(err);
|
||||
}
|
||||
}
|
||||
|
||||
enum action {HELP, SET, DROP, TEST};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
enum action act = HELP;
|
||||
int opt, optindex = 0;
|
||||
int ret = 0;
|
||||
bool ensure_root = false;
|
||||
static struct option longopts[] = {
|
||||
{"help", 0, 0, 'h'},
|
||||
{"set", 0, 0, 's'},
|
||||
{"drop", 0, 0, 'd'},
|
||||
{"test", 0, 0, 't'},
|
||||
{"root", 0, 0, 'r'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
if (argv[1] == NULL) {
|
||||
usage(argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "hsdtr",
|
||||
longopts, &optindex)) != EOF) {
|
||||
switch (opt) {
|
||||
case 's': act = SET; break;
|
||||
case 'd': act = DROP; break;
|
||||
case 't': act = TEST; break;
|
||||
case 'r': ensure_root = true; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
fprintf(stderr, "Error: extra parameter found.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ensure_root) {
|
||||
uid_t uid = getuid();
|
||||
uid_t euid = geteuid();
|
||||
|
||||
assert(euid == 0);
|
||||
|
||||
ret = setuid(euid);
|
||||
check_error("setuid", ret);
|
||||
|
||||
uid = getuid();
|
||||
euid = getuid();
|
||||
|
||||
assert(uid == 0);
|
||||
}
|
||||
|
||||
if (act == HELP) {
|
||||
usage(argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
struct sockaddr_un addr;
|
||||
int sock;
|
||||
|
||||
// Create and connect a unix domain socket
|
||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strcpy(&addr.sun_path[1], DRM_HACK_SOCKET_NAME);
|
||||
connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
int fd = recv_fd(sock);
|
||||
close(sock);
|
||||
|
||||
assert(fd != 0);
|
||||
|
||||
if (act == SET) {
|
||||
ret = drmSetMaster(fd);
|
||||
check_error("drmSetMaster", ret);
|
||||
} else if (act == DROP) {
|
||||
ret = drmDropMaster(fd);
|
||||
check_error("drmDropMaster", ret);
|
||||
} else if (act == TEST) {
|
||||
printf("received fd: %d\n", fd);
|
||||
dprintf(fd, "drm_master_util: writing to received fd ;)\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user