// File: nilnilnil[P]autocomplete/deps/mongoose/mongoose.c
// Function: spawn_process
static pid_t spawn_process(struct mg_connection *conn, const char *prog,
                           char *envblk, char *envp[], int fd_stdin,
                           int fd_stdout, const char *dir) {
  pid_t pid;
  const char *interp;

  envblk = NULL; // Unused

  if ((pid = fork()) == -1) {
    // Parent
    send_http_error(conn, 500, http_500_error, "fork(): %s", strerror(ERRNO));
  } else if (pid == 0) {
    // Child
    if (chdir(dir) != 0) {
      cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
    } else if (dup2(fd_stdin, 0) == -1) {
      cry(conn, "%s: dup2(%d, 0): %s", __func__, fd_stdin, strerror(ERRNO));
    } else if (dup2(fd_stdout, 1) == -1) {
      cry(conn, "%s: dup2(%d, 1): %s", __func__, fd_stdout, strerror(ERRNO));
    } else {
      (void) dup2(fd_stdout, 2);
      (void) close(fd_stdin);
      (void) close(fd_stdout);

      // Execute CGI program. No need to lock: new process
      interp = conn->ctx->config[CGI_INTERPRETER];
      if (interp == NULL) {
        (void) execle(prog, prog, NULL, envp);
        cry(conn, "%s: execle(%s): %s", __func__, prog, strerror(ERRNO));
      } else {
        (void) execle(interp, interp, prog, NULL, envp);
        cry(conn, "%s: execle(%s %s): %s", __func__, interp, prog,
            strerror(ERRNO));
      }
    }
    exit(EXIT_FAILURE);
  } else {
    // Parent. Close stdio descriptors
    (void) close(fd_stdin);
    (void) close(fd_stdout);
  }

  return pid;
}

// Assembly:
subq $0xa8, %rsp
movq 0xb0(%rsp), %rax
movq %rdi, 0xa0(%rsp)
movq %rsi, 0x98(%rsp)
movq %rdx, 0x90(%rsp)
movq %rcx, 0x88(%rsp)
movl %r8d, 0x84(%rsp)
movl %r9d, 0x80(%rsp)
movq $0x0, 0x90(%rsp)
callq 0x5130
movl %eax, 0x7c(%rsp)
cmpl $-0x1, %eax
jne 0x20523
movq 0xa0(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0xb573(%rip), %rax      # 0x2ba60
movq %rax, 0x68(%rsp)
callq 0x5060
movl (%rax), %edi
callq 0x5190
movq 0x60(%rsp), %rdi
movq 0x68(%rsp), %rdx
movq %rax, %r8
movl $0x1f4, %esi            # imm = 0x1F4
leaq 0x3259(%rip), %rcx      # 0x23770
movb $0x0, %al
callq 0x1bc40
jmp 0x207a6
cmpl $0x0, 0x7c(%rsp)
jne 0x2078c
movq 0xb0(%rsp), %rdi
callq 0x58b0
cmpl $0x0, %eax
je 0x2058d
movq 0xa0(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0xb0(%rsp), %rax
movq %rax, 0x58(%rsp)
callq 0x5060
movl (%rax), %edi
callq 0x5190
movq 0x50(%rsp), %rdi
movq 0x58(%rsp), %rcx
movq %rax, %r8
leaq 0x3201(%rip), %rsi      # 0x2377b
leaq 0x320c(%rip), %rdx      # 0x2378d
movb $0x0, %al
callq 0x184e0
jmp 0x20782
movl 0x84(%rsp), %edi
xorl %esi, %esi
callq 0x5500
cmpl $-0x1, %eax
jne 0x205ea
movq 0xa0(%rsp), %rax
movq %rax, 0x40(%rsp)
movl 0x84(%rsp), %eax
movl %eax, 0x4c(%rsp)
callq 0x5060
movl (%rax), %edi
callq 0x5190
movq 0x40(%rsp), %rdi
movl 0x4c(%rsp), %ecx
movq %rax, %r8
leaq 0x31c4(%rip), %rsi      # 0x2379b
leaq 0x31af(%rip), %rdx      # 0x2378d
movb $0x0, %al
callq 0x184e0
jmp 0x20780
movl 0x80(%rsp), %edi
movl $0x1, %esi
callq 0x5500
cmpl $-0x1, %eax
jne 0x2064a
movq 0xa0(%rsp), %rax
movq %rax, 0x30(%rsp)
movl 0x80(%rsp), %eax
movl %eax, 0x3c(%rsp)
callq 0x5060
movl (%rax), %edi
callq 0x5190
movq 0x30(%rsp), %rdi
movl 0x3c(%rsp), %ecx
movq %rax, %r8
leaq 0x3178(%rip), %rsi      # 0x237af
leaq 0x314f(%rip), %rdx      # 0x2378d
movb $0x0, %al
callq 0x184e0
jmp 0x2077e
movl 0x80(%rsp), %edi
movl $0x2, %esi
callq 0x5500
movl 0x84(%rsp), %edi
callq 0x5b70
movl 0x80(%rsp), %edi
callq 0x5b70
movq 0xa0(%rsp), %rax
movq 0x458(%rax), %rax
movq 0x28(%rax), %rax
movq %rax, 0x70(%rsp)
cmpq $0x0, 0x70(%rsp)
jne 0x20700
movq 0x98(%rsp), %rdi
movq 0x98(%rsp), %rsi
movq 0x88(%rsp), %rcx
xorl %eax, %eax
movl %eax, %edx
movb $0x0, %al
callq 0x58f0
movq 0xa0(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x28(%rsp)
callq 0x5060
movl (%rax), %edi
callq 0x5190
movq 0x20(%rsp), %rdi
movq 0x28(%rsp), %rcx
movq %rax, %r8
leaq 0x30d3(%rip), %rsi      # 0x237c3
leaq 0x3096(%rip), %rdx      # 0x2378d
movb $0x0, %al
callq 0x184e0
jmp 0x2077c
movq 0x70(%rsp), %rdi
movq 0x70(%rsp), %rsi
movq 0x98(%rsp), %rdx
movq 0x88(%rsp), %r8
xorl %eax, %eax
movl %eax, %ecx
movb $0x0, %al
callq 0x58f0
movq 0xa0(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x70(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x98(%rsp), %rax
movq %rax, 0x18(%rsp)
callq 0x5060
movl (%rax), %edi
callq 0x5190
movq 0x8(%rsp), %rdi
movq 0x10(%rsp), %rcx
movq 0x18(%rsp), %r8
movq %rax, %r9
leaq 0x3068(%rip), %rsi      # 0x237d6
leaq 0x3018(%rip), %rdx      # 0x2378d
movb $0x0, %al
callq 0x184e0
jmp 0x2077e
jmp 0x20780
jmp 0x20782
movl $0x1, %edi
callq 0x56e0
movl 0x84(%rsp), %edi
callq 0x5b70
movl 0x80(%rsp), %edi
callq 0x5b70
jmp 0x207a6
movl 0x7c(%rsp), %eax
addq $0xa8, %rsp
retq
nopw %cs:(%rax,%rax)