|
Packit |
4a16fb |
/*
|
|
Packit |
4a16fb |
* This library is free software; you can redistribute it and/or
|
|
Packit |
4a16fb |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
4a16fb |
* License as published by the Free Software Foundation; either
|
|
Packit |
4a16fb |
* version 2 of the License, or (at your option) any later version.
|
|
Packit |
4a16fb |
*
|
|
Packit |
4a16fb |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
4a16fb |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
4a16fb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
4a16fb |
* Lesser General Public License for more details.
|
|
Packit |
4a16fb |
*
|
|
Packit |
4a16fb |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
4a16fb |
* License along with this library; if not, write to the Free Software
|
|
Packit |
4a16fb |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
4a16fb |
*
|
|
Packit |
4a16fb |
* Support for the verb/device/modifier core logic and API,
|
|
Packit |
4a16fb |
* command line tool and file parser was kindly sponsored by
|
|
Packit |
4a16fb |
* Texas Instruments Inc.
|
|
Packit |
4a16fb |
* Support for multiple active modifiers and devices,
|
|
Packit |
4a16fb |
* transition sequences, multiple client access and user defined use
|
|
Packit |
4a16fb |
* cases was kindly sponsored by Wolfson Microelectronics PLC.
|
|
Packit |
4a16fb |
*
|
|
Packit |
4a16fb |
* Copyright (C) 2019 Red Hat Inc.
|
|
Packit |
4a16fb |
* Authors: Jaroslav Kysela <perex@perex.cz>
|
|
Packit |
4a16fb |
*/
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
#include "ucm_local.h"
|
|
Packit Service |
f36a15 |
#include <stdbool.h>
|
|
Packit |
4a16fb |
#include <sys/stat.h>
|
|
Packit |
4a16fb |
#include <limits.h>
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
static char *rval_open_name(snd_use_case_mgr_t *uc_mgr)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
const char *name;
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_format < 3)
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
name = uc_mgr->card_name;
|
|
Packit Service |
f36a15 |
if (name) {
|
|
Packit Service |
f36a15 |
if (strncmp(name, "strict:", 7) == 0)
|
|
Packit Service |
f36a15 |
name += 7;
|
|
Packit Service |
f36a15 |
return strdup(name);
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static char *rval_conf_topdir(snd_use_case_mgr_t *uc_mgr)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
const char *dir;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_format < 3)
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
dir = uc_mgr_config_dir(uc_mgr->conf_format);
|
|
Packit Service |
f36a15 |
if (dir && dir[0])
|
|
Packit Service |
f36a15 |
return strdup(dir);
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static char *rval_conf_dir(snd_use_case_mgr_t *uc_mgr)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_format < 3)
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_dir_name && uc_mgr->conf_dir_name[0])
|
|
Packit Service |
f36a15 |
return strdup(uc_mgr->conf_dir_name);
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit |
4a16fb |
static char *rval_conf_name(snd_use_case_mgr_t *uc_mgr)
|
|
Packit |
4a16fb |
{
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_file_name && uc_mgr->conf_file_name[0])
|
|
Packit |
4a16fb |
return strdup(uc_mgr->conf_file_name);
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
static char *get_card_number(struct ctl_list *ctl_list)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
char num[16];
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (ctl_list == NULL)
|
|
Packit Service |
f36a15 |
return strdup("");
|
|
Packit Service |
f36a15 |
snprintf(num, sizeof(num), "%i", snd_ctl_card_info_get_card(ctl_list->ctl_info));
|
|
Packit Service |
f36a15 |
return strdup(num);
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static char *rval_card_number(snd_use_case_mgr_t *uc_mgr)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_format < 3)
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
return get_card_number(uc_mgr_get_master_ctl(uc_mgr));
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit |
4a16fb |
static char *rval_card_id(snd_use_case_mgr_t *uc_mgr)
|
|
Packit |
4a16fb |
{
|
|
Packit |
4a16fb |
struct ctl_list *ctl_list;
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
ctl_list = uc_mgr_get_master_ctl(uc_mgr);
|
|
Packit |
4a16fb |
if (ctl_list == NULL)
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
return strdup(snd_ctl_card_info_get_id(ctl_list->ctl_info));
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
static char *rval_card_driver(snd_use_case_mgr_t *uc_mgr)
|
|
Packit |
4a16fb |
{
|
|
Packit |
4a16fb |
struct ctl_list *ctl_list;
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
ctl_list = uc_mgr_get_master_ctl(uc_mgr);
|
|
Packit |
4a16fb |
if (ctl_list == NULL)
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
return strdup(snd_ctl_card_info_get_driver(ctl_list->ctl_info));
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
static char *rval_card_name(snd_use_case_mgr_t *uc_mgr)
|
|
Packit |
4a16fb |
{
|
|
Packit |
4a16fb |
struct ctl_list *ctl_list;
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
ctl_list = uc_mgr_get_master_ctl(uc_mgr);
|
|
Packit |
4a16fb |
if (ctl_list == NULL)
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
return strdup(snd_ctl_card_info_get_name(ctl_list->ctl_info));
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
static char *rval_card_longname(snd_use_case_mgr_t *uc_mgr)
|
|
Packit |
4a16fb |
{
|
|
Packit |
4a16fb |
struct ctl_list *ctl_list;
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
ctl_list = uc_mgr_get_master_ctl(uc_mgr);
|
|
Packit |
4a16fb |
if (ctl_list == NULL)
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
return strdup(snd_ctl_card_info_get_longname(ctl_list->ctl_info));
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
static char *rval_card_components(snd_use_case_mgr_t *uc_mgr)
|
|
Packit |
4a16fb |
{
|
|
Packit |
4a16fb |
struct ctl_list *ctl_list;
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
ctl_list = uc_mgr_get_master_ctl(uc_mgr);
|
|
Packit |
4a16fb |
if (ctl_list == NULL)
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
return strdup(snd_ctl_card_info_get_components(ctl_list->ctl_info));
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
static struct ctl_list *get_ctl_list_by_name(snd_use_case_mgr_t *uc_mgr, const char *id)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
char *name, *index;
|
|
Packit Service |
f36a15 |
long idx = 0;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
name = alloca(strlen(id) + 1);
|
|
Packit Service |
f36a15 |
strcpy(name, id);
|
|
Packit Service |
f36a15 |
index = strchr(name, '#');
|
|
Packit Service |
f36a15 |
if (index) {
|
|
Packit Service |
f36a15 |
*index = '\0';
|
|
Packit Service |
f36a15 |
if (safe_strtol(index + 1, &idx))
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
return uc_mgr_get_ctl_by_name(uc_mgr, name, idx);
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static char *rval_card_number_by_name(snd_use_case_mgr_t *uc_mgr, const char *id)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_format < 3) {
|
|
Packit Service |
f36a15 |
uc_error("CardNumberByName substitution is supported in v3+ syntax");
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
return get_card_number(get_ctl_list_by_name(uc_mgr, id));
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
static char *rval_card_id_by_name(snd_use_case_mgr_t *uc_mgr, const char *id)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
struct ctl_list *ctl_list;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_format < 3) {
|
|
Packit Service |
f36a15 |
uc_error("CardIdByName substitution is supported in v3+ syntax");
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
ctl_list = get_ctl_list_by_name(uc_mgr, id);
|
|
Packit Service |
f36a15 |
if (ctl_list == NULL)
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
return strdup(snd_ctl_card_info_get_id(ctl_list->ctl_info));
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit |
4a16fb |
static char *rval_env(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *id)
|
|
Packit |
4a16fb |
{
|
|
Packit |
4a16fb |
char *e;
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
e = getenv(id);
|
|
Packit |
4a16fb |
if (e)
|
|
Packit |
4a16fb |
return strdup(e);
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
static char *rval_sysfs(snd_use_case_mgr_t *uc_mgr ATTRIBUTE_UNUSED, const char *id)
|
|
Packit |
4a16fb |
{
|
|
Packit |
4a16fb |
char path[PATH_MAX], link[PATH_MAX + 1];
|
|
Packit |
4a16fb |
struct stat sb;
|
|
Packit |
4a16fb |
ssize_t len;
|
|
Packit |
4a16fb |
char *e;
|
|
Packit |
4a16fb |
int fd;
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
e = getenv("SYSFS_PATH");
|
|
Packit |
4a16fb |
if (e == NULL)
|
|
Packit |
4a16fb |
e = "/sys";
|
|
Packit |
4a16fb |
if (id[0] == '/')
|
|
Packit |
4a16fb |
id++;
|
|
Packit |
4a16fb |
snprintf(path, sizeof(path), "%s/%s", e, id);
|
|
Packit |
4a16fb |
if (lstat(path, &sb) != 0)
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
if (S_ISLNK(sb.st_mode)) {
|
|
Packit |
4a16fb |
len = readlink(path, link, sizeof(link) - 1);
|
|
Packit |
4a16fb |
if (len <= 0) {
|
|
Packit |
4a16fb |
uc_error("sysfs: cannot read link '%s' (%d)", path, errno);
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
link[len] = '\0';
|
|
Packit |
4a16fb |
e = strrchr(link, '/');
|
|
Packit |
4a16fb |
if (e)
|
|
Packit |
4a16fb |
return strdup(e + 1);
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
if (S_ISDIR(sb.st_mode))
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
if ((sb.st_mode & S_IRUSR) == 0)
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
fd = open(path, O_RDONLY);
|
|
Packit |
4a16fb |
if (fd < 0) {
|
|
Packit |
4a16fb |
uc_error("sysfs open failed for '%s' (%d)", path, errno);
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
len = read(fd, path, sizeof(path)-1);
|
|
Packit |
4a16fb |
close(fd);
|
|
Packit |
4a16fb |
if (len < 0) {
|
|
Packit |
4a16fb |
uc_error("sysfs unable to read value '%s' (%d)", path, errno);
|
|
Packit |
4a16fb |
return NULL;
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
while (len > 0 && path[len-1] == '\n')
|
|
Packit |
4a16fb |
len--;
|
|
Packit |
4a16fb |
path[len] = '\0';
|
|
Packit |
4a16fb |
return strdup(path);
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
static char *rval_var(snd_use_case_mgr_t *uc_mgr, const char *id)
|
|
Packit Service |
f36a15 |
{
|
|
Packit Service |
f36a15 |
const char *v;
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
if (uc_mgr->conf_format < 3) {
|
|
Packit Service |
f36a15 |
uc_error("variable substitution is supported in v3+ syntax");
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
v = uc_mgr_get_variable(uc_mgr, id);
|
|
Packit Service |
f36a15 |
if (v)
|
|
Packit Service |
f36a15 |
return strdup(v);
|
|
Packit Service |
f36a15 |
return NULL;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
|
|
Packit Service |
f36a15 |
#define MATCH_VARIABLE(name, id, fcn, empty_ok) \
|
|
Packit |
4a16fb |
if (strncmp((name), (id), sizeof(id) - 1) == 0) { \
|
|
Packit |
4a16fb |
rval = fcn(uc_mgr); \
|
|
Packit |
4a16fb |
idsize = sizeof(id) - 1; \
|
|
Packit Service |
f36a15 |
allow_empty = (empty_ok); \
|
|
Packit |
4a16fb |
goto __rval; \
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit Service |
f36a15 |
#define MATCH_VARIABLE2(name, id, fcn, empty_ok) \
|
|
Packit |
4a16fb |
if (strncmp((name), (id), sizeof(id) - 1) == 0) { \
|
|
Packit |
4a16fb |
idsize = sizeof(id) - 1; \
|
|
Packit Service |
f36a15 |
allow_empty = (empty_ok); \
|
|
Packit Service |
f36a15 |
fcn2 = (fcn); \
|
|
Packit Service |
f36a15 |
goto __match2; \
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
int uc_mgr_get_substituted_value(snd_use_case_mgr_t *uc_mgr,
|
|
Packit |
4a16fb |
char **_rvalue,
|
|
Packit |
4a16fb |
const char *value)
|
|
Packit |
4a16fb |
{
|
|
Packit |
4a16fb |
size_t size, nsize, idsize, rvalsize, dpos = 0;
|
|
Packit |
4a16fb |
const char *tmp;
|
|
Packit Service |
f36a15 |
char *r, *nr, *rval, v2[48];
|
|
Packit Service |
f36a15 |
bool ignore_error, allow_empty;
|
|
Packit Service |
f36a15 |
char *(*fcn2)(snd_use_case_mgr_t *, const char *id);
|
|
Packit |
4a16fb |
int err;
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
if (value == NULL)
|
|
Packit |
4a16fb |
return -ENOENT;
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
size = strlen(value) + 1;
|
|
Packit |
4a16fb |
r = malloc(size);
|
|
Packit |
4a16fb |
if (r == NULL)
|
|
Packit |
4a16fb |
return -ENOMEM;
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
while (*value) {
|
|
Packit Service |
f36a15 |
if (*value != '$') {
|
|
Packit Service |
f36a15 |
__std:
|
|
Packit Service |
f36a15 |
r[dpos++] = *value;
|
|
Packit Service |
f36a15 |
value++;
|
|
Packit Service |
f36a15 |
continue;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
ignore_error = false;
|
|
Packit Service |
f36a15 |
if (value[1] == '$' && value[2] == '{' && uc_mgr->conf_format >= 3) {
|
|
Packit Service |
f36a15 |
value++;
|
|
Packit Service |
f36a15 |
ignore_error = true;
|
|
Packit Service |
f36a15 |
} else if (value[1] != '{') {
|
|
Packit Service |
f36a15 |
goto __std;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
allow_empty = false;
|
|
Packit Service |
f36a15 |
fcn2 = NULL;
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${OpenName}", rval_open_name, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${ConfTopDir}", rval_conf_topdir, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${ConfDir}", rval_conf_dir, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${ConfName}", rval_conf_name, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${CardNumber}", rval_card_number, true);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${CardId}", rval_card_id, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${CardDriver}", rval_card_driver, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${CardName}", rval_card_name, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${CardLongName}", rval_card_longname, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE(value, "${CardComponents}", rval_card_components, true);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE2(value, "${env:", rval_env, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE2(value, "${sys:", rval_sysfs, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE2(value, "${var:", rval_var, true);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE2(value, "${CardNumberByName:", rval_card_number_by_name, false);
|
|
Packit Service |
f36a15 |
MATCH_VARIABLE2(value, "${CardIdByName:", rval_card_id_by_name, false);
|
|
Packit Service |
f36a15 |
__merr:
|
|
Packit Service |
f36a15 |
err = -EINVAL;
|
|
Packit Service |
f36a15 |
tmp = strchr(value, '}');
|
|
Packit Service |
f36a15 |
if (tmp) {
|
|
Packit Service |
f36a15 |
strncpy(r, value, tmp + 1 - value);
|
|
Packit Service |
f36a15 |
r[tmp + 1 - value] = '\0';
|
|
Packit Service |
f36a15 |
uc_error("variable '%s' is not known!", r);
|
|
Packit Service |
f36a15 |
} else {
|
|
Packit Service |
f36a15 |
uc_error("variable reference '%s' is not complete", value);
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
goto __error;
|
|
Packit Service |
f36a15 |
__match2:
|
|
Packit Service |
f36a15 |
tmp = strchr(value + idsize, '}');
|
|
Packit Service |
f36a15 |
if (tmp) {
|
|
Packit Service |
f36a15 |
rvalsize = tmp - (value + idsize);
|
|
Packit Service |
f36a15 |
if (rvalsize >= sizeof(v2)) {
|
|
Packit Service |
f36a15 |
err = -ENOMEM;
|
|
Packit Service |
f36a15 |
goto __error;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
strncpy(v2, value + idsize, rvalsize);
|
|
Packit Service |
f36a15 |
v2[rvalsize] = '\0';
|
|
Packit Service |
f36a15 |
idsize += rvalsize + 1;
|
|
Packit Service |
f36a15 |
if (*v2 == '$' && uc_mgr->conf_format >= 3) {
|
|
Packit Service |
f36a15 |
tmp = uc_mgr_get_variable(uc_mgr, v2 + 1);
|
|
Packit Service |
f36a15 |
if (tmp == NULL) {
|
|
Packit Service |
f36a15 |
uc_error("define '%s' is not reachable in this context!", v2 + 1);
|
|
Packit Service |
f36a15 |
rval = NULL;
|
|
Packit Service |
f36a15 |
} else {
|
|
Packit Service |
f36a15 |
rval = fcn2(uc_mgr, tmp);
|
|
Packit Service |
f36a15 |
}
|
|
Packit |
4a16fb |
} else {
|
|
Packit Service |
f36a15 |
rval = fcn2(uc_mgr, v2);
|
|
Packit |
4a16fb |
}
|
|
Packit Service |
f36a15 |
goto __rval;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
goto __merr;
|
|
Packit |
4a16fb |
__rval:
|
|
Packit Service |
f36a15 |
if (rval == NULL || (!allow_empty && rval[0] == '\0')) {
|
|
Packit Service |
f36a15 |
free(rval);
|
|
Packit Service |
f36a15 |
if (ignore_error) {
|
|
Packit Service |
f36a15 |
value += idsize;
|
|
Packit Service |
f36a15 |
continue;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
strncpy(r, value, idsize);
|
|
Packit Service |
f36a15 |
r[idsize] = '\0';
|
|
Packit Service |
f36a15 |
uc_error("variable '%s' is not defined in this context!", r);
|
|
Packit Service |
f36a15 |
err = -EINVAL;
|
|
Packit Service |
f36a15 |
goto __error;
|
|
Packit Service |
f36a15 |
}
|
|
Packit Service |
f36a15 |
value += idsize;
|
|
Packit Service |
f36a15 |
rvalsize = strlen(rval);
|
|
Packit Service |
f36a15 |
nsize = size + rvalsize - idsize;
|
|
Packit Service |
f36a15 |
if (nsize > size) {
|
|
Packit Service |
f36a15 |
nr = realloc(r, nsize);
|
|
Packit Service |
f36a15 |
if (nr == NULL) {
|
|
Packit |
4a16fb |
free(rval);
|
|
Packit Service |
f36a15 |
err = -ENOMEM;
|
|
Packit |
4a16fb |
goto __error;
|
|
Packit |
4a16fb |
}
|
|
Packit Service |
f36a15 |
size = nsize;
|
|
Packit Service |
f36a15 |
r = nr;
|
|
Packit |
4a16fb |
}
|
|
Packit Service |
f36a15 |
strcpy(r + dpos, rval);
|
|
Packit Service |
f36a15 |
dpos += rvalsize;
|
|
Packit Service |
f36a15 |
free(rval);
|
|
Packit |
4a16fb |
}
|
|
Packit |
4a16fb |
r[dpos] = '\0';
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
*_rvalue = r;
|
|
Packit |
4a16fb |
return 0;
|
|
Packit |
4a16fb |
|
|
Packit |
4a16fb |
__error:
|
|
Packit |
4a16fb |
free(r);
|
|
Packit |
4a16fb |
return err;
|
|
Packit |
4a16fb |
}
|