int main()

in daemon/src/daemon.cpp [198:414]


int main( int argc, const char* argv[] )
{
    std::pair<int, void*> pthread_status;
    std::string cred_file;
    std::string cred_file_lease_id;
    void* grpc_pthread;
    void* krb_refresh_pthread;

    int status = parse_options( argc, argv, cf_daemon );
    if ( status != EXIT_SUCCESS )
    {
        exit( EXIT_FAILURE );
    }

    cf_daemon.krb_files_dir = CF_KRB_DIR;
    cf_daemon.logging_dir = CF_LOGGING_DIR;
    cf_daemon.unix_socket_dir = CF_UNIX_DOMAIN_SOCKET_DIR;

    std::string log_msg = "Credentials-fetcher daemon has started running";
    std::cerr << log_msg << std::endl;
    cf_daemon.cf_logger.logger( LOG_ERR, log_msg.c_str() );
    std::cerr << "on request failures check logs located at " + cf_daemon.logging_dir << std::endl;
    ;

    if ( getenv( ENV_CF_CRED_SPEC_FILE ) != NULL )
    {
        int parseResult =
            parse_cred_file_path( getenv( ENV_CF_CRED_SPEC_FILE ), cred_file, cred_file_lease_id );

        if ( parseResult == EXIT_FAILURE )
        {
            std::cerr << "Failed parsing environment variable " << getenv( ENV_CF_CRED_SPEC_FILE )
                      << std::endl;
            std::string log_message = "Failed parsing environment variable " +
                                      std::string( getenv( ENV_CF_CRED_SPEC_FILE ) );
            cf_daemon.cf_logger.logger( LOG_ERR, log_message.c_str() );

            exit( EXIT_FAILURE );
        }

        if ( !std::filesystem::exists( cred_file ) )
        {
            cred_file_lease_id.clear();
            std::cerr << "Ignoring CF_CREF_FILE, file " << cred_file << " not found" << std::endl;
        }
        else
        {
            cf_daemon.cred_file = cred_file;
        }
    }

    /**
     * Domain name and gmsa account are usually set in APIs.
     * The options below can be used as a test.
     */
    cf_daemon.domain_name = CF_TEST_DOMAIN_NAME;
    cf_daemon.gmsa_account_name = CF_TEST_GMSA_ACCOUNT;
    std::string log_message;

    std::cerr << "krb_files_dir = " << cf_daemon.krb_files_dir << std::endl;
    log_message = "krb_files_dir = " + cf_daemon.krb_files_dir;
    cf_daemon.cf_logger.logger( LOG_ERR, log_message.c_str() );

    std::cerr << "cred_file = " << cf_daemon.cred_file << " (lease id: " << cred_file_lease_id
              << ")" << std::endl;
    log_message = "cred_file = " + cf_daemon.cred_file + " (lease id: " + cred_file_lease_id + ")";
    cf_daemon.cf_logger.logger( LOG_ERR, log_message.c_str() );

    std::cerr << "logging_dir = " << cf_daemon.logging_dir << std::endl;
    log_message = "logging_dir = " + cf_daemon.logging_dir;
    cf_daemon.cf_logger.logger( LOG_ERR, log_message.c_str() );

    std::cerr << "unix_socket_dir = " << cf_daemon.unix_socket_dir << std::endl;
    log_message = "unix_socket_dir = " + cf_daemon.unix_socket_dir;
    cf_daemon.cf_logger.logger( LOG_ERR, log_message.c_str() );

    if ( cf_daemon.run_diagnostic )
    {
        exit( read_meta_data_json_test() || read_meta_data_invalid_json_test() ||
              renewal_failure_krb_dir_not_found_test() || write_meta_data_json_test() );
    }

    struct sigaction sa;
    cf_daemon.got_systemd_shutdown_signal = 0;
    memset( &sa, 0, sizeof( struct sigaction ) );
    sa.sa_handler = &systemd_shutdown_signal_catcher;
    if ( ( sigaction( SIGTERM, &sa, NULL ) == -1 ) || ( sigaction( SIGINT, &sa, NULL ) == -1 ) ||
         ( sigaction( SIGHUP, &sa, NULL ) == -1 ) )
    {
        perror( "sigaction" );
        return EXIT_FAILURE;
    }

    /* We need to run three parallel processes */
    // 1. Systemd - daemon
    // 2. grpc server
    // 3. timer to run every 45 min
    if ( !cf_daemon.cred_file.empty() )
    {
        log_message = "Credential file exists " + cf_daemon.cred_file;
        cf_daemon.cf_logger.logger( LOG_INFO, log_message.c_str() );

        int specFileReturn = ProcessCredSpecFile( cf_daemon.krb_files_dir, cf_daemon.cred_file,
                                                  cf_daemon.cf_logger, cred_file_lease_id );
        if ( specFileReturn == EXIT_FAILURE )
        {
            std::cerr << "ProcessCredSpecFile() non 0 " << std::endl;
            exit( EXIT_FAILURE );
        }
    }

    /* Create one pthread for gRPC processing */
    pthread_status = create_pthread( grpc_thread_start, grpc_thread_name, -1 );
    if ( pthread_status.first < 0 )
    {
        log_message =
            "Error " + std::to_string( pthread_status.first ) + ": Cannot create pthreads";
        cf_daemon.cf_logger.logger( LOG_ERR, log_message.c_str() );
        exit( EXIT_FAILURE );
    }
    grpc_pthread = pthread_status.second;
    if ( grpc_pthread == nullptr )
    {
        log_message = "Warning: grpc_pthread is null";
    }
    else
    {
        std::ostringstream address_stream;
        address_stream << grpc_pthread;
        log_message = "grpc pthread is at " + address_stream.str();
    }
    cf_daemon.cf_logger.logger( LOG_INFO, log_message.c_str() );

    /* Create pthread for refreshing krb tickets */
    pthread_status =
        create_pthread( refresh_krb_tickets_thread_start, "krb_ticket_refresh_thread", -1 );
    if ( pthread_status.first < 0 )
    {
        log_message =
            "Error " + std::to_string( pthread_status.first ) + ": Cannot create pthreads";
        cf_daemon.cf_logger.logger( LOG_ERR, log_message.c_str() );
        exit( EXIT_FAILURE );
    }
    krb_refresh_pthread = pthread_status.second;
    if ( krb_refresh_pthread == nullptr )
    {
        log_message = "Warning: krb_refresh_pthread is null";
    }
    else
    {
        std::ostringstream address_stream;
        address_stream << krb_refresh_pthread;
        log_message = "krb refresh pthread is at " + address_stream.str();
    }
    cf_daemon.cf_logger.logger( LOG_INFO, log_message.c_str() );

    cf_daemon.cf_logger.set_log_level( LOG_NOTICE );

    char* daemon_started_by_systemd = getenv( "CREDENTIALS_FETCHERD_STARTED_BY_SYSTEMD" );

    if ( daemon_started_by_systemd != NULL )
    {
        /*
         * This is a 'new-style daemon', fork() and other book-keeping is not required.
         * https://www.freedesktop.org/software/systemd/man/daemon.html#New-Style%20Daemons
         */

        /*
         * If the daemon does not invoke sd_watchdog_enabled() in the interval, systemd will restart
         * the daemon
         */
        bool watchdog = sd_watchdog_enabled( 0, &cf_daemon.watchdog_interval_usecs ) > 0;
        if ( watchdog )
        {
            fprintf( stderr, SD_NOTICE "watchdog enabled with interval value = %ld",
                     cf_daemon.watchdog_interval_usecs );
        }
        else
        {
            fprintf( stderr, SD_ERR "ERROR Cannot setup watchdog, interval value = %ld",
                     cf_daemon.watchdog_interval_usecs );
            /* TBD: Use exit code scheme as defined in the LSB recommendations for SysV init scripts
             */
            exit( EXIT_FAILURE );
        }
    }

    /* Tells the service manager that service startup is finished */
    sd_notify( 0, "READY=1" );
    pthread_status =
        create_pthread( watchdog_thread, "watchdog_thread", -1 );
    if ( pthread_status.first < 0 )
    {
        log_message =
            "Error " + std::to_string( pthread_status.first ) + ": Cannot create pthreads";
        cf_daemon.cf_logger.logger( LOG_ERR, log_message.c_str() );
        exit( EXIT_FAILURE );
    }

    while ( !cf_daemon.got_systemd_shutdown_signal )
    {
#ifdef EXIT_USING_FILE
        struct stat st;
        if ( lstat( "/tmp/credentials_fetcher_exit.txt", &st ) != -1 )
        {
            if ( S_ISREG( st.st_mode ) )
            {
                cf_daemon.got_systemd_shutdown_signal = 1;
            }
        }
#endif
        sleep(1); // Main thread waits for shutdown

    }

    return EXIT_SUCCESS;
}