// File: /workspace/github_cpp_makefile_star2_O3/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, %r14
movl %edi, %ebp
movq (%rsi), %rbx
leaq 0x1(%rbx), %rax
movzbl -0x1(%rax), %ecx
cmpl $0x2f, %ecx
je 0x3678
testl %ecx, %ecx
jne 0x367b
jmp 0x3680
movq %rax, %rbx
incq %rax
jmp 0x3669
leaq 0x4999(%rip), %rsi      # 0x8020
movq %rbx, %rdi
callq 0x3370
testl %eax, %eax
je 0x36b1
leaq 0x498d(%rip), %rsi      # 0x8027
movq %rbx, %rdi
callq 0x3370
testl %eax, %eax
sete %r15b
addb %r15b, %r15b
addb $0x3, %r15b
jmp 0x36b4
movb $0x4, %r15b
cmpl $0x1, %ebp
jle 0x37cd
movb %r15b, 0x5(%rsp)
movl %ebp, %r12d
negq %r12
movl $0x1, %r13d
movl $0x0, 0x8(%rsp)
movl $0x0, 0xc(%rsp)
xorl %r15d, %r15d
incq %r13
movq -0x8(%r14,%r13,8), %rbp
cmpb $0x2d, (%rbp)
jne 0x37b6
movq %rbp, %rdi
leaq 0x4c47(%rip), %rsi      # 0x8344
callq 0x3370
testl %eax, %eax
je 0x3971
movq %rbp, %rdi
leaq 0x4c37(%rip), %rsi      # 0x834b
callq 0x3370
testl %eax, %eax
je 0x3774
cmpb $0x72, 0x1(%rbp)
jne 0x3729
cmpb $0x0, 0x2(%rbp)
je 0x377c
cmpb $0x68, 0x1(%rbp)
jne 0x3735
cmpb $0x0, 0x2(%rbp)
je 0x3783
cmpb $0x70, 0x1(%rbp)
jne 0x3741
cmpb $0x0, 0x2(%rbp)
je 0x378a
cmpb $0x73, 0x1(%rbp)
jne 0x374d
cmpb $0x0, 0x2(%rbp)
je 0x3791
cmpb $0x6b, 0x1(%rbp)
jne 0x3759
cmpb $0x0, 0x2(%rbp)
je 0x3798
movq %rbp, %rdi
leaq 0x4bf4(%rip), %rsi      # 0x8357
callq 0x3370
movb $0x1, %r15b
testl %eax, %eax
je 0x379d
jmp 0x3abe
movb $0x1, %al
movl %eax, 0xc(%rsp)
jmp 0x379d
movb $0x4, 0x5(%rsp)
jmp 0x379d
movb $0x2, 0x5(%rsp)
jmp 0x379d
movb $0x3, 0x5(%rsp)
jmp 0x379d
movb $0x5, 0x5(%rsp)
jmp 0x379d
movb $0x6, 0x5(%rsp)
leaq (%r12,%r13), %rax
incq %rax
incq %r13
cmpq $0x1, %rax
jne 0x36e4
jmp 0x3966
movb $0x1, %al
movl %eax, 0x8(%rsp)
movq %r12, %rax
addq %r13, %rax
jne 0x36e1
jmp 0x3971
movl $0x1, %esi
movl $0xd, %edi
callq 0x32d0
movl $0x1, %edi
movl $0x1, %esi
xorl %edx, %edx
callq 0x3060
cmpl $-0x1, %eax
je 0x3afd
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)
movl %ebx, %edi
movl $0x10, %edx
callq 0x3200
cmpl $-0x1, %eax
je 0x3b06
leaq 0x10(%rsp), %rdx
movq $0x0, 0x400(%rdx)
movl $0x1, %edi
movl $0x5, %esi
movl %ebx, %ecx
callq 0x43f6
movb $0xa, 0x6(%rsp)
movb %r15b, 0x7(%rsp)
movq 0x8753(%rip), %r14      # 0xbfb8
leaq 0x4dde(%rip), %rsi      # 0x864a
movl $0x1b, %edx
movq %r14, %rdi
callq 0x32c0
movq (%r14), %rax
addq -0x18(%rax), %r14
movq %r14, %rdi
movl $0xa, %esi
callq 0x3280
movsbl %al, %esi
movq 0x8721(%rip), %rdi      # 0xbfb8
callq 0x3030
movq %rax, %rdi
callq 0x31a0
movl $0x2, %r15d
leaq 0x6(%rsp), %r14
xorl %ebp, %ebp
movl %r15d, %edx
movl %ebx, %edi
movq %r14, %rsi
callq 0x30c0
cmpl $-0x1, %eax
je 0x38d0
addl %eax, %ebp
movslq %eax, %rcx
addq %rcx, %r14
subl %eax, %r15d
jmp 0x38de
callq 0x3040
cmpl $0x4, (%rax)
jne 0x3992
testl %r15d, %r15d
jg 0x38b1
cmpl $-0x1, %ebp
je 0x399a
leaq 0x10(%rsp), %rdi
movl %ebx, %esi
callq 0x4653
movl 0x410(%rsp), %eax
leal -0x400(%rax), %ecx
cmpl $0x400, %eax            # imm = 0x400
cmovbl %eax, %ecx
cmpb $0x32, 0x10(%rsp,%rcx)
jne 0x391b
callq 0x3050
jmp 0x3914
movq 0x86c6(%rip), %rbx      # 0xbfe8
leaq 0x4d3d(%rip), %rsi      # 0x8666
movl $0x27, %edx
movq %rbx, %rdi
callq 0x32c0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x3280
movsbl %al, %esi
movq 0x8694(%rip), %rdi      # 0xbfe8
callq 0x3030
movq %rax, %rdi
callq 0x31a0
jmp 0x39f7
testb $0x1, 0x8(%rsp)
je 0x3a0e
testq %rbx, %rbx
je 0x39c1
movq %rbx, %rdi
callq 0x30f0
movq 0x8633(%rip), %rdi      # 0xbfb8
movq %rbx, %rsi
movq %rax, %rdx
callq 0x32c0
jmp 0x39df
testl %ebp, %ebp
jg 0x38ec
movl $0x4, %edi
callq 0x3130
movq %rax, %rbx
callq 0x3040
movl (%rax), %eax
movl %eax, (%rbx)
leaq 0x80e9(%rip), %rsi      # 0xbaa0
movq %rbx, %rdi
xorl %edx, %edx
callq 0x3430
movq 0x85f0(%rip), %rax      # 0xbfb8
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
leaq (%rax,%rcx), %rdi
movl 0x20(%rax,%rcx), %esi
orl $0x1, %esi
callq 0x3420
movq 0x85d2(%rip), %rdi      # 0xbfb8
leaq 0x49a1(%rip), %rsi      # 0x838e
movl $0x29e, %edx            # imm = 0x29E
callq 0x32c0
movl $0x1, %eax
addq $0x418, %rsp            # imm = 0x418
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testb $0x1, 0xc(%rsp)
je 0x3a21
movsbl 0x5(%rsp), %edi
callq 0x3c51
jmp 0x39f7
movl $0x1, %esi
movl $0xd, %edi
callq 0x32d0
testb $0x1, %r15b
je 0x3af3
leaq 0x4e7f(%rip), %rdi      # 0x88c0
callq 0x32e0
testq %rax, %rax
je 0x3af3
movq %rax, %r14
leaq 0x10(%rsp), %r15
movq %rax, %rdi
movq %r15, %rsi
movl $0xa, %edx
callq 0x3380
cmpq %r14, (%r15)
je 0x3af3
movq %rax, %rbx
callq 0x3040
movq %rax, %r14
movl $0x0, (%rax)
movl %ebx, %edi
movl $0x3, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x3170
cmpl $-0x1, %eax
movb 0x5(%rsp), %r15b
je 0x3b17
andl $0xfffff7ff, %eax       # imm = 0xFFFFF7FF
movl %ebx, %edi
movl $0x4, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x3170
cmpl $-0x1, %ebx
jne 0x3833
jmp 0x37dc
movq 0x8523(%rip), %rbx      # 0xbfe8
leaq 0x489c(%rip), %rsi      # 0x8368
movl $0x25, %edx
movq %rbx, %rdi
callq 0x32c0
movq -0x8(%r14,%r13,8), %rsi
movq %rbx, %rdi
callq 0x3290
movq %rax, %rdi
callq 0x3120
jmp 0x39f7
movb 0x5(%rsp), %r15b
jmp 0x37dc
leaq 0x4b29(%rip), %rdi      # 0x862d
jmp 0x3b0d
leaq 0x4b35(%rip), %rdi      # 0x8642
callq 0x3210
jmp 0x39f7
cmpl $0x0, (%r14)
je 0x3a9b
xorl %ebx, %ebx
jmp 0x3833
jmp 0x3b2c
jmp 0x3b2c
movq %rax, %rbx
cmpl $0x4, %edx
jne 0x3b65
movq %rbx, %rdi
callq 0x30e0
movq 0x84a5(%rip), %rdi      # 0xbfe8
leaq 0x4bce(%rip), %rsi      # 0x8718
movl $0x39, %edx
callq 0x32c0
movq 0x848d(%rip), %rdi      # 0xbfe8
callq 0x3120
jmp 0x3c11
cmpl $0x3, %edx
jne 0x3b98
movq %rbx, %rdi
callq 0x30e0
movq 0x846f(%rip), %rdi      # 0xbfe8
leaq 0x4b6d(%rip), %rsi      # 0x86ed
movl $0x2a, %edx
callq 0x32c0
movq 0x8457(%rip), %rdi      # 0xbfe8
callq 0x3120
jmp 0x3c11
cmpl $0x2, %edx
jne 0x3bcb
movq %rbx, %rdi
callq 0x30e0
movq 0x843c(%rip), %rdi      # 0xbfe8
leaq 0x4b02(%rip), %rsi      # 0x86b5
movl $0x37, %edx
callq 0x32c0
movq 0x8424(%rip), %rdi      # 0xbfe8
callq 0x3120
jmp 0x3c11
cmpl $0x1, %edx
jne 0x3c41
movq %rbx, %rdi
callq 0x30e0
movq %rax, %rbx
movq 0x8406(%rip), %rdi      # 0xbfe8
leaq 0x4aa5(%rip), %rsi      # 0x868e
movl $0x26, %edx
callq 0x32c0
movl (%rbx), %edi
callq 0x30b0
movq 0x83e7(%rip), %rdi      # 0xbfe8
movq %rax, %rsi
callq 0x3290
movq %rax, %rdi
callq 0x3120
callq 0x3400
jmp 0x39f7
movq %rax, %rbx
callq 0x3400
jmp 0x3c41
movq %rax, %rbx
callq 0x3400
jmp 0x3c41
movq %rax, %rbx
callq 0x3400
jmp 0x3c41
movq %rax, %rbx
callq 0x3400
movq %rbx, %rdi
callq 0x3440
movq %rax, %rdi
callq 0x47e6