Shell Lab

作者: 漫游之光 | 来源:发表于2020-08-09 14:04 被阅读0次
    void eval(char *cmdline) 
    {
        char *argv[MAXARGS];
        char buf[MAXLINE];
    
        int bg;
        pid_t pid;
        strcpy(buf,cmdline);
    
        bg = parseline(buf,argv);
        if(argv[0] == NULL){
            return;
        }
    
        if( !builtin_cmd(argv) ){
            /* parent process block SIGCHLD signal before call fork*/
            sigset_t mask,pre_mask;
            sigemptyset(&mask);
            sigaddset(&mask,SIGCHLD);
            sigprocmask(SIG_BLOCK,&mask,&pre_mask);
    
            pid = fork();
            if(pid < 0){
                unix_error("fork error");
            }
            if(pid == 0){
                /* child process unblock SIGCHLD signal before call execve */
                sigprocmask(SIG_SETMASK,&pre_mask,NULL);
                setpgid(0,0);
                if( execve(argv[0],argv,environ) < 0){
                    printf("%s: Command not found.\n",argv[0]);
                    exit(0);
                }
            }
            addjob(jobs,pid,bg?BG:FG,cmdline);
            /* parent process unblock SIGCHLD signal after call addjob */
            sigprocmask(SIG_SETMASK,&pre_mask,NULL);
            if( !bg ){
                /* wait for child process */
                waitfg(pid);
            }else{
                struct job_t *job;
                job = getjobpid(jobs,pid);
                printf("[%d] (%d) %s",job->jid,job->pid,job->cmdline);
            }
        }
    
        return;
    }
    
    int builtin_cmd(char **argv) 
    {
        if( !strcmp(argv[0],"quit") ){
            exit(0);
        }
        if( !strcmp(argv[0],"jobs") ){
            listjobs(jobs);
            return 1;
        }
        if(!strcmp(argv[0],"kill") ){
            if(argv[1] != NULL){
    
            }
            return 1;
        }
        if( !strcmp(argv[0],"bg") || !strcmp(argv[0],"fg") ){
            do_bgfg(argv);
            return 1;
        }
    
        return 0;     /* not a builtin command */
    }
    
    void do_bgfg(char **argv) 
    {
        if(argv[1] == NULL){
            printf("%s command requires PID or %%jobid argument\n",argv[0]);
            return;
        }
        int bg,isjob,jid;
        pid_t pid;
        if( !strcmp(argv[0],"bg") ){
            bg = 1;
        }else{
            bg = 0;
        }
        struct job_t *job = NULL;
        if( *(argv[1]) == '%' ){
            isjob = 1;
            /* check whether all the char is number*/
            jid = atoi(argv[1] + 1);
            /* if atoi function fail, the return is 0 */
            if(jid == 0){
                printf("%s: argument must be a PID or %%jobid\n",argv[0]);
                return;
            }
            job = getjobjid(jobs,jid);
        }else{
            isjob = 0;
            pid = atoi(argv[1]);
            if(pid == 0){
                printf("%s: argument must be a PID or %%jobid\n",argv[0]);
                return;
            }
            job = getjobpid(jobs,pid);
        }
        
        if(job == NULL){
            if(isjob){
                printf("%%%d: No such job\n",jid);
            }else{
                printf("(%d): No such process\n",pid);
            }
            return;
        }
        if(bg){
            printf("[%d] (%d) %s",job->jid,job->pid,job->cmdline);
            job->state = BG;
            kill(-(job->pid),SIGCONT);
        }else{
            job->state = FG;
            /* the difference between bg and fg are the shell waiting for the bg.
             * them both running in another process */
            kill(-(job->pid),SIGCONT);
            waitfg(job->pid);
        }
    
        return;
    }
    
    void waitfg(pid_t pid)
    {
        /* reap child always in signal handler,here just wait for global varien change */
        while(pid == fgpid(jobs) ){
            sleep(0);
        }
        return;
    }
    
    void sigchld_handler(int sig) 
    {
        pid_t pid;
        int status;
        while( (pid = waitpid(-1,&status,WNOHANG | WUNTRACED) )>0 ){
            int sig;
            if( WSTOPSIG(status) ){
                sig = WSTOPSIG(status);
                printf("Job [%d] (%d) stopped by signal %d\n",pid2jid(pid),pid,SIGTSTP);
                getjobpid(jobs,pid)->state = ST;
            }else if(WIFSIGNALED(status)){
                sig = WTERMSIG(status);
                printf("Job [%d] (%d) teminated by signal %d\n",pid2jid(pid),pid,sig);
                deletejob(jobs,pid);
            }else if(WIFEXITED(status)){
                deletejob(jobs,pid);
            }
        }
        return;
    }
    
    void sigtstp_handler(int sig) 
    {
        //printf("catch SIGTSTP");
        /* this pid is not belong to shell */
        pid_t pid = fgpid(jobs);
        if(pid > 0){
            int ret = kill(-pid,SIGTSTP);
            if(ret == -1){
                unix_error("kill error");
            }
            
            //deletejob(jobs,pid);
        }
        return;
    }
    
    void sigint_handler(int sig) 
    {
        /* maintain errno unchanged */
        int temp = errno;
        /* this pid is not belong to shell */
        pid_t pid = fgpid(jobs);
        if(pid > 0){
            int ret = kill(-pid,SIGINT);
            if(ret == -1){
                unix_error("kill error");
            }
        }
        errno = temp;
        return;
    }
    

    相关文章

      网友评论

          本文标题:Shell Lab

          本文链接:https://www.haomeiwen.com/subject/uaccrctx.html