#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; //The command with arguments char* user_input; pid_t child_pid; int stat_loc; //??? (Needed for waitpid) signal(SIGINT, SIG_IGN); //Tell vsh to ignore SIGINT (^C) while(1) { user_input = prompt(); argv = create_argv(user_input); if(strcmp(argv[0], "cd") == 0) { if(cd(&user_input[3]) < 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) { //If the child couldn't run, assume no memory perror("Out of memory"); exit(1); } else if(child_pid == 0) { //If we are the child, allow ^C signal(SIGINT, SIG_DFL); if(execvp(argv[0], argv) < 0) { perror(argv[0]); exit(1); } } else { 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) { //If couldn't allocate argv, assume no memory perror("Out of 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(512, sizeof(*input)); if(input == NULL) { //If input allocate failed, assume no memory perror("Out of memory"); exit(1); } printf("%s", prompt); fgets(input, 512, stdin); //Is 512 enough? What about really long commands? 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); }