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
|
nonzero: src/nonzero.c
|
||||||
$(CC) $(CFLAGS) -o bin/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
|
runlength: noargvzero sysexits src/runlength.c
|
||||||
$(CC) $(CFLAGS) -o bin/runlength 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