예제 #1
0
/* 
 * 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 */
}
예제 #2
0
파일: pmsh.c 프로젝트: pdsouza/pmsh
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);
        }
    }
}