/* * builtin_cmd - If the user has typed a built-in command then execute * it immediately. */ int builtin_cmd(char **argv) { char *cmd = argv[0]; if (!strcmp(cmd, "help")) { /* quit command */ do_help(); return 1; } if (!strcmp(cmd, "stop")) { /* quit command */ do_stop(argv); return 1; } if (!strcmp(cmd, "exit")) { /* quit command */ do_exit(); return 1; } if (!strcmp(cmd, "jobs")) { /* jobs command */ do_jobs(); return 1; } if (!strcmp(cmd, "bg")) { /* bg and fg commands */ do_bg(argv); return 1; } if (!strcmp(cmd, "fg")) { /* bg and fg commands */ do_fg(argv); return 1; } if (!strcmp(cmd, "kill")) { /* bg and fg commands */ do_kill(argv); return 1; } return 0; /* not a builtin command */ }
int main(int argc, char** argv) { ssize_t cmd_size; int i; int pipefd[2], fin, fout; char buf[BUFFER_SIZE]; char *cmd; char **args; job *j; job_list = init_list(); msg_q = init_list(); pid_t pgid; /* initial setup */ shell_pgid = getpgid(0); sync_pwd(); /* disable (ignore) job control signals */ signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTERM, SIG_IGN); signal(SIGTSTP, SIG_IGN); signal(SIGINT, SIG_IGN); set_handler(); /*** Shell loop ***/ for(;;) { /* Print out queued messages */ for(i=0;i<msg_q->size;i++) { message *m = (message *) get(msg_q, i); printf("%s: %s\n", m->status ? "Finished" : "Stopped", m->msg); } // clear the queue while(msg_q->size > 0) free(del(msg_q,0)); /* TODO: shell print macro */ printf("%s %s %s ", SHELL, pwd, PROMPT); fflush(stdout); do cmd_size = read(STDIN_FILENO, buf, BUFFER_SIZE); while(cmd_size == -1 && errno == EINTR); // ignore system call interrupts if(cmd_size == -1) { perror("read"); continue; } else if(cmd_size == 0) { // EOF (quit) write(STDOUT_FILENO, EXIT_MSG, STRING_SIZE(EXIT_MSG)); cleanup(); _exit(EXIT_SUCCESS); } else if(cmd_size == 1 && buf[0] == '\n') { continue; } if(buf[cmd_size-1] != '\n') { // overflow write(STDOUT_FILENO, OFLOW_MSG, STRING_SIZE(OFLOW_MSG)); pflush(); continue; } buf[cmd_size-1] = '\0'; // strip the newline j = parse(buf); if(j == (job *) NULL) { printf("Invalid redirections you moron!\n"); continue; } args = j->cmds[0]; if (!my_strcmp(args[0], "fg")) { do_fg(args); free_job(j); continue; } else if (!my_strcmp(args[0], "bg")) { do_bg(args); free_job(j); continue; } else if (!my_strcmp(args[0], "jobs")) { print_bg(job_list); free_job(j); continue; } else if (!my_strcmp(args[0], "cd")) { do_cd(args); free_job(j); continue; } j->job_id = gen_job_id(job_list); j->running = 1; j->complete = 0; push(job_list, JOB, (void *)j); pgid = 0; // set the job pgid to be the first child's pid fin = STDIN_FILENO; for(i=0;i<(j->numcmds);i++) { args = j->cmds[i]; cmd = args[0]; if(i + 1 < (j->numcmds)) { // not last process in job //printf("Creating a pipe!\n"); if(pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } fout = pipefd[1]; } else fout = STDOUT_FILENO; /*printf("Forking %s\n", cmd); k = 0; while( args[k] != (char *) NULL ) { printf("\targv[%d] = %s\n", k, args[k]); ++k; }*/ pid = fork(); if(pid == -1) { perror("fork"); continue; } /*** CHILD ***/ if(!pid) { // < if(j->fin[i] != (char *) NULL) { if( (fin = open(j->fin[i], O_RDONLY)) == -1 ) { perror("open"); } } // > if(j->fout[i] != (char *) NULL) { if( (fout = open(j->fout[i], O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1 ) { perror("open"); } } exec_process(cmd, args, pgid, fin, fout, j->fg); } /*** PARENT ***/ else { if(!pgid) { // set to first child's pid (process group leader) pgid = pid; j->pgid = pgid; //printf("Set job's pgid to %d\n", pgid); } process *proc = malloc(sizeof(process)); proc->complete = 0; proc->pid = pid; proc->pgid = pgid; push(j->pid_list, PROCESS, (void *)proc); if( setpgid(pid, pgid) == -1 ) { perror("setpgid"); _exit(EXIT_FAILURE); } } if(fin != STDIN_FILENO) close(fin); if(fout != STDOUT_FILENO) close(fout); fin = pipefd[0]; } //print_jobs(); if(j->fg) { // foreground // give terminal control to job if( tcsetpgrp(STDIN_FILENO, pgid) == -1 ) { perror("tcsetpgrp"); _exit(EXIT_FAILURE); } // wait for job to finish jwait(j); // give pmsh terminal control again if( tcsetpgrp(STDIN_FILENO, shell_pgid) == -1 ) { perror("tcsetpgrp"); _exit(EXIT_FAILURE); } } else { // background printf("Running: %s\n", j->rawcmd); } } }