// File: /workspace/github_c_makefile_star2_O0/deplinenoise[P]tundra/src/ExecUnix.cpp
// Function: t2::ExecuteProcess(char const*, int, t2::EnvVariable const*, int, int, char const*)
ExecResult
ExecuteProcess(
		const char* cmd_line,
		int env_count,
		const EnvVariable *env_vars,
		int job_id,
		int echo_cmdline,
		const char *annotation)
{
  ExecResult result;

  result.m_ReturnCode   = 1;
  result.m_WasSignalled = false;

	pid_t child;
	const int pipe_read = 0;
	const int pipe_write = 1;

	/* Create a pair of pipes to read back stdout, stderr */
	int stdout_pipe[2], stderr_pipe[2];

	if (-1 == pipe(stdout_pipe))
	{
		perror("pipe failed");
		return result;
	}

	if (-1 == pipe(stderr_pipe))
	{
		perror("pipe failed");
		close(stdout_pipe[0]);
		close(stdout_pipe[1]);
		return result;
	}

	if (0 == (child = fork()))
	{
		const char *args[] = { "/bin/sh", "-c", cmd_line, NULL };

		close(stdout_pipe[pipe_read]);
		close(stderr_pipe[pipe_read]);

		if (-1 == dup2(stdout_pipe[pipe_write], STDOUT_FILENO))
			perror("dup2 failed");
		if (-1 == dup2(stderr_pipe[pipe_write], STDERR_FILENO))
			perror("dup2 failed");

		close(stdout_pipe[pipe_write]);
		close(stderr_pipe[pipe_write]);

		sigset_t sigs;
		sigfillset(&sigs);
		if (0 != sigprocmask(SIG_UNBLOCK, &sigs, 0))
			perror("sigprocmask failed");

		for (int i = 0; i < env_count; ++i)
		{
			setenv(env_vars[i].m_Name, env_vars[i].m_Value, /*overwrite:*/ 1);
		}

		if (-1 == execv("/bin/sh", (char **) args))
			exit(1);
		/* we never get here */
		abort();
	}
	else if (-1 == child)
	{
		perror("fork failed");
		close(stdout_pipe[pipe_read]);
		close(stderr_pipe[pipe_read]);
		close(stdout_pipe[pipe_write]);
		close(stderr_pipe[pipe_write]);
		return result;
	}
	else
	{
		pid_t p;
		int return_code = 0;
		int sort_key = 0;
		int rfd_count = 2;
		int rfds[2];
		fd_set read_fds;

		rfds[0] = stdout_pipe[pipe_read];
		rfds[1] = stderr_pipe[pipe_read];

		SetFdNonBlocking(rfds[0]);
		SetFdNonBlocking(rfds[1]);

		/* Close write end of the pipe, we're just going to be reading */
		close(stdout_pipe[pipe_write]);
		close(stderr_pipe[pipe_write]);

		if (annotation)
			TerminalIoPrintf(job_id, -200, "%s\n", annotation);

		if (echo_cmdline)
			TerminalIoPrintf(job_id, -199, "%s\n", cmd_line);

		/* Sit in a select loop over the two fds */

		for (;;)
		{
			int fd;
			int count;
			int max_fd = 0;
			struct timeval timeout;

			/* don't select if we know both pipes are closed */
			if (rfd_count > 0)
			{
				FD_ZERO(&read_fds);

				for (fd = 0; fd < 2; ++fd)
				{
					if (rfds[fd])
					{
						if (rfds[fd] > max_fd)
							max_fd = rfds[fd];
						FD_SET(rfds[fd], &read_fds);
					}
				}

				++max_fd;

				timeout.tv_sec = 0;
				timeout.tv_usec = 500000;

				count = select(max_fd, &read_fds, NULL, NULL, &timeout);

				if (-1 == count) // happens in gdb due to syscall interruption
					continue;

				for (fd = 0; fd < 2; ++fd)
				{
					if (0 != rfds[fd] && FD_ISSET(rfds[fd], &read_fds))
					{
						if (0 != EmitData(job_id, /*is_stderr:*/ 1 == fd, sort_key++, rfds[fd]))
						{
							/* Done with this FD. */
							rfds[fd] = 0;
							--rfd_count;
						}
					}
				}
			}

			return_code = 0;
			p = waitpid(child, &return_code, rfd_count > 0 ? WNOHANG : 0);

			if (0 == p)
			{
				/* child still running */
				continue;
			}
			else if (p != child)
			{
				return_code = 1;
				perror("waitpid failed");
				break;
			}
			else
			{
				/* fall out of the loop here - process has exited. */
				/* FIXME - is there a race between getting the last data out of
				 * the pipes vs quitting here? Probably there is. But it seems
				 * to work well in practice. If I put a blocking waitpid()
				 * after the loop I got deadlocks on Mac OS X in select. */
				break;
			}
		}

		close(stdout_pipe[pipe_read]);
		close(stderr_pipe[pipe_read]);

		if (WIFSIGNALED(return_code))
    {
			result.m_ReturnCode   = 1;
			result.m_WasSignalled = true;

			int sig = WTERMSIG(return_code);
			TerminalIoPrintf(job_id, INT_MAX, "child process exited on signal %d: %s\n", sig, cmd_line);
		}
		else
    {
			result.m_ReturnCode   = WEXITSTATUS(return_code);

			if (0 != result.m_ReturnCode && !echo_cmdline)
			{
				TerminalIoPrintf(job_id, INT_MAX, "child process failed with exit code %d: %s\n", result.m_ReturnCode, cmd_line);
			}
    }

		TerminalIoJobExit(job_id);

		return result;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1d0, %rsp            # imm = 0x1D0
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movl %r8d, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movl $0x1, -0x8(%rbp)
movb $0x0, -0x4(%rbp)
movl $0x0, -0x38(%rbp)
movl $0x1, -0x3c(%rbp)
leaq -0x44(%rbp), %rdi
callq 0x3460
movl %eax, %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl %ecx, %eax
jne 0x1ec3f
leaq 0x699e(%rip), %rdi      # 0x255d3
callq 0x32b0
jmp 0x1f22c
leaq -0x4c(%rbp), %rdi
callq 0x3460
movl %eax, %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl %ecx, %eax
jne 0x1ec74
leaq 0x6979(%rip), %rdi      # 0x255d3
callq 0x32b0
movl -0x44(%rbp), %edi
callq 0x3640
movl -0x40(%rbp), %edi
callq 0x3640
jmp 0x1f22c
callq 0x30a0
movl %eax, %ecx
movl %ecx, -0x34(%rbp)
xorl %eax, %eax
cmpl %ecx, %eax
jne 0x1edd0
leaq 0x6950(%rip), %rax      # 0x255df
movq %rax, -0x70(%rbp)
leaq 0x694d(%rip), %rax      # 0x255e7
movq %rax, -0x68(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x60(%rbp)
movq $0x0, -0x58(%rbp)
movl -0x44(%rbp), %edi
callq 0x3640
movl -0x4c(%rbp), %edi
callq 0x3640
movl -0x40(%rbp), %edi
movl $0x1, %esi
callq 0x3320
movl %eax, %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl %ecx, %eax
jne 0x1ece2
leaq 0x690d(%rip), %rdi      # 0x255ea
callq 0x32b0
movl -0x48(%rbp), %edi
movl $0x2, %esi
callq 0x3320
movl %eax, %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl %ecx, %eax
jne 0x1ed06
leaq 0x68e9(%rip), %rdi      # 0x255ea
callq 0x32b0
movl -0x40(%rbp), %edi
callq 0x3640
movl -0x48(%rbp), %edi
callq 0x3640
leaq -0xf0(%rbp), %rdi
callq 0x30d0
movl $0x1, %edi
leaq -0xf0(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x3190
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x1ed4b
leaq 0x68b0(%rip), %rdi      # 0x255f6
callq 0x32b0
movl $0x0, -0xf4(%rbp)
movl -0xf4(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x1eda6
movq -0x20(%rbp), %rax
movslq -0xf4(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rdi
movq -0x20(%rbp), %rax
movslq -0xf4(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rsi
movl $0x1, %edx
callq 0x3500
movl -0xf4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xf4(%rbp)
jmp 0x1ed55
leaq -0x70(%rbp), %rsi
leaq 0x682e(%rip), %rdi      # 0x255df
callq 0x32f0
movl %eax, %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl %ecx, %eax
jne 0x1edcb
movl $0x1, %edi
callq 0x33f0
callq 0x31d0
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl -0x34(%rbp), %eax
jne 0x1ee0b
leaq 0x6828(%rip), %rdi      # 0x25609
callq 0x32b0
movl -0x44(%rbp), %edi
callq 0x3640
movl -0x4c(%rbp), %edi
callq 0x3640
movl -0x40(%rbp), %edi
callq 0x3640
movl -0x48(%rbp), %edi
callq 0x3640
jmp 0x1f22c
movl $0x0, -0xfc(%rbp)
movl $0x0, -0x100(%rbp)
movl $0x2, -0x104(%rbp)
movl -0x44(%rbp), %eax
movl %eax, -0x10c(%rbp)
movl -0x4c(%rbp), %eax
movl %eax, -0x108(%rbp)
movl -0x10c(%rbp), %edi
callq 0x1f240
movl -0x108(%rbp), %edi
callq 0x1f240
movl -0x40(%rbp), %edi
callq 0x3640
movl -0x48(%rbp), %edi
callq 0x3640
cmpq $0x0, -0x30(%rbp)
je 0x1ee82
movl -0x24(%rbp), %edi
movq -0x30(%rbp), %rcx
movl $0xffffff38, %esi       # imm = 0xFFFFFF38
leaq 0x57be(%rip), %rdx      # 0x24639
movb $0x0, %al
callq 0x226b0
cmpl $0x0, -0x28(%rbp)
je 0x1eea2
movl -0x24(%rbp), %edi
movq -0x10(%rbp), %rcx
movl $0xffffff39, %esi       # imm = 0xFFFFFF39
leaq 0x579e(%rip), %rdx      # 0x24639
movb $0x0, %al
callq 0x226b0
jmp 0x1eea4
movl $0x0, -0x19c(%rbp)
cmpl $0x0, -0x104(%rbp)
jle 0x1f11f
jmp 0x1eebd
leaq -0x190(%rbp), %rax
movq %rax, -0x1c0(%rbp)
movl $0x0, -0x1b4(%rbp)
movl -0x1b4(%rbp), %eax
cmpq $0x10, %rax
jae 0x1ef07
movq -0x1c0(%rbp), %rax
movl -0x1b4(%rbp), %ecx
movq $0x0, (%rax,%rcx,8)
movl -0x1b4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1b4(%rbp)
jmp 0x1eed5
jmp 0x1ef09
movl $0x0, -0x194(%rbp)
cmpl $0x2, -0x194(%rbp)
jge 0x1efbe
movslq -0x194(%rbp), %rax
cmpl $0x0, -0x10c(%rbp,%rax,4)
je 0x1efa8
movslq -0x194(%rbp), %rax
movl -0x10c(%rbp,%rax,4), %eax
cmpl -0x19c(%rbp), %eax
jle 0x1ef5b
movslq -0x194(%rbp), %rax
movl -0x10c(%rbp,%rax,4), %eax
movl %eax, -0x19c(%rbp)
movslq -0x194(%rbp), %rax
movl -0x10c(%rbp,%rax,4), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl %eax, %ecx
movl $0x1, %eax
shlq %cl, %rax
movq %rax, %rcx
movslq -0x194(%rbp), %rax
movl -0x10c(%rbp,%rax,4), %eax
movl $0x40, %esi
cltd
idivl %esi
cltq
orq -0x190(%rbp,%rax,8), %rcx
movq %rcx, -0x190(%rbp,%rax,8)
jmp 0x1efaa
movl -0x194(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x194(%rbp)
jmp 0x1ef13
movl -0x19c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x19c(%rbp)
movq $0x0, -0x1b0(%rbp)
movq $0x7a120, -0x1a8(%rbp) # imm = 0x7A120
movl -0x19c(%rbp), %edi
leaq -0x190(%rbp), %rsi
xorl %eax, %eax
movl %eax, %ecx
leaq -0x1b0(%rbp), %r8
movq %rcx, %rdx
callq 0x3340
movl %eax, -0x198(%rbp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl -0x198(%rbp), %eax
jne 0x1f01b
jmp 0x1eea4
movl $0x0, -0x194(%rbp)
cmpl $0x2, -0x194(%rbp)
jge 0x1f11d
movslq -0x194(%rbp), %rcx
xorl %eax, %eax
cmpl -0x10c(%rbp,%rcx,4), %eax
je 0x1f107
movslq -0x194(%rbp), %rax
movl -0x10c(%rbp,%rax,4), %eax
movl $0x40, %ecx
cltd
idivl %ecx
cltq
movq -0x190(%rbp,%rax,8), %rax
movq %rax, -0x1d0(%rbp)
movslq -0x194(%rbp), %rax
movl -0x10c(%rbp,%rax,4), %eax
movl $0x40, %ecx
cltd
idivl %ecx
movq -0x1d0(%rbp), %rax
movl %edx, %ecx
movl $0x1, %edx
shlq %cl, %rdx
movq %rdx, %rcx
andq %rcx, %rax
cmpq $0x0, %rax
je 0x1f107
movl -0x24(%rbp), %edi
movl $0x1, %eax
cmpl -0x194(%rbp), %eax
sete %al
andb $0x1, %al
movzbl %al, %esi
movl -0x100(%rbp), %edx
movl %edx, %eax
addl $0x1, %eax
movl %eax, -0x100(%rbp)
movslq -0x194(%rbp), %rax
movl -0x10c(%rbp,%rax,4), %ecx
callq 0x1f2a0
movl %eax, %ecx
xorl %eax, %eax
cmpl %ecx, %eax
je 0x1f105
movslq -0x194(%rbp), %rax
movl $0x0, -0x10c(%rbp,%rax,4)
movl -0x104(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x104(%rbp)
jmp 0x1f107
jmp 0x1f109
movl -0x194(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x194(%rbp)
jmp 0x1f025
jmp 0x1f11f
movl $0x0, -0xfc(%rbp)
movl -0x34(%rbp), %edi
movl -0x104(%rbp), %ecx
xorl %edx, %edx
movl $0x1, %eax
cmpl $0x0, %ecx
cmovgl %eax, %edx
leaq -0xfc(%rbp), %rsi
callq 0x3290
movl %eax, -0xf8(%rbp)
xorl %eax, %eax
cmpl -0xf8(%rbp), %eax
jne 0x1f160
jmp 0x1eea4
movl -0xf8(%rbp), %eax
cmpl -0x34(%rbp), %eax
je 0x1f183
movl $0x1, -0xfc(%rbp)
leaq 0x6499(%rip), %rdi      # 0x25615
callq 0x32b0
jmp 0x1f185
jmp 0x1f185
movl -0x44(%rbp), %edi
callq 0x3640
movl -0x4c(%rbp), %edi
callq 0x3640
movl -0xfc(%rbp), %eax
andl $0x7f, %eax
addl $0x1, %eax
movsbl %al, %eax
sarl %eax
cmpl $0x0, %eax
jle 0x1f1e7
movl $0x1, -0x8(%rbp)
movb $0x1, -0x4(%rbp)
movl -0xfc(%rbp), %eax
andl $0x7f, %eax
movl %eax, -0x1c4(%rbp)
movl -0x24(%rbp), %edi
movl -0x1c4(%rbp), %ecx
movq -0x10(%rbp), %r8
movl $0x7fffffff, %esi       # imm = 0x7FFFFFFF
leaq 0x6446(%rip), %rdx      # 0x25624
movb $0x0, %al
callq 0x226b0
jmp 0x1f224
movl -0xfc(%rbp), %eax
andl $0xff00, %eax           # imm = 0xFF00
sarl $0x8, %eax
movl %eax, -0x8(%rbp)
xorl %eax, %eax
cmpl -0x8(%rbp), %eax
je 0x1f222
cmpl $0x0, -0x28(%rbp)
jne 0x1f222
movl -0x24(%rbp), %edi
movl -0x8(%rbp), %ecx
movq -0x10(%rbp), %r8
movl $0x7fffffff, %esi       # imm = 0x7FFFFFFF
leaq 0x6430(%rip), %rdx      # 0x2564b
movb $0x0, %al
callq 0x226b0
jmp 0x1f224
movl -0x24(%rbp), %edi
callq 0x22620
movq -0x8(%rbp), %rax
addq $0x1d0, %rsp            # imm = 0x1D0
popq %rbp
retq
nopl (%rax)