From c4da1b15cfde65a1d1173d3ae256bb54369fa4e4 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sat, 19 Jul 2025 15:22:06 -0400 Subject: usr: osh: Introduce '&' for background tasks Previously, when running programs from the shell. The execution must finish before anything else can be done. This commit allows users to add an ampersand ('&') after the command in order to run it in the background. This is an example of its usage: -- @ beep at 400 Hz for 9000ms (to annoy people for fun). @ We will be running it in the background and do a 'kstat' @ to see that the number of tasks have increased. beep 400 9000 & kstat .. -- Signed-off-by: Ian Moffett --- usr.bin/osh/osh.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) (limited to 'usr.bin/osh') diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c index fcb19aa..af7f4ab 100644 --- a/usr.bin/osh/osh.c +++ b/usr.bin/osh/osh.c @@ -84,6 +84,15 @@ struct builtin_cmd { void (*func)(int argc, char *argv[]); }; +/* + * Results after parsing a command + * + * @bg: Run command in background + */ +struct parse_state { + uint8_t bg : 1; +}; + static struct builtin_cmd cmds[] = { {"help",cmd_help}, {"exit",cmd_exit}, @@ -146,7 +155,7 @@ cmd_bell(int argc, char *argv[]) } static int -parse_args(char *input, char *argv[], int max_args) +parse_args(char *input, char *argv[], int max_args, struct parse_state *p) { int argc = 0; @@ -155,6 +164,10 @@ parse_args(char *input, char *argv[], int max_args) return 0; } + /* setup default state */ + p->bg = 0; + + /* parse loop */ while (*input != '\0') { /* skip leading spaces */ while (*input == ' ') { @@ -171,6 +184,11 @@ parse_args(char *input, char *argv[], int max_args) break; } + /* run in background? */ + if (*input == '&') { + p->bg = 1; + } + if (argc < max_args) { argv[argc++] = input; /* mark start of the argument */ } @@ -344,6 +362,7 @@ parse_line(char *input) { int argc; char *argv[16]; + struct parse_state state = {0}; pid_t child; /* Ensure the aux vector is zeored */ @@ -353,13 +372,13 @@ parse_line(char *input) * Grab args from the user, there should be * at least one. */ - argc = parse_args(input, argv, sizeof(argv)); + argc = parse_args(input, argv, sizeof(argv), &state); if (argc == 0) { return -EAGAIN; } child = command_match(input, argc, argv); - if (child > 0) { + if (child > 0 && !state.bg) { waitpid(child, NULL, 0); } -- cgit v1.2.3