int main() { init_dsh(); DEBUG("Successfully initialized\n"); while(1) { job_t *j = NULL; if(!(j = readcmdline(promptmsg(getpid())))) { if (feof(stdin)) { /* End of file (ctrl-d) */ fflush(stdout); printf("\n"); exit(EXIT_SUCCESS); } continue; /* NOOP; user entered return or spaces with return */ } /* Only for debugging purposes to show parser output; turn off in the * final code */ // if(PRINT_INFO) print_job(j); /* Your code goes here */ /* You need to loop through jobs list since a command line can contain ;*/ /* Check for built-in commands */ /* If not built-in */ /* If job j runs in foreground */ /* spawn_job(j,true) */ /* else */ /* spawn_job(j,false) */ while (j != NULL) { // if EOF builtincmd of quit //active jobs is last job? // if not a command at all ? bool is_built_in_cmd = builtin_cmd(j, (j->first_process)->argc, (j->first_process)->argv); if(!is_built_in_cmd) { if(j->bg == true) { spawn_job(j, false); } else { spawn_job(j, true); } if(active_jobs_head == NULL) { active_jobs_head = j; } else { job_t *lastJob = find_last_job(active_jobs_head); lastJob->next = j; j->next = NULL; } } j = j->next; } } }
bool readcmdline(char *msg) { print_colored_prompt(stdout, msg); char *cmdline = (char *)calloc(MAX_LEN_CMDLINE, sizeof(char)); if(!cmdline) return invokefree(NULL, "malloc: no space"); fgets(cmdline, MAX_LEN_CMDLINE, stdin); /* sequence is true only when the command line contains ; */ bool sequence = false; /* seq_pos is used for storing the command line before ; */ int seq_pos = 0; int cmdline_pos = 0; /*iterator for command line; */ while(1) { job_t *current_job = find_last_job(); int cmd_pos = 0; /* iterator for a command */ int iofile_seek = 0; /*iofile_seek for file */ bool valid_input = true; /* check for valid input */ bool end_of_input = false; /* check for end of input */ /* cmdline is NOOP, i.e., just return with spaces*/ while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */ if(cmdline[cmdline_pos] == '\n' || cmdline[cmdline_pos] == '\0' || feof(stdin)) return false; if (cmdline[cmdline_pos] == '#') //no commands, just a comment return false; /* Check for invalid special symbols (characters) */ if(cmdline[cmdline_pos] == ';' || cmdline[cmdline_pos] == '&' || cmdline[cmdline_pos] == '<' || cmdline[cmdline_pos] == '>' || cmdline[cmdline_pos] == '|') return false; char *cmd = (char *)calloc(MAX_LEN_CMDLINE, sizeof(char)); if(!cmd) return invokefree(NULL,"malloc: no space"); job_t *newjob = (job_t *)malloc(sizeof(job_t)); if(!newjob) return invokefree(NULL,"malloc: no space"); if(!first_job) first_job = current_job = newjob; else { current_job->next = newjob; current_job = current_job->next; } if(!init_job(current_job)) return invokefree(current_job,"init_job: malloc failed"); process_t *current_process = find_last_process(current_job); while(cmdline[cmdline_pos] != '\n' && cmdline[cmdline_pos] != '\0') { switch (cmdline[cmdline_pos]) { case '<': /* input redirection */ current_job->ifile = (char *) calloc(MAX_LEN_FILENAME, sizeof(char)); if(!current_job->ifile) return invokefree(current_job,"malloc: no space"); ++cmdline_pos; while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */ iofile_seek = 0; while(cmdline[cmdline_pos] != '\0' && !isspace(cmdline[cmdline_pos])){ if(MAX_LEN_FILENAME == iofile_seek) return invokefree(current_job,"input redirection: file length exceeded"); current_job->ifile[iofile_seek++] = cmdline[cmdline_pos++]; } current_job->ifile[iofile_seek] = '\0'; current_job->mystdin = INPUT_FD; while(isspace(cmdline[cmdline_pos])) { if(cmdline[cmdline_pos] == '\n') break; ++cmdline_pos; } valid_input = false; break; case '>': /* output redirection */ current_job->ofile = (char *) calloc(MAX_LEN_FILENAME, sizeof(char)); if(!current_job->ofile) return invokefree(current_job,"malloc: no space"); ++cmdline_pos; while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */ iofile_seek = 0; while(cmdline[cmdline_pos] != '\0' && !isspace(cmdline[cmdline_pos])){ if(MAX_LEN_FILENAME == iofile_seek) return invokefree(current_job,"input redirection: file length exceeded"); current_job->ofile[iofile_seek++] = cmdline[cmdline_pos++]; } current_job->ofile[iofile_seek] = '\0'; current_job->mystdout = OUTPUT_FD; while(isspace(cmdline[cmdline_pos])) { if(cmdline[cmdline_pos] == '\n') break; ++cmdline_pos; } valid_input = false; break; case '|': /* pipeline */ cmd[cmd_pos] = '\0'; process_t *newprocess = (process_t *)malloc(sizeof(process_t)); if(!newprocess) return invokefree(current_job,"malloc: no space"); if(!init_process(newprocess)) return invokefree(current_job,"init_process: failed"); if(!current_job->first_process) current_process = current_job->first_process = newprocess; else { current_process->next = newprocess; current_process = current_process->next; } if(!readprocessinfo(current_process, cmd)) return invokefree(current_job,"parse cmd: error"); ++cmdline_pos; cmd_pos = 0; /*Reinitialze for new cmd */ valid_input = true; break; case '&': /* background job */ current_job->bg = true; while (isspace(cmdline[cmdline_pos])){++cmdline_pos;} /* ignore any spaces */ if(cmdline[cmdline_pos+1] != '\n' && cmdline[cmdline_pos+1] != '\0') fprintf(stderr, "reading bg: extra input ignored"); end_of_input = true; break; case ';': /* sequence of jobs*/ sequence = true; strncpy(current_job->commandinfo,cmdline+seq_pos,cmdline_pos-seq_pos); seq_pos = cmdline_pos + 1; break; case '#': /* comment */ end_of_input = true; break; default: if(!valid_input) return invokefree(current_job,"reading cmdline: could not fathom input"); if(cmd_pos == MAX_LEN_CMDLINE-1) return invokefree(current_job,"reading cmdline: length exceeds the max limit"); cmd[cmd_pos++] = cmdline[cmdline_pos++]; break; } if(end_of_input || sequence) break; } cmd[cmd_pos] = '\0'; process_t *newprocess = (process_t *)malloc(sizeof(process_t)); if(!newprocess) return invokefree(current_job,"malloc: no space"); if(!init_process(newprocess)) return invokefree(current_job,"init_process: failed"); if(!current_job->first_process) current_process = current_job->first_process = newprocess; else { current_process->next = newprocess; current_process = current_process->next; } if(!readprocessinfo(current_process, cmd)) return invokefree(current_job,"read process info: error"); if(!sequence) { strncpy(current_job->commandinfo,cmdline+seq_pos,cmdline_pos-seq_pos); break; } sequence = false; ++cmdline_pos; } return true; }
/* * builtin_cmd - If the user has typed a built-in command then execute * it immediately. */ bool builtin_cmd(job_t *last_job, int argc, char **argv) { /* check whether the cmd is a built in command */ if (!strcmp("quit", argv[0])) { /* Your code here */ exit(EXIT_SUCCESS); } else if (!strcmp("jobs", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; job_t* deletedJob = NULL; while(currentJob != NULL) { // print active jobs and then change notified to 0 //if((currentJob->first_process)->completed == true && currentJob->notified == false) { //need to check if every process has completed for a job to be complete, not just the first process if (job_is_completed(currentJob) == true) { printf("%d (Completed): %s\n", currentJob->pgid, currentJob->commandinfo); deletedJob = currentJob; //currentJob->notified = true; } //otherwise it is stopped else if (job_is_stopped(currentJob) == true) { printf("%d (Stopped): %s\n", currentJob->pgid, currentJob->commandinfo); } else { printf("%d (Running): %s\n", currentJob->pgid, currentJob->commandinfo); } currentJob = currentJob->next; // delete job after it is completed, don't need to save notified if (deletedJob != NULL) { if (deletedJob == active_jobs_head) { active_jobs_head = deletedJob->next; free_job(deletedJob); //TBD warning about this? } else { delete_job(deletedJob, active_jobs_head); } deletedJob = NULL; } } return true; } else if (!strcmp("cd", argv[0])) { int chdir_return = chdir(argv[1]); if(chdir_return == -1) { printf("cd: %s: No such file or directory\n", argv[1]); } return true; } else if (!strcmp("bg", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; process_t* p2; if(argv[1] == NULL) { // continue most recent stopped job //use find_last_job currentJob = find_last_job(active_jobs_head); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while(p2 != NULL) { p2->stopped = false; struct sigaction action; action.sa_sigaction = sighandler; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); p2 = p2->next; } seize_tty(getpid()); } else { pid_t job_number = atoi(argv[1]); while(currentJob != NULL) { // Need to eventually iterate through all processes? if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) { //seize_tty(currentJob->pgid); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while (p2 != NULL) { p2->stopped = false; struct sigaction action; action.sa_sigaction = sighandler; sigfillset(&action.sa_mask); action.sa_flags = SA_SIGINFO; sigaction(SIGCHLD, &action, NULL); p2 = p2->next; } seize_tty(getpid()); break; } else if (currentJob->pgid == job_number) { printf("%s\n", "This process wasn't stopped`"); } else { printf("%s\n", "This job number is not the requested one"); } currentJob = currentJob->next; } } return true; } else if (!strcmp("fg", argv[0])) { /* Your code here */ job_t* currentJob = active_jobs_head; process_t* p2; if(argv[1] == NULL) { // continue most recent stopped job //use find_last_job currentJob = find_last_job(active_jobs_head); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while(p2 != NULL) { waiting(p2); p2 = p2->next; } seize_tty(getpid()); } else { pid_t job_number = atoi(argv[1]); while(currentJob != NULL) { if((job_is_stopped(currentJob)) && currentJob->pgid == job_number) { //seize_tty(currentJob->pgid); continue_job(currentJob); seize_tty(currentJob->pgid); p2 = currentJob->first_process; while (p2 != NULL) { waiting(p2); p2 = p2->next; } seize_tty(getpid()); break; } else if (currentJob->pgid == job_number) { printf("%s\n", "This process wasn't stopped`"); } else { printf("%s\n", "This job number is not the requested one"); } currentJob = currentJob->next; } } return true; } /* not a builtin command */ return false; }