#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); } }