fix nutshell warnings
This commit is contained in:
parent
feb781afc1
commit
3a65d3d91f
3
Makefile
3
Makefile
@ -76,6 +76,9 @@ lowercase: sysexits src/lowercase.c
|
||||
nonzero: src/nonzero.c
|
||||
$(CC) $(CFLAGS) -o bin/nonzero src/nonzero.c
|
||||
|
||||
nutshell: src/nutshell.c src/nutshell.h src/nutshell_builtins.c
|
||||
$(CC) $(CFLAGS) -o bin/nutshell src/nutshell.c
|
||||
|
||||
runlength: noargvzero sysexits src/runlength.c
|
||||
$(CC) $(CFLAGS) -o bin/runlength src/runlength.c
|
||||
|
||||
|
115
src/nutshell.c
Normal file
115
src/nutshell.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "nutshell.h"
|
||||
#include "nutshell_builtins.c"
|
||||
|
||||
int
|
||||
fdputd(int fd, int d){
|
||||
if(d < 0){
|
||||
putc('-', stdout);
|
||||
d *= -1;
|
||||
}
|
||||
return printf("%d\n", d);
|
||||
}
|
||||
|
||||
/* Probably not buggy. */
|
||||
int
|
||||
fdputs(int fd, char *s){
|
||||
int r;
|
||||
|
||||
r = write(1, s, strlen(s));
|
||||
r += write(1, "\n", 1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
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 */
|
||||
for(i = 0; i < ARRAYLEN(builtins); ++i)
|
||||
if(strcmp(builtins[i].name, argv[0]) == 0)
|
||||
return builtins[i].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];
|
||||
|
||||
srand(time(NULL));
|
||||
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;
|
||||
}
|
49
src/nutshell.h
Normal file
49
src/nutshell.h
Normal file
@ -0,0 +1,49 @@
|
||||
#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)
|
||||
strlen(3)
|
||||
*/
|
||||
#include <sys/wait.h> /*
|
||||
wait(2)
|
||||
*/
|
||||
#include <time.h> /*
|
||||
time(3)
|
||||
*/
|
||||
#include <unistd.h> /*
|
||||
fork(2)
|
||||
write(2)
|
||||
*/
|
||||
|
||||
#define ARRAYLEN(a) sizeof(a) / sizeof(*(a))
|
||||
|
||||
/* conservative defaults */
|
||||
#define ARGV_MAX 10
|
||||
#define BUF_MAX 100
|
||||
|
||||
char *empty_argv[1] = { NULL };
|
||||
char *nethack_name = "nethack";
|
||||
char prompt[] = "^_^?: ";
|
||||
|
||||
struct {
|
||||
int jailed;
|
||||
int status;
|
||||
}state = {
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
int fdputd(int fd, int d);
|
||||
int fdputs(int fd, char *s);
|
72
src/nutshell_builtins.c
Normal file
72
src/nutshell_builtins.c
Normal file
@ -0,0 +1,72 @@
|
||||
int builtin_escape (int, char **);
|
||||
int builtin_init (int, char **);
|
||||
int builtin_jail (int, char **);
|
||||
int builtin_nethack (int, char **);
|
||||
int builtin_reassure (int, char **);
|
||||
int builtin_status (int, char **);
|
||||
|
||||
struct {
|
||||
char *name;
|
||||
int (*f)(int, char **);
|
||||
}builtins[] = {
|
||||
{"escape", builtin_escape},
|
||||
{"init", builtin_init},
|
||||
{"jail", builtin_jail},
|
||||
{"nethack", builtin_nethack},
|
||||
{"status", builtin_status}
|
||||
};
|
||||
|
||||
int
|
||||
builtin_escape(int argc, char **argv){
|
||||
char *s;
|
||||
|
||||
if((s = getenv("SHELL")) == NULL){
|
||||
fdputs(1, "$SHELL seems to be empty. This is an OS error.\n");
|
||||
}else if(fork() == 0)
|
||||
execl(s, s, NULL);
|
||||
else
|
||||
wait(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_init(int argc, char **argv){
|
||||
fdputs(1,"\
|
||||
\
|
||||
A voice whispers to you. \"Play NetHack...\" (\"nethack\" [enter]).\n\
|
||||
What would you like to do?"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_jail(int argc, char **argv){
|
||||
printf("%s\n", argv[1]);
|
||||
if(argv[1] == NULL)
|
||||
fdputd(1, state.jailed);
|
||||
else if(strcmp(argv[1], "break") == 0 || strcmp(argv[1], "build") == 0)
|
||||
state.jailed = (argv[1][1] - 'r') / ('u' - 'r'); /* cheap */
|
||||
else
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_nethack(int argc, char **argv){
|
||||
char *a[2];
|
||||
if(fork() == 0){
|
||||
a[0] = nethack_name;
|
||||
a[1] = NULL;
|
||||
execvp("nethack", a);
|
||||
}else
|
||||
wait(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
builtin_status(int argc, char **argv){
|
||||
fdputd(1, state.status);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user