/* system.c - replacement for system() call
 */

#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include "terminal.h"
#include "hook.h"

typedef void (*sighandler_t) (int);


/* Execute command "cmd", after dropping privileges, by doing "/bin/sh -c
 * cmd". Does a chdir() to directory "d" if it is not 0; not being able to
 * enter the directory is not an error, as it will just run from "/".
 */
void menuview_system(char *cmd, char *d)
{
	char buf[1024];
	sighandler_t osc;
	sighandler_t osr;
	pid_t c, r;
	int s;

	c = fork();
	if (c < 0)
		return;

	if (c == 0) {
		bbs_hook(HOOK_DROP_PRIVS, cmd, 0);
		chdir("/");
		if (d)
			chdir(d);
		if (!getcwd(buf, sizeof(buf) - 1))
			chdir("/");
		signal(SIGCONT, SIG_DFL);
		signal(SIGTTIN, SIG_IGN);
		signal(SIGTTOU, SIG_IGN);
		execl("/bin/sh", "sh", "-c", cmd, 0);
		exit(1);
	}

	osc = signal(SIGCONT, SIG_DFL);
	osr = signal(SIGWINCH, SIG_DFL);

	do {

		alarm(10);		    /* update status every 10 seconds */
		r = KEY_NONE;
		bbs_hook(HOOK_KEY_PRESSED, &c, &r);

		r = waitpid(c, &s, 0);
		if ((r <= 0) && ((errno == EAGAIN) || (errno == EINTR)))
			r = 1;
	} while (r > 0);

	signal(SIGCONT, osc);
	signal(SIGWINCH, osr);

	sleep(1);
}


/* SIGINT handler: does nothing.
 */
void sh_int(int s)
{
	signal(SIGINT, sh_int);
}


/* SIGQUIT handler: does nothing.
 */
void sh_quit(int s)
{
	signal(SIGQUIT, sh_quit);
}

/* EOF */
