diff --git a/make b/make index 54d8b21..69155c3 100755 --- a/make +++ b/make @@ -1,7 +1,7 @@ #!/bin/sh LIB="" -echo make +printf -- "\n\nmake\n" if [[ "$1" == "debug" ]]; then clang -o ./bin/shell ./src/main.c $LIB -Wall -g -fsanitize=address else diff --git a/src/helper_functions.c b/src/helper_functions.c new file mode 100644 index 0000000..9427b87 --- /dev/null +++ b/src/helper_functions.c @@ -0,0 +1,54 @@ +#ifndef shell_helper_functions +#define shell_helper_functions + +#include +#include + +// You must free the result if result is non-NULL. +char *str_replace(char *orig, char *rep, char *with) { + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; (tmp = strstr(ins, rep)); ++count) { + ins = tmp + len_rep; + } + + tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if (!result) + return NULL; + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} + +#endif diff --git a/src/lsh_builtins.c b/src/lsh_builtins.c new file mode 100644 index 0000000..34aced5 --- /dev/null +++ b/src/lsh_builtins.c @@ -0,0 +1,91 @@ +#ifndef shell_builtins +#define shell_builtins + +#include "lsh_main_func.c" +#include +#include +#include + +/* + 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); +} + +#endif diff --git a/src/lsh_main_func.c b/src/lsh_main_func.c new file mode 100644 index 0000000..af20b1b --- /dev/null +++ b/src/lsh_main_func.c @@ -0,0 +1,106 @@ +#ifndef shell_main_func +#define shell_main_func + +#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; +} + +#endif diff --git a/src/main.c b/src/main.c index e07319a..a107950 100755 --- a/src/main.c +++ b/src/main.c @@ -4,183 +4,8 @@ #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); -} - +#include "lsh_main_func.c" +#include "lsh_builtins.c" typedef struct{ char *prompt; @@ -206,31 +31,11 @@ void lsh_loop(SHELL_OB *shell_obj) 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); + //get the hostname + char *hostname = (char *)malloc(sizeof(char) * 1024); + gethostname(hostname,sizeof(char) * 1024); - 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), "> "); + shell_obj.prompt=strcat(strcat(strcat(getenv("USER"), "@"), (char *)hostname), "> "); lsh_loop(&shell_obj);