diff options
author | Singustromo <singustromo@disroot.org> | 2024-05-19 03:49:20 +0200 |
---|---|---|
committer | Singustromo <singustromo@disroot.org> | 2024-05-19 03:49:20 +0200 |
commit | b5834f69641f54110c78d8d642cb6afa5b3a124e (patch) | |
tree | 2612d86b71f1d67612b7d929b516777827e8ab29 | |
parent | 5cd0bbde6fbe6325d00bb5e1b2b7331757f0dcf3 (diff) | |
download | operating-systems_3_clash-b5834f69641f54110c78d8d642cb6afa5b3a124e.tar.gz operating-systems_3_clash-b5834f69641f54110c78d8d642cb6afa5b3a124e.zip |
Crude first implementation
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | src/clash.c | 148 | ||||
-rw-r--r-- | src/clash.h | 0 | ||||
-rw-r--r-- | src/plist.c | 4 |
4 files changed, 151 insertions, 9 deletions
diff --git a/Makefile b/Makefile index 59ba575..9e6f02c 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,12 @@ -.PHONY: clean test test-spec - -SHELL = /bin/bash +.PHONY: clean CC = gcc -CFLAGS = -Wall -Werror -std=c11 -pedantic -D_XOPEN_SOURCE=700 +CFLAGS = -std=c11 -pedantic -Wall -Werror -D_XOPEN_SOURCE=700 -O0 -g VPATH=src # search for a prerequisite in those directories (delimiter is :) BUILD_TARGET=clash BUILD_DIR=bin -OBJS = $(patsubst %.o, $(BUILD_DIR)/%.o, plist.o $(BUILD_TARGET).o) +OBJS = $(patsubst %.o, $(BUILD_DIR)/%.o, plist.o strictmem.o $(BUILD_TARGET).o) $(BUILD_TARGET): $(OBJS) $(CC) -o $@ $(CFLAGS) $(OBJS) diff --git a/src/clash.c b/src/clash.c index e41edc3..2717e1f 100644 --- a/src/clash.c +++ b/src/clash.c @@ -1,8 +1,152 @@ +#include <stdio.h> #include <stdlib.h> +#include <stdbool.h> + +#include <unistd.h> +#include <string.h> // e.g. strtok +#include <linux/limits.h> // e.g. PATH_MAX +#include <sys/wait.h> -#include "clash.h" #include "plist.h" -int main(int argc, char* argv[]) { +#define PROMPTSIZE 1337 +#define MAX_PARAMETERS 50 + +static int getline_skew(char *buffer, int limit); + +static bool update_current_path(char *path); +static void print_prompt(char *current_path, int child_exitcode, int job_count); + +static int process_commandline(char *prompt, char **command, char *parameters[]); + +int main(int argc, char *argv[]) { + char current_path[PATH_MAX]; + char prompt[PROMPTSIZE]; + + if (! update_current_path(current_path)) + exit(EXIT_FAILURE); + + int prompt_length, cmdline_arg_count; + prompt_length = cmdline_arg_count = 0; + + char *command = NULL, *cmdline[MAX_PARAMETERS]; + int background_jobs = 0; + + print_prompt(current_path, 0, 0); + while ((prompt_length = getline_skew(prompt, PROMPTSIZE)) > 0) { + if (prompt_length == 1) { + print_prompt(current_path, 0, 0); + continue; + } else if (prompt_length > PROMPTSIZE) { + fprintf(stderr, "[!] input line is too long!\n"); + print_prompt(current_path, 0, 0); + continue; + } + + if ((cmdline_arg_count = process_commandline(prompt, &command, cmdline)) < 1) { + printf("[!] "); + print_prompt(current_path, 0, 0); + continue; + } + + bool background_job = false; + + // Determine, if it should be executed in the background + if (strcmp(cmdline[cmdline_arg_count -1], "&") == 0) { // we only check last token + cmdline[cmdline_arg_count -1] = NULL; // for exec + background_job = true; + } else + cmdline[cmdline_arg_count] = NULL; + + int wstatus = 0; // status information of child process + pid_t child_pid = fork(); + if (child_pid == -1) { + perror("[!] fork"); + print_prompt(current_path, 0, background_jobs); + continue; + } else if (child_pid == 0) // child process + if (execvp(command, cmdline) == -1) // command failed? + exit(EXIT_FAILURE); + + if (! background_job) { + do { + child_pid = wait(&wstatus); + } while (! WIFEXITED(wstatus) && ! WIFSIGNALED(wstatus)); + } else { + insertElement(child_pid, prompt); + printf("[%d] %d\n", ++background_jobs, child_pid); + } + + print_prompt(current_path, WEXITSTATUS(wstatus), background_jobs); + } + + puts("\0"); // terminate output properly exit(EXIT_SUCCESS); } + +/* Saves address of tokens into command pointer and parameter pointer array + * command is duplicated into array[0] + * + * @returns token count (0 on error) + */ +static int process_commandline(char *prompt, char **command, char *parameters[]) { + char *previous_token, *current_token; + int token_index = 0; + + *command = strtok(prompt, "\n\t "); // do not include new line + if (! *command) return token_index; + + // according to specification argv[0] + parameters[token_index++] = *command; + + previous_token = prompt; + while ((current_token = strtok(NULL, "\n\t ")) != NULL) { + if (previous_token > prompt) + parameters[token_index++] = previous_token; + + previous_token = current_token; + } + + if (previous_token > prompt) // still need to save pointer of another token? + parameters[token_index++] = previous_token; + + return token_index; +} + +static void print_prompt(char *current_path, int child_exitcode, int job_count) { + if (child_exitcode != 0) + printf("[%d] ", child_exitcode); + + printf("%s: ", current_path); +} + +static bool update_current_path(char *path) { + if (getcwd(path, PATH_MAX) == NULL) { + perror("[!] unable to get current working directory"); + return false; + } + + return true; +} + +/* + * Reads data until new line or up to (limit -1) characters (NUL byte) + * If limit is reached, it truncates the rest of the line and + * updates the character count accordingly. Omits new line + * + * @returns character count (counts new line) + */ +static int getline_skew(char *buffer, int limit) { + int c, charcount; + + for (charcount = 0; (c = getchar()) != EOF && c != '\n'; ++charcount) + if (charcount < limit) // otherwise seek further + buffer[charcount] = c; + + if (c == '\n' && charcount < limit) + buffer[charcount++] = c; + + buffer[(charcount < limit) ? charcount: limit -1] = '\0'; + + return charcount; +} diff --git a/src/clash.h b/src/clash.h deleted file mode 100644 index e69de29..0000000 --- a/src/clash.h +++ /dev/null diff --git a/src/plist.c b/src/plist.c index 2767e34..9a60330 100644 --- a/src/plist.c +++ b/src/plist.c @@ -20,8 +20,8 @@ static struct queue_element *head; void walkList(bool (*callback) (pid_t, const char *)) { struct queue_element* current = head; - while (current && (callback(current->pid, current->cmdLine) != 0)) - ; + while (current && (callback(current->pid, current->cmdLine) == false)) + current = current->next; } int insertElement(pid_t pid, const char *cmdLine) { |