R_CONFIG(3)

NAME
r_config - Configuration management library for radare2

SYNOPSIS
#include <r_config.h>

DESCRIPTION
The r_config API implements the configuration registry used by radare2 and its subcommands. It stores named configuration keys (strings, integers and booleans), metadata (description, options and read-only flags), and supports setters/getters so components can react to configuration changes. Common uses include global defaults (architecture, bits), binding config keys to internal variables, temporary overrides for an operation and serializing configuration into project files.

The primary container is struct r_config_t, which keeps a list and hash table of struct r_config_node_t, each node holding the key name, value, type flags, optional callbacks and a human-readable description.

INITIALIZATION
Create and destroy configuration objects. An `RConfig` is typically attached to a higher-level context (for example a `RCore` instance keeps one `RConfig`). Cloning produces a shallow copy of nodes suitable for temporary manipulation.

    /* prototypes */
    RConfig *r_config_new(void *user);
    RConfig *r_config_clone(RConfig *cfg);
    void r_config_free(RConfig *cfg);

    RConfig *cfg = r_config_new (core);
    /* ... use cfg ... */
    r_config_free (cfg);

SETTING VALUES
Setters update or create nodes and may call a node setter callback. Use the `_cb` variants or `r_config_set_setter*` helpers to bind a setter to propagate the change to internal state (see `libr/config/callback.c`).

    /* prototypes */
    RConfigNode *r_config_set(RConfig *cfg, const char *name, const char *value);
    RConfigNode *r_config_set_i(RConfig *cfg, const char *name, const ut64 i);
    RConfigNode *r_config_set_b(RConfig *cfg, const char *name, bool b);
    RConfigNode *r_config_set_cb(RConfig *cfg, const char *name, const char *value, RConfigCallback cb);
    RConfigNode *r_config_set_i_cb(RConfig *cfg, const char *name, int ivalue, RConfigCallback cb);
    RConfigNode *r_config_set_b_cb(RConfig *cfg, const char *name, bool bvalue, RConfigCallback cb);
    bool r_config_set_setter(RConfig *cfg, const char *key, RConfigCallback cb);

Notes: - When a node has a setter, it is invoked after the new value is parsed. If the setter returns false the previous value is restored. - The `r_config_set*` helpers create nodes if they do not exist; use `r_config_node_new` for manual node construction when you need to populate options or a long description first.

    /* example: CLI-style configuration used in many binaries */
    r_config_set (cfg, "asm.arch", "x86");
    r_config_set_i (cfg, "asm.bits", 64);
    r_config_set_b (cfg, "scr.interactive", false);

GETTING VALUES
Accessors return the current effective value for a key. If a node has an attached getter callback it may compute values on demand.

    /* prototypes */
    const char *r_config_get(RConfig *cfg, const char *name);
    ut64 r_config_get_i(RConfig *cfg, const char *name);
    bool r_config_get_b(RConfig *cfg, const char *name);
    bool r_config_toggle(RConfig *cfg, const char *name);
    bool r_config_rm(RConfig *cfg, const char *name);

    const char *arch = r_config_get (cfg, "asm.arch");
    ut64 bits = r_config_get_i (cfg, "asm.bits");
    bool pseudo = r_config_get_b (cfg, "asm.pseudo");
    r_config_toggle (cfg, "asm.pseudo");

ADVANCED FEATURES
This section covers higher-level utilities used in real radare2 code: locks, short expression evaluation (used by CLI option parsers), bulk listing and the hold/restore pattern which captures values to restore them later.

    /* prototypes */
    void r_config_lock(RConfig *cfg, bool lock);
    char *r_config_eval(RConfig *cfg, const char *str, bool many, bool *error);
    RConfigHold *r_config_hold_new(RConfig *cfg);
    bool r_config_hold(RConfigHold *h, ...);
    void r_config_hold_restore(RConfigHold *h);
    void r_config_hold_free(RConfigHold *h);
    void r_config_bump(RConfig *cfg, const char *key);
    char *r_config_list(RConfig *cfg, const char *str, int rad);

Behavior and tips: - `r_config_lock` sorts nodes and flips a lock flag (useful before serializing a stable snapshot). - `r_config_eval` understands `key=value` to set keys, `key.` to list matching keys, and colon-separated lists when `many` is true; this mirrors how CLI handlers parse compact config expressions. - `r_config_hold_new` + `r_config_hold` capture current values for a list of keys; `r_config_hold_restore` restores them. This mirrors patterns used when temporarily switching architectures or analysis depth.

    /* hold/restore example (used in several core components) */
    RConfigHold *hold = r_config_hold_new (cfg);
    r_config_hold (hold, "asm.arch", "asm.bits", NULL);
    /* temporarily override */
    r_config_set (cfg, "asm.arch", "arm");
    r_config_set_i (cfg, "asm.bits", 32);
    /* restore original */
    r_config_hold_restore (hold);
    r_config_hold_free (hold);

NODE MANAGEMENT
Direct node manipulation is useful when registering a config key with a long description, a collection of valid options or custom setter/getter callbacks. Most callers use the `r_config_set*` helpers which create nodes implicitly; use the node API for more control.

    /* prototypes */
    RConfigNode *r_config_node_new(const char *name, const char *value);
    RConfigNode *r_config_node_get(RConfig *cfg, const char *name);
    RConfigNode *r_config_node_desc(RConfigNode *node, const char *desc);
    void r_config_node_add_option(RConfigNode *node, const char *option);
    void r_config_node_purge_options(RConfigNode *node);
    char *r_config_node_tostring(RConfigNode *node);
    void r_config_node_free(void *n);

    /* create a node with options and description */
    RConfigNode *node = r_config_node_new ("custom.var", "default");
    r_config_node_desc (node, "Description for UI and help output");
    r_config_node_add_option (node, "opt1");
    r_config_node_add_option (node, "opt2");
    /* attach node into cfg (internal helpers in libr/config do this) */
    r_config_node_free (node);

SERIALIZATION
Serialize and unserialize configuration into an `Sdb` database. These routines are used when saving/loading projects so configuration survives between sessions.

    /* prototypes */
    void r_config_serialize(RConfig * R_NONNULL config, Sdb * R_NONNULL db);
    bool r_config_unserialize(RConfig * R_NONNULL config, Sdb * R_NONNULL db, char ** R_NULLABLE err);

    Sdb *db = sdb_new0 ();
    r_config_serialize (cfg, db);
    /* write sdb to disk via sdb API */
    sdb_free (db);

EXAMPLES
Examples below demonstrate patterns taken from real radare2 code: binding config keys to variables, temporary overrides, and evaluating compact config expressions.

    #include <r_config.h>

    int main(void) {
        RConfig *cfg = r_config_new (NULL);

        /* common set/get pattern used in many binaries */
        r_config_set (cfg, "asm.arch", "x86");
        r_config_set_i (cfg, "asm.bits", 64);
        printf ("Arch: %s, r_config_get (cfg, "asm.arch"));

        /* bind a config key to a C variable using setter helpers (see
         * libr/config/callback.c for the implementation used in the tree): */
        int term_color = 0;
        r_config_set_setter_i (cfg, "scr.color", &term_color);
        r_config_set_i (cfg, "scr.color", 2); /* updates term_color */

        /* temporarily override and restore: */
        RConfigHold *hold = r_config_hold_new (cfg);
        r_config_hold (hold, "asm.arch", "asm.bits", NULL);
        r_config_set (cfg, "asm.arch", "arm");
        r_config_set_i (cfg, "asm.bits", 32);
        r_config_hold_restore (hold);
        r_config_hold_free (hold);

        /* evaluate a compact CLI expression (used in CLI parsing code): */
        char *res = r_config_eval (cfg, "asm.arch=arm:asm.bits=32", true, NULL);
        free (res);

        r_config_free (cfg);
        return 0;
    }

SEE ALSO
r_core(3), r_util(3)