runtime: cmdcall: implement resolution of native commands
This commit is contained in:
@@ -77,11 +77,119 @@ static const fx_value *get_arg(struct bshell_cmdcall_p *cmdcall, size_t index)
|
|||||||
return &cmdcall->cmd_args.items[cmdcall->cmd_args.count - index - 1];
|
return &cmdcall->cmd_args.items[cmdcall->cmd_args.count - index - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bshell_command *__resolve_call_target(
|
static bshell_command *resolve_cmdlet(
|
||||||
const char *callable_name,
|
struct bshell_cmdcall_p *cmdcall,
|
||||||
struct bshell_runtime *rt)
|
struct bshell_runtime *rt,
|
||||||
|
fx_string *cmd_name)
|
||||||
{
|
{
|
||||||
return bshell_runtime_find_command(rt, callable_name);
|
while (1) {
|
||||||
|
const char *cmd_name_cstr = fx_string_get_cstr(cmd_name);
|
||||||
|
bshell_command *cmd
|
||||||
|
= bshell_runtime_find_command(rt, cmd_name_cstr);
|
||||||
|
if (!cmd) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bshell_alias_class *alias
|
||||||
|
= fx_object_get_interface(cmd, BSHELL_TYPE_ALIAS);
|
||||||
|
if (alias) {
|
||||||
|
fx_string_clear(cmd_name);
|
||||||
|
fx_string_append_cstr(cmd_name, alias->a_target_name);
|
||||||
|
bshell_command_unref(cmd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const fx_string *get_path(void)
|
||||||
|
{
|
||||||
|
fx_process *self = fx_process_get_self();
|
||||||
|
if (!self) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fx_hashtable *env = fx_process_get_environment(self);
|
||||||
|
if (!env) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fx_value *path_v = fx_hashtable_get(env, &FX_CSTR("PATH"));
|
||||||
|
if (!path_v) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fx_string *path = NULL;
|
||||||
|
fx_value_get_object(path_v, (fx_object **)&path);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bshell_command *resolve_native_command_local(
|
||||||
|
struct bshell_cmdcall_p *cmdcall,
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
fx_string *cmd_name)
|
||||||
|
{
|
||||||
|
const char *cmd_name_cstr = fx_string_get_cstr(cmd_name);
|
||||||
|
fx_path *cmd_path = fx_path_create_from_cstr(cmd_name_cstr);
|
||||||
|
if (!fx_path_is_file(cmd_path)) {
|
||||||
|
fx_path_unref(cmd_path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bshell_command *result
|
||||||
|
= bshell_native_command_create(fx_path_ptr(cmd_path));
|
||||||
|
fx_path_unref(cmd_path);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bshell_command *resolve_native_command(
|
||||||
|
struct bshell_cmdcall_p *cmdcall,
|
||||||
|
struct bshell_runtime *rt,
|
||||||
|
fx_string *cmd_name)
|
||||||
|
{
|
||||||
|
const char *cmd_name_cstr = fx_string_get_cstr(cmd_name);
|
||||||
|
if (cmd_name_cstr[0] == '/'
|
||||||
|
|| (cmd_name_cstr[0] == '.' && cmd_name_cstr[1] == '/')
|
||||||
|
|| (cmd_name_cstr[0] == '.' && cmd_name_cstr[1] == '.'
|
||||||
|
&& cmd_name_cstr[2] == '/')) {
|
||||||
|
return resolve_native_command_local(cmdcall, rt, cmd_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_path *cmd_name_path = fx_path_create_from_cstr(cmd_name_cstr);
|
||||||
|
const char *delim[] = {":"};
|
||||||
|
const fx_string *path = get_path();
|
||||||
|
const fx_iterator *it = fx_string_tokenise(
|
||||||
|
path,
|
||||||
|
delim,
|
||||||
|
sizeof delim / sizeof delim[0],
|
||||||
|
FX_STRING_TOK_F_NORMAL);
|
||||||
|
bshell_command *result = NULL;
|
||||||
|
|
||||||
|
fx_foreach(v, it)
|
||||||
|
{
|
||||||
|
const char *tok = NULL;
|
||||||
|
fx_value_get_cstr(v, &tok);
|
||||||
|
|
||||||
|
fx_path *dir_path = fx_path_create_from_cstr(tok);
|
||||||
|
const fx_path *parts[] = {dir_path, cmd_name_path};
|
||||||
|
fx_path *full_path
|
||||||
|
= fx_path_join(parts, sizeof parts / sizeof parts[0]);
|
||||||
|
fx_path_unref(dir_path);
|
||||||
|
if (!fx_path_is_file(full_path)) {
|
||||||
|
fx_path_unref(full_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = bshell_native_command_create(fx_path_ptr(full_path));
|
||||||
|
fx_path_unref(full_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fx_iterator_unref(it);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum bshell_status resolve_call_target(
|
static enum bshell_status resolve_call_target(
|
||||||
@@ -100,28 +208,17 @@ static enum bshell_status resolve_call_target(
|
|||||||
fx_string *cmd_name_s = NULL;
|
fx_string *cmd_name_s = NULL;
|
||||||
fx_value_get_object(cmd_name_v, &cmd_name_s);
|
fx_value_get_object(cmd_name_v, &cmd_name_s);
|
||||||
|
|
||||||
while (1) {
|
if ((cmdcall->cmd_target = resolve_cmdlet(cmdcall, rt, cmd_name_s))) {
|
||||||
const char *cmd_name_cstr = fx_string_get_cstr(cmd_name_s);
|
|
||||||
bshell_command *cmd
|
|
||||||
= bshell_runtime_find_command(rt, cmd_name_cstr);
|
|
||||||
if (!cmd) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bshell_alias_class *alias
|
|
||||||
= fx_object_get_interface(cmd, BSHELL_TYPE_ALIAS);
|
|
||||||
if (alias) {
|
|
||||||
fx_string_clear(cmd_name_s);
|
|
||||||
fx_string_append_cstr(cmd_name_s, alias->a_target_name);
|
|
||||||
bshell_command_unref(cmd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdcall->cmd_target = cmd;
|
|
||||||
cmdcall->cmd_type = CMDCALL_CMDLET;
|
cmdcall->cmd_type = CMDCALL_CMDLET;
|
||||||
return BSHELL_SUCCESS;
|
return BSHELL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cmdcall->cmd_target
|
||||||
|
= resolve_native_command(cmdcall, rt, cmd_name_s))) {
|
||||||
|
cmdcall->cmd_type = CMDCALL_NATIVE;
|
||||||
|
return BSHELL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
const char *cmd_name_cstr = fx_string_get_cstr(cmd_name_s);
|
const char *cmd_name_cstr = fx_string_get_cstr(cmd_name_s);
|
||||||
#if BSHELL_INTERACTIVE == 1
|
#if BSHELL_INTERACTIVE == 1
|
||||||
fx_printf("[bold,bright_red]");
|
fx_printf("[bold,bright_red]");
|
||||||
|
|||||||
Reference in New Issue
Block a user