From c1210928632586c10b9683652df0c5590fb3ef01 Mon Sep 17 00:00:00 2001 From: s492459 Date: Sat, 4 Jan 2025 14:30:25 +0100 Subject: [PATCH] vanilla --- .vscode/c_cpp_properties.json | 16 ++++ .vscode/launch.json | 39 ++++++++++ .vscode/settings.json | 6 ++ .vscode/tasks.json | 37 ++++++++++ main.c | 134 ++++++++++++++++++++++++++++++++++ 5 files changed, 232 insertions(+) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 main.c diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..4039bef --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,16 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c17", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..91d5397 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,39 @@ +{ + "configurations": [ + { + "name": "C/C++: gcc build and debug active file", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/a.out", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + }, + // { "description":"In this mode GDB will be attached to both processes after a call to fork() or vfork().", + // "text": "-gdb-set detach-on-fork off", + // "ignoreFailures": true + // }, + // { "description": "The new process is debugged after a fork. The parent process runs unimpeded.", + // "text": "-gdb-set follow-fork-mode child", + // "ignoreFailures": true + // } + ], + "preLaunchTask": "build main_logging.c", + "miDebuggerPath": "/usr/bin/gdb" + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d6536fa --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "files.associations": { + "unistd.h": "c", + "wait.h": "c" + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..6706c60 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,37 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build main.c", + "type": "shell", + "command": "/usr/bin/gcc", + "args": [ + "-g", + "main.c", + "-o", + "a.out" + ], + "group": "build", + "problemMatcher": [ + "$gcc" + ], + "detail": "Build the main.c file using gcc" + }, + { + "label": "build main_logging.c", + "type": "shell", + "command": "/usr/bin/gcc", + "args": [ + "-g", + "main_logging.c", + "-o", + "a.out" + ], + "group": "build", + "problemMatcher": [ + "$gcc" + ], + "detail": "Build the main_logging.c file using gcc" + } + ] +} \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..051e936 --- /dev/null +++ b/main.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SIZE 1024 + +// int LogCommandHistory(char* buf, char** command_log, int n) { +// command_log[n] = buf; +// } + +void PrintCurrentDir() { // pwd + char cwd[MAX_SIZE]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + printf("[%s] $ ", cwd); + } else { + perror("getcwd() error"); + } +} + +int ChangeDirectory(char** args) { // cd + args++; // Moving pointer to the next element (cd requires local or global path, the first argument is command name, so it's skipped) + char* path = args[0]; + if (path == NULL || strcmp(path, "~") == 0) { + path = getenv("HOME"); + } + if (chdir(path) != 0) { + perror("cd"); + return -1; + } + return 0; +} + +void PrintHelp() { // help + printf("C Microshell implementation by Maciej Życzyński\n"); +} + +int HandleBuiltInCommands(char* command, char** args) { // Manual implementation of commands unsupported by execvp() + if (strcmp(command, "cd") == 0) { + ChangeDirectory(args); + return 1; + } + else if (strcmp(command, "help") == 0) { + PrintHelp(); + return 1; + } + else if (strcmp(command, "exit") == 0) { + return 2; + } + return 0; +} + +int HandleCommand(char* command, char** args) { // Execute commands supported by execvp() + if (execvp(command, args) == -1) { + perror("Error executing command"); + return -1; + } + return 0; +} + +int ParseCommand(char* buf, char** command, char** args) { + char buf_cp[MAX_SIZE]; + strcpy(buf_cp, buf); // Leave the original buffer (important for command history implementation) + buf_cp[strlen(buf_cp) - 1] = '\0'; // Remove newline from input string + + char* token = strtok(buf_cp, " "); + int tok_count = 0; + + if (token == NULL) { // Retrieve command and arguments + return -1; + } + *command = token; + + while (token != NULL) { + args[tok_count] = token; + tok_count++; + token = strtok(NULL, " "); + } + args[tok_count] = NULL; // Manually add NULL at the end (execvp() requires the argument array to be null-terminated) + + return 0; +} + +int main() { + char buf[MAX_SIZE]; + char* command_log[MAX_SIZE]; + int n = 0; + + while (1) { + PrintCurrentDir(); + + char* command; + char* args[MAX_SIZE]; + fgets(buf, sizeof(buf), stdin); + + if (ParseCommand(buf, &command, args) < 0) { + printf("Invalid command\n"); + continue; + } + + // LogCommandHistory(buf, &command_log, n); + // n++; + + int handler_value = HandleBuiltInCommands(command, args); + if (handler_value == 2) { // Exit command + break; + } + else if (handler_value == 0) { // Not a built-in command + + // Forking logic + pid_t pid = fork(); + if (pid < 0) { + perror("Error while forking\n"); + } + else if (pid == 0) { // Child process + if (HandleCommand(command, args) == -1) { + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); + } + else { // Parent process + int status; + if (waitpid(pid, &status, 0) == -1) { + perror("Error with parent process\n"); + } + } + } + } + + return 0; +} \ No newline at end of file