CE implement running commands in background
All checks were successful
Build ISO image / build-and-deploy (push) Successful in 3m15s
Build documentation / build-and-deploy (push) Successful in 2m53s

This commit is contained in:
2026-03-29 19:55:24 +02:00
parent 482afb47d7
commit dc556d1524
4 changed files with 52 additions and 19 deletions

View File

@@ -370,7 +370,7 @@ static void cmd_write_proc (void* arg) {
}
}
static void execute_cmd (struct ast_cmd* cmd, struct context* context) {
static void execute_cmd (struct ast_cmd* cmd, struct context* context, bool run_bg) {
if (strcmp (cmd->name, "echo") == 0) {
echo (context, cmd->args, cmd->arg_count);
} else if (strcmp (cmd->name, "help") == 0) {
@@ -444,18 +444,25 @@ static void execute_cmd (struct ast_cmd* cmd, struct context* context) {
i++;
}
struct cmd_write_proc_ctx wpctx = {.pgid = pgid, .cancel_pid = pid};
if (run_bg) {
exec_partial_fini (pid);
struct process_data* write_pdata = process_spawn (&cmd_write_proc, (void*)&wpctx);
struct process_data* collect_pdata = process_spawn (&cmd_collect_proc, (void*)(uintptr_t)pgid);
cprintf (context, "started background process: PID %d\n", pid);
} else {
struct cmd_write_proc_ctx wpctx = {.pgid = pgid, .cancel_pid = pid};
exec_partial_fini (pid);
wait_for_pid (pid);
struct process_data* write_pdata = process_spawn (&cmd_write_proc, (void*)&wpctx);
struct process_data* collect_pdata =
process_spawn (&cmd_collect_proc, (void*)(uintptr_t)pgid);
kill (write_pdata->pid);
process_data_free (write_pdata);
kill (collect_pdata->pid);
process_data_free (collect_pdata);
exec_partial_fini (pid);
wait_for_pid (pid);
kill (write_pdata->pid);
process_data_free (write_pdata);
kill (collect_pdata->pid);
process_data_free (collect_pdata);
}
}
}
@@ -507,24 +514,27 @@ static void execute_redir (struct ast_redir* redir, struct context* context) {
filewriter_fini (&fw);
}
void execute (struct ast_node* root, struct context* context) {
void execute (struct ast_node* root, struct context* context, bool run_bg) {
struct context subcontext;
memset (&subcontext, 0, sizeof (subcontext));
switch (root->class) {
case AST_NODE_CLASS_CMD:
execute_cmd (&root->u.cmd, context);
execute_cmd (&root->u.cmd, context, run_bg);
break;
case AST_NODE_CLASS_SUBSHELL:
execute (root->u.subshell.inner, &subcontext);
execute (root->u.subshell.inner, &subcontext, run_bg);
break;
case AST_NODE_CLASS_SEQ:
execute (root->u.seq.left, context);
execute (root->u.seq.right, context);
execute (root->u.seq.left, context, run_bg);
execute (root->u.seq.right, context, run_bg);
break;
case AST_NODE_CLASS_REDIR:
execute (root->u.redir.source, &subcontext);
execute (root->u.redir.source, &subcontext, run_bg);
execute_redir (&root->u.redir, &subcontext);
break;
case AST_NODE_CLASS_RUN_BG:
execute (root->u.run_bg.expr, context, true);
break;
}
}

View File

@@ -5,7 +5,7 @@
#include "parser.h"
#include <stdbool.h>
void execute (struct ast_node* root, struct context* context);
void execute (struct ast_node* root, struct context* context, bool run_bg);
bool interp_is_running (void);

View File

@@ -13,6 +13,7 @@ static struct parse_rule parse_rules[] = {
[TOKEN_CLASS_CPAREN] = {NULL, NULL, PREC_NONE},
[TOKEN_CLASS_SEMICOLON] = {NULL, &semicolon_led, PREC_SEQ},
[TOKEN_CLASS_REDIR] = {NULL, &redir_led, PREC_REDIR},
[TOKEN_CLASS_AMPERSAND] = {NULL, &run_bg_led, PREC_RUN_BG},
};
static struct token* get_token (struct list_node_link* link) {
@@ -114,6 +115,16 @@ struct ast_node* redir_led (struct parser* parser, struct token* token, struct a
return node;
}
struct ast_node* run_bg_led (struct parser* parser, struct token* token, struct ast_node* left) {
(void)token;
struct ast_node* node = arena_malloc (&arena, sizeof (*node));
node->class = AST_NODE_CLASS_RUN_BG;
node->u.run_bg.expr = left;
return node;
}
void tokenize (struct list_node_link** tokens, const char* text) {
const char* p = text;
@@ -123,7 +134,7 @@ void tokenize (struct list_node_link** tokens, const char* text) {
continue;
}
if (*p == '(' || *p == ')' || *p == ';' || *p == '>') {
if (*p == '(' || *p == ')' || *p == ';' || *p == '>' || *p == '&') {
struct token* token = arena_malloc (&arena, sizeof (*token));
memset (token, 0, sizeof (*token));
@@ -136,6 +147,8 @@ void tokenize (struct list_node_link** tokens, const char* text) {
token->class = TOKEN_CLASS_SEMICOLON;
else if (*p == '>')
token->class = TOKEN_CLASS_REDIR;
else if (*p == '&')
token->class = TOKEN_CLASS_AMPERSAND;
list_append (*tokens, &token->tokens_link);
p++;
@@ -174,7 +187,7 @@ void parse_and_execute (struct list_node_link* tokens) {
if (root != NULL) {
struct context context;
memset (&context, 0, sizeof (context));
execute (root, &context);
execute (root, &context, false);
if (context.strbuf.items != NULL)
mprintf ("%.*s", (int)context.strbuf.count, context.strbuf.items);

View File

@@ -11,6 +11,7 @@
#define TOKEN_CLASS_WORD 2
#define TOKEN_CLASS_SEMICOLON 3
#define TOKEN_CLASS_REDIR 4
#define TOKEN_CLASS_AMPERSAND 5
struct token {
struct list_node_link tokens_link;
@@ -22,11 +23,13 @@ struct token {
#define PREC_LOWEST 1
#define PREC_SEQ 2
#define PREC_REDIR 3
#define PREC_RUN_BG 4
#define AST_NODE_CLASS_CMD 0
#define AST_NODE_CLASS_SUBSHELL 1
#define AST_NODE_CLASS_SEQ 2
#define AST_NODE_CLASS_REDIR 3
#define AST_NODE_CLASS_RUN_BG 4
struct ast_node;
@@ -50,6 +53,10 @@ struct ast_redir {
char* file_path;
};
struct ast_run_bg {
struct ast_node* expr;
};
struct ast_node {
int class;
union {
@@ -57,6 +64,7 @@ struct ast_node {
struct ast_subshell subshell;
struct ast_seq seq;
struct ast_redir redir;
struct ast_run_bg run_bg;
} u;
};
@@ -85,6 +93,8 @@ struct ast_node* semicolon_led (struct parser* parser, struct token* token, stru
struct ast_node* redir_led (struct parser* parser, struct token* token, struct ast_node* left);
struct ast_node* run_bg_led (struct parser* parser, struct token* token, struct ast_node* left);
void tokenize (struct list_node_link** tokens, const char* text);
void parse_and_execute (struct list_node_link* tokens);