#include #include #include #include #include #include #include #include #include #include int position = 0; char pwd[128]; // FIXME: change to PATH_MAX char hostname[1024]; // Hostname of machine struct passwd *pw; // Struct of passwd for uid char *username; // Current username char *homedir; // HOME directory of current user pid_t shell_pid; // pid of current shell (gets only on start) pid_t pid; // FIXME: this shouldn't be global i think char prompt[2048]; char **split_line(char *line, char *delim) { int bufsize = 64; position = 0; char **tokens = malloc(bufsize * sizeof(char*)); char *token; if (!tokens) { fprintf(stderr, "orsh: allocation error\n"); exit(EXIT_FAILURE); } token = strtok(line, delim); while (token != NULL) { tokens[position] = token; position++; token = strtok(NULL, delim); } tokens[position] = NULL; return tokens; } int execute(char **command, int status) { status = 0; pid_t wpid; pid = fork(); if (pid == 0) { // Child process if (execvp(command[0], command) == -1) { perror("orsh"); } status = 1; // FIXME: add error status exit(EXIT_FAILURE); } else if (pid < 0) { // Error forking perror("orsh"); status = 1; // FIXME: add error status } else { // Parent process do { wpid = waitpid(pid, &status, WUNTRACED); // FIXME: warning unused variable } while (!WIFEXITED(status) && !WIFSIGNALED(status)); } if (status >= 256) status = 1; return status; } int parse_command(char **command, int status) { int variable = 0; int where_var[position - 1]; for (int i = 0; i <= position - 1; i++) { // Loop for checking if line has variable if (command[i][0] == '$') { // FIXME where_var[i] = 1; variable++; } else if (command[i][0] == '~') { // FIXME command[i] = homedir; } } if (variable >= 1) { for (int i = 0; i <= position - 1; i++) { if(where_var[i] == 1) { command[i]++; // Deleting '$' char if(!strcmp(command[i], "?")) { char status_string[256]; // FIXME sprintf(status_string, "%d", status); command[i] = status_string; } else { command[i] = getenv(command[i]); if (command[i] == NULL) command[i] = ""; } } } } if (command[0][strlen(command[0]) - 1] == ';'){ // FIXME: parse all word not only first command[0][strlen(command[0])-1] = '\0'; } else if (command[0][0] == ';'){ // Check if command is ; or first char of command is ; command[0][0] = '\0'; } if (status >= 256) status = 1; if (!strcmp(command[0], "exit")) { // FIXME: add switch statement (if possible) printf("exit\n"); exit(0); } else if (!strcmp(command[0], "echo")) { for (int i = 1; i <= position - 1; i++) printf("%s ", command[i]); printf("\n"); return 0; } else if (!strcmp(command[0], "cd")) { if (position == 1) { chdir(homedir); getcwd(pwd, sizeof(pwd)); } else if (position >= 3) { printf("orsh: cd: too many arguments\n"); } else { chdir(command[1]); getcwd(pwd, sizeof(pwd)); } } else if (!strcmp(command[0], "pwd")) { printf("%s\n", pwd); } else if (!strcmp(command[0], "export")) { for (int i = 1; i <= position - 1; i++) { status = putenv(command[i]); if (status != 0) return status; } } else if (!strcmp(command[0], "!")) { if (status != 0) status = 0; else if (status == 0) status = 1; } else { status = execute(command, status); } return status; } void init() { // Some initial tasks getcwd(pwd, sizeof(pwd)); // Get directory where shell was started gethostname(hostname, sizeof(hostname)); // Get hostname pw = getpwuid(getuid()); // Get passwd struct for current uid username = pw->pw_name; homedir = pw->pw_dir; shell_pid = getpid(); } void gen_prompt() { // TODO: add parsing config file if (!strcmp(pwd, homedir)) { sprintf(prompt, "%s@%s %s> ", username, hostname, "~"); } else { sprintf(prompt, "%s@%s %s> ", username, hostname, basename(pwd)); } } void signal_handler(int sig) { if (pid == 0 || shell_pid == getpid()) { printf("\n"); printf("%s", prompt); } else raise(sig); } int main(int argc, char *argv[]) { char *line = NULL; char script_line[100]; // FIXME init(); char** commands; char** args; int status = 0; // FIXME int command_status = 0; // FIXME signal(SIGINT, signal_handler); if (argc >= 2) { FILE *script = fopen(argv[1], "r"); if (script == NULL) { printf("Error opening file: %s\n", argv[1]); // FIXME: add proper error message return 1; } while (fgets(script_line, 100, script) != NULL) { args = split_line(script_line, " "); command_status = parse_command(args, command_status); } } else { using_history(); while(1) { gen_prompt(); line = readline(prompt); // FIXME: add prompt if (line == NULL) { printf("exit\n"); break; } add_history(line); commands = split_line(line, ";"); int after_parse_position = position; // To know where we in ; list FIXME for (int i = 0; i <= after_parse_position - 1; i++) { args = split_line(commands[i], " "); command_status = parse_command(args, command_status); } } } return command_status; }