aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2016-03-02 14:20:38 +1300
committerTom Ryder <tom@sanctum.geek.nz>2016-03-02 14:20:38 +1300
commitd0b392c0a4c4ef72a972a32cee2a4e4f155faf5f (patch)
tree04ca5d9349dc0d463d0edc89a5219c3213c035d1
downloadspsh-d0b392c0a4c4ef72a972a32cee2a4e4f155faf5f.tar.gz
spsh-d0b392c0a4c4ef72a972a32cee2a4e4f155faf5f.zip
First commit of sps(1)
-rw-r--r--Makefile10
-rw-r--r--banner.c9
-rw-r--r--cmd.c57
-rw-r--r--loop.c27
-rw-r--r--main.c15
-rw-r--r--sps.h28
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;
+}
+
diff --git a/cmd.c b/cmd.c
new file mode 100644
index 0000000..b0486a3
--- /dev/null
+++ b/cmd.c
@@ -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;
+}
+
diff --git a/loop.c b/loop.c
new file mode 100644
index 0000000..107b4b2
--- /dev/null
+++ b/loop.c
@@ -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;
+}
+
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..c4c57f0
--- /dev/null
+++ b/main.c
@@ -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);
+}
+
diff --git a/sps.h b/sps.h
new file mode 100644
index 0000000..c23e311
--- /dev/null
+++ b/sps.h
@@ -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
+