// File: davmac314[P]dinit/src/shutdown.cc
// Function: run_process(char const**, dasynq::v2::event_loop<dasynq::null_mutex, dasynq::v2::default_traits<dasynq::null_mutex>>&, subproc_buffer&)
static loop_t::child_proc_watcher::proc_status_t run_process(const char * prog_args[],
        loop_t &loop, subproc_buffer &sub_buf)
{
    class sp_watcher_t : public loop_t::child_proc_watcher_impl<sp_watcher_t>
    {
        public:
        bool terminated = false;
        proc_status_t exit_status;

        rearm status_change(loop_t &, pid_t child, proc_status_t status)
        {
            terminated = true;
            exit_status = status;
            return rearm::REMOVE;
        }
    };

    sp_watcher_t sp_watcher;

    // Create output pipe
    bool have_pipe = true;
    int pipefds[2];
    if (dasynq::pipe2(pipefds, O_NONBLOCK) == -1) {
        sub_buf.append("Warning: ");
        sub_buf.append(prog_args[0]);
        sub_buf.append(": could not create pipe for subprocess output\n");
        have_pipe = false;
        // Note, we proceed and let the sub-process run with our stdout/stderr.
    }

    subproc_out_watch owatch {sub_buf};

    if (have_pipe) {
        try {
            owatch.add_watch(loop, pipefds[0], dasynq::IN_EVENTS);
        }
        catch (...) {
            // failed to create the watcher for the subprocess output; again, let it run with
            // our stdout/stderr
            sub_buf.append("Warning: could not create output watch for subprocess\n");
            close(pipefds[0]);
            close(pipefds[1]);
            have_pipe = false;
        }
    }

    // If we've buffered any messages/output, give them a chance to go out now:
    loop.poll();

    pid_t ch_pid = sp_watcher.fork(loop);
    if (ch_pid == 0) {
        // child
        // Dup output pipe to stdout, stderr
        if (have_pipe) {
            dup2(pipefds[1], STDOUT_FILENO);
            dup2(pipefds[1], STDERR_FILENO);
            close(pipefds[0]);
            close(pipefds[1]);
        }
        execv(prog_args[0], const_cast<char **>(prog_args));
        puts("Failed to execute subprocess: ");
        perror(prog_args[0]);
        _exit(1);
    }
    if (have_pipe) {
        close(pipefds[1]);
    }

    do {
        loop.run();
    } while (!sp_watcher.terminated);

    if (have_pipe) {
        owatch.deregister(loop);
        close(pipefds[0]);
    }

    return sp_watcher.exit_status;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
leaq -0x68(%rbp), %rdi
callq 0x4760
movb $0x1, -0x69(%rbp)
leaq -0x74(%rbp), %rdi
movl $0x800, %esi            # imm = 0x800
callq 0x3170
cmpl $-0x1, %eax
jne 0x4377
movq -0x20(%rbp), %rdi
leaq 0xd5b3(%rip), %rsi      # 0x118e5
callq 0x5370
jmp 0x4339
movq -0x20(%rbp), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rsi
callq 0x5370
jmp 0x434b
movq -0x20(%rbp), %rdi
leaq 0xd599(%rip), %rsi      # 0x118ef
callq 0x5370
jmp 0x435d
movb $0x0, -0x69(%rbp)
jmp 0x4377
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x4561
movq -0x20(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
callq 0x9970
jmp 0x4389
testb $0x1, -0x69(%rbp)
je 0x4435
movq -0x18(%rbp), %rsi
movl -0x74(%rbp), %edx
leaq -0xc0(%rbp), %rdi
movl $0x1, %r8d
movl $0x32, %r9d
movl %r8d, %ecx
callq 0x5b20
jmp 0x43b7
jmp 0x4404
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
movq -0x80(%rbp), %rdi
callq 0x30d0
movq -0x20(%rbp), %rdi
leaq 0xd542(%rip), %rsi      # 0x1191e
callq 0x5370
jmp 0x43e3
movl -0x74(%rbp), %edi
callq 0x3440
jmp 0x43ed
movl -0x70(%rbp), %edi
callq 0x3440
jmp 0x43f7
movb $0x0, -0x69(%rbp)
callq 0x33e0
jmp 0x4402
jmp 0x4404
jmp 0x4435
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
callq 0x33e0
jmp 0x4430
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x80(%rbp)
movl %eax, -0x84(%rbp)
jmp 0x4555
jmp 0x4555
movq -0x18(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x5500
movq -0x18(%rbp), %rsi
leaq -0x68(%rbp), %rdi
xorl %edx, %edx
movl $0x32, %ecx
callq 0x99c0
movl %eax, -0xc8(%rbp)
jmp 0x445f
movl -0xc8(%rbp), %eax
movl %eax, -0xc4(%rbp)
cmpl $0x0, -0xc4(%rbp)
jne 0x44de
testb $0x1, -0x69(%rbp)
je 0x44aa
movl -0x70(%rbp), %edi
movl $0x1, %esi
callq 0x3240
movl -0x70(%rbp), %edi
movl $0x2, %esi
callq 0x3240
movl -0x74(%rbp), %edi
callq 0x3440
jmp 0x449e
movl -0x70(%rbp), %edi
callq 0x3440
jmp 0x44a8
jmp 0x44aa
movq -0x10(%rbp), %rsi
movq (%rsi), %rdi
callq 0x3230
leaq 0xd498(%rip), %rdi      # 0x11955
callq 0x33c0
jmp 0x44c4
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x31f0
jmp 0x44d2
movl $0x1, %edi
callq 0x33d0
jmp 0x44de
testb $0x1, -0x69(%rbp)
je 0x44f0
movl -0x70(%rbp), %edi
callq 0x3440
jmp 0x44ee
jmp 0x44f0
jmp 0x44f2
movq -0x18(%rbp), %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
callq 0x5430
movb -0x2c(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x44f2
testb $0x1, -0x69(%rbp)
je 0x452b
movq -0x18(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
callq 0x81b0
movl -0x74(%rbp), %edi
callq 0x3440
jmp 0x4529
jmp 0x452b
movq -0x28(%rbp), %rax
movq %rax, -0x8(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x9af0
leaq -0x68(%rbp), %rdi
callq 0x47a0
movq -0x8(%rbp), %rax
addq $0xd0, %rsp
popq %rbp
retq
leaq -0xc0(%rbp), %rdi
callq 0x9af0
leaq -0x68(%rbp), %rdi
callq 0x47a0
movq -0x80(%rbp), %rdi
callq 0x3410
movq %rax, %rdi
callq 0x52b0
nopl (%rax,%rax)