packages feed

unix-process-conduit-0.1.0.1: cbits/forkExecute.c

#define _GNU_SOURCE

#include <unistd.h>

extern void blockUserSignals(void);
extern void unblockUserSignals(void);
extern void stopTimer(void);
extern void startTimer(void);

int forkExecuteFile
	( char *const args[]
	, int path
	, char *workingDirectory
	, char **environment
	, int fdStdIn
	, int fdStdOut
	, int fdStdErr
	)
{
	int pid;

	blockUserSignals();
	stopTimer();

	switch (pid = fork()) {
	case -1:
		unblockUserSignals();
		startTimer();
		if (fdStdIn != -1) close(fdStdIn);
		if (fdStdOut != -1) close(fdStdOut);
		if (fdStdErr != -1) close(fdStdErr);
		return -1;
	case 0:
		unblockUserSignals();
		if (workingDirectory) {
			if (chdir (workingDirectory) < 0) {
				_exit(126);
			}
		}
		if (fdStdIn != -1) {
			dup2(fdStdIn, 0);
			close(fdStdIn);
		}
		if (fdStdOut != -1) {
			dup2(fdStdOut, 1);
			close(fdStdOut);
		}
		if (fdStdErr != -1) {
			dup2(fdStdErr, 2);
			close(fdStdErr);
		}

		// FIXME close file descriptors
		if (environment) {
			if (path) execvpe(args[0], args, environment);
			else      execve (args[0], args, environment);
		} else {
			if (path) execvp(args[0], args);
			else      execv (args[0], args);
		}
		_exit(127);
	default: break;
	}
	unblockUserSignals();
	startTimer();
	return pid;
}