From 53fc85a9e64c48e19ad3cc4a2ad14ce3639943a8 Mon Sep 17 00:00:00 2001 From: g1n Date: Fri, 17 Sep 2021 18:24:48 +0300 Subject: [PATCH] Initial commit --- README.org | 12 +++++ src/Makefile | 14 ++++++ src/main.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 README.org create mode 100644 src/Makefile create mode 100644 src/main.c diff --git a/README.org b/README.org new file mode 100644 index 0000000..482b37d --- /dev/null +++ b/README.org @@ -0,0 +1,12 @@ +#+TITLE: GRU orsh - simple shell on C + +** Features: + - echo and pwd builtin + - working environment variables + +** How to build: + - cd src + - make + - orsh is executable of shell + + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..12bbfe1 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,14 @@ +CC = gcc +CFLAGS= -O2 -Wall -Wextra +LFLAGS= + +SRCFILES= main.c +OBJFILES= orsh + +.PHONY: all clean + +all: main + +main: + $(CC) $(CFLAGS) $(SRCFILES) -o $(OBJFILES) + diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d2a3d4e --- /dev/null +++ b/src/main.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include + +int position = 0; +char pwd[128]; // FIXME: change to PATH_MAX + +char **split_line(char *line) { + int bufsize = 64; + position = 0; + char **tokens = malloc(bufsize * sizeof(char*)); + char *token; + + if (!tokens) { + fprintf(stderr, "orsh: allocation error\n"); + exit(EXIT_FAILURE); + } + + token = strtok(line, " "); + while (token != NULL) { + tokens[position] = token; + position++; + token = strtok(NULL, " "); + } + tokens[position] = NULL; + return tokens; +} + +int execute(char **command, int status) { + status = 0; + pid_t pid, wpid; + + pid = fork(); + if (pid == 0) { + // Child process + if (execvp(command[0], command) == -1) { + perror("orsh"); + } + status = 1; // FIXME: add error status + exit(EXIT_FAILURE); + } else if (pid < 0) { + // Error forking + perror("orsh"); + status = 1; // FIXME: add error status + } else { + // Parent process + do { + wpid = waitpid(pid, &status, WUNTRACED); // FIXME: warning unused variable + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + } + + + return status; +} + +int parse_command(char **command) { + int variable = 0; + int where_var[position - 1]; + for (int i = 0; i <= position - 1; i++) { // Loop for checking if line has variable + if (command[i][0] == '$') { + where_var[i] = 1; + variable++; + } + } + if (variable >= 1) { + for (int i = 0; i <= position - 1; i++) { + if(where_var[i] == 1) { + command[i]++; // Deleting '$' char + command[i] = getenv(command[i]); + } + } + } + + int status = 0; // FIXME: add status as argument (to know status of last command) + + if (command[0][strlen(command[0]) - 1] == ';'){ // FIXME: parse all word not only first + command[0][strlen(command[0])-1] = '\0'; + } else if (command[0][0] == ';'){ // Check if command is ; or first char of command is ; + command[0][0] = '\0'; + } + + if (!strcmp(command[0], "exit")) { // FIXME: add switch statement (if possible) + printf("exit\n"); + exit(0); + } else if (!strcmp(command[0], "echo")) { + for (int i = 1; i <= position - 1; i++) + printf("%s ", command[i]); + printf("\n"); + return 0; + } else if (!strcmp(command[0], "cd")) { + if (position == 1) { + printf("HOME todo\n"); + } else if (position >= 3) { + printf("orsh: cd: too many arguments\n"); + } else { + chdir(command[1]); + getcwd(pwd, sizeof(pwd)); + } + } else if (!strcmp(command[0], "pwd")) { + printf("%s\n", pwd); + } else { + status = execute(command, status); + } + return status; +} + +int main() {//int argc, char *argv[]) { + char *line = NULL; + size_t len = 0; + char** args; + int status = 0; // FIXME + int command_status = 0; // FIXME + getcwd(pwd, sizeof(pwd)); + while(1) { + printf("orsh> "); // FIXME or TODO: add PS1 var + status = getline(&line, &len, stdin); + if (status == EOF) { + printf("\nexit\n"); + break; + } + line[strlen(line) - 1] = '\0'; + args = split_line(line); + + command_status = parse_command(args); + + } + return command_status; +}