// File: /workspace/github_cpp_makefile_star2_O2/davmac314[P]dinit/src/shutdown.cc
// Function: main
int main(int argc, char **argv)
{
    using namespace std;
    
    bool show_help = false;
    bool sys_shutdown = false;
    bool use_passed_cfd = false;
    
    auto shutdown_type = shutdown_type_t::POWEROFF;

    const char *execname = base_name(argv[0]);
    if (strcmp(execname, reboot_execname) == 0) {
        shutdown_type = shutdown_type_t::REBOOT;
    }
    else if (strcmp(execname, soft_reboot_execname) == 0) {
        shutdown_type = shutdown_type_t::SOFTREBOOT;
    }
        
    for (int i = 1; i < argc; i++) {
        if (argv[i][0] == '-') {
            if (strcmp(argv[i], "--help") == 0) {
                show_help = true;
                break;
            }
            
            if (strcmp(argv[i], "--system") == 0) {
                sys_shutdown = true;
            }
            else if (strcmp(argv[i], "-r") == 0) {
                shutdown_type = shutdown_type_t::REBOOT;
            }
            else if (strcmp(argv[i], "-h") == 0) {
                shutdown_type = shutdown_type_t::HALT;
            }
            else if (strcmp(argv[i], "-p") == 0) {
                shutdown_type = shutdown_type_t::POWEROFF;
            }
            else if (strcmp(argv[i], "-s") == 0) {
                shutdown_type = shutdown_type_t::SOFTREBOOT;
            }
            else if (strcmp(argv[i], "-k") == 0) {
                shutdown_type = shutdown_type_t::KEXEC;
            }
            else if (strcmp(argv[i], "--use-passed-cfd") == 0) {
                use_passed_cfd = true;
            }
            else {
                cerr << "Unrecognized command-line parameter: " << argv[i] << endl;
                return 1;
            }
        }
        else {
            // time argument? TODO
            show_help = true;
        }
    }

    if (show_help) {
        cout << execname << " :   shutdown the system\n"
                "  --help           : show this help\n"
                "  -r               : reboot\n"
                "  -s               : soft-reboot (restart dinit with same boot-time arguments)\n"
#if defined(RB_HALT_SYSTEM) || defined(RB_HALT)
                "  -h               : halt system\n"
#endif
#ifdef RB_POWER_OFF
                "  -p               : power down (default)\n"
#endif
#ifdef RB_KEXEC
                "  -k               : stop dinit and reboot directly into kernel loaded with kexec\n"
#endif
                "  --use-passed-cfd : use the socket file descriptor identified by the DINIT_CS_FD\n"
                "                     environment variable to communicate with the init daemon.\n"
                "  --system         : perform shutdown immediately, instead of issuing shutdown\n"
                "                     command to the init program. Not recommended for use\n"
                "                     by users.\n";
        return 1;
    }
    
    if (sys_shutdown) {
        do_system_shutdown(shutdown_type);
        return 1; // likely to cause panic; the above shouldn't return
    }

    if (reboot_cmd_unsupported(shutdown_type)) {
        cerr << "Unsupported shutdown type\n";
        return 1;
    }

    signal(SIGPIPE, SIG_IGN);
    
    int socknum = -1;
    
    if (use_passed_cfd) {
        socknum = get_passed_cfd();
        if (socknum == -1) {
            use_passed_cfd = false;
        }
    }
    
    if (!use_passed_cfd) {
        socknum = socket(AF_UNIX, SOCK_STREAM, 0);
        if (socknum == -1) {
            perror("socket");
            return 1;
        }
        
        const char *naddr = SYSCONTROLSOCKET;
        
        struct sockaddr_un name;
        name.sun_family = AF_UNIX;
        strcpy(name.sun_path, naddr);
        int sunlen = offsetof(struct sockaddr_un, sun_path) + strlen(naddr) + 1; // family, (string), nul
        
        int connr = connect(socknum, (struct sockaddr *) &name, sunlen);
        if (connr == -1) {
            perror("connect");
            return 1;
        }
    }

    try {
        cpbuffer_t rbuffer;
    
        check_protocol_version(min_cp_version, max_cp_version, rbuffer, socknum);

        // Build buffer;
        constexpr int bufsize = 2;
        char buf[bufsize];

        buf[0] = (dinit_cptypes::cp_cmd_t)cp_cmd::SHUTDOWN;
        buf[1] = static_cast<char>(shutdown_type);

        cout << "Issuing shutdown command..." << endl;

        write_all_x(socknum, buf, bufsize);

        // Wait for ACK/NACK
    
        wait_for_reply(rbuffer, socknum);
        
        if (rbuffer[0] != (dinit_cptypes::cp_rply_t)cp_rply::ACK) {
            cerr << "shutdown: control socket protocol error" << endl;
            return 1;
        }
    }
    catch (cp_old_client_exception &e) {
        std::cerr << "shutdown: too old (server reports newer protocol version)" << std::endl;
        return 1;
    }
    catch (cp_old_server_exception &e) {
        std::cerr << "shutdown: server too old or protocol error" << std::endl;
        return 1;
    }
    catch (cp_read_exception &e) {
        cerr << "shutdown: control socket read failure or protocol error" << endl;
        return 1;
    }
    catch (cp_write_exception &e) {
        cerr << "shutdown: control socket write error: " << std::strerror(e.errcode) << endl;
        return 1;
    }

    while (true) {
        pause();
    }
    
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x418, %rsp            # imm = 0x418
movq %rsi, %rbx
movl %edi, %ebp
movq (%rsi), %rdi
callq 0x4068
movq %rax, %r14
leaq 0x4a8c(%rip), %rsi      # 0x8020
movq %rax, %rdi
callq 0x3340
testl %eax, %eax
movq %r14, 0x8(%rsp)
je 0x35c3
leaq 0x4a7b(%rip), %rsi      # 0x8027
movq %r14, %rdi
callq 0x3340
testl %eax, %eax
sete %al
addb %al, %al
addb $0x3, %al
movb %al, 0x1(%rsp)
jmp 0x35c8
movb $0x4, 0x1(%rsp)
movslq %ebp, %r12
pushq $0x1
popq %r13
xorl %r14d, %r14d
movl $0x0, 0x4(%rsp)
xorl %r15d, %r15d
cmpq %r12, %r13
jge 0x36ab
movq (%rbx,%r13,8), %rbp
cmpb $0x2d, (%rbp)
jne 0x3675
movq %rbp, %rdi
leaq 0x4d46(%rip), %rsi      # 0x8344
callq 0x3340
testl %eax, %eax
je 0x36b1
movq %rbp, %rdi
leaq 0x4d36(%rip), %rsi      # 0x834b
callq 0x3340
testl %eax, %eax
je 0x367a
cmpb $0x72, 0x1(%rbp)
jne 0x362a
cmpb $0x0, 0x2(%rbp)
je 0x3682
cmpb $0x68, 0x1(%rbp)
jne 0x3636
cmpb $0x0, 0x2(%rbp)
je 0x3689
cmpb $0x70, 0x1(%rbp)
jne 0x3642
cmpb $0x0, 0x2(%rbp)
je 0x3690
cmpb $0x73, 0x1(%rbp)
jne 0x364e
cmpb $0x0, 0x2(%rbp)
je 0x3697
cmpb $0x6b, 0x1(%rbp)
jne 0x365a
cmpb $0x0, 0x2(%rbp)
je 0x369e
movq %rbp, %rdi
leaq 0x4cf3(%rip), %rsi      # 0x8357
callq 0x3340
movb $0x1, %r14b
testl %eax, %eax
je 0x36a3
jmp 0x3809
movb $0x1, %r15b
jmp 0x36a3
movb $0x1, %al
movl %eax, 0x4(%rsp)
jmp 0x36a3
movb $0x4, 0x1(%rsp)
jmp 0x36a3
movb $0x2, 0x1(%rsp)
jmp 0x36a3
movb $0x3, 0x1(%rsp)
jmp 0x36a3
movb $0x5, 0x1(%rsp)
jmp 0x36a3
movb $0x6, 0x1(%rsp)
incq %r13
jmp 0x35dd
testb $0x1, %r15b
je 0x36d6
movq 0x9900(%rip), %rdi      # 0xcfb8
movq 0x8(%rsp), %rsi
callq 0x3270
leaq 0x4cc5(%rip), %rsi      # 0x838e
movq %rax, %rdi
callq 0x3270
jmp 0x3830
testb $0x1, 0x4(%rsp)
je 0x36ec
movsbl 0x1(%rsp), %edi
callq 0x3962
jmp 0x3830
pushq $0xd
popq %rdi
pushq $0x1
popq %rsi
callq 0x32a0
testb $0x1, %r14b
je 0x3713
callq 0x4087
movl %eax, %ebx
xorl %eax, %eax
cmpl $-0x1, %ebx
movzbl %r14b, %r14d
cmovel %eax, %r14d
jmp 0x3716
pushq $-0x1
popq %rbx
testb $0x1, %r14b
jne 0x376c
pushq $0x1
popq %rdi
movl %edi, %esi
xorl %edx, %edx
callq 0x3050
cmpl $-0x1, %eax
je 0x3845
movl %eax, %ebx
leaq 0x10(%rsp), %rsi
movw $0x1, (%rsi)
movabsq $0x6e69642f6e75722f, %rax # imm = 0x6E69642F6E75722F
movq %rax, 0x2(%rsi)
movabsq $0x6c746374696e69, %rax # imm = 0x6C746374696E69
movq %rax, 0x8(%rsi)
pushq $0x10
popq %rdx
movl %ebx, %edi
callq 0x31f0
cmpl $-0x1, %eax
je 0x384e
leaq 0x10(%rsp), %rdx
andq $0x0, 0x400(%rdx)
pushq $0x1
popq %rdi
pushq $0x5
popq %rsi
movl %ebx, %ecx
callq 0x410a
movb $0xa, 0x2(%rsp)
movb 0x1(%rsp), %al
movb %al, 0x3(%rsp)
movq 0x981e(%rip), %rdi      # 0xcfb8
leaq 0x4ea9(%rip), %rsi      # 0x864a
callq 0x3270
movq %rax, %rdi
callq 0x3120
leaq 0x2(%rsp), %rsi
pushq $0x2
popq %rdx
movl %ebx, %edi
callq 0x4200
leaq 0x10(%rsp), %rdi
movl %ebx, %esi
callq 0x4232
movl 0x410(%rsp), %eax
leal -0x400(%rax), %ecx
cmpl $0x400, %eax            # imm = 0x400
cmovbl %eax, %ecx
cmpb $0x32, 0x10(%rsp,%rcx)
jne 0x37ec
callq 0x3040
jmp 0x37e5
movq 0x97f5(%rip), %rdi      # 0xcfe8
leaq 0x4e6c(%rip), %rsi      # 0x8666
callq 0x3270
movq %rax, %rdi
callq 0x3120
jmp 0x3830
movq 0x97d8(%rip), %rdi      # 0xcfe8
leaq 0x4b51(%rip), %rsi      # 0x8368
callq 0x3270
movq (%rbx,%r13,8), %rsi
movq %rax, %rdi
callq 0x3270
movq %rax, %rdi
callq 0x3120
pushq $0x1
popq %rax
addq $0x418, %rsp            # imm = 0x418
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4de1(%rip), %rdi      # 0x862d
jmp 0x3855
leaq 0x4ded(%rip), %rdi      # 0x8642
callq 0x3200
jmp 0x3830
jmp 0x385e
movq %rax, %rbx
cmpl $0x4, %edx
jne 0x388e
movq %rbx, %rdi
callq 0x30d0
movq 0x9773(%rip), %rdi      # 0xcfe8
leaq 0x4e9c(%rip), %rsi      # 0x8718
callq 0x3270
movq %rax, %rdi
callq 0x3120
jmp 0x3922
cmpl $0x3, %edx
jne 0x38b8
movq %rbx, %rdi
callq 0x30d0
movq 0x9746(%rip), %rdi      # 0xcfe8
leaq 0x4e44(%rip), %rsi      # 0x86ed
callq 0x3270
movq %rax, %rdi
callq 0x3120
jmp 0x3922
cmpl $0x2, %edx
jne 0x38e2
movq %rbx, %rdi
callq 0x30d0
movq 0x971c(%rip), %rdi      # 0xcfe8
leaq 0x4de2(%rip), %rsi      # 0x86b5
callq 0x3270
movq %rax, %rdi
callq 0x3120
jmp 0x3922
cmpl $0x1, %edx
jne 0x3952
movq %rbx, %rdi
callq 0x30d0
movq %rax, %rbx
movq 0x96ef(%rip), %rdi      # 0xcfe8
leaq 0x4d8e(%rip), %rsi      # 0x868e
callq 0x3270
movq %rax, %r14
movl (%rbx), %edi
callq 0x30a0
movq %r14, %rdi
movq %rax, %rsi
callq 0x3270
movq %rax, %rdi
callq 0x3120
callq 0x33d0
jmp 0x3830
movq %rax, %rbx
callq 0x33d0
jmp 0x3952
movq %rax, %rbx
callq 0x33d0
jmp 0x3952
movq %rax, %rbx
callq 0x33d0
jmp 0x3952
movq %rax, %rbx
callq 0x33d0
movq %rbx, %rdi
callq 0x3400
movq %rax, %rdi
callq 0x42c3