commit 70ab6da52b9ca530d37e49e4ac35f5e24d6a2a1c Author: Kamil Sowiński Date: Mon Jul 9 22:03:45 2018 +0200 Intial commit diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..93fafcb --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +myshell: main.c + gcc -o myshell main.c -I . \ No newline at end of file diff --git a/main.c b/main.c new file mode 100755 index 0000000..4ed2b14 --- /dev/null +++ b/main.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include + +// Removes new line from string +char *remove_nl(char *p) { + char *nl = strchr( p, '\n' ); + if (nl) + *nl = 0; + memset(nl, 0, sizeof nl); + return p; +} + +// Checks for env variables in string and set them if found +int set_evar(char *evar) { + char *end_evar; + char *value; + char *key; + + key = strtok_r(evar, "=", &end_evar); + value = strtok_r(NULL, "=", &end_evar); + + setenv(key, value, 1); + + memset(evar, 0, sizeof evar); + memset(end_evar, 0, sizeof end_evar); + memset(key, 0, sizeof key); + memset(value, 0, sizeof value); + + return 0; +} + +// Displays basic shell prompt +int display_prompt() { + char hostname[1024]; + char cwd[1024]; + char *username_p; + + gethostname(hostname, 1024); + username_p = getenv("USER"); + getcwd(cwd, 1024); + + printf("[%s@%s %s] $ ", hostname, username_p, cwd); + + // Flush memory + memset(hostname, 0, sizeof hostname); + memset(cwd, 0, sizeof cwd); + + return 0; +} + +// Commands +int my_exit(char *param_list[64]) { + if (param_list[0] != NULL) { + exit( (int)strtol(param_list[0], NULL, 0) ); + } else { + exit(0); + } +} + +int my_cd(char *param_list[64]) { + if (param_list[0] != NULL) { + if (chdir(param_list[0]) == -1) { + printf("cd: %s: %s\n", param_list[0], strerror(errno)); + return 1; + } + } + + return 0; +} + +int my_kill(char *param_list[64]) { + if (param_list[0] != NULL) { + int process_pid = (int)strtol(param_list[0], NULL, 0); + + if (process_pid > 0) { + if (kill(process_pid, SIGKILL) == -1) { + printf("kill: %s\n", strerror(errno)); + memset(&process_pid, 0, sizeof process_pid); + return 1; + } else { + printf("kill: Killing process %d", process_pid); + memset(&process_pid, 0, sizeof process_pid); + return 0; + } + } else { + printf("kill: Invalid PID: %s\n" , param_list[0]); + memset(&process_pid, 0, sizeof process_pid); + return 1; + } + } else { + printf("Please specify PID\n"); + return 1; + } +} + +// Allows you to run subshell +int my_myshell() { + pid_t child_pid; + child_pid = fork(); + + if (child_pid != 0) { + waitpid(child_pid, NULL, 0); //Wait for child + } +} + +int main() { + char input[1024]; + char *input_p; + char *param_p; + char *command_p; + char *param_list[64]; + char evar[256]; + pid_t child_pid; + + while (1) { + evar[0] = '\0'; + display_prompt(); + + fgets(input, 1024, stdin); + + input_p = input; + input_p = remove_nl(input_p); + + command_p = strtok(input_p, " "); + + if (command_p != NULL) { + if (strchr(command_p, '=') != NULL) { + strcpy(evar, command_p); + command_p = strtok(NULL, " "); + } + + if (!command_p || !command_p[0]) { + if (evar[0] != '\0') { + set_evar(evar); + } + } else { + param_p = strtok(NULL, " "); + + int i = 0; + do { + param_list[i] = param_p; + param_p = strtok(NULL, " "); + i=i+1; + } while(param_p != NULL); + memset(&i, 0, sizeof i); + + if (strcmp(command_p, "exit") == 0) { + my_exit(param_list); + } else if (strcmp(command_p, "cd") == 0) { + my_cd(param_list); + } else if (strcmp(command_p, "kill") == 0) { + my_kill(param_list); + } else if (strcmp(command_p, "myshell") == 0) { + my_myshell(); + } else if (strcmp(command_p, "help") == 0) { + printf(" MyShell is Bash-like shell written in C\n"); + printf(" Available commands: cd, kill, myshell, help, version, exit\n"); + } else if (strcmp(command_p, "version") == 0) { + printf(" Version: 0.0.1\n Author: Kamil Sowińśki\n"); + } else { + child_pid = fork(); + if (child_pid == 0) { + char *args[66]; + int i = 1; + int param_list_s = sizeof(param_list) / sizeof(param_list[0]); + + if (evar[0] != '\0') { + set_evar(evar); + } + + args[0] = command_p; + while (i < param_list_s) { + args[i] = param_list[i - 1]; + i++; + } + args[i] = NULL; + memset(&i, 0, sizeof i); + + if (execvp(command_p, args) == -1) { + printf("%s: command not found\n", command_p); + exit(1); + } + + memset(args, 0, sizeof args); + } else { + waitpid(child_pid, NULL, 0); //Wait for child + } + memset(command_p, 0, sizeof command_p); + } + } + } + + // Fush memory + memset(param_list, 0, sizeof param_list); + memset(input, 0, sizeof input); + memset(input_p, 0, sizeof input_p); + } +} \ No newline at end of file