commit 5436c4c2eaab9022a8b603b15b4c8e664ec16615 Author: Nathan Giddings Date: Tue May 28 17:19:44 2024 -0500 New repo setup diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3565c83 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.o +*.idea +shell +init \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..25c8d4f --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +CC = aarch64-none-elf-gcc +CXX = aarch64-none-elf-g++ +AS = aarch64-none-elf-as +AR = aarch64-none-elf-ar +prefix:=$(HOME)/.cros/root + +COMMANDS_SRCS = $(wildcard src/commands/*.cpp) +SHELL_OBJS = src/shell.o src/utility.o src/command.o +INIT_OBJ = init.o + +COMMANDS_TARGETS = $(COMMANDS_SRCS:src/commands/%.cpp=bin/%) +SHELL_TARGET = shell +INIT_TARGET = init + +CXXFLAGS = -I$(prefix)/include -Isrc -Isrc/commands -ffreestanding -nostdlib -fpermissive -fno-exceptions -fno-rtti -Wall -Wextra -ggdb -O0 +LDFLAGS = -L$(prefix)/lib -nostdlib +LIBS = -lc -lsyscall + +.PHONY: all +all: $(COMMANDS_TARGETS) $(SHELL_TARGET) $(INIT_TARGET) + +.PHONY: clean +clean: + rm -rf ./bin $(SHELL_TARGET) $(INIT_TARGET) $(SHELL_OBJS) $(INIT_OBJ) src/commands/*.o + +.PHONY: install +install: + mkdir -p $(prefix)/bin + cp -a bin/. $(prefix)/bin + cp $(SHELL_TARGET) $(prefix)/bin + cp $(INIT_TARGET) $(prefix)/bin + +# Compiling individual command files +bin/%: src/commands/%.o + @mkdir -p bin + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $< $(LIBS) + +# Compiling shell.cpp +$(SHELL_TARGET): $(SHELL_OBJS) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) + +# Compiling shell INIT +$(INIT_TARGET): $(INIT_OBJ) + $(CXX) $(LDFLAGS) $(CXXFLAGS) -o $@ $^ $(LIBS) diff --git a/README.md b/README.md new file mode 100644 index 0000000..20a5af0 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# SHELL COMMAND DOCUMENTATION: +1. `$ help` provides a quick reference for available commands. +3. `$ echo <(opt) args>` Echos back the provided argument(s). Will include double quote. +4. `$ joke` provides a tasteful joke. +5. `$ ls <(opt) arg>` Provides the files and directories at the provided location. Prints files and directories in current directory if no arg given. +6. `$ cd ` BUILT-IN: Changes current directory to provided file location. +7. `$ pwd` BUILT-IN: Provides an exact location of the current directory. + +--- +# ./commands/* + +Commands created as separate cpp files. Compiled into `./bin` during `make`. + +pwd and cd are built-ins. + +--- +# Compiling and Running + +* `make` +* `make install prefix=PATH_TO_INSTALL_DIRECTORY` + +* Don't forget `make clean` + +Authored by Connor +echo.cpp authored by Kyle diff --git a/init.cpp b/init.cpp new file mode 100644 index 0000000..cc066cf --- /dev/null +++ b/init.cpp @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include + +char **envp_global; +int pipefd_stdout[2]; +int pipefd_stdin[2]; + +void shellThread(void *ptr) +{ + fddup(pipefd_stdout[1], 1); + fddup(pipefd_stdin[0], 0); + char *args[] = {"/bin/shell", NULL}; + // exec("/bin/shell", args, envp); + execve("shell", args, envp_global); + terminate(); +} + +int main(int argc, char **argv, char **envp) +{ + const int stackSize = 1024; + printf("%s: Starting shell\n", argv[0]); + void *stack = malloc(stackSize); + envp_global = envp; + + printf("%s: Creating pipes\n", argv[0]); + create_pipe(pipefd_stdout); + create_pipe(pipefd_stdin); + + printf("%s: Spawning new thread\n", argv[0]); + clone(shellThread, stack + stackSize, nullptr, 0); + + printf("%s: Entering I/O loop\n", argv[0]); + char line[1024]; + char buffer[1024]; + int pos = 0; + while (true) + { + // printf("init: I/O loop\n"); + int status = read(0, &buffer[pos], 1); + // printf("init: Read status: %d\n", status); + while (status > 0) + { + char str[2]; + str[0] = buffer[pos]; + str[1] = '\0'; + printf("%s", str); + if (str[0] == '\r') + { + printf("\n"); + } + + pos += status; + if (buffer[pos - 1] == '\r') + { + buffer[pos - 1] = '\n'; + buffer[pos] = '\0'; + fprintf(&pipefd_stdin[1], "%s", buffer); + pos = 0; + } + else if (pos == 1023) + { + buffer[pos] = '\0'; + fprintf(&pipefd_stdin[1], "%s", buffer); + pos = 0; + } + + status = read(0, &buffer[pos], 1); + } + + if (status < 0) + { + printf("init: Error reading from UART.\n"); + } + + status = read(pipefd_stdout[0], line, 1023); + // printf("init: Read2 status: %d\n", status); + if (status > 0) + { + line[status] = '\0'; + printf("%s", line); + } + + yield(); + // printk("hi"); + } +} diff --git a/src/command.cpp b/src/command.cpp new file mode 100644 index 0000000..9a8a8d7 --- /dev/null +++ b/src/command.cpp @@ -0,0 +1,164 @@ +#include "command.h" +#include +#include +#include +#include +#include "utility.h" +#include + +void spawn_command(char **args) +{ + execvp(args[0], args); + terminate(); +} + +int Command::parse(std::string input) +{ + // if input has \n appended to the end, remove it + if (input[input.size() - 1] == '\n') + { + input = input.substr(0, input.size() - 1); + } + + std::string pipe_delim = "|"; + std::vector parsed_input = split_string(input, pipe_delim); + + if (Command::setup_command(parsed_input) < 0) + { + return -1; + } + + return 0; +} + +int Command::run() +{ + int i, j, pid; + int num_instructions = instructions.size(); + + // If there is no pipe, just fork and execute the first command + if (num_instructions == 1) + { + + // Check for built-in commands + if (instructions[0][0] == "cd") + { + if (instructions[0].size() > 1) + { + return cd(instructions[0][1].c_str()); + } + return cd("/"); + } + else if (instructions[0][0] == "clear") + { + clear(); + return 0; + } + + // No built-ins, execute elsewhere + exec_instruction(instructions[0]); + wait(NULL); + return 0; + } + ////////////////////////////////// + + // Piping logic: + // Initialize file descriptors for some piping + int fd[num_instructions][2]; + + // Init the pipes + int result = -1; + for (i = 0; i < num_instructions; i++) + { + pipe(fd[i]); + } + + // Fork every instruction + for (i = 0; i < num_instructions; i++) + { + pid = fork(); + + if (pid == 0) + { + + // If this is not the first instruction + if (i > 0) + { + + if (fd[i - 1][0] != 0) + { + dup2(fd[i - 1][0], 0); + } + } + + // If this is not the last instruction + if (i < num_instructions - 1) + { + if (fd[i][1] != 1) + { + dup2(fd[i][1], 1); + } + } + + // Close all descriptors + for (j = 0; j < num_instructions; j++) + { + close(fd[j][0]); + close(fd[j][1]); + } + + // Execute instruction + exec_instruction(instructions[i]); + } + } + + // Close parent file descriptors + for (i = 0; i < num_instructions; i++) + { + close(fd[i][0]); + close(fd[i][1]); + } + + // Wait for all processes to finish + for (int i = 0; i < num_instructions; i++) + { + wait(NULL); + } + + return 0; +} + +int Command::setup_command(std::vector &parsed_input) +{ + std::string space_delim = " "; + while (!parsed_input.empty()) + { + std::string input = parsed_input.front(); + std::vector instruction = split_string(input, space_delim); + // terminate setup if input error + if (instruction.empty()) + { + return -1; + } + + instructions.push_back(instruction); + parsed_input.remove(0); + } + + return 0; +} + +int Command::exec_instruction(std::vector &instruction) +{ + int num_args = instruction.size(); + char **arg = new char *[num_args + 1]; + for (size_t i = 0; i < num_args; i++) + { + arg[i] = new char[instruction[i].size() + 1]; + strcpy(arg[i], instruction[i].c_str()); + } + arg[num_args] = nullptr; + void *stack = malloc(1024); + clone(spawn_command, stack + 1024, (void *)arg, 0); + return 0; +} diff --git a/src/command.h b/src/command.h new file mode 100644 index 0000000..d04ff21 --- /dev/null +++ b/src/command.h @@ -0,0 +1,50 @@ +#ifndef _COMMAND_H_ +#define _COMMAND_H_ + +#include +#include + +/** + * The entire line parsed is a "Command" + * Each process with arguments included are an "Instruction" + * The Command class stores each instruction as a vector and will pipe between + * each instruction in the vector. + */ +class Command +{ +public: + /** + * Parse each input by the pipe deliminator. + * Setup the command with each parsed input. + * @return 0 if successful + * @return not 0 otherwise + */ + int parse(std::string command); + + /** + * Fork and exec the command. + * Pipe to the next command if applicable. + */ + int run(); + +private: + std::vector> instructions; + + /** + * Loops through every parsed input in a vector + * Separates each segment o f a command by spaces + * Embeds each segment of a command as an "instruction" + * Each "instruction" is added to a vector called "instructions" + * @param parsed_input a vector of commands separated by a vertical pipe "|" + */ + int setup_command(std::vector &instructions); + + /** + * Executes the command + * @param curr_command + * @return + */ + int exec_instruction(std::vector &instruction); +}; + +#endif // !_COMMAND_H_ diff --git a/src/commands/cp.cpp b/src/commands/cp.cpp new file mode 100644 index 0000000..de98328 --- /dev/null +++ b/src/commands/cp.cpp @@ -0,0 +1,66 @@ +// +// Created by connor on 2/12/24. +// +// +#include +#include + +void cp(char* src_file_name, char* dest_file_name, bool overwrite) { + FILE* src_file = fopen(src_file_name, "r"); + if (src_file == NULL) { + fprintf(stderr, "Error opening src file: %s\n", src_file_name); + exit(1); + } + + FILE* dest_file = fopen(dest_file_name, "r"); + if (dest_file != NULL) { + fclose(dest_file); + if (!overwrite) { + fclose(src_file); + return; + } + } + + dest_file = fopen(dest_file_name, "w"); + if (dest_file == NULL) { + fprintf(stderr, "Error opening dest file: %s\n", dest_file_name); + fclose(src_file); + exit(1); + } + + int ch; + while ((ch = fgetc(src_file)) != EOF) { + fputc(ch, dest_file); + } + + fclose(src_file); + fclose(dest_file); +} + +int main(int argc, char* argv[]) { + if (argc < 3) { + printf("Usage: cp ...\n"); + } else { + int i = 1; + char* flags = argv[1]; + int size = sizeof(flags); + bool overwrite = false; + if (flags[0] == '-') { + i++; + for (int j = 1; j < size; j++) { + switch (flags[j]) { + case 'o': + overwrite = true; + break; + default: + break; + } + } + } + + for (int j = i + 1; j < argc; j++) + cp(argv[i], argv[j], overwrite); + + return 0; + } +} diff --git a/src/commands/echo.cpp b/src/commands/echo.cpp new file mode 100644 index 0000000..128705e --- /dev/null +++ b/src/commands/echo.cpp @@ -0,0 +1,20 @@ +// +// Created by connor on 2/7/24. +// functions similarly to linux ls +// +#include + +void echo(int argc, char* argv[]) { + for (int i = 0; i < argc; i++) { + printf("%s ", argv[i]); + } + printf("\n"); +} + +int main(int argc, char* argv[]) { + if (argc < 2) + printf("Usage: echo \n"); + else + echo(argc, argv); + return 0; +} \ No newline at end of file diff --git a/src/commands/help.cpp b/src/commands/help.cpp new file mode 100644 index 0000000..16b9916 --- /dev/null +++ b/src/commands/help.cpp @@ -0,0 +1,23 @@ +// +// Created by connor on 2/12/24. +// +// +#include +int main() { + printf("Commands:\n"); + printf(" joke\n"); + printf(" echo \n"); + printf(" ls \n"); + printf(" cd \n"); + printf(" pwd\n"); + printf(" search ...\n"); + printf(" -v: verbose\n"); + printf(" wc ...\n"); + printf(" -b: byte count\n"); + printf(" -c: character count\n"); + printf(" -w: word count\n"); + printf(" -l: line count\n"); + printf(" cp ...\n"); + printf(" -o: overwrite file\n"); + return 0; +} diff --git a/src/commands/joke.cpp b/src/commands/joke.cpp new file mode 100644 index 0000000..6196644 --- /dev/null +++ b/src/commands/joke.cpp @@ -0,0 +1,35 @@ +/* + * Created by connor on 2/7/24. + * 16 of the classiest jokes. + */ + +#include +#include + +void joke() { + const char* jokes[] = { + "What do you call a factory that makes okay products? \nA satisfactory.", + "What did one wall say to the other? \nI'll meet you at the corner.", + "What did the zero say to the eight? \nThat belt looks good on you.", + "If my wife thinks I'm obsessed with programming, she's crazy. \nendif.", + "Hey girl, are you an object-oriented programming language?\nBecause you've got class.", + "How many lightbulbs does it take to change a programmer? \nI don't know, but it sounds like somebody learned about dependency inversion.", + "[\"Hip\",\"Hip\"]\nHip Hip Array!", + "Why do programmers prefer dark mode?\nBecause the light attracts bugs!", + "Why don't scientists trust atoms?\nBecause they make up everything!", + "Why do Java developers wear glasses?\nBecause they don't see sharp!", + "Why did the programmer quit his job?\nHe didn't get arrays!", + "Why did the scarecrow win an award?\nBecause he was outstanding in his field!", + "I told my wife she was drawing her eyebrows too high.\nShe looked surprised!", + "I asked the librarian if the library had any books on paranoia.\nShe whispered, 'They're right behind you.'", + "I used to play piano by ear. \nNow I use my hands and fingers.", + "I told my wife she should embrace her mistakes.\nShe gave me a hug."}; + + int joke_index = rand() % 16; + printf("%s\n", jokes[joke_index]); +} + +int main() { + joke(); + return 0; +} diff --git a/src/commands/ls.cpp b/src/commands/ls.cpp new file mode 100644 index 0000000..40e2587 --- /dev/null +++ b/src/commands/ls.cpp @@ -0,0 +1,38 @@ +// +// Created by connor on 2/7/24. +// functions similarly to linux ls +// + +#include +#include +#include +#include +#include + +void ls(char* dir_path) { + DIR* dir = opendir(dir_path); + if (dir == NULL) { + fprintf(stderr, "Error opening directory: %s\n", dir_path); + exit(1); + } + + struct dirent* entry; + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, "..")) + printf("%s\n", entry->d_name); + } + + closedir(dir); +} + +int main(int argc, char* argv[]) { + if (argc == 1) { + char dir[100]; + getcwd(dir, sizeof(dir)); + ls(dir); + } else { + for (int i = 1; i < argc; i++) + ls(argv[i]); + } + return 0; +} \ No newline at end of file diff --git a/src/commands/mkdir.cpp b/src/commands/mkdir.cpp new file mode 100644 index 0000000..f6804a7 --- /dev/null +++ b/src/commands/mkdir.cpp @@ -0,0 +1,18 @@ +// +// Created by connor on 2/12/24. +// +// +#include +#include + +void mkdir_func(char* dir_path) { + mkdir(dir_path); +} + +int main(int argc, char* argv[]) { + if (argc > 1) { + mkdir_func(argv[2]); + } + printf("mkdir not implemented."); + return 0; +} diff --git a/src/commands/mv.cpp b/src/commands/mv.cpp new file mode 100644 index 0000000..f470bda --- /dev/null +++ b/src/commands/mv.cpp @@ -0,0 +1,9 @@ +// +// Created by connor on 2/12/24. +// +// +#include +int main() { + printf("mv not implemented."); + return 0; +} diff --git a/src/commands/pwd.cpp b/src/commands/pwd.cpp new file mode 100644 index 0000000..dc89c81 --- /dev/null +++ b/src/commands/pwd.cpp @@ -0,0 +1,18 @@ +// +// Created by connor on 2/12/24. +// +// +#include +#include + +int pwd() { + char cwd[128]; + getcwd(cwd, sizeof(cwd)); + return printf("%s\n", cwd); +} + +int main() { + pwd(); + + return 0; +} diff --git a/src/commands/rm.cpp b/src/commands/rm.cpp new file mode 100644 index 0000000..dd1cd0b --- /dev/null +++ b/src/commands/rm.cpp @@ -0,0 +1,9 @@ +// +// Created by connor on 2/12/24. +// +// +#include +int main() { + printf("rm not implemented."); + return 0; +} diff --git a/src/commands/search.cpp b/src/commands/search.cpp new file mode 100644 index 0000000..435ffd2 --- /dev/null +++ b/src/commands/search.cpp @@ -0,0 +1,78 @@ +// +// Created by connor on 2/12/24. +// +// +#include +#include +#include + +void search(char *token, char *file_name, bool verbose) +{ + FILE *file; + file = fopen(file_name, "r"); + if (file == NULL) + { + fprintf(stderr, "Error opening file: %s\n", file_name); + exit(1); + } + + char line[1024]; // assuming max line length is 1024 chars + int line_number = 1; + + if (verbose) + { + printf("%s:\n", file_name); + printf("%s occurences:\n", token); + } + + while (fgets(line, sizeof(line), file) != NULL) + { + char *occurrence = strstr(line, token); + while (occurrence != NULL) + { + if (verbose) + printf(" line: %d, index: %d %s", line_number, occurrence - line + 1, line); + else + printf("%d %d %s", line_number, occurrence - line + 1, line); + occurrence = strstr(occurrence + 1, token); + } + line_number++; + } + + fclose(file); +} + +int main(int argc, char *argv[]) +{ + if (argc <= 2) + { + printf("Usage: search ...\n"); + } + else + { + int i = 2; + char *flags = argv[1]; + int size = sizeof(flags); + bool verbose = false; + if (flags[0] == '-') + { + i++; + for (int j = 1; j < size; j++) + { + switch (flags[j]) + { + case 'v': + verbose = true; + break; + default: + break; + } + } + } + + char *token = argv[i - 1]; + for (; i < argc; i++) + search(token, argv[i], verbose); + } + return 0; +} diff --git a/src/commands/wc.cpp b/src/commands/wc.cpp new file mode 100644 index 0000000..2f9aa63 --- /dev/null +++ b/src/commands/wc.cpp @@ -0,0 +1,127 @@ +// +// Created by connor on 2/12/24. +// +// +#include +#include + +void wc(char *file_name, bool show_chars, bool show_bytes, bool show_words, bool show_lines) +{ + FILE *file; + file = fopen(file_name, "r"); + if (file == NULL) + { + fprintf(stderr, "Error opening file: %s\n", file_name); + exit(1); + } + + int lines = 1; + int words = 0; + int characters = 0; + int bytes = 0; + + if (show_chars || show_words || show_lines) + { + int in_word = 0; + int ch = 0; + + while ((ch = fgetc(file)) != EOF) + { + characters++; + + if (ch == '\n') + { + lines++; + } + + if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\v' || ch == '\f') + { + in_word = 0; + } + else if (in_word == 0) + { + in_word = 1; + words++; + } + } + } + + if (show_bytes) + { + if (fseek(file, 0, SEEK_END) != 0) + { + fprintf(stderr, "Error reading file: %s\n", file_name); + exit(1); + } + + bytes = ftell(file); + if (bytes == -1) + { + fprintf(stderr, "Error reading file: %s\n", file_name); + exit(1); + } + } + + fclose(file); + + printf("%s:\n", file_name); + if (show_bytes) + printf(" bytes: %d\n", bytes); + if (show_chars) + printf(" characters: %d\n", characters); + if (show_words) + printf(" words: %d\n", words); + if (show_lines) + printf(" lines: %d\n", lines); +} + +int main(int argc, char *argv[]) +{ + if (argc <= 1) + { + printf("Usage: wc ...\n"); + } + else + { + int i = 1; + char *flags = argv[1]; + int size = sizeof(flags); + bool show_chars = false; + bool show_bytes = false; + bool show_words = false; + bool show_lines = false; + if (flags[0] == '-') + { + i++; + for (int j = 1; j < size; j++) + { + switch (flags[j]) + { + case 'c': + show_chars = true; + break; + case 'b': + show_bytes = true; + break; + case 'w': + show_words = true; + break; + case 'l': + show_lines = true; + break; + default: + break; + } + } + } + + for (; i < argc; i++) + { + if (!show_chars && !show_bytes && !show_words && !show_lines) + wc(argv[i], show_chars, show_bytes, true, show_lines); + else + wc(argv[i], show_chars, show_bytes, show_words, show_lines); + } + } + return 0; +} diff --git a/src/shell.cpp b/src/shell.cpp new file mode 100644 index 0000000..85c4d67 --- /dev/null +++ b/src/shell.cpp @@ -0,0 +1,74 @@ +// +// Created by connor on 2/20/24. +// +#include +#include + +#include "command.h" +#include "utility.h" +#include + +#define INPUT_MAX 128 +#define HISTORY_MAX 10 +char HISTORY[HISTORY_MAX]; + +/** + * Main loop for the terminal. + * 1. Print the prompt including current fs location + * 2. Get the userinput using fgets into input + * 3. Convert char input into string input_str + * 4. Create a new command object and parse the input into the object. + * 5. Call the run() method on the command object if parsed successfully. + * 6. Flush input + */ +int main() +{ + + // stuff from utility.h + clear(); + PRINT_BANNER(); + // + + while (1) + { + // user input and file system location + int parse_status, run_status; + char input[INPUT_MAX], cwd[128]; + + // get the current fs location and print a prompt + getcwd(cwd, sizeof(cwd)); + printf("\033[32m%s\033[0m$ ", cwd); + if (!fgets(input, sizeof(input), stdin)) { + // if something is wrong with stdin, we're screwed. + continue; + } + + // get user input as a string and check for empty input + std::string input_str(input); + + // BLANK INPUT + if (input_str.size() <= 1) + { + continue; + } + + // printf("%s", input); + + // parse the new command + Command command; + parse_status = command.parse(input_str); + if (parse_status < 0) { + printf("\033[1;31mUnrecognized command..\n\033[0m"); + continue; + } + + run_status = command.run(); + if (run_status < 0) { + printf("\033[1;31mUnexpected failure running command..\n\033[0m"); + } + + // flush input + // scanf("%*[^\n]%*1[\n]"); + // getchar(); + } +} diff --git a/src/utility.cpp b/src/utility.cpp new file mode 100644 index 0000000..0dced47 --- /dev/null +++ b/src/utility.cpp @@ -0,0 +1,51 @@ +// +// Created by connor on 2/21/24. +// +#include "utility.h" +#include +#include +#include + +std::vector split_string(std::string &str, + const std::string &delimiter) { + size_t pos = 0; + std::vector parsed_input; + if (str.find(delimiter) != std::string::npos) { + while ((pos = str.find(delimiter)) != std::string::npos) { + std::string token = str.substr(0, pos); + if (token.size() > 0) { + parsed_input.push_back(token); + } + str.erase(0, pos + delimiter.size()); + } + } + if (str.size() > 0) + parsed_input.push_back(str); + return parsed_input; +} + +int cd(const char *str) { + if (chdir(str) != 0) { + printf("Unable to find path.\n"); + return -1; + } + return 0; +} + +void PRINT_BANNER() { + printf("\033[32m________ ________ ________ ________\n\033[0m"); + printf("\033[32m|\\ ____\\|\\ __ \\|\\ __ \\|\\ ____\\\n\033[0m"); + printf("\033[32m\\ \\ \\___|\\ \\ \\|\\ \\ \\ \\|\\ \\ \\ \\___|_\n\033[0m"); + printf("\033[32m \\ \\ \\ \\ \\ _ _\\ \\ \\\\\\ \\ \\_____ \\\n\033[0m"); + printf("\033[32m \\ \\ \\____\\ \\ \\\\ \\\\ \\ \\\\\\ \\|____|\\ \\\n\033[0m"); + printf("\033[32m \\ \\_______\\ \\__\\\\ _\\\\ \\_______\\____\\_\\ \\\n\033[0m"); + printf("\033[32m \\|_______|\\|__|\\|__|\\|_______|\\_________\\\n\033[0m"); + printf("\033[32m \\|_________|\n\033[0m"); + printf("\033[32m \"Powered by terminal gremlins and questionable memory accessing.\"\n\n\033[0m"); + + printf("Input a command or use '\033[34mhelp\033[0m' for some ideas\n"); +} + +void clear() { + printf("\033[H\033[J"); +} \ No newline at end of file diff --git a/src/utility.h b/src/utility.h new file mode 100644 index 0000000..338e4f3 --- /dev/null +++ b/src/utility.h @@ -0,0 +1,32 @@ +// +// Created by connor on 2/21/24. +// + +#ifndef EOS_UTILITY_H +#define EOS_UTILITY_H + +#include +#include + +/* + * split up a string into a vector of strings based on the given delimiter + */ +std::vector split_string(std::string &str, + const std::string &delimiter); + +/* + * change directory + */ +int cd(const char *str); + +/* + * Prints a banner. + */ +void PRINT_BANNER(); + +/* + * Clears the screen. + */ +void clear(); + +#endif // EOS_UTILITY_H