移除内建命令

This commit is contained in:
2026-04-18 17:47:44 +08:00
parent 1678af87b8
commit 97a65b3580
15 changed files with 613 additions and 8 deletions

View File

@@ -7,7 +7,7 @@ static int ush_cmd_cat(const ush_state *sh, const char *arg) {
u64 fd;
if (arg == (const char *)0 || arg[0] == '\0') {
if (ush_pipeline_stdin_text != (const char *)0 && ush_pipeline_stdin_len > 0ULL) {
if (ush_pipeline_stdin_text != (const char *)0) {
(void)fputs(ush_pipeline_stdin_text, 1);
return 1;
}

View File

@@ -2,6 +2,87 @@
const char *ush_pipeline_stdin_text = (const char *)0;
u64 ush_pipeline_stdin_len = 0ULL;
static char ush_pipeline_stdin_buf[USH_COPY_MAX + 1U];
static int ush_cmd_runtime_has_prefix(const char *text, const char *prefix) {
u64 i = 0ULL;
if (text == (const char *)0 || prefix == (const char *)0) {
return 0;
}
while (prefix[i] != '\0') {
if (text[i] != prefix[i]) {
return 0;
}
i++;
}
return 1;
}
static int ush_cmd_runtime_stdin_pipe_enabled(char **envp) {
u64 i = 0ULL;
if (envp == (char **)0) {
return 0;
}
while (envp[i] != (char *)0) {
const char *entry = envp[i];
if (ush_cmd_runtime_has_prefix(entry, "USH_STDIN_MODE=PIPE") != 0) {
return 1;
}
i++;
}
return 0;
}
static void ush_cmd_runtime_capture_stdin_pipe(void) {
u64 total = 0ULL;
int truncated = 0;
char drain[256];
for (;;) {
u64 got;
if (total < (u64)USH_COPY_MAX) {
got = cleonos_sys_fd_read(0ULL, ush_pipeline_stdin_buf + total, (u64)USH_COPY_MAX - total);
} else {
got = cleonos_sys_fd_read(0ULL, drain, (u64)sizeof(drain));
truncated = 1;
}
if (got == (u64)-1 || got == 0ULL) {
break;
}
if (total < (u64)USH_COPY_MAX) {
total += got;
}
}
ush_pipeline_stdin_buf[total] = '\0';
ush_pipeline_stdin_text = ush_pipeline_stdin_buf;
ush_pipeline_stdin_len = total;
if (truncated != 0) {
ush_writeln("[pipe] input truncated");
}
}
void cleonos_cmd_runtime_pre_main(char **envp) {
ush_pipeline_stdin_text = (const char *)0;
ush_pipeline_stdin_len = 0ULL;
ush_pipeline_stdin_buf[0] = '\0';
if (ush_cmd_runtime_stdin_pipe_enabled(envp) != 0) {
ush_cmd_runtime_capture_stdin_pipe();
}
}
void ush_zero(void *ptr, u64 size) {
if (ptr == (void *)0 || size == 0ULL) {

View File

@@ -2438,6 +2438,23 @@ static int ush_cmd_not_supported(const char *name, const char *why) {
return 0;
}
static volatile int ush_builtin_fallback_enabled = 0;
static int ush_builtin_fallback_is_enabled(void) {
return ush_builtin_fallback_enabled;
}
static void ush_report_external_not_found(const char *cmd) {
ush_write("command not found (external ELF required): ");
if (cmd == (const char *)0 || cmd[0] == '\0') {
ush_writeln("(empty)");
return;
}
ush_writeln(cmd);
}
static int ush_execute_single_command(ush_state *sh,
const char *cmd,
const char *arg,
@@ -2462,13 +2479,31 @@ static int ush_execute_single_command(ush_state *sh,
return 0;
}
if (allow_external != 0 && ush_try_exec_external(sh, cmd, arg, &success) != 0) {
(void)allow_external;
if (ush_try_exec_external(sh, cmd, arg, &success) != 0) {
if (out_success != (int *)0) {
*out_success = success;
}
return 1;
}
if (ush_builtin_fallback_is_enabled() == 0) {
known = 0;
success = 0;
ush_report_external_not_found(cmd);
if (out_known != (int *)0) {
*out_known = known;
}
if (out_success != (int *)0) {
*out_success = success;
}
return 1;
}
if (ush_streq(cmd, "help") != 0) {
success = ush_cmd_help();
} else if (ush_streq(cmd, "ls") != 0 || ush_streq(cmd, "dir") != 0) {
@@ -2743,6 +2778,23 @@ static int ush_pipeline_open_write_fd(const char *path, u64 flags, u64 *out_fd)
return 1;
}
static int ush_pipeline_open_read_fd(const char *path, u64 *out_fd) {
u64 fd;
if (path == (const char *)0 || out_fd == (u64 *)0) {
return 0;
}
fd = cleonos_sys_fd_open(path, CLEONOS_O_RDONLY, 0ULL);
if (fd == (u64)-1) {
return 0;
}
*out_fd = fd;
return 1;
}
static int ush_pipeline_read_path_into_buffer(const char *path, char *buffer, u64 buffer_size, u64 *out_len) {
u64 fd;
u64 total = 0ULL;
@@ -2864,6 +2916,114 @@ static int ush_execute_pipeline(ush_state *sh,
return 0;
}
if (ush_builtin_fallback_is_enabled() == 0) {
const char *pipe_input_path_external = (const char *)0;
int pipe_output_toggle_external = 0;
for (i = 0ULL; i < stage_count; i++) {
int stage_known = 1;
int stage_success = 0;
u64 stage_stdin_fd = CLEONOS_FD_INHERIT;
u64 stage_stdout_fd = CLEONOS_FD_INHERIT;
u64 opened_in_fd = (u64)-1;
u64 opened_out_fd = (u64)-1;
const char *stage_pipe_out = (const char *)0;
if (i + 1ULL < stage_count && stages[i].redirect_mode != 0) {
ush_writeln("pipe: redirection is only supported on final stage");
known = 1;
success = 0;
break;
}
if (pipe_input_path_external != (const char *)0) {
if (ush_pipeline_open_read_fd(pipe_input_path_external, &opened_in_fd) == 0) {
ush_writeln("pipe: failed to open stage input");
success = 0;
break;
}
stage_stdin_fd = opened_in_fd;
}
if (i + 1ULL < stage_count) {
stage_pipe_out = (pipe_output_toggle_external == 0) ? USH_PIPE_TMP_A : USH_PIPE_TMP_B;
if (ush_pipeline_open_write_fd(stage_pipe_out,
CLEONOS_O_WRONLY | CLEONOS_O_CREAT | CLEONOS_O_TRUNC,
&opened_out_fd) == 0) {
ush_writeln("pipe: failed to open temp stream");
if (opened_in_fd != (u64)-1) {
(void)cleonos_sys_fd_close(opened_in_fd);
}
success = 0;
break;
}
stage_stdout_fd = opened_out_fd;
} else if (stages[i].redirect_mode != 0) {
if (ush_pipeline_open_redirect_fd(sh, &stages[i], &opened_out_fd) == 0) {
if (opened_in_fd != (u64)-1) {
(void)cleonos_sys_fd_close(opened_in_fd);
}
success = 0;
break;
}
stage_stdout_fd = opened_out_fd;
}
stage_known = ush_try_exec_external_with_fds(sh,
stages[i].cmd,
stages[i].arg,
stage_stdin_fd,
stage_stdout_fd,
CLEONOS_FD_INHERIT,
&stage_success);
if (opened_in_fd != (u64)-1) {
(void)cleonos_sys_fd_close(opened_in_fd);
}
if (opened_out_fd != (u64)-1) {
(void)cleonos_sys_fd_close(opened_out_fd);
}
if (stage_known == 0) {
known = 0;
success = 0;
ush_report_external_not_found(stages[i].cmd);
break;
}
if (stage_success == 0) {
success = 0;
break;
}
if (i + 1ULL < stage_count) {
pipe_input_path_external = stage_pipe_out;
pipe_output_toggle_external = (pipe_output_toggle_external == 0) ? 1 : 0;
}
}
(void)cleonos_sys_fs_remove(USH_PIPE_TMP_A);
(void)cleonos_sys_fs_remove(USH_PIPE_TMP_B);
if (out_known != (int *)0) {
*out_known = known;
}
if (out_success != (int *)0) {
*out_success = success;
}
return 1;
}
for (i = 0ULL; i < stage_count; i++) {
int stage_known = 1;
int stage_success = 0;

View File

@@ -137,10 +137,16 @@ int ush_command_ret_read(ush_cmd_ret *out_ret) {
return (got == (u64)sizeof(*out_ret)) ? 1 : 0;
}
int ush_try_exec_external(ush_state *sh, const char *cmd, const char *arg, int *out_success) {
int ush_try_exec_external_with_fds(ush_state *sh,
const char *cmd,
const char *arg,
u64 stdin_fd,
u64 stdout_fd,
u64 stderr_fd,
int *out_success) {
const char *canonical;
char path[USH_PATH_MAX];
char env_line[USH_PATH_MAX + USH_CMD_MAX + 32ULL];
char env_line[USH_PATH_MAX + USH_CMD_MAX + 96ULL];
u64 status;
ush_cmd_ret ret;
@@ -179,7 +185,11 @@ int ush_try_exec_external(ush_state *sh, const char *cmd, const char *arg, int *
ush_append_text(env_line, (u64)sizeof(env_line), ";CMD=");
ush_append_text(env_line, (u64)sizeof(env_line), canonical);
status = cleonos_sys_exec_pathv(path, arg, env_line);
if (stdin_fd != CLEONOS_FD_INHERIT) {
ush_append_text(env_line, (u64)sizeof(env_line), ";USH_STDIN_MODE=PIPE");
}
status = cleonos_sys_exec_pathv_io(path, arg, env_line, stdin_fd, stdout_fd, stderr_fd);
if (status == (u64)-1) {
ush_writeln("exec: request failed");
@@ -218,3 +228,13 @@ int ush_try_exec_external(ush_state *sh, const char *cmd, const char *arg, int *
return 1;
}
int ush_try_exec_external(ush_state *sh, const char *cmd, const char *arg, int *out_success) {
return ush_try_exec_external_with_fds(sh,
cmd,
arg,
CLEONOS_FD_INHERIT,
CLEONOS_FD_INHERIT,
CLEONOS_FD_INHERIT,
out_success);
}

View File

@@ -112,6 +112,13 @@ void ush_command_ret_reset(void);
int ush_command_ret_write(const ush_cmd_ret *ret);
int ush_command_ret_read(ush_cmd_ret *out_ret);
int ush_try_exec_external(ush_state *sh, const char *cmd, const char *arg, int *out_success);
int ush_try_exec_external_with_fds(ush_state *sh,
const char *cmd,
const char *arg,
u64 stdin_fd,
u64 stdout_fd,
u64 stderr_fd,
int *out_success);
#endif