CE implement running commands in background
This commit is contained in:
42
ce/interp.c
42
ce/interp.c
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
17
ce/parser.c
17
ce/parser.c
@@ -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);
|
||||
|
||||
10
ce/parser.h
10
ce/parser.h
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user