// File: cybozu[P]yrmcds/src/main.cpp
// Function: main
int main(int argc, char** argv) {
    std::vector<std::string> args;
    for( int i = 1; i < argc; ++i )
        args.push_back(argv[i]);

    if( std::find(args.begin(), args.end(), "-h") != args.end() ) {
        print_help();
        return 0;
    }

    if( std::find(args.begin(), args.end(), "-v") != args.end() ) {
        print_version();
        return 0;
    }

    using cybozu::logger;

    seed_siphash();

    try {
        if( ! load_config(args) )
            return 1;

        if( yrmcds::g_config.lock_memory() ) {
            if( ::mlockall( MCL_CURRENT | MCL_FUTURE ) == -1 )
                cybozu::throw_unix_error(errno, "mlockall");
        }

        // first, set group id (as root)
        const std::string& g = yrmcds::g_config.group();
        if( ! g.empty() ) {
            if( getuid() != 0 ) {
                std::cerr << "Ignored group configuration." << std::endl;
            } else {
                struct group* grp = getgrnam(g.c_str());
                if( grp == nullptr ) {
                    std::cerr << "No such group: " << g << std::endl;
                    return 1;
                }
                if( setgid(grp->gr_gid) == -1 ) {
                    std::cerr << "Failed to set group id!" << std::endl;
                    return 1;
                }
            }
        }

        const std::string& u = yrmcds::g_config.user();
        if( ! u.empty() ) {
            if( getuid() != 0 ) {
                std::cerr << "Ignored user configuration." << std::endl;
            } else {
                struct passwd* p = getpwnam(u.c_str());
                if( p == nullptr ) {
                    std::cerr << "No such user: " << u << std::endl;
                    return 1;
                }
                if( setuid(p->pw_uid) == -1 ) {
                    std::cerr << "Failed to set user id!" << std::endl;
                    return 1;
                }
            }
        }

        // make it core dumpable
        if( prctl(PR_SET_DUMPABLE, 1) == -1 ) {
            std::cerr << "WARNING: failed to enable core dump!" << std::endl;
        }

        // setup logger
        logger::set_threshold(yrmcds::g_config.threshold());
        if( ! yrmcds::g_config.logfile().empty() )
            logger::instance().open(yrmcds::g_config.logfile());

        yrmcds::server().serve();

    } catch( const std::system_error& e ) {
        cybozu::demangler t( typeid(e).name() );
        logger::error() << "[" << t.name() << "] (" << e.code() << ") "
                        << e.what();
        std::cerr << "Exception [" << t.name() << "] (" << e.code() << ") "
                  << e.what() << std::endl;
        return 1;

    } catch( const std::exception& e ) {
        cybozu::demangler t( typeid(e).name() );
        logger::error() << "[" << t.name() << "] " << e.what();
        std::cerr << "Exception [" << t.name() << "] " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3e0, %rsp            # imm = 0x3E0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x28(%rbp), %rdi
callq 0xa110
movl $0x1, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x92ae
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x298(%rbp)
leaq -0x51(%rbp), %rdi
movq %rdi, -0x290(%rbp)
callq 0x8bd0
movq -0x298(%rbp), %rsi
movq -0x290(%rbp), %rdx
leaq -0x50(%rbp), %rdi
callq 0xa160
jmp 0x9251
leaq -0x28(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0xa130
jmp 0x9260
leaq -0x50(%rbp), %rdi
callq 0x83f0
leaq -0x51(%rbp), %rdi
callq 0x86a0
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x9209
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x92a0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x83f0
leaq -0x51(%rbp), %rdi
callq 0x86a0
jmp 0x9cdc
leaq -0x28(%rbp), %rdi
movq %rdi, -0x2a8(%rbp)
callq 0xa2a0
movq -0x2a8(%rbp), %rdi
movq %rax, -0x78(%rbp)
callq 0xa2d0
movq %rax, -0x80(%rbp)
movq -0x78(%rbp), %rdi
movq -0x80(%rbp), %rsi
leaq 0x70d43(%rip), %rdx     # 0x7a024
callq 0xa250
movq %rax, -0x2a0(%rbp)
jmp 0x92ef
movq -0x2a0(%rbp), %rax
movq %rax, -0x70(%rbp)
leaq -0x28(%rbp), %rdi
callq 0xa2d0
movq %rax, -0x88(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0xa210
testb $0x1, %al
jne 0x9320
jmp 0x934e
callq 0x9d00
jmp 0x9327
movl $0x0, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
jmp 0x9cc7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x9cdc
leaq -0x28(%rbp), %rdi
movq %rdi, -0x2b8(%rbp)
callq 0xa2a0
movq -0x2b8(%rbp), %rdi
movq %rax, -0xa0(%rbp)
callq 0xa2d0
movq %rax, -0xa8(%rbp)
movq -0xa0(%rbp), %rdi
movq -0xa8(%rbp), %rsi
leaq 0x70c9a(%rip), %rdx     # 0x7a027
callq 0xa250
movq %rax, -0x2b0(%rbp)
jmp 0x939b
movq -0x2b0(%rbp), %rax
movq %rax, -0x98(%rbp)
leaq -0x28(%rbp), %rdi
callq 0xa2d0
movq %rax, -0xb0(%rbp)
leaq -0x98(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0xa210
testb $0x1, %al
jne 0x93d2
jmp 0x93ef
callq 0x9d30
jmp 0x93d9
movl $0x0, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
jmp 0x9cc7
callq 0x9d80
jmp 0x93f6
leaq -0x28(%rbp), %rdi
callq 0x9e40
movb %al, -0x2b9(%rbp)
jmp 0x9407
movb -0x2b9(%rbp), %al
testb $0x1, %al
jne 0x943a
jmp 0x9413
movl $0x1, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
jmp 0x9cc7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x9816
leaq 0xa68bf(%rip), %rdi     # 0xafd00
callq 0xa300
testb $0x1, %al
jne 0x944c
jmp 0x9472
movl $0x3, %edi
callq 0x8b90
cmpl $-0x1, %eax
jne 0x9470
callq 0x8050
movl (%rax), %edi
leaq 0x70bc1(%rip), %rsi     # 0x7a02a
callq 0xa320
jmp 0x9470
jmp 0x9472
leaq 0xa6887(%rip), %rdi     # 0xafd00
callq 0xa3a0
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rdi
callq 0x8b10
testb $0x1, %al
jne 0x95d0
callq 0x8300
cmpl $0x0, %eax
je 0x94d9
movq 0xa5b3e(%rip), %rdi     # 0xaefe8
leaq 0x70b82(%rip), %rsi     # 0x7a033
callq 0x8630
movq %rax, -0x2c8(%rbp)
jmp 0x94bf
movq -0x2c8(%rbp), %rdi
movq 0xa5a8b(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x94d4
jmp 0x95ce
movq -0xb8(%rbp), %rdi
callq 0x8240
movq %rax, %rdi
callq 0x8610
movq %rax, -0x2d0(%rbp)
jmp 0x94f6
movq -0x2d0(%rbp), %rax
movq %rax, -0xc0(%rbp)
cmpq $0x0, -0xc0(%rbp)
jne 0x9571
movq 0xa5ad3(%rip), %rdi     # 0xaefe8
leaq 0x70b34(%rip), %rsi     # 0x7a050
callq 0x8630
movq %rax, -0x2d8(%rbp)
jmp 0x952a
movq -0x2d8(%rbp), %rdi
movq -0xb8(%rbp), %rsi
callq 0x85a0
movq %rax, -0x2e0(%rbp)
jmp 0x9546
movq -0x2e0(%rbp), %rdi
movq 0xa5a04(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x955b
movl $0x1, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
jmp 0x9cc7
movq -0xc0(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x8be0
cmpl $-0x1, %eax
jne 0x95cc
movq 0xa5a5c(%rip), %rdi     # 0xaefe8
leaq 0x70acd(%rip), %rsi     # 0x7a060
callq 0x8630
movq %rax, -0x2e8(%rbp)
jmp 0x95a1
movq -0x2e8(%rbp), %rdi
movq 0xa59a9(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x95b6
movl $0x1, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
jmp 0x9cc7
jmp 0x95ce
jmp 0x95d0
leaq 0xa6729(%rip), %rdi     # 0xafd00
callq 0xa3c0
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rdi
callq 0x8b10
testb $0x1, %al
jne 0x972e
callq 0x8300
cmpl $0x0, %eax
je 0x9637
movq 0xa59e0(%rip), %rdi     # 0xaefe8
leaq 0x70a69(%rip), %rsi     # 0x7a078
callq 0x8630
movq %rax, -0x2f0(%rbp)
jmp 0x961d
movq -0x2f0(%rbp), %rdi
movq 0xa592d(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x9632
jmp 0x972c
movq -0xc8(%rbp), %rdi
callq 0x8240
movq %rax, %rdi
callq 0x8520
movq %rax, -0x2f8(%rbp)
jmp 0x9654
movq -0x2f8(%rbp), %rax
movq %rax, -0xd0(%rbp)
cmpq $0x0, -0xd0(%rbp)
jne 0x96cf
movq 0xa5975(%rip), %rdi     # 0xaefe8
leaq 0x70a1a(%rip), %rsi     # 0x7a094
callq 0x8630
movq %rax, -0x300(%rbp)
jmp 0x9688
movq -0x300(%rbp), %rdi
movq -0xc8(%rbp), %rsi
callq 0x85a0
movq %rax, -0x308(%rbp)
jmp 0x96a4
movq -0x308(%rbp), %rdi
movq 0xa58a6(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x96b9
movl $0x1, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
jmp 0x9cc7
movq -0xd0(%rbp), %rax
movl 0x10(%rax), %edi
callq 0x8c90
cmpl $-0x1, %eax
jne 0x972a
movq 0xa58fe(%rip), %rdi     # 0xaefe8
leaq 0x709b2(%rip), %rsi     # 0x7a0a3
callq 0x8630
movq %rax, -0x310(%rbp)
jmp 0x96ff
movq -0x310(%rbp), %rdi
movq 0xa584b(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x9714
movl $0x1, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
jmp 0x9cc7
jmp 0x972c
jmp 0x972e
movl $0x4, %edi
movl $0x1, %esi
movb $0x0, %al
callq 0x8840
cmpl $-0x1, %eax
jne 0x9777
movq 0xa589d(%rip), %rdi     # 0xaefe8
leaq 0x70968(%rip), %rsi     # 0x7a0ba
callq 0x8630
movq %rax, -0x318(%rbp)
jmp 0x9760
movq -0x318(%rbp), %rdi
movq 0xa57ea(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x9775
jmp 0x9777
leaq 0xa6582(%rip), %rdi     # 0xafd00
callq 0xa410
movl %eax, %edi
callq 0xa3e0
jmp 0x978c
leaq 0xa656d(%rip), %rdi     # 0xafd00
callq 0xa430
movq %rax, %rdi
callq 0x8b10
testb $0x1, %al
jne 0x97d1
callq 0xa450
movq %rax, -0x320(%rbp)
jmp 0x97b2
leaq 0xa6547(%rip), %rdi     # 0xafd00
callq 0xa430
movq -0x320(%rbp), %rdi
movq %rax, %rsi
callq 0xa4e0
jmp 0x97cf
jmp 0x97d1
leaq -0x208(%rbp), %rdi
callq 0x1f8b0
jmp 0x97df
leaq -0x208(%rbp), %rdi
callq 0x1fbd0
jmp 0x97ed
leaq -0x208(%rbp), %rdi
callq 0xa560
jmp 0x9cb6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x208(%rbp), %rdi
callq 0xa560
movl -0x64(%rbp), %eax
movl %eax, -0x324(%rbp)
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x9a5c
movq -0x60(%rbp), %rdi
callq 0x8230
movq %rax, -0x250(%rbp)
movq -0x250(%rbp), %rax
movq (%rax), %rax
movq -0x8(%rax), %rdi
callq 0xa5c0
movq %rax, %rsi
leaq -0x270(%rbp), %rdi
callq 0x16a50
jmp 0x9860
leaq -0x280(%rbp), %rdi
callq 0xa600
jmp 0x986e
leaq 0x70877(%rip), %rsi     # 0x7a0ec
leaq -0x280(%rbp), %rdi
callq 0xa650
movq %rax, -0x330(%rbp)
jmp 0x988a
leaq -0x270(%rbp), %rdi
callq 0xa6d0
movq %rax, -0x338(%rbp)
jmp 0x989f
movq -0x338(%rbp), %rsi
movq -0x330(%rbp), %rdi
callq 0xa690
movq %rax, -0x340(%rbp)
jmp 0x98bb
movq -0x340(%rbp), %rdi
leaq 0x70825(%rip), %rsi     # 0x7a0ee
callq 0xa7f0
movq %rax, -0x348(%rbp)
jmp 0x98d7
movq -0x250(%rbp), %rdi
callq 0xa870
movq -0x348(%rbp), %rdi
movq %rax, %rsi
callq 0xa830
movq %rax, -0x350(%rbp)
jmp 0x98fb
movq -0x350(%rbp), %rdi
leaq 0x707e9(%rip), %rsi     # 0x7a0f2
callq 0xa6e0
movq %rax, -0x358(%rbp)
jmp 0x9917
movq -0x250(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq -0x358(%rbp), %rdi
movq %rax, -0x288(%rbp)
leaq -0x288(%rbp), %rsi
callq 0xa720
jmp 0x9943
leaq -0x280(%rbp), %rdi
callq 0xa770
movq 0xa5692(%rip), %rdi     # 0xaefe8
leaq 0x70785(%rip), %rsi     # 0x7a0e2
callq 0x8630
movq %rax, -0x360(%rbp)
jmp 0x996b
leaq -0x270(%rbp), %rdi
callq 0xa6d0
movq %rax, -0x368(%rbp)
jmp 0x9980
movq -0x368(%rbp), %rsi
movq -0x360(%rbp), %rdi
callq 0x85a0
movq %rax, -0x370(%rbp)
jmp 0x999c
movq -0x370(%rbp), %rdi
leaq 0x70744(%rip), %rsi     # 0x7a0ee
callq 0x8630
movq %rax, -0x378(%rbp)
jmp 0x99b8
movq -0x250(%rbp), %rdi
callq 0xa870
movq -0x378(%rbp), %rdi
movq %rax, %rsi
callq 0xa890
movq %rax, -0x380(%rbp)
jmp 0x99dc
movq -0x380(%rbp), %rdi
leaq 0x70708(%rip), %rsi     # 0x7a0f2
callq 0x8630
movq %rax, -0x388(%rbp)
jmp 0x99f8
movq -0x250(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq -0x388(%rbp), %rdi
movq %rax, %rsi
callq 0x8630
movq %rax, -0x390(%rbp)
jmp 0x9a20
movq -0x390(%rbp), %rdi
movq 0xa552a(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x9a35
movl $0x1, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
leaq -0x270(%rbp), %rdi
callq 0xa7c0
callq 0x8ae0
jmp 0x9cab
movl -0x324(%rbp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0x9cdc
movq -0x60(%rbp), %rdi
callq 0x8230
movq %rax, -0x210(%rbp)
movq -0x210(%rbp), %rax
movq (%rax), %rax
movq -0x8(%rax), %rdi
callq 0xa5c0
movq %rax, %rsi
leaq -0x230(%rbp), %rdi
callq 0x16a50
jmp 0x9aa3
leaq -0x240(%rbp), %rdi
callq 0xa600
jmp 0x9ab1
leaq 0x70634(%rip), %rsi     # 0x7a0ec
leaq -0x240(%rbp), %rdi
callq 0xa650
movq %rax, -0x398(%rbp)
jmp 0x9acd
leaq -0x230(%rbp), %rdi
callq 0xa6d0
movq %rax, -0x3a0(%rbp)
jmp 0x9ae2
movq -0x3a0(%rbp), %rsi
movq -0x398(%rbp), %rdi
callq 0xa690
movq %rax, -0x3a8(%rbp)
jmp 0x9afe
movq -0x3a8(%rbp), %rdi
leaq 0x705d3(%rip), %rsi     # 0x7a0df
callq 0xa6e0
movq %rax, -0x3b0(%rbp)
jmp 0x9b1a
movq -0x210(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq -0x3b0(%rbp), %rdi
movq %rax, -0x248(%rbp)
leaq -0x248(%rbp), %rsi
callq 0xa720
jmp 0x9b46
leaq -0x240(%rbp), %rdi
callq 0xa770
movq 0xa548f(%rip), %rdi     # 0xaefe8
leaq 0x70582(%rip), %rsi     # 0x7a0e2
callq 0x8630
movq %rax, -0x3b8(%rbp)
jmp 0x9b6e
leaq -0x230(%rbp), %rdi
callq 0xa6d0
movq %rax, -0x3c0(%rbp)
jmp 0x9b83
movq -0x3c0(%rbp), %rsi
movq -0x3b8(%rbp), %rdi
callq 0x85a0
movq %rax, -0x3c8(%rbp)
jmp 0x9b9f
movq -0x3c8(%rbp), %rdi
leaq 0x70532(%rip), %rsi     # 0x7a0df
callq 0x8630
movq %rax, -0x3d0(%rbp)
jmp 0x9bbb
movq -0x210(%rbp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq -0x3d0(%rbp), %rdi
movq %rax, %rsi
callq 0x8630
movq %rax, -0x3d8(%rbp)
jmp 0x9be3
movq -0x3d8(%rbp), %rdi
movq 0xa5367(%rip), %rsi     # 0xaef58
callq 0x8680
jmp 0x9bf8
movl $0x1, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
leaq -0x230(%rbp), %rdi
callq 0xa7c0
callq 0x8ae0
jmp 0x9c5e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x9c60
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x9c50
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x240(%rbp), %rdi
callq 0xa770
leaq -0x230(%rbp), %rdi
callq 0xa7c0
jmp 0x9c60
jmp 0x9cc7
callq 0x8ae0
jmp 0x9c67
jmp 0x9cdc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x9cad
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x9c9d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x280(%rbp), %rdi
callq 0xa770
leaq -0x270(%rbp), %rdi
callq 0xa7c0
jmp 0x9cad
jmp 0x9cc7
callq 0x8ae0
jmp 0x9cb4
jmp 0x9cdc
movl $0x0, -0x4(%rbp)
movl $0x1, -0x8c(%rbp)
leaq -0x28(%rbp), %rdi
callq 0xa900
movl -0x4(%rbp), %eax
addq $0x3e0, %rsp            # imm = 0x3E0
popq %rbp
retq
leaq -0x28(%rbp), %rdi
callq 0xa900
movq -0x60(%rbp), %rdi
callq 0x8bc0
movq %rax, %rdi
callq 0xa7e0
nopw %cs:(%rax,%rax)