#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include #define ARG_SEP " " /* Argument separator for commands */ #define PROMPT " $ " char** create_argv(char* command); int get_argc(char* command); char* prompt(); int cd(char* path); int main() { char** argv; char* user_input; pid_t child_pid; int stat_loc; /* ??? (Needed for waitpid) */ signal(SIGINT, SIG_IGN); while(1) { user_input = prompt(); argv = create_argv(user_input); if(strcmp(argv[0], "cd") == 0) { if(cd(argv[1]) < 0) { perror(argv[1]); } /* causes the fork to get skipped */ continue; } else if(strcmp(argv[0], "exit") == 0 || strcmp(argv[0], "quit") == 0) { exit(0); } child_pid = fork(); if(child_pid < 0) { /* Could not start child process. Check why and error out. */ if(errno == EAGAIN) { perror("Could not execute command: insufficient resources"); exit(1); } else if(errno == ENOMEM) { /* Is this out of RAM or out of storage? */ perror("Could not execute command: insufficient storage space"); exit(1); } else { perror("Could not execute command: unknown failure"); exit(1); } } else if(child_pid == 0) { /* We are the child, so allow ^C */ signal(SIGINT, SIG_DFL); if(execvp(argv[0], argv) < 0) { perror(argv[0]); exit(1); } } else { /* Wait for the child to finish */ waitpid(child_pid, &stat_loc, WUNTRACED); } free(user_input); free(argv); } return 0; } char** create_argv(char* command) { int argc = get_argc(command) + 1; char* temp; int i = 0; char** argv = calloc(argc, sizeof(*argv)); if(argv == NULL) { perror("Unable to parse command: could not allocate memory"); exit(1); } for(temp = strtok(command, ARG_SEP); temp != NULL; temp = strtok(NULL, ARG_SEP)) { argv[i] = temp; i++; } /* Set last item in argv to NULL, since execvp requires it */ argv[i] = NULL; return argv; } char* prompt() { char cwd[PATH_MAX]; getcwd(cwd, sizeof(cwd)); char* bname = basename(cwd); char prompt[PATH_MAX + 5] = ""; strcat(prompt, bname); strcat(prompt, PROMPT); char* input = calloc(LINE_MAX, sizeof(*input)); if(input == NULL) { perror("Unable to read command: could not allocate memory"); exit(1); } printf("%s", prompt); fgets(input, LINE_MAX, stdin); input[strcspn(input, "\r\n")] = '\0'; return input; } int get_argc(char* command) { int argc = 0, word = 0; char* command_iter = command; do { switch(*command_iter) { case '\0': case ' ': case '\t': if(word) { word = 0; argc++; } default: word = 1; } } while(*(command_iter++)); return argc; } int cd(char* path) { return chdir(path); }