* commit 'bd5f10addfba8df40c8293d95c002044acbfa526': init: do expand_props before calling the builtins.
This commit is contained in:
commit
57eb040ba9
5 changed files with 76 additions and 145 deletions
|
|
@ -62,14 +62,8 @@ extern "C" int init_module(void *, unsigned long, const char *);
|
||||||
|
|
||||||
static int insmod(const char *filename, char *options)
|
static int insmod(const char *filename, char *options)
|
||||||
{
|
{
|
||||||
char filename_val[PROP_VALUE_MAX];
|
|
||||||
if (expand_props(filename_val, filename, sizeof(filename_val)) == -1) {
|
|
||||||
ERROR("insmod: cannot expand '%s'\n", filename);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string module;
|
std::string module;
|
||||||
if (!read_file(filename_val, &module)) {
|
if (!read_file(filename, &module)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -468,17 +462,11 @@ int do_mount_all(int nargs, char **args)
|
||||||
int child_ret = -1;
|
int child_ret = -1;
|
||||||
int status;
|
int status;
|
||||||
struct fstab *fstab;
|
struct fstab *fstab;
|
||||||
char fstabfile[PROP_VALUE_MAX];
|
|
||||||
|
|
||||||
if (nargs != 2) {
|
if (nargs != 2) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
const char* fstabfile = args[1];
|
||||||
if (expand_props(fstabfile, args[1], sizeof(fstabfile)) == -1) {
|
|
||||||
ERROR("mount_all: cannot expand '%s' \n", args[1]);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and
|
* Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and
|
||||||
* do the call in the child to provide protection to the main init
|
* do the call in the child to provide protection to the main init
|
||||||
|
|
@ -572,15 +560,7 @@ int do_setprop(int nargs, char **args)
|
||||||
{
|
{
|
||||||
const char *name = args[1];
|
const char *name = args[1];
|
||||||
const char *value = args[2];
|
const char *value = args[2];
|
||||||
char prop_val[PROP_VALUE_MAX];
|
property_set(name, value);
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = expand_props(prop_val, value, sizeof(prop_val));
|
|
||||||
if (ret) {
|
|
||||||
ERROR("cannot expand '%s' while assigning to '%s'\n", value, name);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
property_set(name, prop_val);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -626,19 +606,12 @@ int do_restart(int nargs, char **args)
|
||||||
|
|
||||||
int do_powerctl(int nargs, char **args)
|
int do_powerctl(int nargs, char **args)
|
||||||
{
|
{
|
||||||
char command[PROP_VALUE_MAX];
|
const char* command = args[1];
|
||||||
int res;
|
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int cmd = 0;
|
int cmd = 0;
|
||||||
const char *reboot_target;
|
const char *reboot_target;
|
||||||
void (*callback_on_ro_remount)(const struct mntent*) = NULL;
|
void (*callback_on_ro_remount)(const struct mntent*) = NULL;
|
||||||
|
|
||||||
res = expand_props(command, args[1], sizeof(command));
|
|
||||||
if (res) {
|
|
||||||
ERROR("powerctl: cannot expand '%s'\n", args[1]);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(command, "shutdown", 8) == 0) {
|
if (strncmp(command, "shutdown", 8) == 0) {
|
||||||
cmd = ANDROID_RB_POWEROFF;
|
cmd = ANDROID_RB_POWEROFF;
|
||||||
len = 8;
|
len = 8;
|
||||||
|
|
@ -666,13 +639,7 @@ int do_powerctl(int nargs, char **args)
|
||||||
|
|
||||||
int do_trigger(int nargs, char **args)
|
int do_trigger(int nargs, char **args)
|
||||||
{
|
{
|
||||||
char prop_val[PROP_VALUE_MAX];
|
action_for_each_trigger(args[1], action_add_queue_tail);
|
||||||
int res = expand_props(prop_val, args[1], sizeof(prop_val));
|
|
||||||
if (res) {
|
|
||||||
ERROR("trigger: cannot expand '%s'\n", args[1]);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
action_for_each_trigger(prop_val, action_add_queue_tail);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -727,13 +694,7 @@ int do_write(int nargs, char **args)
|
||||||
{
|
{
|
||||||
const char *path = args[1];
|
const char *path = args[1];
|
||||||
const char *value = args[2];
|
const char *value = args[2];
|
||||||
|
return write_file(path, value);
|
||||||
char expanded_value[256];
|
|
||||||
if (expand_props(expanded_value, value, sizeof(expanded_value))) {
|
|
||||||
ERROR("cannot expand '%s' while writing to '%s'\n", value, path);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
return write_file(path, expanded_value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_copy(int nargs, char **args)
|
int do_copy(int nargs, char **args)
|
||||||
|
|
@ -856,18 +817,12 @@ int do_restorecon_recursive(int nargs, char **args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_loglevel(int nargs, char **args) {
|
int do_loglevel(int nargs, char **args) {
|
||||||
int log_level;
|
|
||||||
char log_level_str[PROP_VALUE_MAX] = "";
|
|
||||||
if (nargs != 2) {
|
if (nargs != 2) {
|
||||||
ERROR("loglevel: missing argument\n");
|
ERROR("loglevel: missing argument\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expand_props(log_level_str, args[1], sizeof(log_level_str))) {
|
int log_level = atoi(args[1]);
|
||||||
ERROR("loglevel: cannot expand '%s'\n", args[1]);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
log_level = atoi(log_level_str);
|
|
||||||
if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) {
|
if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) {
|
||||||
ERROR("loglevel: invalid log level'%d'\n", log_level);
|
ERROR("loglevel: invalid log level'%d'\n", log_level);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
||||||
|
|
@ -570,25 +570,24 @@ static int is_last_command(struct action *act, struct command *cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void build_triggers_string(char *name_str, int length, struct action *cur_action) {
|
std::string build_triggers_string(struct action *cur_action) {
|
||||||
|
std::string result;
|
||||||
struct listnode *node;
|
struct listnode *node;
|
||||||
struct trigger *cur_trigger;
|
struct trigger *cur_trigger;
|
||||||
|
|
||||||
list_for_each(node, &cur_action->triggers) {
|
list_for_each(node, &cur_action->triggers) {
|
||||||
cur_trigger = node_to_item(node, struct trigger, nlist);
|
cur_trigger = node_to_item(node, struct trigger, nlist);
|
||||||
if (node != cur_action->triggers.next) {
|
if (node != cur_action->triggers.next) {
|
||||||
strlcat(name_str, " " , length);
|
result.push_back(' ');
|
||||||
}
|
}
|
||||||
strlcat(name_str, cur_trigger->name , length);
|
result += cur_trigger->name;
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_one_command() {
|
void execute_one_command() {
|
||||||
Timer t;
|
Timer t;
|
||||||
|
|
||||||
char cmd_str[256] = "";
|
|
||||||
char name_str[256] = "";
|
|
||||||
|
|
||||||
if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
|
if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
|
||||||
cur_action = action_remove_queue_head();
|
cur_action = action_remove_queue_head();
|
||||||
cur_command = NULL;
|
cur_command = NULL;
|
||||||
|
|
@ -596,9 +595,8 @@ void execute_one_command() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
build_triggers_string(name_str, sizeof(name_str), cur_action);
|
std::string trigger_name = build_triggers_string(cur_action);
|
||||||
|
INFO("processing action %p (%s)\n", cur_action, trigger_name.c_str());
|
||||||
INFO("processing action %p (%s)\n", cur_action, name_str);
|
|
||||||
cur_command = get_first_command(cur_action);
|
cur_command = get_first_command(cur_action);
|
||||||
} else {
|
} else {
|
||||||
cur_command = get_next_command(cur_action, cur_command);
|
cur_command = get_next_command(cur_action, cur_command);
|
||||||
|
|
@ -607,23 +605,40 @@ void execute_one_command() {
|
||||||
if (!cur_command) {
|
if (!cur_command) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int result = 0;
|
||||||
int result = cur_command->func(cur_command->nargs, cur_command->args);
|
std::vector<std::string> arg_strs(cur_command->nargs);
|
||||||
|
arg_strs[0] = cur_command->args[0];
|
||||||
|
for (int i = 1; i < cur_command->nargs; ++i) {
|
||||||
|
if (expand_props(cur_command->args[i], &arg_strs[i]) == -1) {
|
||||||
|
ERROR("%s: cannot expand '%s'\n", cur_command->args[0], cur_command->args[i]);
|
||||||
|
result = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
std::vector<char*> args;
|
||||||
|
for (auto& s : arg_strs) {
|
||||||
|
args.push_back(&s[0]);
|
||||||
|
}
|
||||||
|
result = cur_command->func(args.size(), &args[0]);
|
||||||
|
}
|
||||||
if (klog_get_level() >= KLOG_INFO_LEVEL) {
|
if (klog_get_level() >= KLOG_INFO_LEVEL) {
|
||||||
for (int i = 0; i < cur_command->nargs; i++) {
|
std::string cmd_str;
|
||||||
strlcat(cmd_str, cur_command->args[i], sizeof(cmd_str));
|
for (int i = 0; i < cur_command->nargs; ++i) {
|
||||||
if (i < cur_command->nargs - 1) {
|
if (i > 0) {
|
||||||
strlcat(cmd_str, " ", sizeof(cmd_str));
|
cmd_str.push_back(' ');
|
||||||
}
|
}
|
||||||
|
cmd_str += cur_command->args[i];
|
||||||
}
|
}
|
||||||
char source[256];
|
std::string trigger_name = build_triggers_string(cur_action);
|
||||||
|
|
||||||
|
std::string source;
|
||||||
if (cur_command->filename) {
|
if (cur_command->filename) {
|
||||||
snprintf(source, sizeof(source), " (%s:%d)", cur_command->filename, cur_command->line);
|
source = android::base::StringPrintf(" (%s:%d)", cur_command->filename, cur_command->line);
|
||||||
} else {
|
|
||||||
*source = '\0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO("Command '%s' action=%s%s returned %d took %.2fs\n",
|
INFO("Command '%s' action=%s%s returned %d took %.2fs\n",
|
||||||
cmd_str, cur_action ? name_str : "", source, result, t.duration());
|
cmd_str.c_str(), trigger_name.c_str(), source.c_str(), result, t.duration());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ extern bool waiting_for_exec;
|
||||||
extern struct selabel_handle *sehandle;
|
extern struct selabel_handle *sehandle;
|
||||||
extern struct selabel_handle *sehandle_prop;
|
extern struct selabel_handle *sehandle_prop;
|
||||||
|
|
||||||
void build_triggers_string(char *name_str, int length, struct action *cur_action);
|
std::string build_triggers_string(struct action *cur_action);
|
||||||
|
|
||||||
void handle_control_message(const char *msg, const char *arg);
|
void handle_control_message(const char *msg, const char *arg);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,9 +95,8 @@ void dump_parser_state() {
|
||||||
list_for_each(node, &action_list) {
|
list_for_each(node, &action_list) {
|
||||||
action* act = node_to_item(node, struct action, alist);
|
action* act = node_to_item(node, struct action, alist);
|
||||||
INFO("on ");
|
INFO("on ");
|
||||||
char name_str[256] = "";
|
std::string trigger_name = build_triggers_string(act);
|
||||||
build_triggers_string(name_str, sizeof(name_str), act);
|
INFO("%s", trigger_name.c_str());
|
||||||
INFO("%s", name_str);
|
|
||||||
INFO("\n");
|
INFO("\n");
|
||||||
|
|
||||||
struct listnode* node2;
|
struct listnode* node2;
|
||||||
|
|
@ -216,27 +215,12 @@ static int lookup_keyword(const char *s)
|
||||||
static void parse_line_no_op(struct parse_state*, int, char**) {
|
static void parse_line_no_op(struct parse_state*, int, char**) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push_chars(char **dst, int *len, const char *chars, int cnt)
|
int expand_props(const char *src, std::string *dst) {
|
||||||
{
|
|
||||||
if (cnt > *len)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
memcpy(*dst, chars, cnt);
|
|
||||||
*dst += cnt;
|
|
||||||
*len -= cnt;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int expand_props(char *dst, const char *src, int dst_size)
|
|
||||||
{
|
|
||||||
char *dst_ptr = dst;
|
|
||||||
const char *src_ptr = src;
|
const char *src_ptr = src;
|
||||||
int ret = 0;
|
|
||||||
int left = dst_size - 1;
|
|
||||||
|
|
||||||
if (!src || !dst || dst_size == 0)
|
if (!src || !dst) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* - variables can either be $x.y or ${x.y}, in case they are only part
|
/* - variables can either be $x.y or ${x.y}, in case they are only part
|
||||||
* of the string.
|
* of the string.
|
||||||
|
|
@ -244,102 +228,75 @@ int expand_props(char *dst, const char *src, int dst_size)
|
||||||
* - no nested property expansion, i.e. ${foo.${bar}} is not supported,
|
* - no nested property expansion, i.e. ${foo.${bar}} is not supported,
|
||||||
* bad things will happen
|
* bad things will happen
|
||||||
*/
|
*/
|
||||||
while (*src_ptr && left > 0) {
|
while (*src_ptr) {
|
||||||
char *c;
|
const char *c;
|
||||||
char prop[PROP_NAME_MAX + 1];
|
|
||||||
int prop_len = 0;
|
|
||||||
|
|
||||||
c = strchr(src_ptr, '$');
|
c = strchr(src_ptr, '$');
|
||||||
if (!c) {
|
if (!c) {
|
||||||
while (left-- > 0 && *src_ptr)
|
dst->append(src_ptr);
|
||||||
*(dst_ptr++) = *(src_ptr++);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(prop, 0, sizeof(prop));
|
dst->append(src_ptr, c);
|
||||||
|
|
||||||
ret = push_chars(&dst_ptr, &left, src_ptr, c - src_ptr);
|
|
||||||
if (ret < 0)
|
|
||||||
goto err_nospace;
|
|
||||||
c++;
|
c++;
|
||||||
|
|
||||||
if (*c == '$') {
|
if (*c == '$') {
|
||||||
*(dst_ptr++) = *(c++);
|
dst->push_back(*(c++));
|
||||||
src_ptr = c;
|
src_ptr = c;
|
||||||
left--;
|
|
||||||
continue;
|
continue;
|
||||||
} else if (*c == '\0') {
|
} else if (*c == '\0') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string prop_name;
|
||||||
if (*c == '{') {
|
if (*c == '{') {
|
||||||
c++;
|
c++;
|
||||||
while (*c && *c != '}' && prop_len < PROP_NAME_MAX)
|
const char* end = strchr(c, '}');
|
||||||
prop[prop_len++] = *(c++);
|
if (!end) {
|
||||||
if (*c != '}') {
|
// failed to find closing brace, abort.
|
||||||
/* failed to find closing brace, abort. */
|
ERROR("unexpected end of string in '%s', looking for }\n", src);
|
||||||
if (prop_len == PROP_NAME_MAX)
|
|
||||||
ERROR("prop name too long during expansion of '%s'\n",
|
|
||||||
src);
|
|
||||||
else if (*c == '\0')
|
|
||||||
ERROR("unexpected end of string in '%s', looking for }\n",
|
|
||||||
src);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
prop[prop_len] = '\0';
|
prop_name = std::string(c, end);
|
||||||
c++;
|
c = end + 1;
|
||||||
} else if (*c) {
|
} else {
|
||||||
while (*c && prop_len < PROP_NAME_MAX)
|
prop_name = c;
|
||||||
prop[prop_len++] = *(c++);
|
|
||||||
if (prop_len == PROP_NAME_MAX && *c != '\0') {
|
|
||||||
ERROR("prop name too long in '%s'\n", src);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
prop[prop_len] = '\0';
|
|
||||||
ERROR("using deprecated syntax for specifying property '%s', use ${name} instead\n",
|
ERROR("using deprecated syntax for specifying property '%s', use ${name} instead\n",
|
||||||
prop);
|
c);
|
||||||
|
c += prop_name.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prop_len == 0) {
|
if (prop_name.empty()) {
|
||||||
ERROR("invalid zero-length prop name in '%s'\n", src);
|
ERROR("invalid zero-length prop name in '%s'\n", src);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string prop_val = property_get(prop);
|
std::string prop_val = property_get(prop_name.c_str());
|
||||||
if (prop_val.empty()) {
|
if (prop_val.empty()) {
|
||||||
ERROR("property '%s' doesn't exist while expanding '%s'\n",
|
ERROR("property '%s' doesn't exist while expanding '%s'\n",
|
||||||
prop, src);
|
prop_name.c_str(), src);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = push_chars(&dst_ptr, &left, prop_val.c_str(), prop_val.size());
|
dst->append(prop_val);
|
||||||
if (ret < 0)
|
|
||||||
goto err_nospace;
|
|
||||||
src_ptr = c;
|
src_ptr = c;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*dst_ptr = '\0';
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_nospace:
|
|
||||||
ERROR("destination buffer overflow while expanding '%s'\n", src);
|
|
||||||
err:
|
err:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_import(struct parse_state *state, int nargs, char **args)
|
static void parse_import(struct parse_state *state, int nargs, char **args)
|
||||||
{
|
{
|
||||||
struct listnode *import_list = (listnode*) state->priv;
|
|
||||||
char conf_file[PATH_MAX];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (nargs != 2) {
|
if (nargs != 2) {
|
||||||
ERROR("single argument needed for import\n");
|
ERROR("single argument needed for import\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = expand_props(conf_file, args[1], sizeof(conf_file));
|
std::string conf_file;
|
||||||
|
int ret = expand_props(args[1], &conf_file);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ERROR("error while handling import on line '%d' in '%s'\n",
|
ERROR("error while handling import on line '%d' in '%s'\n",
|
||||||
state->line, state->filename);
|
state->line, state->filename);
|
||||||
|
|
@ -347,7 +304,9 @@ static void parse_import(struct parse_state *state, int nargs, char **args)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct import* import = (struct import*) calloc(1, sizeof(struct import));
|
struct import* import = (struct import*) calloc(1, sizeof(struct import));
|
||||||
import->filename = strdup(conf_file);
|
import->filename = strdup(conf_file.c_str());
|
||||||
|
|
||||||
|
struct listnode *import_list = (listnode*) state->priv;
|
||||||
list_add_tail(import_list, &import->list);
|
list_add_tail(import_list, &import->list);
|
||||||
INFO("Added '%s' to import list\n", import->filename);
|
INFO("Added '%s' to import list\n", import->filename);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
#ifndef _INIT_INIT_PARSER_H_
|
#ifndef _INIT_INIT_PARSER_H_
|
||||||
#define _INIT_INIT_PARSER_H_
|
#define _INIT_INIT_PARSER_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#define INIT_PARSER_MAXARGS 64
|
#define INIT_PARSER_MAXARGS 64
|
||||||
|
|
||||||
struct action;
|
struct action;
|
||||||
|
|
@ -32,7 +34,7 @@ void queue_all_property_triggers();
|
||||||
void queue_builtin_action(int (*func)(int nargs, char **args), const char *name);
|
void queue_builtin_action(int (*func)(int nargs, char **args), const char *name);
|
||||||
|
|
||||||
bool init_parse_config_file(const char* path);
|
bool init_parse_config_file(const char* path);
|
||||||
int expand_props(char *dst, const char *src, int len);
|
int expand_props(const char *src, std::string *dst);
|
||||||
|
|
||||||
service* make_exec_oneshot_service(int argc, char** argv);
|
service* make_exec_oneshot_service(int argc, char** argv);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue