vanilla
This commit is contained in:
commit
c121092863
16
.vscode/c_cpp_properties.json
vendored
Normal file
16
.vscode/c_cpp_properties.json
vendored
Normal file
@ -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
|
||||||
|
}
|
39
.vscode/launch.json
vendored
Normal file
39
.vscode/launch.json
vendored
Normal file
@ -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"
|
||||||
|
}
|
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"unistd.h": "c",
|
||||||
|
"wait.h": "c"
|
||||||
|
}
|
||||||
|
}
|
37
.vscode/tasks.json
vendored
Normal file
37
.vscode/tasks.json
vendored
Normal file
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
134
main.c
Normal file
134
main.c
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user