diff options
Diffstat (limited to 'usr.bin/osh/osh.c')
-rw-r--r-- | usr.bin/osh/osh.c | 107 |
1 files changed, 74 insertions, 33 deletions
diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c index af0ba3a..af7f4ab 100644 --- a/usr.bin/osh/osh.c +++ b/usr.bin/osh/osh.c @@ -30,6 +30,7 @@ #include <sys/types.h> #include <sys/cdefs.h> #include <sys/reboot.h> +#include <sys/errno.h> #include <sys/spawn.h> #include <sys/wait.h> #include <fcntl.h> @@ -39,7 +40,9 @@ #include <string.h> #include <stdio.h> +#define is_printable(C) ((C) >= 32 && (C) <= 126) #define is_ascii(C) ((C) >= 0 && (C) <= 128) + #define COMMENT '@' #define WELCOME \ ":::::::::::::::::::::::::::::::::::::::\n" \ @@ -64,7 +67,6 @@ #define PROMPT "[%s::osmora]~ " static char buf[64]; -static uint8_t buf_i; static int running; static int bell_fd; static bool bs_bell = true; /* Beep on backspace */ @@ -82,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}, @@ -144,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; @@ -153,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 == ' ') { @@ -169,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 */ } @@ -192,14 +212,18 @@ parse_args(char *input, char *argv[], int max_args) return argc; } -static char * +/* + * Grab a string from stdin and return + * the resulting offset within the input + * buffer we are at. + */ +static uint8_t getstr(void) { char c; int input; uint32_t beep_payload; - - buf_i = 0; + uint8_t buf_i = 0; /* * Prepare the beep payload @ 500 Hz @@ -222,7 +246,7 @@ getstr(void) if (c == '\n') { buf[buf_i] = '\0'; putchar('\n'); - return buf; + return buf_i; } /* handle backspaces and DEL */ @@ -233,7 +257,7 @@ getstr(void) } else if (bell_fd > 0 && bs_bell) { write(bell_fd, &beep_payload, sizeof(beep_payload)); } - } else if (is_ascii(c) && buf_i < sizeof(buf) - 1) { + } else if (is_printable(c) && buf_i < sizeof(buf) - 1) { /* write to fd and add to buffer */ buf[buf_i++] = c; putchar(c); @@ -327,13 +351,46 @@ script_skip_comment(int fd) } } +/* + * Parse a single line typed in from the + * user. + * + * @input: Input line + */ +static int +parse_line(char *input) +{ + int argc; + char *argv[16]; + struct parse_state state = {0}; + pid_t child; + + /* Ensure the aux vector is zeored */ + memset(argv, 0, sizeof(argv)); + + /* + * Grab args from the user, there should be + * at least one. + */ + argc = parse_args(input, argv, sizeof(argv), &state); + if (argc == 0) { + return -EAGAIN; + } + + child = command_match(input, argc, argv); + if (child > 0 && !state.bg) { + waitpid(child, NULL, 0); + } + + return 0; +} + static int open_script(const char *pathname) { int fd, argc, buf_i = 0; - char c, *input, *argv[16]; + char c, *input; char buf[256]; - pid_t child; fd = open(pathname, O_RDONLY); if (fd < 0) { @@ -359,15 +416,7 @@ open_script(const char *pathname) if (c == '\n') { buf[buf_i] = '\0'; - argc = parse_args(buf, argv, sizeof(argv)); - - child = command_match(buf, argc, argv); - if (child > 0) { - waitpid(child, NULL, 0); - } - - argv[0] = NULL; - argv[1] = NULL; + parse_line(buf); buf_i = 0; continue; } @@ -382,7 +431,8 @@ main(int argc, char **argv) { int found, prog_argc; int stdout_fd; - char *input, *prog_argv[16], *p; + uint8_t buf_i; + char *p; char c; pid_t child; @@ -390,32 +440,23 @@ main(int argc, char **argv) return open_script(argv[1]); } - buf_i = 0; running = 1; - found = 0; bell_fd = open("/dev/beep", O_WRONLY); - puts(WELCOME); + while (running) { - memset(prog_argv, 0, sizeof(prog_argv)); printf(PROMPT, getlogin()); - input = getstr(); - if (input[0] == '\0') { + buf_i = getstr(); + if (buf[0] == '\0') { continue; } - prog_argc = parse_args(input, prog_argv, sizeof(prog_argv)); - if (prog_argc == 0) { + buf[buf_i] = '\0'; + if (parse_line(buf) < 0) { continue; } - child = command_match(input, prog_argc, prog_argv); - if (child > 0) { - waitpid(child, NULL, 0); - } - - found = 0; buf[0] = '\0'; } return 0; |