#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/stat.h>

#define NODEFINE
#include <u.h>
#include <libc.h>
#include "../9syscall/fd.h"

int
pm_procexec(char *prog, char *args[], int *fd, char **env)
{
	int i, pid;
	int ufd[3];

	if(access(prog, 01) < 0){
		pm_oserror();
		if(pm_debug & PmDebugExec)
			pm_fprint(2, "pm_procexec %s: access failed: %r\n", prog);
		return -1;
	}

	switch(pid = fork()){
	case -1:
		if(pm_debug & PmDebugExec)
			pm_fprint(2, "pm_procexec %s: fork failed\n", prog);
		pm_oserror();
		return -1;
	case 0:
		break;
	default:
		return pid;
	}

	for(i=0; i<3; i++)
		ufd[i] = pm_pmfd2ufd(fd[i]);

	/*
	 * ufd0, ufd1, ufd2 could be 0, 1, or 2.
	 * if the wrong things happen, we might close
	 * a file descriptor before we need one.
	 * rather than figure out the dependencies (which
	 * could be circular anyway), we just dup once at the
	 * beginning to make sure they're not 0, 1, and 2.
	 */

	/* use up 0, 1, 2 if empty */
	open("/dev/null", O_RDONLY);
	open("/dev/null", O_RDONLY);
	open("/dev/null", O_RDONLY);

	/* reposition ufd0, ufd1, ufd2 */
	for(i=0; i<3; i++)
		if(0 <= ufd[i] && ufd[i] < 3)
			ufd[i] = dup(ufd[i]);

	/* now ufd0, ufd1, ufd2 must be >= 3, safe to dup */
	for(i=0; i<3; i++)
		if(ufd[i] >= 0)
			dup2(ufd[i], i);
		else
			close(i);

	for(i=3; i<=100; i++)
		close(i);

	if(env)
		execve(prog, args, env);
	else
		execv(prog, args);

	pm_oserror();
	if(pm_debug & PmDebugExec)
		pm_fprint(2, "pm_procexec %s: %r\n", prog);
	_exit(0);
}

