OrionUserland
Barry Importing existing Orion Userland 19aefaa (3 years, 3 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