#include /* isspace(3) */ #include /* NULL */ #include /* getc(3) */ #include /* getenv(3), rand(3), srand(3) */ #include /* strcmp(3) */ #include /* wait(2) */ #include /* time(3) */ #include /* fork(2), write(2) */ #include "libio.h" #include "usefulmacros.h" #include "nutshell.h" #include "nutshell_builtins.c" static int parse_argv(char *buffer, char **argv, int argc_max){ int i; int j; int s; for(i = 0, j = 0, s = 1; buffer[i] != '\0' && j < argc_max; ++i){ while(isspace(buffer[i])){ s = 1; buffer[i++] = '\0'; } if(s) argv[j++] = buffer + i; } return j; } static char * read_buffer(char *buf, size_t buf_s){ int i; for(i = 0; ; ++i){ /* ..., '\0', buf_s */ /* This isn't perfect but is simple and doesn't matter for * longer buffers that much. */ if(i == buf_s - 1 - 1){ buf[i] = '\0'; break; } buf[i] = getc(stdin); if(buf[i] == EOF) return NULL; else if(buf[i] == '\n'){ buf[i + 1] = '\0'; break; } } return buf; } static int run(char *buf){ int argc; static char *argv[ARGV_MAX]; int i; /* get argv and argc */ for(i = 0; i < ARRAYLEN(argv); ++i){ if(argv[i] == NULL) break; argv[i] = NULL; } argc = parse_argv(buf, argv, ARRAYLEN(argv)); /* builtins get priority */ if((i = isbuiltin(argv[0])) != 0) return builtins[i - 1].f(argc, argv); if(state.jailed) goto runerr; runerr: /* This is what busybox ash(1) does. */ return 127; } int main(int argc, char *argv[]){ static char buf[BUF_MAX]; static char prompt[] = DEFAULT_PROMPT; builtin_init(0, empty_argv); for(;;){ write(1, prompt, ARRAYLEN(prompt)); if(read_buffer(buf, ARRAYLEN(buf)) == NULL){ write(1, "EOF\n", 4); state.status = 0; break; } state.status = run(buf); } return state.status; }