/* XI.C
 * Copyright (c) 2017, 2018 Jesse McClure <code@jessemcclure.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <linux/limits.h>
#include <linux/vt.h>

static volatile int xrunning = 0;

void handler(int sig) {
	if (sig == SIGUSR1) xrunning = 1;
	if (sig == SIGCHLD || sig == SIGTERM) xrunning = 0;
}

int server(const char *dpy, const char *tty, const char *xauth) {
	const char *xorg = "/usr/lib/Xorg";
	int pid;
	if ((pid=fork()) < 0) exit(1);
	else if (pid > 0) return pid;
	signal(SIGTTIN, SIG_IGN);
	signal(SIGTTOU, SIG_IGN);
	signal(SIGUSR1, SIG_IGN);
	execl(xorg, xorg, dpy, tty, "-keeptty", "-nolisten", "tcp", "-quiet", "-auth", xauth, NULL);
	_exit(2);
}

int client(const char *dpy, const char *wm, const char *xauth) {
	int pid;
	if ((pid=fork()) < 0) exit(3);
	else if (pid > 0) return pid;
	setenv("XAUTHORITY", xauth, 1);
	setenv("DISPLAY", dpy, 1);
	execlp(wm, wm, NULL);
	_exit(4);
}

int main(int argc, const char **argv) {
	struct vt_stat vtstat;
	if (ioctl(0, VT_GETSTATE, &vtstat)) {
		perror("get_vt");
		return 1;
	}
	char dpy[] = { ':', '0' + vtstat.v_active, 0 };
	char tty[] = { 'v', 't', '0' + vtstat.v_active, 0 };
	char xauth[PATH_MAX];
	snprintf(xauth, PATH_MAX, "%s/%s", getenv("HOME"), ".Xauthority");

	struct sigaction sa;
	sa.sa_handler = handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sigaction(SIGUSR1, &sa, NULL);
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);

	int xpid = server(dpy, tty, xauth);
	while (!xrunning) pause();
	int cpid = client(dpy, (argc > 1 ? argv[1] : "xterm" ), xauth);
	while (xrunning) pause();

	kill(cpid, SIGTERM);
	waitpid(cpid, NULL, 0);
	kill(xpid, SIGTERM);
	waitpid(xpid, NULL, 0);
	return 0;
}
