// File: grogers0[P]dots_and_boxes/DotsDriver.cpp
// Function: spawn_child(char const*, _IO_FILE*&, _IO_FILE*&, _IO_FILE*&, int&)
void spawn_child(const char *cmd, FILE *&child_stdin,
        FILE *&child_stdout, FILE *&child_stderr, pid_t &child_pid)
{
    int fd_stdin[2];
    int fd_stdout[2];
    int fd_stderr[2];

    assert(pipe(fd_stdin) != -1);
    assert(pipe(fd_stdout) != -1);
    assert(pipe(fd_stderr) != -1);

    pid_t pid = fork();
    assert(pid != -1);

    if (pid > 0) {
        // parent
        close(fd_stdin[0]);
        close(fd_stdout[1]);
        close(fd_stderr[1]);

        child_pid = pid;
        assert(child_stdin = fdopen(fd_stdin[1], "w"));
        assert(child_stdout = fdopen(fd_stdout[0], "r"));
        assert(child_stderr = fdopen(fd_stderr[0], "r"));
    } else {
        // child
        close(fd_stdin[1]);
        close(fd_stdout[0]);
        close(fd_stderr[0]);

        move_fd(fd_stdin[0], STDIN_FILENO);
        move_fd(fd_stdout[1], STDOUT_FILENO);
        move_fd(fd_stderr[1], STDERR_FILENO);

        if (execlp(cmd, cmd, (char*)0) == -1) {
            printf("Failed to execute \"%s\": %s\n",
                    cmd, strerror(errno));
            exit(1);
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
leaq -0x30(%rbp), %rdi
callq 0x2310
cmpl $-0x1, %eax
je 0x8cbc
jmp 0x8cdb
leaq 0x17b8(%rip), %rdi      # 0xa47b
leaq 0x1778(%rip), %rsi      # 0xa442
movl $0x32, %edx
leaq 0x17ba(%rip), %rcx      # 0xa490
callq 0x2150
leaq -0x38(%rbp), %rdi
callq 0x2310
cmpl $-0x1, %eax
je 0x8ceb
jmp 0x8d0a
leaq 0x17e1(%rip), %rdi      # 0xa4d3
leaq 0x1749(%rip), %rsi      # 0xa442
movl $0x33, %edx
leaq 0x178b(%rip), %rcx      # 0xa490
callq 0x2150
leaq -0x40(%rbp), %rdi
callq 0x2310
cmpl $-0x1, %eax
je 0x8d1a
jmp 0x8d39
leaq 0x17c8(%rip), %rdi      # 0xa4e9
leaq 0x171a(%rip), %rsi      # 0xa442
movl $0x34, %edx
leaq 0x175c(%rip), %rcx      # 0xa490
callq 0x2150
callq 0x2060
movl %eax, -0x44(%rbp)
cmpl $-0x1, -0x44(%rbp)
je 0x8d49
jmp 0x8d68
leaq 0x17af(%rip), %rdi      # 0xa4ff
leaq 0x16eb(%rip), %rsi      # 0xa442
movl $0x37, %edx
leaq 0x172d(%rip), %rcx      # 0xa490
callq 0x2150
cmpl $0x0, -0x44(%rbp)
jle 0x8e4f
movl -0x30(%rbp), %edi
callq 0x2460
movl -0x34(%rbp), %edi
callq 0x2460
movl -0x3c(%rbp), %edi
callq 0x2460
movl -0x44(%rbp), %ecx
movq -0x28(%rbp), %rax
movl %ecx, (%rax)
movl -0x2c(%rbp), %edi
leaq 0x176c(%rip), %rsi      # 0xa509
callq 0x2260
movq -0x10(%rbp), %rcx
movq %rax, (%rcx)
cmpq $0x0, %rax
je 0x8db1
jmp 0x8dd0
leaq 0x1753(%rip), %rdi      # 0xa50b
leaq 0x1683(%rip), %rsi      # 0xa442
movl $0x40, %edx
leaq 0x16c5(%rip), %rcx      # 0xa490
callq 0x2150
movl -0x38(%rbp), %edi
leaq 0x1758(%rip), %rsi      # 0xa532
callq 0x2260
movq -0x18(%rbp), %rcx
movq %rax, (%rcx)
cmpq $0x0, %rax
je 0x8dee
jmp 0x8e0d
leaq 0x173f(%rip), %rdi      # 0xa534
leaq 0x1646(%rip), %rsi      # 0xa442
movl $0x41, %edx
leaq 0x1688(%rip), %rcx      # 0xa490
callq 0x2150
movl -0x40(%rbp), %edi
leaq 0x171b(%rip), %rsi      # 0xa532
callq 0x2260
movq -0x20(%rbp), %rcx
movq %rax, (%rcx)
cmpq $0x0, %rax
je 0x8e2b
jmp 0x8e4a
leaq 0x172b(%rip), %rdi      # 0xa55d
leaq 0x1609(%rip), %rsi      # 0xa442
movl $0x42, %edx
leaq 0x164b(%rip), %rcx      # 0xa490
callq 0x2150
jmp 0x8ed8
movl -0x2c(%rbp), %edi
callq 0x2460
movl -0x38(%rbp), %edi
callq 0x2460
movl -0x40(%rbp), %edi
callq 0x2460
movl -0x30(%rbp), %edi
xorl %esi, %esi
callq 0x8c10
movl -0x34(%rbp), %edi
movl $0x1, %esi
callq 0x8c10
movl -0x3c(%rbp), %edi
movl $0x2, %esi
callq 0x8c10
movq -0x8(%rbp), %rdi
movq -0x8(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
movb $0x0, %al
callq 0x2090
cmpl $-0x1, %eax
jne 0x8ed6
movq -0x8(%rbp), %rax
movq %rax, -0x50(%rbp)
callq 0x2030
movl (%rax), %edi
callq 0x20a0
movq -0x50(%rbp), %rsi
movq %rax, %rdx
leaq 0x16c1(%rip), %rdi      # 0xa586
movb $0x0, %al
callq 0x2040
movl $0x1, %edi
callq 0x22e0
jmp 0x8ed8
addq $0x50, %rsp
popq %rbp
retq
nop