106 lines
1.8 KiB
C
106 lines
1.8 KiB
C
#include <ctype.h> /* isspace(3) */
|
|
#include <stddef.h> /* NULL */
|
|
#include <stdio.h> /* getc(3) */
|
|
#include <stdlib.h> /* getenv(3), rand(3), srand(3) */
|
|
#include <string.h> /* strcmp(3) */
|
|
#include <sys/wait.h> /* wait(2) */
|
|
#include <time.h> /* time(3) */
|
|
#include <unistd.h> /* 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;
|
|
}
|