msh

simple shell implementation
Index Commits Files Refs README LICENSE
commit 5d06822349e135a141df1b6088c1e513ea28cbd9
Author: mjkloeckner <martinjkloeckner@gmail.com>
Date:   Mon,  1 May 2023 23:55:43 -0300

first commit

Diffstat:
AMakefile | 20++++++++++++++++++++
Amsh.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 123 insertions(+), 0 deletions(-)
diff --git a/Makefile b/Makefile
@@ -0,0 +1,20 @@
+CC := gcc
+CFLAGS := -Wall -Wshadow -pedantic -ansi -std=c99
+SRCS := $(wildcard *.c)
+OBJS := $(SRCS:.c=.o)
+
+TARGET := msh
+
+.PHONY: all clean
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+    $(CC) $(CLIBS) $(CFLAGS) -o $@ $^
+    rm -f $(OBJS)
+
+%.o: %.c
+    $(CC) $(CLIBS) $(CFLAGS) -c $< -o $@
+
+clean:
+    rm -f $(OBJS)
diff --git a/msh.c b/msh.c
@@ -0,0 +1,103 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#define    READLINE_BUFFER_INIT_SIZE         1000
+#define READLINE_BUFFER_GROWTH_FACTOR    0.5f
+#define TOKENS_BUFFER_INIT_SIZE            16
+
+static bool run = true;
+static size_t alloc_len;
+
+void buffer_clear(char *buf, size_t *len) {
+    for (size_t i = 0; i < *len; i++)
+        buf[i] = '\0';
+
+    *len = 0;
+}
+
+void buffer_read_line(char *buffer, size_t *len) {
+    int c;
+    char *tmp;
+
+    /* read line into buffer */
+    while(1) {
+        c = fgetc(stdin);
+        if((c == '\n') || (c == EOF)) break;
+
+        if((*len + 2 == alloc_len)) {
+            alloc_len += alloc_len * READLINE_BUFFER_GROWTH_FACTOR;
+            if((tmp = realloc(buffer, alloc_len)) == NULL) return;
+            buffer = tmp;
+        }
+
+        buffer[(*len)++] = c;
+    }
+    buffer[*len] = '\0';
+    if (c == EOF) run = false;
+}
+
+void buffer_split(char *b, size_t *len, char ***tokens, size_t *tokens_count) {
+    if(b == NULL) return;
+
+    size_t token_alloc;
+    char *start, **tmp;
+
+    start = b;
+    *tokens_count = 0;
+
+    if(*tokens != NULL) return; 
+
+    *tokens = malloc((sizeof(char *) * TOKENS_BUFFER_INIT_SIZE));
+    token_alloc = TOKENS_BUFFER_INIT_SIZE;
+    if (*tokens == NULL) return;
+
+    (*tokens)[*tokens_count] = strtok(b, " ");
+    while((*tokens)[*tokens_count] != NULL) {
+        (*tokens)[++(*tokens_count)] = strtok(NULL, " ");
+        if (*tokens_count == token_alloc) {
+            token_alloc += TOKENS_BUFFER_INIT_SIZE;
+            tmp = realloc(*tokens, sizeof(char *) * token_alloc);
+            if(tmp == NULL) return;
+            *tokens = tmp;
+        }
+    }
+
+    b = start;
+}
+
+void msh_loop(void) {
+    char *buffer;
+    size_t len;
+
+    len = 0;
+    buffer = malloc(alloc_len = READLINE_BUFFER_INIT_SIZE);
+
+    while (run) {
+        buffer_clear(buffer, &len);
+
+        printf("> ");
+
+        buffer_read_line(buffer, &len);
+
+        /* printf("%s\n", buffer); */
+
+        char **tokens = NULL;
+        size_t tokens_count = 0;
+        buffer_split(buffer, &len, &tokens, &tokens_count);
+
+        printf("tokens_count: %ld\n", tokens_count);
+        for(size_t t = 0; t < tokens_count; t++)
+            printf("%s\n", tokens[t]);
+    }
+}
+
+int main (void) {
+    /* load config files */
+
+    msh_loop();
+
+    /* cleanup */
+    return 0;
+}