commit ed16684cf50e2525072861cfd06e19ca4410b54f Author: iceyrazor Date: Mon Feb 9 13:24:11 2026 -0600 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..534cfcc --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.clangd +bin/** diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e4e5954 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 iceyrazor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/make b/make new file mode 100755 index 0000000..54d8b21 --- /dev/null +++ b/make @@ -0,0 +1,9 @@ +#!/bin/sh +LIB="" + +echo make +if [[ "$1" == "debug" ]]; then + clang -o ./bin/shell ./src/main.c $LIB -Wall -g -fsanitize=address +else + clang -o ./bin/shell ./src/main.c $LIB +fi diff --git a/src/main.c b/src/main.c new file mode 100755 index 0000000..e07319a --- /dev/null +++ b/src/main.c @@ -0,0 +1,239 @@ +#include +#include +#include +#include +#include + +#define LSH_RL_BUFSIZE 1024 +char *lsh_read_line(void) +{ + int bufsize = LSH_RL_BUFSIZE; + int position = 0; + char *buffer = malloc(sizeof(char) * bufsize); + int c; + + if (!buffer) { + fprintf(stderr, "lsh: allocation error\n"); + exit(EXIT_FAILURE); + } + + while (1) { + // Read a character + c = getchar(); + + // If we hit EOF, replace it with a null character and return. + if (c == EOF || c == '\n') { + buffer[position] = '\0'; + return buffer; + } else { + buffer[position] = c; + } + position++; + + // If we have exceeded the buffer, reallocate. + if (position >= bufsize) { + bufsize += LSH_RL_BUFSIZE; + buffer = realloc(buffer, bufsize); + if (!buffer) { + fprintf(stderr, "lsh: allocation error\n"); + exit(EXIT_FAILURE); + } + } + } +} + +#define LSH_TOK_BUFSIZE 64 +#define LSH_TOK_DELIM " \t\r\n\a" +char **lsh_split_line(char *line) +{ + int bufsize = LSH_TOK_BUFSIZE, position = 0; + char **tokens = malloc(bufsize * sizeof(char*)); + char *token; + + if (!tokens) { + fprintf(stderr, "lsh: allocation error\n"); + exit(EXIT_FAILURE); + } + + token = strtok(line, LSH_TOK_DELIM); + while (token != NULL) { + tokens[position] = token; + position++; + + if (position >= bufsize) { + bufsize += LSH_TOK_BUFSIZE; + tokens = realloc(tokens, bufsize * sizeof(char*)); + if (!tokens) { + fprintf(stderr, "lsh: allocation error\n"); + exit(EXIT_FAILURE); + } + } + + token = strtok(NULL, LSH_TOK_DELIM); + } + tokens[position] = NULL; + return tokens; +} + +int lsh_launch(char **args) +{ + pid_t pid, wpid; + int status; + + pid = fork(); + if (pid == 0) { + // Child process + if (execvp(args[0], args) == -1) { + perror("lsh"); + } + exit(EXIT_FAILURE); + } else if (pid < 0) { + // Error forking + perror("lsh"); + } else { + // Parent process + do { + wpid = waitpid(pid, &status, WUNTRACED); + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + } + + return 1; +} + +/* + Function Declarations for builtin shell commands: + */ +int lsh_cd(char **args); +int lsh_help(char **args); +int lsh_exit(char **args); + +/* + List of builtin commands, followed by their corresponding functions. + */ +char *builtin_str[] = { + "cd", + "help", + "exit" +}; + +int (*builtin_func[]) (char **) = { + &lsh_cd, + &lsh_help, + &lsh_exit +}; + +int lsh_num_builtins() { + return sizeof(builtin_str) / sizeof(char *); +} + +/* + Builtin function implementations. +*/ +int lsh_cd(char **args) +{ + if (args[1] == NULL) { + fprintf(stderr, "lsh: expected argument to \"cd\"\n"); + } else { + if (chdir(args[1]) != 0) { + perror("lsh"); + } + } + return 1; +} + +int lsh_help(char **args) +{ + int i; + printf("Stephen Brennan's LSH\n"); + printf("Type program names and arguments, and hit enter.\n"); + printf("The following are built in:\n"); + + for (i = 0; i < lsh_num_builtins(); i++) { + printf(" %s\n", builtin_str[i]); + } + + printf("Use the man command for information on other programs.\n"); + return 1; +} + +int lsh_exit(char **args) +{ + return 0; +} + + + +int lsh_execute(char **args) +{ + int i; + + if (args[0] == NULL) { + // An empty command was entered. + return 1; + } + + for (i = 0; i < lsh_num_builtins(); i++) { + if (strcmp(args[0], builtin_str[i]) == 0) { + return (*builtin_func[i])(args); + } + } + + return lsh_launch(args); +} + + +typedef struct{ + char *prompt; +} SHELL_OB; + +void lsh_loop(SHELL_OB *shell_obj) +{ + char *line; + char **args; + int status; + + do { + printf("%s",shell_obj->prompt); + line = lsh_read_line(); + args = lsh_split_line(line); + status = lsh_execute(args); + + free(line); + free(args); + } while (status); +} + +int main(int argc, char **argv){ + SHELL_OB shell_obj; + + //very jank lol + char *hostname = NULL; + long file_size; + FILE *hostfile = fopen("/etc/hostname","r"); + if (hostfile != NULL){ + fseek(hostfile, 0, SEEK_END); + file_size = ftell(hostfile); + rewind(hostfile); + + hostname = (char *)malloc(file_size + 1 + 24); + fread(hostname, file_size, 1, hostfile); + hostname[file_size+1] = '\0'; + + fclose(hostfile); + + for (int i = file_size-1; i > -1; i--){ + hostname[i+1] = hostname[i]; + } + hostname[0] = '@'; + hostname[file_size] = '\0'; + } else { + hostname = (char *)malloc(1); + hostname[0] = '\0'; + } + shell_obj.prompt=strcat(strcat(getenv("USER"), (char *)hostname), "> "); + + lsh_loop(&shell_obj); + + free(hostname); + return EXIT_SUCCESS; +}