diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2016-03-02 14:20:38 +1300 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2016-03-02 14:20:38 +1300 |
commit | d0b392c0a4c4ef72a972a32cee2a4e4f155faf5f (patch) | |
tree | 04ca5d9349dc0d463d0edc89a5219c3213c035d1 | |
download | spsh-d0b392c0a4c4ef72a972a32cee2a4e4f155faf5f.tar.gz spsh-d0b392c0a4c4ef72a972a32cee2a4e4f155faf5f.zip |
First commit of sps(1)
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | banner.c | 9 | ||||
-rw-r--r-- | cmd.c | 57 | ||||
-rw-r--r-- | loop.c | 27 | ||||
-rw-r--r-- | main.c | 15 | ||||
-rw-r--r-- | sps.h | 28 |
6 files changed, 146 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4a131b1 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +CC = gcc +LDFLAGS = -lreadline +CFLAGS = -Wall -Wpedantic -ansi -pedantic-errors + +sps : main.o banner.o cmd.o loop.o + $(CC) $(CFLAGS) $(LDFLAGS) -o sps main.o banner.o cmd.o loop.o + +clean : + rm -f -- *.o sps + diff --git a/banner.c b/banner.c new file mode 100644 index 0000000..ff70d7c --- /dev/null +++ b/banner.c @@ -0,0 +1,9 @@ +#include "sps.h" + +/* Print the welcome and warning banners */ +void banner() { + fprintf(stdout, "%s\n", WELCOME); + fprintf(stdout, "%s\n", WARNING); + return; +} + @@ -0,0 +1,57 @@ +#include "sps.h" + +/* Process a read line into a command and arguments and try to execute it */ +void cmd(char *line) { + char *cmd, *cmd_arg; + pid_t pid; + int status, cmd_argc; + char *cmd_argv[MAX_ARGS]; + char *cmd_envp[MAX_ENVS]; + + /* First argument is always the executable file itself; we make it NULL to + * start with, and then terminate the array with NULL */ + cmd_argv[0] = cmd_argv[1] = NULL; + cmd_argc = 1; + + /* Environment is just empty for now, I'll figure this out later */ + cmd_envp[0] = NULL; + + + /* Read the command as the first token of the line */ + cmd = strtok(line, ARG_DELIM); + + /* Iterate through the remaining arguments with subsequent calls to strtok() */ + while ((cmd_arg = strtok(NULL, ARG_DELIM)) != NULL) { + cmd_argc++; + if (cmd_argc < MAX_ARGS) { + cmd_argv[cmd_argc - 1] = cmd_arg; + cmd_argv[cmd_argc] = NULL; + } + } + + /* If there were too many arguments, say so */ + if (cmd_argc >= MAX_ARGS) { + fprintf(stderr, "Too many arguments (%u given, max is %u)\n", cmd_argc, MAX_ARGS); + return; + } + + /* If the command looks to be executable ... */ + if (access(cmd, X_OK) != -1) { + + /* ... fork and try to execute it; wait until the fork is done. */ + pid = fork(); + if (pid == 0) { + cmd_argv[0] = cmd; + execve(cmd, cmd_argv, cmd_envp); + } + waitpid(pid, &status, 0); + + /* Otherwise, print an error, because we couldn't find the command */ + } else { + fprintf(stderr, "Command ā%sā not found\n", cmd); + return; + } + + return; +} + @@ -0,0 +1,27 @@ +#include "sps.h" + +/* Loop through reading commands until we see an EOF (^D) */ +void loop() { + char *line; + + /* Loop until we break */ + while (1) { + + /* Read a line from the user */ + line = readline(PROMPT); + + /* If the line is valid, try to run it as a command */ + if (line != NULL) { + cmd(line); + } + + /* If the line is EOF (^D), break out of the loop */ + else { + fputs("\n", stdout); + break; + } + } + + return; +} + @@ -0,0 +1,15 @@ +#include "sps.h" + +/* Entry function */ +int main(int argc, char *argv[]) { + + /* Show the banner with the warning */ + banner(); + + /* Start looping through commands */ + loop(); + + /* If we get to this point, things should be good */ + exit(EXIT_SUCCESS); +} + @@ -0,0 +1,28 @@ +#ifndef SPS_H +#define SPS_H + +#include <readline/history.h> +#include <readline/readline.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> + +#define WELCOME "Welcome to sps(1), the shitposting shell" +#define WARNING "(pretty much nothing works, just fyi)" + +#define MAX_ARGS 64 +#define MAX_ENVS 64 + +#define PROMPT "sps$ " + +#define ARG_DELIM " " + +void banner(); +void loop(); +void cmd(char *line); + +#endif + |