Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46ccee6e authored by David Ng's avatar David Ng Committed by Steve Kondik
Browse files

init: Allow basic environment variable expansion in env assignment

Allow environment variable expansion in 'export' command if the
value begins with "${_var_}" (where "${_var_}" will be replaced
with the current value of environment variable _var_).  Expansion
will only occur one time.

e.g.
export BOOTCLASSPATH ${BOOTCLASSPATH}:/system/framework/abc.jar
(cherry picked from commit 7940299507f15055851a6e8b61ae8d8a7d7f3484)

Change-Id: If9e4adfa1aba2c7a4ca243978ced3c46c2cb4d73
parent b34f581c
Loading
Loading
Loading
Loading
+86 −2
Original line number Diff line number Diff line
@@ -105,21 +105,105 @@ static unsigned emmc_boot = 0;

static unsigned charging_mode = 0;

static const char *expand_environment(const char *val)
{
    int n;
    const char *prev_pos = NULL, *copy_pos;
    size_t len, prev_len = 0, copy_len;
    char *expanded;

    /* Basic expansion of environment variable; for now
       we only assume 1 expansion at the start of val
       and that it is marked as ${var} */
    if (!val) {
        return NULL;
    }

    if ((val[0] == '$') && (val[1] == '{')) {
        for (n = 0; n < 31; n++) {
            if (ENV[n]) {
                len = strcspn(ENV[n], "=");
                if (!strncmp(&val[2], ENV[n], len)
                      && (val[2 + len] == '}')) {
                    /* Matched existing env */
                    prev_pos = &ENV[n][len + 1];
                    prev_len = strlen(prev_pos);
                    break;
                }
            }
        }
        copy_pos = index(val, '}');
        if (copy_pos) {
            copy_pos++;
            copy_len = strlen(copy_pos);
        } else {
            copy_pos = val;
            copy_len = strlen(val);
        }
    } else {
        copy_pos = val;
        copy_len = strlen(val);
    }

    len = prev_len + copy_len + 1;
    expanded = malloc(len);
    if (expanded) {
        if (prev_pos) {
            snprintf(expanded, len, "%s%s", prev_pos, copy_pos);
        } else {
            snprintf(expanded, len, "%s", copy_pos);
        }
    }

    /* caller free */
    return expanded;
}

/* add_environment - add "key=value" to the current environment */
int add_environment(const char *key, const char *val)
{
    int n;
    const char *expanded;

    expanded = expand_environment(val);
    if (!expanded) {
        goto failed;
    }

    for (n = 0; n < 31; n++) {
        if (!ENV[n]) {
            size_t len = strlen(key) + strlen(val) + 2;
            size_t len = strlen(key) + strlen(expanded) + 2;
            char *entry = malloc(len);
            snprintf(entry, len, "%s=%s", key, val);
            if (!entry) {
                goto failed_cleanup;
            }
            snprintf(entry, len, "%s=%s", key, expanded);
            free((char *)expanded);
            ENV[n] = entry;
            return 0;
        } else {
            char *entry;
            size_t len = strlen(key);
            if(!strncmp(ENV[n], key, len) && ENV[n][len] == '=') {
                len = len + strlen(expanded) + 2;
                entry = malloc(len);
                if (!entry) {
                    goto failed_cleanup;
                }

                free((char *)ENV[n]);
                snprintf(entry, len, "%s=%s", key, expanded);
                free((char *)expanded);
                ENV[n] = entry;
                return 0;
            }
        }
    }

failed_cleanup:
    free((char *)expanded);
failed:
    ERROR("Fail to add env variable: %s. Not enough memory!", key);
    return 1;
}