OrionUserland
Barry Importing existing Orion Userland 19aefaa (2 years, 4 months ago)diff --git a/sh/Makefile b/sh/Makefile new file mode 100644 index 0000000..5254c7c --- /dev/null +++ b/sh/Makefile @@ -0,0 +1,46 @@ +PRODUCT=$(notdir $(abspath $(CURDIR))) + +CC=i686-orion-gcc +CFLAGS= + +AS=i686-orion-as +AFLAGS= + +LD=i686-orion-gcc +LFLAGS= + +AS_SOURCES := $(shell find . -name '*.S') +OBJS = $(sort $(subst ./,build/,$(subst .S,.o,$(AS_SOURCES)))) + +C_SOURCES := $(shell find . -name '*.c') +OBJS += $(sort $(subst ./,build/,$(subst .c,.o,$(C_SOURCES)))) + +.PHONY: clean all install + +all: $(PRODUCT) + +clean: + @echo "REMOVING OBJECT FILES" + @mkdir -p build + @rm -rf build + @touch $(PRODUCT) + @rm $(PRODUCT) + +install: $(PRODUCT) + @echo "INSTALLING $^" + @mkdir -p ${SYSROOT}/bin/ + @install -Dm 755 $(PRODUCT) -t ${SYSROOT}/bin/ + +$(PRODUCT): $(OBJS) + @echo "LINKING $@" + @$(LD) -o $@ $^ $(LFLAGS) + +build/%.o: %.c + @echo "COMPILING $<" + @mkdir -p $(@D) + @$(CC) -c $< -o $@ $(CFLAGS) + +build/%.o: %.S + @echo "ASSEMBLING $<" + @mkdir -p $(@D) + @$(AS) $< -o $@ $(AFLAGS) diff --git a/sh/main.c b/sh/main.c new file mode 100644 index 0000000..d1319ad --- /dev/null +++ b/sh/main.c @@ -0,0 +1,131 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/mount.h> +#include <limits.h> +#include <sys/wait.h> +#include <signal.h> +#include <dirent.h> +#include <errno.h> +#include <pwd.h> + +#define PS1 "\033[1;31m%s\033[0m@\033[1m%s\033[0m:\033[1;32m%s\033[0m$> " + +int argparser(char *str, char **res); + +/* Get the nice current working directory */ +static void +shell_getcwd(char *cwd, char *homedir) +{ + getcwd(cwd, PATH_MAX); + /* Replace the homedir with "~" */ + if (!strncmp(cwd, homedir, strlen(homedir))) { + strncpy(cwd + 1, cwd + strlen(homedir), + PATH_MAX - strlen(homedir)); + cwd[0] = '~'; + } +} + +/* Main function */ +int +main(int argc, char *argv[]) +{ + int fd, sz, i; + char *buf; + struct stat statbuf; + struct dirent *de; + + /* Get username */ + uid_t uid = getuid(); + char *hostname, *username, *cwd, *homedir, *line, *ptr; + username = malloc(33); + homedir = malloc(PATH_MAX); + Passwd *pwd = getpwuid(uid); + strcpy(username, pwd->username); + strcpy(homedir, pwd->homedir); + + /* Get hostname */ + hostname = malloc(HOST_NAME_MAX + 1); + fd = open("/etc/hostname", O_RDONLY); + sz = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + read(fd, hostname, sz - 1); + close(fd); + + /* Get current working directory */ + cwd = malloc(PATH_MAX); + shell_getcwd(cwd, homedir); + + line = malloc(1024); + pid_t child; + int err, count, status; + char *v[256], filename[PATH_MAX] = {'/','b','i','n','/'}; + while (1) { + printf(PS1, username, hostname, cwd); + memset(line, 0, 1024); + sz = read(STDIN_FILENO, line, 1024); + + line[--sz] = '\0'; + if (sz < 1) + continue; + + count = argparser(line, v); + + /* Change directory (built-in) */ + if (!strcmp(v[0], "cd")) { + err = chdir(v[1]); + if (err < 0) { + printf("%s: cd: ", argv[0]); + perror(NULL); + } else { + shell_getcwd(cwd, homedir); + } + continue; + } + /* Exit (built-in) */ + if (!strcmp(v[0], "exit")) + exit(0); + + /* Check if program exists */ + memcpy(filename+5, v[0], PATH_MAX-5); + err = stat(filename, NULL); + if (err < 0) { + if (errno == ENOENT) { + printf("%s: %s: Command not found\n", + argv[0], v[0]); + } else { + printf("%s: %s: ", argv[0], v[0]); + perror(NULL); + } + continue; + } + + /* Execute program */ + child = fork(); + if (!child) { + err = execv(filename, v); + if (err < 0) { + printf("%s: %s: ", argv[0], v[0]); + perror(NULL); + } + exit(EXIT_FAILURE); + } else { + if (waitpid(child, &status, 0) < 0) + perror("waitpid"); + if (WIFEXITED(status) && WEXITSTATUS(status)) + printf("Exited with status %d\n", + WEXITSTATUS(status)); + if (WIFSIGNALED(status) && WTERMSIG(status)) { + switch (WTERMSIG(status)) { + case SIGSEGV: + printf("Segmentation fault\n"); + break; + } + } + } + child = 0; + } +} diff --git a/sh/parser.c b/sh/parser.c new file mode 100644 index 0000000..6c0af04 --- /dev/null +++ b/sh/parser.c @@ -0,0 +1,24 @@ +#include <string.h> + +/* Split a string into separate strings */ +int +argparser(char *str, char **res) +{ + int count = 0; + char *finder; + + memset(res, 0, 1024); + finder = str; + while (*finder == ' ') finder++; + res[count++] = finder; + while (*finder) { + if (*finder == ' ') { + res[count++] = finder + 1; + *finder = '\0'; + } + finder++; + } + res[count] = NULL; + + return count; +} diff --git a/sh/sh b/sh/sh new file mode 100755 index 0000000..6326a89 Binary files /dev/null and b/sh/sh differ