int main()

in src/agent/src/main.c [902:1111]


int main(int argc, char** argv)
{
    ADUC_LaunchArguments launchArgs;

    InitializeModeledComponents();

    int ret = ParseLaunchArguments(argc, argv, &launchArgs);
    if (ret < 0)
    {
        return ret;
    }

    if (launchArgs.showVersion)
    {
        puts(ADUC_VERSION);
        return 0;
    }

    // Need to set ret and goto done after this to ensure proper shutdown and deinitialization.
    ADUC_Logging_Init(launchArgs.logLevel, "du-agent");

    ADUCPAL_setenv(ADUC_CONFIG_FOLDER_ENV, launchArgs.configFolder, 1);

    const ADUC_ConfigInfo* config = ADUC_ConfigInfo_GetInstance();
    if (config == NULL)
    {
        Log_Error("Cannot initialize config info.");
        return -1;
    }

    // default to failure
    ret = 1;

    if (launchArgs.healthCheckOnly)
    {
        if (HealthCheck(&launchArgs))
        {
            ret = 0;
        }

        goto done;
    }

    if (launchArgs.extensionFilePath != NULL)
    {
        switch (launchArgs.extensionRegistrationType)
        {
        case ExtensionRegistrationType_None:
            Log_Error("Missing --extension-type argument.");
            goto done;

        case ExtensionRegistrationType_UpdateContentHandler:
            if (launchArgs.extensionId == NULL)
            {
                Log_Error("Missing --extension-id argument.");
                goto done;
            }

            if (RegisterUpdateContentHandler(launchArgs.extensionId, launchArgs.extensionFilePath))
            {
                ret = 0;
            }

            goto done;

        case ExtensionRegistrationType_ComponentEnumerator:
            if (RegisterComponentEnumeratorExtension(launchArgs.extensionFilePath))
            {
                ret = 0;
            }

            goto done;

        case ExtensionRegistrationType_ContentDownloadHandler:
            if (RegisterContentDownloaderExtension(launchArgs.extensionFilePath))
            {
                ret = 0;
            }

            goto done;

        case ExtensionRegistrationType_DownloadHandler:
            if (launchArgs.extensionId == NULL)
            {
                Log_Error("Missing --extension-id argument.");
                goto done;
            }

            if (RegisterDownloadHandler(launchArgs.extensionId, launchArgs.extensionFilePath))
            {
                ret = 0;
            }

            goto done;

        default:
            Log_Error("Unknown ExtensionRegistrationType: %d", launchArgs.extensionRegistrationType);
            goto done;
        }
    }

#ifdef ADUC_COMMAND_HELPER_H
    // This instance of an agent is launched for sending command to the main agent process.
    if (launchArgs.ipcCommand != NULL)
    {
        if (SendCommand(launchArgs.ipcCommand))
        {
            ret = 0;
        }

        goto done;
    }
#endif // #ifdef ADUC_COMMAND_HELPER_H

    // Switch to specified agent.runas user.
    // Note: it's important that we do this only when we're not performing any
    // high-privileged tasks, such as, registering agent's extension(s).
    if (!RunAsDesiredUser())
    {
        goto done;
    }

    Log_Info("Agent (%s; %s) starting.", ADUC_PLATFORM_LAYER, ADUC_VERSION);
#ifdef ADUC_GIT_INFO
    Log_Info("Git Info: %s", ADUC_GIT_INFO);
#endif
    Log_Info(
        "Supported Update Manifest version: min: %d, max: %d",
        SUPPORTED_UPDATE_MANIFEST_VERSION_MIN,
        SUPPORTED_UPDATE_MANIFEST_VERSION_MAX);

    bool healthy = HealthCheck(&launchArgs);
    if (launchArgs.healthCheckOnly || !healthy)
    {
        if (healthy)
        {
            Log_Info("Agent is healthy.");
            ret = 0;
        }
        else
        {
            Log_Error("Agent health check failed.");
        }

        goto done;
    }

    // Ensure that the ADU data folder exists.
    // Normally, ADUC_DATA_FOLDER is created by install script.
    // However, if we want to run the Agent without installing the package, we need to manually
    // create the folder. (e.g. when running UTs in build pipelines, side-loading for testing, etc.)
    int dir_result = ADUC_SystemUtils_MkDirRecursiveDefault(ADUC_DATA_FOLDER);
    if (dir_result != 0)
    {
        Log_Error("Cannot create data folder.");
        goto done;
    }

    //
    // Catch ctrl-C and shutdown signals so we do a best effort of cleanup.
    //
    signal(SIGINT, OnShutdownSignal);
    signal(SIGTERM, OnShutdownSignal);

    if (!StartupAgent(&launchArgs))
    {
        goto done;
    }

    //
    // Main Loop
    //

    Log_Info("Agent running.");
    while (ADUC_ShutdownService_ShouldKeepRunning())
    {
        // If any components have requested a DoWork callback, regularly call it.
        for (unsigned index = 0; index < ARRAY_SIZE(componentList); ++index)
        {
            PnPComponentEntry* entry = componentList + index;

            if (entry->DoWork != NULL)
            {
                entry->DoWork(entry->Context);
            }
        }

        IoTHub_CommunicationManager_DoWork(&g_iotHubClientHandle);
        ADUC_D2C_Messaging_DoWork();

        // NOTE: When using low level samples (iothub_ll_*), the IoTHubDeviceClient_LL_DoWork
        // function must be called regularly (eg. every 100 milliseconds) for the IoT device client to work properly.
        // See: https://github.com/Azure/azure-iot-sdk-c/tree/master/iothub_client/samples
        // NOTE: For this example the above has been wrapped to support module and device client methods using
        // the client_handle_helper.h function ClientHandle_DoWork()

        ThreadAPI_Sleep(100);
    };

    ret = 0; // Success.

done:
    Log_Info("Agent exited with code %d", ret);

    ShutdownAgent();

    ADUC_ConfigInfo_ReleaseInstance(config);

    return ret;
}