// File: /workspace/github_c_makefile_star2_O1/ebiggers[P]mysh/mysh_main.c
// Function: execute_pipeline
static int execute_pipeline(struct list_head command_tokens[],
			    unsigned ncommands)
{
	unsigned i;
	int ret;

	bool async;
	struct list_head redir_lists[ncommands];
	struct list_head cmd_arg_lists[ncommands];
	struct list_head var_assignment_lists[ncommands];
	unsigned cmd_nargs[ncommands];
	unsigned num_redirs[ncommands];

	int pipe_fds[2];
	int prev_read_end;
	pid_t child_pids[ncommands];

	mysh_assert(ncommands > 0);
	async = false;
	i = 0;
	do {
		INIT_LIST_HEAD(&cmd_arg_lists[i]);
		INIT_LIST_HEAD(&redir_lists[i]);
		INIT_LIST_HEAD(&var_assignment_lists[i]);
	} while (++i != ncommands);
	i = 0;
	do {
		ret = parse_tok_list(&command_tokens[i],
				     (i == ncommands - 1) ? &async : NULL,
				     &cmd_arg_lists[i],
				     &var_assignment_lists[i],
				     &redir_lists[i],
				     &cmd_nargs[i],
				     &num_redirs[i]);
		if (ret)
			goto out_free_lists;
	} while (++i != ncommands);

	if (mysh_noexecute)
		goto out_free_lists;

	/* If the pipeline only has one command and is not being executed
	 * asynchronously, try interpreting the command as a sequence of
	 * variable assignments or as a shell builtin.  Note: this means that
	 * with the current code, builtins cannot be used as parts of a
	 * multi-component pipeline. */
	if (ncommands == 1 && !async) {
		if (cmd_nargs[0] == 0) {
			/* No arguments: just process leading variable
			 * assignments. */
			ret = process_var_assignments(&var_assignment_lists[0]);
			goto out_free_lists;
		} else if (maybe_execute_builtin(&cmd_arg_lists[0],
						 &redir_lists[0],
						 cmd_nargs[0], &ret))
			goto out_free_lists;
		/* Not a builtin */
	}

	/* Verify that there is a command to execute for each component of the
	 * pipeline (e.g. there isn't a component that is only redirections) */
	i = 0;
	do {
		if (cmd_nargs[i] == 0) {
			mysh_error("Expected command name");
			ret = -1;
			goto out_free_lists;
		}
	} while (++i != ncommands);

	/* Execute the commands in the pipeline.  This essentially is done by
	 * fork() followed by execvp() for each command.  Redirections are
	 * handled by the forked child processes before calling execvp().  Pipes
	 * are created with pipe() before the fork.  Note that each component of
	 * the pipeline other than the first and last is involved with two
	 * different pipes: one to read from, and one to write to.  The
	 * @prev_read_end variable is used to save the read end of a pipe for
	 * the next pipeline component. */
	prev_read_end = pipe_fds[0] = pipe_fds[1] = -1;
	i = 0;
	do {
		/* Unless this is the last command, create a new pair of pipes */
		if (i != ncommands - 1) {
			if (pipe(pipe_fds)) {
				mysh_error_with_errno("can't create pipes");
				goto out_close_pipes;
			}
		}

		/* Fork the process */
		ret = fork();
		if (ret < 0) {
			/* fork() error */
			mysh_error_with_errno("can't fork child process");
			goto out_close_pipes;
		} else if (ret == 0) {
			if (async) {
				/* Background processes are executed with a new
				 * session ID and with standard input redirected
				 * from /dev/null. */
				int fd;

				errno = 0;
				setsid();
				fd = open("/dev/null", O_RDONLY);
				dup2(fd, STDIN_FILENO);
				close(fd);
				if (errno) {
					mysh_error_with_errno("problem daemonizing "
							      "background process");
				}
			}
			/* Child: set up redirections and execute new process */
			start_child(&cmd_arg_lists[i],
				    &redir_lists[i],
				    &var_assignment_lists[i],
				    cmd_nargs[i], i, ncommands,
				    pipe_fds, prev_read_end);
			/* Not reached */
			mysh_assert(0);
		}

		/* Parent: save child pid in an array */
		child_pids[i] = ret;

		/* Close any pipes we created that are no longer needed; also
		 * save the read end of the pipe (if any) in the prev_read_end
		 * variable.  */
		if (prev_read_end >= 0)
			close(prev_read_end);
		prev_read_end = pipe_fds[0];
		pipe_fds[0] = -1;
		if (pipe_fds[1] >= 0) {
			close(pipe_fds[1]);
			pipe_fds[1] = -1;
		}
	} while (++i != ncommands);
	ret = 0;
out_close_pipes:
	if (pipe_fds[0] >= 0)
		close(pipe_fds[0]);
	if (pipe_fds[1] >= 0)
		close(pipe_fds[1]);
	if (prev_read_end >= 0)
		close(prev_read_end);
	/* If no error has occurred and the pipeline is not being executed
	 * asynchronously, wait for the commands to terminate.  'ret' is set to
	 * the exit status of the last command in the pipeline.
	 *
	 * If the pipeline is to be asynchronous, don't wait for any children;
	 * just add an entry to the list of background pipelines. */
	if (ret == 0) {
		if (async)
			ret = add_background_pipeline(child_pids, ncommands);
		else
			ret = wait_for_children(child_pids, ncommands);
	}
out_free_lists:
	i = 0;
	do {
		free_string_list(&cmd_arg_lists[i]);
		free_string_list(&var_assignment_lists[i]);
		free_redir_list(&redir_lists[i]);
	} while (++i != ncommands);
	return ret;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdi, -0x48(%rbp)
movq %rsp, %rdi
movl %esi, %r9d
movq %rsp, %r14
movq %r9, %rax
shlq $0x4, %rax
subq %rax, %r14
movq %r14, %rsp
movq %rsp, %r12
subq %rax, %r12
movq %r12, %rsp
movq %rsp, %r8
subq %rax, %r8
movq %r8, %rsp
movq %rsp, %rbx
leaq 0xf(,%r9,4), %rax
andq $-0x10, %rax
subq %rax, %rbx
movq %rbx, %rsp
movq %rsp, %r13
subq %rax, %r13
movq %r13, %rsp
movq %rsp, %rcx
subq %rax, %rcx
movq %rcx, -0x60(%rbp)
movq %rcx, %rsp
movq %rsi, -0x40(%rbp)
testl %esi, %esi
je 0x41c4
movb $0x0, -0x29(%rbp)
movq %r9, %rax
shlq $0x4, %rax
xorl %ecx, %ecx
leaq (%r12,%rcx), %rdx
movq %rdx, (%r12,%rcx)
movq %rdx, 0x8(%r12,%rcx)
leaq (%r14,%rcx), %rdx
movq %rdx, (%r14,%rcx)
movq %rdx, 0x8(%r14,%rcx)
leaq (%r8,%rcx), %rdx
movq %rdx, (%r8,%rcx)
movq %rdx, 0x8(%r8,%rcx)
addq $0x10, %rcx
cmpq %rcx, %rax
jne 0x3eef
movq %rdi, -0x80(%rbp)
movq -0x40(%rbp), %rax
decl %eax
movq %rax, -0x78(%rbp)
shlq $0x4, %rax
movq %rax, -0x90(%rbp)
movq %r9, -0x68(%rbp)
shlq $0x4, %r9
movq %r9, -0x88(%rbp)
xorl %r15d, %r15d
movq %rbx, -0x58(%rbp)
movq %r14, -0x70(%rbp)
movq %r8, -0x50(%rbp)
cmpq %r15, -0x90(%rbp)
movl $0x0, %esi
leaq -0x29(%rbp), %rax
cmoveq %rax, %rsi
movq -0x48(%rbp), %rax
leaq (%rax,%r15), %rdi
leaq (%r12,%r15), %rdx
leaq (%r8,%r15), %rcx
leaq (%r14,%r15), %r8
subq $0x8, %rsp
movq %rbx, %r9
pushq %r13
callq 0x5544
addq $0x10, %rsp
movl %eax, -0x30(%rbp)
testl %eax, %eax
jne 0x413c
addq $0x10, %r15
addq $0x4, %rbx
addq $0x4, %r13
cmpq %r15, -0x88(%rbp)
movq -0x50(%rbp), %r8
jne 0x3f56
cmpl $0x0, 0x727d(%rip)      # 0xb238
jne 0x413c
cmpl $0x1, -0x40(%rbp)
jne 0x3ff2
cmpb $0x0, -0x29(%rbp)
jne 0x3ff2
movq -0x58(%rbp), %rax
movl (%rax), %edx
testl %edx, %edx
je 0x40bd
leaq -0x30(%rbp), %rcx
movq %r12, %rdi
movq %r14, %rsi
callq 0x26bc
testb %al, %al
jne 0x413c
xorl %eax, %eax
movq -0x58(%rbp), %rdx
movl %eax, %ecx
cmpl $0x0, (%rdx,%rcx,4)
je 0x409a
incl %eax
cmpl %eax, -0x40(%rbp)
jne 0x3ff8
leaq -0x38(%rbp), %rax
movq $-0x1, (%rax)
movl -0x78(%rbp), %eax
movq %rax, -0x48(%rbp)
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
xorl %ebx, %ebx
xorl %r13d, %r13d
cmpq %r13, -0x48(%rbp)
je 0x403f
leaq -0x38(%rbp), %rdi
callq 0x21d0
testl %eax, %eax
jne 0x40d7
callq 0x23b0
movl %eax, -0x30(%rbp)
testl %eax, %eax
js 0x40b4
je 0x41e3
movq -0x60(%rbp), %rcx
movl %eax, (%rcx,%r13,4)
testl %r15d, %r15d
js 0x4066
movl %r15d, %edi
callq 0x21c0
movl -0x38(%rbp), %r15d
movl -0x34(%rbp), %edi
movl $0xffffffff, -0x38(%rbp) # imm = 0xFFFFFFFF
testl %edi, %edi
js 0x4084
callq 0x21c0
movl $0xffffffff, -0x34(%rbp) # imm = 0xFFFFFFFF
incq %r13
addq $-0x10, %rbx
cmpl %r13d, -0x68(%rbp)
jne 0x4028
movl $0x0, -0x30(%rbp)
jmp 0x40e5
leaq 0x3522(%rip), %rdi      # 0x75c3
xorl %eax, %eax
callq 0x23e0
movl $0xffffffff, -0x30(%rbp) # imm = 0xFFFFFFFF
jmp 0x413c
leaq 0x3531(%rip), %rdi      # 0x75ec
jmp 0x40de
movq -0x50(%rbp), %r15
movq (%r15), %rbx
cmpq %r15, %rbx
je 0x4123
movq -0x18(%rbx), %rdi
callq 0x4bc1
movq (%rbx), %rbx
jmp 0x40c4
leaq 0x34fb(%rip), %rdi      # 0x75d9
xorl %eax, %eax
callq 0x249f
movl -0x38(%rbp), %edi
testl %edi, %edi
js 0x40f1
callq 0x21c0
movl -0x34(%rbp), %edi
testl %edi, %edi
js 0x40fd
callq 0x21c0
testl %r15d, %r15d
js 0x410a
movl %r15d, %edi
callq 0x21c0
cmpl $0x0, -0x30(%rbp)
jne 0x413c
cmpb $0x1, -0x29(%rbp)
jne 0x412c
movq -0x60(%rbp), %rdi
movq -0x68(%rbp), %rsi
callq 0x4403
movl $0x0, -0x30(%rbp)
jmp 0x413c
movq -0x60(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x44b7
movl %eax, -0x30(%rbp)
xorl %r13d, %r13d
movq %r13, %rbx
shlq $0x4, %rbx
movq %r12, %r14
leaq (%r12,%rbx), %rdi
callq 0x688b
movq -0x50(%rbp), %rax
leaq (%rax,%rbx), %rdi
callq 0x688b
movq -0x70(%rbp), %rax
leaq (%rax,%rbx), %r15
movq (%rax,%rbx), %rbx
cmpq %r15, %rbx
je 0x41a2
movq (%rbx), %r12
movq 0x8(%rbx), %rax
movq %rax, 0x8(%r12)
movq %r12, (%rax)
cmpb $0x1, -0x20(%rbx)
jne 0x418e
movq -0x18(%rbx), %rdi
callq 0x2050
addq $-0x20, %rbx
movq %rbx, %rdi
callq 0x2050
movq %r12, %rbx
cmpq %r15, %r12
jne 0x4170
incq %r13
cmpl -0x40(%rbp), %r13d
movq %r14, %r12
jne 0x413f
movl -0x30(%rbp), %eax
movq -0x80(%rbp), %rsp
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x33b3(%rip), %rdi      # 0x757e
leaq 0x335d(%rip), %rsi      # 0x752f
leaq 0x33b3(%rip), %rcx      # 0x758c
movl $0x14c, %edx            # imm = 0x14C
callq 0x2160
cmpb $0x1, -0x29(%rbp)
jne 0x4238
callq 0x2060
movq %rax, -0x48(%rbp)
movl $0x0, (%rax)
callq 0x21e0
leaq 0x3401(%rip), %rdi      # 0x7605
xorl %esi, %esi
xorl %eax, %eax
callq 0x22c0
movl %eax, %r14d
movl %eax, %edi
xorl %esi, %esi
callq 0x2120
movl %r14d, %edi
callq 0x21c0
movq -0x48(%rbp), %rax
cmpl $0x0, (%rax)
je 0x4238
leaq 0x33de(%rip), %rdi      # 0x760f
xorl %eax, %eax
callq 0x249f
subq %rbx, %r12
movq -0x70(%rbp), %rsi
subq %rbx, %rsi
movq -0x50(%rbp), %rdx
subq %rbx, %rdx
movq -0x58(%rbp), %rax
movl (%rax,%r13,4), %ecx
movq %r12, %rdi
movl %r13d, %r8d
movq -0x40(%rbp), %r9
pushq %r15
leaq -0x38(%rbp), %rax
pushq %rax
callq 0x4267