### Install libamxrt Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Install the compiled library using the make target. ```bash cd ~/amx_project/libraries/libamxrt sudo -E make install ``` -------------------------------- ### Install build dependencies Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Install required system libraries for building libamxrt. ```bash sudo apt update sudo apt install libamxc libamxj libamxp libamxd libamxb libamxs libamxo libevent libcap-ng-dev ``` -------------------------------- ### Package libamxrt Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Create installation packages and install them using dpkg. ```bash cd ~/amx_project/libraries/libamxrt make package ``` ```bash sudo dpkg -i ~/amx_project/libraries/libamxrt/libamxrt-.deb ``` -------------------------------- ### Launch Development Container Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Start the container with volume mapping and user ID synchronization for development. ```bash docker run -ti -d --name oss-dbg --restart always --cap-add=SYS_PTRACE --sysctl net.ipv6.conf.all.disable_ipv6=1 -e "USER=$USER" -e "UID=$(id -u)" -e "GID=$(id -g)" -v ~/amx_project/:/home/$USER/amx_project/ registry.gitlab.com/soft.at.home/docker/oss-dbg:latest ``` -------------------------------- ### Serve coverage reports Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Start a local HTTP server to view coverage reports in a browser. ```bash cd ~/amx_project/ python3 -m http.server 8080 & ``` ```bash USER@:~/amx_project/libraries/libamxrt$ ip a ``` -------------------------------- ### amxrt_init Source: https://context7.com/prpl-foundation/components/llms.txt Initializes the runtime without starting the event loop, allowing for custom setup between initialization and execution. ```APIDOC ## amxrt_init ### Description Initializes the runtime without starting the event loop, allowing for additional setup between initialization and execution. It parses arguments, loads ODL files, loads backends, connects to sockets, and creates the event loop components. ``` -------------------------------- ### Start Event Loop with amxrt_run Source: https://context7.com/prpl-foundation/components/llms.txt Starts the blocking event loop to handle file descriptors, timers, and signals. ```c #include int main(int argc, char* argv[]) { int retval = 0; amxrt_new(); retval = amxrt_init(argc, argv, NULL); if (retval != 0) goto cleanup; retval = amxrt_register_or_wait(); if (retval != 0) goto cleanup; printf("Starting event loop...\n"); // Blocks until amxrt_el_stop() is called // Handles: file descriptor events, timers, system signals retval = amxrt_run(); printf("Event loop stopped with code: %d\n", retval); cleanup: amxrt_stop(); amxrt_delete(); return retval; } ``` -------------------------------- ### Advanced Control with Ambiorix Runtime Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md This example demonstrates more control over the Ambiorix runtime, suitable for creating data model provider applications. It allows for custom configuration, ODL file loading, and signal handling. ```c #include int main(int argc, char* argv[]) { int retval = 0; int index = 0; amxc_var_t* syssigs = NULL; amxc_var_t* config = NULL; amxd_dm_t* dm = NULL; amxo_parser_t* parser = NULL; amxrt_new(); config = amxrt_get_config(); dm = amxrt_get_dm(); parser = amxrt_get_parser(); // read env vars (AMXB_BACKENDS, AMXRT_PREFIX_PATH, AMXRT_PLUGIN_DIR, AMXRT_CFG_DIR) // set default directories configuration options (include-dirs, import-dirs, mib-dirs) // set name configuration option (name) // parse command line options (index is set to command line options where parsing has stopped) // the index will be set to the first non option command line argument retval = amxrt_config_init(argc, argv, &index, NULL); when_failed(retval, leave); // parse odl string provided with command line argument -O // parse odl files passed with command line after the options // the index should point to the first odl file in the command line arguments // or set to argc when no odl files are passed at the command line retval = amxrt_load_odl_files(argc, argv, index); when_failed(retval, leave); // search for backends and known unix domain sockets, if auto-detect is set amxrt_config_scan_backend_dirs(); // add the auto save - needs configuration in config section amxo_parser_add_entry_point(parser, amxrt_dm_save_load_main); // load all backends // connect to all sockets (if any) // create listen sockets (if any) // apply process settings (daemonize, set nice level, create pid file, open syslog) retval = amxrt_connect(); when_failed(retval, leave); // enable linux signals syssigs = GET_ARG(config, "system-signals"); if(syssigs != NULL) { amxrt_enable_syssigs(syssigs); } // create event loop retval = amxrt_el_create(); when_failed(retval, leave); // register data model or wait for required objects // if all required objects are available the data model will be registered // (after starting the event loop) // call entry points when data model is registered // start object & parameter synchronization if any was defined in one of the loaded odl files // send app:start ambiorix signal when data model is registered retval = amxrt_register_or_wait(); when_failed(retval, leave); // the app:start signal will be triggered when registration is done // this can be immediatly or when all required objects are available. // start the event loop amxrt_el_start(); // will block until amxrt_el_stop is called // app:stop ambiorix signal is send when the above function exits leave: // stop amx runtime and cleanup amxrt_stop(); amxrt_delete(); return retval; } ``` -------------------------------- ### Initialize Ambiorix Runtime without Event Loop using amxrt_init Source: https://context7.com/prpl-foundation/components/llms.txt Initializes the runtime without starting the event loop, allowing for custom setup between initialization and execution. It parses arguments, loads ODL files, backends, connects sockets, and creates event loop components. Call amxrt_new() before this. ```c #include int main(int argc, char* argv[]) { int retval = 0; amxrt_new(); // Initialize without starting event loop retval = amxrt_init(argc, argv, NULL); if (retval != 0) { fprintf(stderr, "Initialization failed: %d\n", retval); goto cleanup; } // Perform custom setup here amxc_var_t* config = amxrt_get_config(); amxd_dm_t* dm = amxrt_get_dm(); // Add custom data model objects amxd_object_t* root = amxd_dm_get_root(dm); // ... customize data model ... // Register data model (or wait for required objects) retval = amxrt_register_or_wait(); if (retval != 0) { fprintf(stderr, "Registration failed: %d\n", retval); goto cleanup; } // Start the event loop (blocks until stopped) retval = amxrt_run(); cleanup: amxrt_stop(); amxrt_delete(); return retval; } ``` -------------------------------- ### Configure ODL Persistent Storage Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Example configuration for enabling persistent data storage in the main ODL file. Requires setting the storage-type to odl and defining the save behavior and directory. ```odl %config { odl = { dm-save = true, dm-save-on-changed = true, dm-save-init-delay = 10000, dm-save-delay = 1000, directory = "${storage-path}/odl" }; } ``` -------------------------------- ### Start the Event Loop with amxrt_el_start Source: https://context7.com/prpl-foundation/components/llms.txt Starts the event loop and blocks execution until amxrt_el_stop is called. It handles file descriptors, timers, and signals. ```c #include // Signal handler to stop event loop void handle_custom_signal(const char* const sig_name, const amxc_var_t* const data, void* const priv) { printf("Received signal: %s, stopping event loop\n", sig_name); amxrt_el_stop(); } int main(int argc, char* argv[]) { amxrt_new(); int retval = amxrt_init(argc, argv, NULL); if (retval != 0) goto cleanup; // Connect to custom signal amxp_slot_connect(NULL, "sig:usr1", NULL, handle_custom_signal, NULL); retval = amxrt_register_or_wait(); if (retval != 0) goto cleanup; printf("Event loop starting...\n"); // Blocks until amxrt_el_stop() is called // Default signal handlers: // - SIGINT -> stops event loop // - SIGTERM -> stops event loop // - SIGALRM -> used for ambiorix timers retval = amxrt_el_start(); printf("Event loop stopped\n"); cleanup: amxrt_stop(); amxrt_delete(); return retval; } ``` -------------------------------- ### amxrt_el_start - Start Event Loop Source: https://context7.com/prpl-foundation/components/llms.txt Starts the event loop, which dispatches events for file descriptors, timers, and signals. This function blocks until amxrt_el_stop() is called. ```APIDOC ## amxrt_el_start ### Description Starts the event loop. Blocks until amxrt_el_stop() is called. The event loop dispatches events for file descriptors, timers, and signals. ### Method (Not applicable, C function) ### Endpoint (Not applicable, C function) ### Parameters (None) ### Request Example (Not applicable, C function) ### Response (Not applicable, C function) ### Example Usage (C) ```c #include // Signal handler to stop event loop void handle_custom_signal(const char* const sig_name, const amxc_var_t* const data, void* const priv) { printf("Received signal: %s, stopping event loop\n", sig_name); amxrt_el_stop(); } int main(int argc, char* argv[]) { amxrt_new(); int retval = amxrt_init(argc, argv, NULL); if (retval != 0) goto cleanup; // Connect to custom signal amxp_slot_connect(NULL, "sig:usr1", NULL, handle_custom_signal, NULL); retval = amxrt_register_or_wait(); if (retval != 0) goto cleanup; printf("Event loop starting...\n"); // Blocks until amxrt_el_stop() is called // Default signal handlers: // - SIGINT -> stops event loop // - SIGTERM -> stops event loop // - SIGALRM -> used for ambiorix timers retval = amxrt_el_start(); printf("Event loop stopped\n"); cleanup: amxrt_stop(); amxrt_delete(); return retval; } ``` ``` -------------------------------- ### Run Complete Ambiorix Application with amxrt Source: https://context7.com/prpl-foundation/components/llms.txt The main entry point that creates a complete Ambiorix application with a single call. It handles argument parsing, ODL file loading, bus connection, data model registration, and starts the event loop, blocking until stopped. Ensure amxrt_new() is called before this. ```c #include int main(int argc, char* argv[]) { int retval = 0; // Initialize runtime amxrt_new(); // Run the complete application lifecycle // This will: // 1. Parse command line arguments // 2. Load ODL files (from args or default /etc/amx//.odl) // 3. Load and connect to bus backends (ubus, pcb) // 4. Register data model // 5. Start event loop (blocks until stopped) // 6. Clean up on exit retval = amxrt(argc, argv, NULL); // Cleanup amxrt_delete(); return retval; } // Example command line usage: // ./myapp -u ubus:/var/run/ubus/ubus.sock /etc/amx/myapp/myapp.odl // ./myapp -D -l /etc/amx/myapp/myapp.odl # Run as daemon with syslog ``` -------------------------------- ### amxrt_run API Source: https://context7.com/prpl-foundation/components/llms.txt Starts the event loop, which blocks until explicitly stopped. It handles all file descriptor events, timers, and signals. ```APIDOC ## amxrt_run ### Description Starts the event loop. This function blocks until the event loop is stopped via `amxrt_el_stop()`. The event loop handles all file descriptor events, timers, and signals. ### Method C Function Call ### Endpoint N/A (Library Function) ### Parameters None. ### Request Example ```c #include int main(int argc, char* argv[]) { int retval = 0; amxrt_new(); retval = amxrt_init(argc, argv, NULL); if (retval != 0) goto cleanup; retval = amxrt_register_or_wait(); if (retval != 0) goto cleanup; printf("Starting event loop...\n"); // Blocks until amxrt_el_stop() is called retval = amxrt_run(); printf("Event loop stopped with code: %d\n", retval); cleanup: amxrt_stop(); amxrt_delete(); return retval; } ``` ### Response #### Success Response (0) Returns 0 when the event loop is stopped cleanly. #### Response Example ``` Starting event loop... Event loop stopped with code: 0 ``` ``` -------------------------------- ### Initialize Runtime Configuration Source: https://context7.com/prpl-foundation/components/llms.txt Initializes the runtime environment by parsing command-line arguments and reading standard environment variables. ```c #include int main(int argc, char* argv[]) { int retval = 0; int index = 0; amxrt_new(); // Initialize configuration // - Reads AMXB_BACKENDS, AMXRT_PREFIX_PATH, AMXRT_PLUGIN_DIR, AMXRT_CFG_DIR // - Sets default include/import/mib directories // - Sets application name from argv[0] // - Parses command line options // - Returns index of first non-option argument retval = amxrt_config_init(argc, argv, &index, my_handler); if (retval != 0) { fprintf(stderr, "Configuration failed\n"); amxrt_delete(); return 1; } printf("First non-option argument at index: %d\n", index); printf("Application name: %s\n", GET_CHAR(amxrt_get_config(), "name")); // Continue with ODL loading... amxrt_delete(); return 0; } ``` -------------------------------- ### Initialize and Run Ambiorix Runtime Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md This snippet shows the basic steps to initialize, run, and clean up the Ambiorix runtime. It's suitable for straightforward applications. ```c #include int main(int argc, char* argv[]) { int retval = 0; amxrt_new(); // read env vars (AMXB_BACKENDS, AMXRT_PREFIX_PATH, AMXRT_PLUGIN_DIR, AMXRT_CFG_DIR) // set default directories configuration options (include-dirs, import-dirs, mib-dirs) // set name configuration option (name) // parse command line options (index is set to command line options where parsing has stopped) // search for backends and known unix domain sockets, if auto-detect is set // parse odl string provided with command line argument -O // parse odl files passed with command line after the options // add the auto save - needs configuration in config section // load all backends // connect to all sockets (if any) // create listen sockets (if any) // apply process settings (daemonize, set nice level, create pid file, open syslog) // enable linux signals // create event loop retval = amxrt_init(argc, argv, NULL); when_failed(retval, leave); // register data model or wait for required objects // if all required objects are available the data model will be registered // (after starting the event loop) // call entry points when data model is registered // start object & parameter synchronization if any was defined in one of the loaded odl files // send app:start ambiorix signal when data model is registered retval = amxrt_register_or_wait(); when_failed(retval, leave); // start the event loop retval = amxrt_run(); leave: amxrt_stop(); amxrt_delete(); return retval; } ``` -------------------------------- ### Build libamxrt Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Set the version prefix and compile the library. ```bash export VERSION_PREFIX="master_" ``` ```bash cd ~/amx_project/libraries/libamxrt make ``` -------------------------------- ### Create Shared Project Directory Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Prepare a local directory to be mounted into the Docker container. ```bash mkdir -p ~/amx_project/libraries/ ``` -------------------------------- ### Connect to Bus Systems with amxrt_connect Source: https://context7.com/prpl-foundation/components/llms.txt Initializes backends, detects sockets, and establishes connections to bus systems. This is typically called after configuration and ODL loading. ```c #include int main(int argc, char* argv[]) { int retval = 0; int index = 0; amxrt_new(); // Parse config and load ODL retval = amxrt_config_init(argc, argv, &index, NULL); if (retval != 0) goto cleanup; retval = amxrt_load_odl_files(argc, argv, index); if (retval != 0) goto cleanup; // Scan for available backends amxrt_config_scan_backend_dirs(); // Connect to bus systems // - Loads backends from config // - Detects sockets if auto-detect enabled // - Daemonizes if configured // - Connects to all URIs // - Creates listen sockets // - Sets process priority // - Creates PID file retval = amxrt_connect(); if (retval != 0) { fprintf(stderr, "Failed to connect: %d\n", retval); goto cleanup; } printf("Connected to bus systems successfully\n"); // Continue with event loop setup... cleanup: amxrt_delete(); return retval; } ``` -------------------------------- ### amxrt_connect - Connect to Bus Systems Source: https://context7.com/prpl-foundation/components/llms.txt Loads backends, detects sockets, connects to all URIs, creates listen sockets, and applies process settings. This is a crucial step for establishing communication with bus systems. ```APIDOC ## amxrt_connect ### Description Loads backends, detects sockets (if auto-detect enabled), connects to all URIs, creates listen sockets, and applies process settings. ### Method (Not applicable, C function) ### Endpoint (Not applicable, C function) ### Parameters (None) ### Request Example (Not applicable, C function) ### Response (Not applicable, C function) ### Example Usage (C) ```c #include int main(int argc, char* argv[]) { int retval = 0; int index = 0; amxrt_new(); // Parse config and load ODL retval = amxrt_config_init(argc, argv, &index, NULL); if (retval != 0) goto cleanup; retval = amxrt_load_odl_files(argc, argv, index); if (retval != 0) goto cleanup; // Scan for available backends amxrt_config_scan_backend_dirs(); // Connect to bus systems // - Loads backends from config // - Detects sockets if auto-detect enabled // - Daemonizes if configured // - Connects to all URIs // - Creates listen sockets // - Sets process priority // - Creates PID file retval = amxrt_connect(); if (retval != 0) { fprintf(stderr, "Failed to connect: %d\n", retval); goto cleanup; } printf("Connected to bus systems successfully\n"); // Continue with event loop setup... cleanup: amxrt_delete(); return retval; } ``` ``` -------------------------------- ### Pull Docker Container Image Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Download the pre-configured development environment image. ```bash docker pull registry.gitlab.com/soft.at.home/docker/oss-dbg:latest ``` -------------------------------- ### Initialize amxrt in C Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Basic boilerplate for initializing and running the Ambiorix runtime within a C application. ```c #include int main(int argc, char* argv[]) { int retval = 0; amxrt_new(); retval = amxrt(argc, argv, NULL); amxrt_delete(); return retval; } ``` -------------------------------- ### amxrt_new Source: https://context7.com/prpl-foundation/components/llms.txt Initializes the Ambiorix runtime environment, including the ODL parser, data model storage, and configuration container. ```APIDOC ## amxrt_new ### Description Initializes the Ambiorix runtime environment. This function must be called before any other amxrt function. It creates the ODL parser, data model storage, configuration container, and sets up the default command-line options. ``` -------------------------------- ### Run tests Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Execute standard tests or tests with coverage reporting. ```bash cd ~/amx_project/libraries/libamxrt/tests make ``` ```bash cd ~/amx_project/libraries/libamxrt/tests make run coverage ``` -------------------------------- ### Configure User, Group, and Capabilities in libamxrt Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md This configuration switches the process to the 'webui' user and 'webui' group, dropping all capabilities except CAP_CHOWN. Ensure the user and group exist on the system. ```config %config { privileges = { user = "webui", group = "webui", capabilities = [ "CAP_CHOWN" ] } } ``` -------------------------------- ### Display amxrt command-line help Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md View available command-line options for the amxrt utility. ```bash $ amxrt -h amxrt [OPTIONS] Options: -h --help Print usage help and exit -H --HELP Print extended help and exit -B --backend Loads the shared object as bus backend -u --uri Adds an uri to the list of uris -A --no-auto-detect Do not auto detect unix domain sockets and back-ends -C --no-connect Do not auto connect the provided or detected uris -I --include-dir Adds include directory for odl parser, multiple allowed -L --import-dir Adds import directory for odl parser, multiple allowed -o --option Adds a configuration option -F --forced-option Adds a configuration option, which can not be overwritten by odl files -O --ODL An ODL in string format, only one ODL string allowed -D --daemon Daemonize the process -p --priority Sets the process nice level -N --no-pid-file Disables the creation of a pid-file in /var/run -E --eventing Enables eventing during loading of ODL files -d --dump-config Dumps configuration options at start-up -l --log Write to syslog instead of stdout and stderr -R --requires Checks if datamodel objects are available or waits until they are available -V --version Print version ``` -------------------------------- ### Initialize Ambiorix Runtime with amxrt_new Source: https://context7.com/prpl-foundation/components/llms.txt Initializes the Ambiorix runtime environment. This function must be called before any other amxrt function. It sets up core components like the ODL parser, data model storage, and configuration. ```c #include int main(int argc, char* argv[]) { // Initialize the runtime - must be called first amxrt_new(); // Runtime is now ready for configuration and use // Get references to core components amxc_var_t* config = amxrt_get_config(); amxo_parser_t* parser = amxrt_get_parser(); amxd_dm_t* dm = amxrt_get_dm(); // ... perform operations ... // Cleanup when done amxrt_delete(); return 0; } ``` -------------------------------- ### Load ODL Files with Amxrt Source: https://context7.com/prpl-foundation/components/llms.txt Loads ODL files from command line arguments or default locations. It prioritizes global configuration, then command-line ODL strings, followed by ODL files, and finally extensions. ```c #include int main(int argc, char* argv[]) { int retval = 0; int index = 0; amxrt_new(); // Parse command line (returns index of first non-option) retval = amxrt_config_init(argc, argv, &index, NULL); if (retval != 0) goto cleanup; // Load ODL files // Order: // 1. ${prefix}${cfg-dir}/global.d/*.odl (optional) // 2. ODL string from -O option (optional) // 3. ODL files from command line (or default /etc/amx//.odl) // 4. ${prefix}${cfg-dir}/${name}/extensions/*.odl (optional) retval = amxrt_load_odl_files(argc, argv, index); if (retval != 0) { fprintf(stderr, "Failed to load ODL files\n"); goto cleanup; } // Data model is now populated amxd_dm_t* dm = amxrt_get_dm(); amxd_object_t* root = amxd_dm_get_root(dm); printf("Data model loaded successfully\n"); cleanup: amxrt_delete(); return retval; } // Example usage: // ./myapp myservice.odl # Load specific file // ./myapp # Load /etc/amx/myapp/myapp.odl // ./myapp -O "%define { object Test {} }" # Load ODL string ``` -------------------------------- ### Dependency Graph Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Visual representation of the library dependencies for libamxrt. ```mermaid graph TD; libamxrt-->libamxo libamxrt-->libamxj libamxrt-->libevent libamxrt-->libcap-ng libamxp-->libamxc libamxd-->libamxp libamxo-->libamxs libamxs-->libamxb libamxb-->libamxd libamxj-->libamxc ``` -------------------------------- ### Dump libamxrt default configuration Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Use the -d flag with the amxrt command to print all default configuration options to stdout. ```bash $ amxrt -d Configuration: { auto-connect = true, auto-detect = true, auto-resolver-order = [ "ftab", "import", "*" ], backend-dir = "/usr/bin/mods/amxb", backend-order = [ "ubus", "pcb", "dummy" ], backends = [ "/usr/bin/mods/amxb/05-mod-amxb-ubus.so", "/usr/bin/mods/amxb/10-mod-amxb-pcb.so", "/usr/bin/mods/amxb/mod-amxb-dummy.so", "/usr/bin/mods/amxb/mod-amxb-ubus.so" ], cfg-dir = "/etc/amx", connect-retry-max-count = 10, connect-retry-timeout-max = 10000, connect-retry-timeout-min = 5000, daemon = false, data-uris = [ ], dm-eventing-enabled = true, dummy = { register-name = "amxrt" }, dump-caps = false, dump-config = true, extensions-dir = "${prefix}${cfg-dir}/${name}/extensions/", global-dir = "${prefix}${cfg-dir}/global.d/", import-dbg = false, import-dirs = [ ".", "${prefix}${plugin-dir}/${name}", "${prefix}${plugin-dir}/${name}/modules", "${prefix}${plugin-dir}/modules", "${prefix}/usr/local/lib/amx/${name}", "${prefix}/usr/local/lib/amx/modules" ], include-dirs = [ ".", "${prefix}${cfg-dir}/${name}", "${prefix}${cfg-dir}/${name}/modules", "${prefix}${cfg-dir}/modules" ], listen = [ ], log = false, mib-dirs = [ "${prefix}${cfg-dir}/${name}/mibs" ], name = "amxrt", pcb = { acl-dir = "/cfg/etc/acl/", ``` -------------------------------- ### Access ODL Parser and Entry Points Source: https://context7.com/prpl-foundation/components/llms.txt Use amxrt_get_parser to manually parse ODL files or strings and register custom entry points during application startup. ```c #include void custom_odl_loading(void) { amxo_parser_t* parser = amxrt_get_parser(); amxd_dm_t* dm = amxrt_get_dm(); amxd_object_t* root = amxd_dm_get_root(dm); // Parse an additional ODL file int retval = amxo_parser_parse_file(parser, "/tmp/custom_definitions.odl", root); if (retval != 0) { fprintf(stderr, "Failed to parse ODL file\n"); return; } // Parse an ODL string const char* odl_string = "%define { object MyObject { string MyParam = \"value\"; } }"; retval = amxo_parser_parse_string(parser, odl_string, root); // Add custom entry point amxo_parser_add_entry_point(parser, my_entry_point_function); } int my_entry_point_function(int reason, amxd_dm_t* dm, amxo_parser_t* parser) { switch(reason) { case AMXO_START: printf("Application starting\n"); break; case AMXO_STOP: printf("Application stopping\n"); break; } return 0; } ``` -------------------------------- ### Print Usage Information with amxrt_print_usage Source: https://context7.com/prpl-foundation/components/llms.txt Prints the usage information and all available command-line options to stdout. Can be triggered by a custom argument handler, typically for '-h' or '--help'. ```c #include static int handle_args(amxc_var_t* config, int arg_id, const char* value) { if (arg_id == 'h') { amxrt_print_usage(); return -1; // Exit after printing help } return -2; // Use default handler } int main(int argc, char* argv[]) { amxrt_new(); // Customize usage documentation amxrt_cmd_line_set_usage_doc("[OPTIONS] "); // Add custom option amxrt_cmd_line_add_option(0, 'x', "extra", required_argument, "Extra configuration", "config"); int retval = amxrt(argc, argv, handle_args); amxrt_delete(); return retval; } // Output of -h: // myapp [OPTIONS] // // Options: // -h --help Print usage help and exit // -H --HELP Print extended help and exit // -B --backend Loads the shared object as bus backend // -u --uri Adds an uri to the list of uris // ... (more options) // -x --extra Extra configuration ``` -------------------------------- ### Define Custom Command-Line Options Source: https://context7.com/prpl-foundation/components/llms.txt Use amxrt_cmd_line_add_option to register custom flags and arguments, processed via a handler function passed to amxrt(). ```c #include // Custom argument handler static int handle_custom_args(amxc_var_t* config, int arg_id, const char* value) { switch(arg_id) { case 'V': printf("MyApp version 1.0.0\n"); return -1; // Stop processing, exit case 'c': printf("Custom config file: %s\n", value); amxc_var_add_key(cstring_t, config, "custom-config", value); return 0; // Option handled case 'v': amxc_var_set(bool, GET_ARG(config, "verbose"), true); return 0; default: return -2; // Use default handler } } int main(int argc, char* argv[]) { amxrt_new(); // Add custom command-line options // Parameters: id, short_opt, long_opt, has_args, description, arg_description amxrt_cmd_line_add_option(0, 'V', "version", no_argument, "Print version and exit", NULL); amxrt_cmd_line_add_option(0, 'c', "config", required_argument, "Custom configuration file", "file"); amxrt_cmd_line_add_option(0, 'v', "verbose", no_argument, "Enable verbose output", NULL); // Add a boolean config option for verbose mode amxc_var_add_key(bool, amxrt_get_config(), "verbose", false); // Run with custom handler int retval = amxrt(argc, argv, handle_custom_args); amxrt_delete(); return retval; } // Usage: // ./myapp --version // ./myapp -c /etc/myapp.conf -v /etc/amx/myapp/myapp.odl // ./myapp --config=/etc/myapp.conf --verbose ``` -------------------------------- ### Dump Process Capabilities with Amxrt Source: https://context7.com/prpl-foundation/components/llms.txt Prints the current process capabilities to standard output. This is useful for debugging privilege configuration and verifying that capabilities are set as expected. ```c #include int main(int argc, char* argv[]) { amxrt_new(); // Enable capability dumping via command line or config amxc_var_set(bool, GET_ARG(amxrt_get_config(), "dump-caps"), true); int retval = amxrt_init(argc, argv, NULL); if (retval != 0) goto cleanup; // Manually dump capabilities printf("Current process capabilities:\n"); amxrt_caps_dump(); retval = amxrt_run(); cleanup: amxrt_stop(); amxrt_delete(); return retval; } // Command line: // ./myapp -d caps /etc/amx/myapp/myapp.odl ``` -------------------------------- ### Read Custom Environment Variables Source: https://context7.com/prpl-foundation/components/llms.txt Reads environment variables and maps them to the runtime configuration with specified types. ```c #include void read_custom_env_vars(void) { // Read string environment variable amxrt_config_read_env_var("MY_APP_PREFIX", "custom-prefix", AMXC_VAR_ID_CSTRING); // Read list environment variable (semicolon separated) // Example: MY_APP_BACKENDS="/path/be1.so;/path/be2.so" amxrt_config_read_env_var("MY_APP_BACKENDS", "custom-backends", AMXC_VAR_ID_LIST); // Read boolean environment variable amxrt_config_read_env_var("MY_APP_DEBUG", "debug-mode", AMXC_VAR_ID_BOOL); // Verify amxc_var_t* config = amxrt_get_config(); const char* prefix = GET_CHAR(config, "custom-prefix"); if (prefix != NULL) { printf("Custom prefix: %s\n", prefix); } } ``` -------------------------------- ### Access and Modify Configuration with amxrt_get_config Source: https://context7.com/prpl-foundation/components/llms.txt Retrieves the runtime configuration htable and demonstrates how to read and modify settings programmatically. ```c #include void configure_runtime(void) { amxc_var_t* config = amxrt_get_config(); // Read configuration values const char* name = GET_CHAR(config, "name"); bool auto_detect = GET_BOOL(config, "auto-detect"); int32_t priority = GET_INT32(config, "priority"); printf("Application: %s\n", name); printf("Auto-detect: %s\n", auto_detect ? "yes" : "no"); printf("Priority: %d\n", priority); // Modify configuration programmatically amxc_var_set(bool, GET_ARG(config, "daemon"), true); amxc_var_set(bool, GET_ARG(config, "log"), true); // Add URIs amxc_var_add(cstring_t, GET_ARG(config, "uris"), "ubus:/var/run/ubus/ubus.sock"); amxc_var_add(cstring_t, GET_ARG(config, "uris"), "pcb:/var/run/pcb_sys"); // Set persistent storage options amxc_var_set_path(config, "odl.dm-save", &(amxc_var_t){.type_id = AMXC_VAR_ID_BOOL, .data.b = true}, AMXC_VAR_FLAG_AUTO_ADD | AMXC_VAR_FLAG_COPY); } ``` -------------------------------- ### amxrt Source: https://context7.com/prpl-foundation/components/llms.txt The main entry point that executes the complete Ambiorix application lifecycle, including argument parsing, ODL loading, bus connection, and event loop execution. ```APIDOC ## amxrt ### Description The main entry point that creates a complete Ambiorix application with a single call. It parses command-line arguments, loads ODL files, connects to bus systems, registers the data model, and starts the event loop. The function blocks until the event loop is stopped. ``` -------------------------------- ### Configure Data Model Persistence Source: https://context7.com/prpl-foundation/components/llms.txt Configures automatic data model persistence using ODL settings or programmatic configuration within the main entry point. ```c #include int main(int argc, char* argv[]) { amxrt_new(); // Configure persistence in ODL or programmatically amxc_var_t* config = amxrt_get_config(); // Create ODL persistence configuration amxc_var_t* odl = amxc_var_add_key(amxc_htable_t, config, "odl", NULL); amxc_var_add_key(bool, odl, "dm-save", true); // Save on exit amxc_var_add_key(bool, odl, "dm-save-on-changed", true); // Save on changes amxc_var_add_key(uint32_t, odl, "dm-save-delay", 1000); // Delay in ms amxc_var_add_key(uint32_t, odl, "dm-save-init-delay", 10000); amxc_var_add_key(cstring_t, odl, "directory", "/var/lib/myapp/"); // Register persistence entry point manually amxo_parser_t* parser = amxrt_get_parser(); amxo_parser_add_entry_point(parser, amxrt_dm_save_load_main); int retval = amxrt_init(argc, argv, NULL); if (retval != 0) goto cleanup; retval = amxrt_register_or_wait(); if (retval != 0) goto cleanup; retval = amxrt_run(); cleanup: amxrt_stop(); amxrt_delete(); return retval; } // ODL configuration example: // %config { // odl = { // dm-save = true, // dm-save-on-changed = true, // dm-save-delay = 500, // dm-save-init-delay = 30000, // directory = "${storage-path}/odl" // }; // } ``` -------------------------------- ### Usage Information Source: https://context7.com/prpl-foundation/components/llms.txt Function to print usage information and command-line options. ```APIDOC ## amxrt_print_usage ### Description Prints the usage information and all available command-line options to stdout. ### Method (Not specified, likely a C function call) ### Endpoint N/A (C function) ### Parameters None directly passed to `amxrt_print_usage`, but it relies on the configured command-line options. ### Request Example ```c #include static int handle_args(amxc_var_t* config, int arg_id, const char* value) { if (arg_id == 'h') { amxrt_print_usage(); return -1; // Exit after printing help } return -2; // Use default handler } int main(int argc, char* argv[]) { amxrt_new(); // Customize usage documentation amxrt_cmd_line_set_usage_doc("[OPTIONS] "); // Add custom option amxrt_cmd_line_add_option(0, 'x', "extra", required_argument, "Extra configuration", "config"); int retval = amxrt(argc, argv, handle_args); amxrt_delete(); return retval; } ``` ### Response (Prints to stdout, does not return a specific value indicating success/failure of printing itself, but the example shows it can trigger an exit.) #### Success Response (Prints usage information to stdout) #### Response Example ``` myapp [OPTIONS] Options: -h --help Print usage help and exit -H --HELP Print extended help and exit -B --backend Loads the shared object as bus backend -u --uri Adds an uri to the list of uris ... (more options) -x --extra Extra configuration ``` ``` -------------------------------- ### Create Event Loop with amxrt_el_create Source: https://context7.com/prpl-foundation/components/llms.txt Creates and initializes the event loop components, adding file descriptors for bus connections and system signals (SIGINT, SIGTERM, SIGALRM) for monitoring. This function is part of a manual initialization sequence that includes configuration loading and connection establishment. ```c #include int main(int argc, char* argv[]) { int retval = 0; int index = 0; amxrt_new(); // Manual initialization sequence retval = amxrt_config_init(argc, argv, &index, NULL); if (retval != 0) goto cleanup; retval = amxrt_load_odl_files(argc, argv, index); if (retval != 0) goto cleanup; amxrt_config_scan_backend_dirs(); retval = amxrt_connect(); if (retval != 0) goto cleanup; // Create event loop // - Adds file descriptors for bus connections // - Sets up signal handlers (SIGINT, SIGTERM, SIGALRM) retval = amxrt_el_create(); if (retval != 0) { fprintf(stderr, "Failed to create event loop\n"); goto cleanup; } retval = amxrt_register_or_wait(); if (retval != 0) goto cleanup; // Start the event loop amxrt_el_start(); cleanup: amxrt_el_destroy(); amxrt_delete(); return retval; } ``` -------------------------------- ### Handle custom command-line arguments in amxrt Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Register custom command-line options and provide a handler function to process them during runtime initialization. ```c #include #include #define VERSION_MAJOR 1 #define VERSION_MINOR 0 #define VERSION_BUILD 0 static int handle_cmd_line_arg(amxc_var_t* config, int arg_id, const char* value) { int rv = -1; const char* name = GET_CHAR(amxrt_get_config(), "name"); switch(arg_id) { case 'V': { printf("%s %d.%d.%d\n", name, VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); } break; default: rv = -2; break; } return rv; } int main(int argc, char* argv[]) { int retval = 0; amxrt_new() amxrt_cmd_line_add_option(0, 'V', "version", no_argument, "Print version", NULL); retval = amxrt(argc, argv, handle_cmd_line_arg); amxrt_delete(); return retval; } ``` -------------------------------- ### amxrt_caps_apply Source: https://context7.com/prpl-foundation/components/llms.txt Applies user privileges and Linux capabilities as defined in the configuration for security purposes. ```APIDOC ## amxrt_caps_apply ### Description Applies user privileges and Linux capabilities as defined in configuration. Allows privilege dropping and capability restriction for security. ``` -------------------------------- ### Clone libamxrt repository Source: https://gitlab.com/prpl-foundation/components/ambiorix/libraries/libamxrt/-/blob/main/README.md Clone the library source code into the project directory. ```bash cd ~/amx_project/libraries/ git clone git@gitlab.com:prpl-foundation/components/ambiorix/libraries/libamxrt.git ``` -------------------------------- ### amxrt_caps_dump Source: https://context7.com/prpl-foundation/components/llms.txt Prints current process capabilities to stdout for debugging purposes. ```APIDOC ## amxrt_caps_dump ### Description Prints current process capabilities to stdout. Useful for debugging privilege configuration. ```