1
0

fix nutshell warnings

This commit is contained in:
dtb 2022-06-06 16:06:56 -04:00
parent feb781afc1
commit 3a65d3d91f
4 changed files with 239 additions and 0 deletions

View File

@ -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
View 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
View 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
View 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;
}