commit 165592feeaea63e6f94ed496ffeaf37b222701be Author: Michael Date: Fri Oct 9 12:20:25 2026 +0200 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..849ddff --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +dist/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e5ccacc --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC ?= gcc + +SOURCES := $(wildcard src/*.c) + + +.PHONY: clean + +all: dist/msh + +dist/msh: $(SOURCES) dist + $(CC) -o $@ $(SOURCES) + +dist: + mkdir -p dist + +clean: + rm -rf dist diff --git a/src/msh.c b/src/msh.c new file mode 100644 index 0000000..cc48b34 --- /dev/null +++ b/src/msh.c @@ -0,0 +1,135 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + + +#define ESC \x1B + + +const int LINESIZE = 512; + +int cd(int argc, char** argv) { + if (argc != 1) { + fprintf(stderr, "Usage: cd \n"); + return 1; + } + + return chdir(argv[0]); +} + + +void pretty_path_home(char** path) { + char* home = secure_getenv("HOME"); + int home_len = strlen(home); + + if (strncmp(home, *path, home_len) == 0) { + (*path)[home_len-1] = '~'; + *path = *path + (home_len - 1); + } +} + + +int main(int argc, char** argv) { + char* tokens[LINESIZE] = {}; + char** args; + char line[LINESIZE] = {}; + char* tokenwork; + char* token; + char* newline; + int ntokens = 0; + + int i; + int result; + + int pid; + int laststatus = 0; + + int wstatus; + char pwd[LINESIZE] = {}; + char* pwd_disp; + + char* user; + char* host; + + struct utsname uts = {}; + + user = secure_getenv("USER"); + + result = uname(&uts); + if (result != 0) { + fprintf(stderr, "Error: %s\n", strerror(errno)); + return errno; + } + + host = uts.nodename; + + while(1) { + getcwd(pwd, LINESIZE - 1); + pwd_disp = pwd; + + pretty_path_home(&pwd_disp); + + if (laststatus != 0) { + fprintf(stdout, "❌"); + } + fprintf(stdout, "%s@%s %s$ ", user, host, pwd_disp); + char* fgets_res = fgets(line, LINESIZE, stdin); + + if (fgets_res == NULL) { + printf("^D\n"); + return 0; + } + + newline = strrchr(line, '\n'); + if (newline != NULL) { + newline[0] = 0; + } + + for (tokenwork = line, i = 0; ; tokenwork = NULL, i++) { + token = strtok(tokenwork, " \t"); + if (token == NULL) { + break; + } + + tokens[i] = token; + } + + ntokens = i; + tokens[ntokens] = NULL; + args = &tokens[1]; + + if (ntokens == 0) { + continue; + } + + // Shell builtins + if (strcmp("exit", tokens[0]) == 0) { + printf("Goodbye!\n"); + return 0; + } + + if (strcmp("cd", tokens[0]) == 0) { + laststatus = cd(ntokens - 1, args); + continue; + } + + // Execute command + pid = fork(); + + if(pid == 0) { + return execvpe(tokens[0], tokens, NULL); + } else { + waitpid(pid, &wstatus, 0); + + laststatus = WEXITSTATUS(wstatus); + } + + } +} +