示例#1
0
文件: tsh.c 项目: ryosaito999/cs160
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.  
 */
void sigchld_handler(int sig) 
{
	int pid = 1;
	int status ;
	while( pid >0 ){
		pid=waitpid(-1,&status,WNOHANG|WUNTRACED);         

		if( pid > 0){
		    if(WIFEXITED(status)){ // child exited normally
                //printf( "killed job [%d] , PID: %d with SIGINT \n", getjobpid(jobs, pid)->jid, getjobpid(jobs, pid)->pid );		    	
	            deletejob(jobs,pid);
            }
	         //child caught signal!!
	        if(WIFSIGNALED(status)){ 
                    printf( "killed job [%d] , PID: %d with SIGINT \n", getjobpid(jobs, pid)->jid, getjobpid(jobs, pid)->pid );
					deletejob(jobs,pid); // cntrl c so delete the job after kill is called
            }

	        if(WIFSTOPPED(status)){
                    printf( "stopped job [%d] , PID: %d with SIGTSTP\n", getjobpid(jobs, pid)->jid, getjobpid(jobs, pid)->pid );
					getjobpid(jobs, pid)->state=ST; // cntrl z so set the state to stop after kill is called
            }
        }
    }
	

}
示例#2
0
文件: tsh.c 项目: abucraft/ics-Lab
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.  
 */
void sigchld_handler(int sig) 
{
	pid_t pid;
	int status;
	while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0)
	{
		if(WIFSIGNALED(status))
		{
			struct job_t* tempjob;
			if((tempjob=getjobpid(jobs,pid))!=NULL)
			{
				printf("Job [%d] (%d) terminated by signal %d\n",tempjob->jid,tempjob->pid,WTERMSIG(status));
				deletejob(jobs,pid);
			}
			continue;
		}
		if(WIFSTOPPED(status))
		{
			struct job_t* tempjob;
			if((tempjob=getjobpid(jobs,pid))!=NULL)
			{
				if(tempjob->state!=ST)
				{
					printf("Job [%d] (%d) stopped by signal %d\n",tempjob->jid,tempjob->pid,SIGTSTP);
					tempjob->state=ST;
				}
			}
			continue;
		}
		deletejob(jobs,pid);
	}
	
    return;
}
示例#3
0
/*
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.
 */
void sigchld_handler(int sig)
{
    // Save current errno value
    int tempErrNo = errno;
    int status = 0;
    pid_t pid;
    if ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0) {
        if (WIFEXITED(status)) {
            deletejob(jobs, pid);
        }
        else if (WIFSIGNALED(status)) {
            // Get the terminated job
            struct job_t* myJob = getjobpid(jobs, pid);
            // Print info on therminated job
            safe_printf("Job [%d] (%d) terminated by signal %d\n", myJob->jid, myJob->pid, WTERMSIG(status));
            deletejob(jobs, pid);
        }
        else if (WIFSTOPPED(status)) {
            // Get the stopped job
            struct job_t* myJob = getjobpid(jobs, pid);
            // Change the state to stopped
            myJob->state = ST;
            // Print info on stopped job
            safe_printf("Job [%d] (%d) stopped by signal %d\n", myJob->jid, myJob->pid, WSTOPSIG(status));
        }
    }
    else {
        if (errno != 0) {
            unix_error("Waitpid error");
        }
    }
    // Restore errno value
    errno = tempErrNo;
    return;
}
示例#4
0
/*
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.
 */
void sigchld_handler(int sig)
{
    /* reaps all zombie and doesn't block */
    pid_t reap_pid;
    int state = 0;  /* used to determine what causes the SIGCHLD */
    /* waitpid() return 0 immediately when no childs have terminated */
    while (0 < (reap_pid = waitpid(-1, &state, WNOHANG))) {
        /* DBG(("reaped child %d", (int)reap_pid)); */
        /*TODO Is it safe to call getjobpid(), deletejob(), clearjob() in the signal handler?  */
        if (WIFSIGNALED(state)) {
            struct job_t *termjob = getjobpid(jobs, reap_pid);
            fprintf(stdout, "hello Job [%d] (%d) terminated by signal %d\n", termjob->jid, termjob->pid, WTERMSIG(state));
        }
        deletejob(jobs, reap_pid);
        clearjob(getjobpid(jobs, reap_pid));
    }

    if (-1 == reap_pid && errno != ECHILD)
        unix_error("waitpid()");

    /* if a job be suspended, we need to change its state here */
    pid_t stp_pid;
    /* waitpid return 0 if there is no terminated process and stopped process */
    while (0 < (stp_pid = waitpid(-1, &state, WNOHANG | WUNTRACED))) {
        struct job_t *stpjob = getjobpid(jobs, stp_pid);
        stpjob->state = ST;
        if (WIFSTOPPED(state)) {
            fprintf(stdout, "world Job [%d] (%d) stopped by signal %d\n", stpjob->jid, stpjob->pid, WSTOPSIG(state));
        }
    }

    if (-1 == stp_pid && errno != ECHILD)
        unix_error("waitpid()");
}
示例#5
0
文件: tsh.c 项目: sigmaxz/hw-projects
/*
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 * a child job terminates (becomes a zombie), or stops because it
 * received a SIGSTOP or SIGTSTP signal. The handler reaps all
 * available zombie children, but doesn't wait for any other
 * currently running children to terminate.
 */
void sigchld_handler(int sig)
{
        pid_t pid;
        int status;
        while (( pid = waitpid(-1,&status, WNOHANG | WUNTRACED)) > 0) // reaping whatever is ready no hang
        {
					if(WIFSTOPPED(status) )
					{
						if((getjobpid(jobs,pid)->state) != ST)
						{
							 printf("Job [%d] (%d) Stopped by Signal %d\n",(getjobpid(jobs,pid))->jid, pid, SIGTSTP);

						}
						 getjobpid(jobs, pid)->state = ST;
						 return;
					 }
						else if(WIFSIGNALED(status) && fgpid(jobs) ==pid )
						{
							if(pid != 0){ printf("Job [%d] (%d) Terminated by Signal %d\n",(getjobpid(jobs,pid))->jid, pid, SIGINT);
}
							kill(-pid,SIGINT);
						}
                deletejob(jobs, pid);
        }


        return;
}
示例#6
0
文件: tsh.c 项目: cneale/Sample-Code
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU signal. The 
 *     handler reaps all available zombie children, but doesn't wait 
 *     for any other currently running children to terminate.  
 */
void 
sigchld_handler(int sig) 
{
  pid_t pid;
  int status;
  struct job_t *job;
  sigset_t mask;
  sigemptyset(&mask);
  sigaddset(&mask, SIGCHLD);
  sigprocmask(SIG_BLOCK,&mask,NULL);

  while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0)
    {
      if(WIFSTOPPED(status)){
	job = getjobpid(job_list,pid);
	job->state = ST;
	printf("Job [%d] (%d) stopped by signal %d\n",job->jid,job->pid,WSTOPSIG(status));
      }
      else if(WIFSIGNALED(status))
	{
	  job=getjobpid(job_list,pid);
	  printf("Job [%d] (%d) terminated by signal %d\n",job->jid,job->pid,WTERMSIG(status));
	  deletejob(job_list,pid);
	}
      
      else 
	{
	  deletejob(job_list,pid);
	}
    }
  sigprocmask(SIG_UNBLOCK,&mask,NULL);
  return;
}
示例#7
0
文件: tsh.c 项目: sigmaxz/hw-projects
/*
 * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever
 * the user types ctrl-z at the keyboard. Catch it and suspend the
 * foreground job by sending it a SIGTSTP.
 */
void sigtstp_handler(int sig)
{
        pid_t fpid = fgpid(jobs); // gets the fg process
        kill(-fpid, SIGTSTP); // sending to the fg process
        printf("Job [%d] (%d) Stopped by Signal %d\n",(getjobpid(jobs,fpid))->jid, fpid, SIGTSTP);
        getjobpid(jobs, fpid)->state = ST;
    return;
}
示例#8
0
文件: tsh.c 项目: ryosaito999/cs160
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
	struct job_t * selectedJob;

	if(argv[1] == NULL){
		printf("Please include PID/JID in 2nd argument\n");
		return;
	}


	if(argv[2] != NULL){
		printf("Format should be: fg/bg PID/JID\n");
		return;
	}
	
	if(argv[1][0] == '%' ){ // look for %n 
		int jid = argv[1][1] - '0';

		if( getjobjid(jobs, jid) == NULL){ //bad jid
			printf("Invalid JID\n"); 
			return;
		}

		selectedJob = getjobjid(jobs, jid);
	}
	else if( atoi(argv[1] )){ // check if its a pid #
		int pid = atoi(argv[1]); 
		if( getjobpid(jobs, pid) == NULL){ // bad pid
			printf("Invalid PID\n");
			return;
		}

		selectedJob = getjobpid(jobs, pid);
	}	

	else{
		printf("Unkown job ID/pid entered! \n" );
		return;	
	}

	int pid = selectedJob->pid;

    if(strcmp(argv[0],"fg") == 0 ){
    	selectedJob->state = FG;
		kill(-pid, SIGCONT);
		waitfg(pid);       		

    }

    else if(strcmp(argv[0],"bg") == 0 ){
    	selectedJob->state = BG;
		kill(-pid, SIGCONT);
    }
}
示例#9
0
文件: tsh.c 项目: hexinatgithub/CSAPP
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
    pid_t pid;
    if (argv[1][0] == '%')
    {
        pid_t jid = atoi(&argv[1][1]);
        struct job_t *job = getjobjid(jobs, jid);
        if (job == NULL){
            printf("%s No such job\n", argv[1]);  
            return;
        }
        pid = job->pid;
    }
    else
        pid = atoi(argv[1]);
    if(pid == 0)
        return;

    if (!strcmp(argv[0], "bg"))
    {
        if(kill(-pid, SIGCONT) != 0)
            printf("%s No such job\n", argv[1]);
        else
        {
            struct job_t *job = getjobpid(jobs, pid);
            job->state = BG;
            printf("[%d] (%d) %s\n", job->jid, job->pid, job->cmdline);
        }
    }
    else if(!strcmp(argv[0], "fg"))
    {
        if(kill(-pid, SIGCONT) != 0)
            printf("%s No such job\n", argv[1]);
        else
        {
            struct job_t *job = getjobpid(jobs, pid);
            job->state = FG;
            printf("[%d] (%d) %s\n", job->jid, job->pid, job->cmdline);
            int status;
            if(waitpid(pid, &status, WUNTRACED) > 0)
            {
                if(WIFEXITED(status) || WIFSIGNALED(status))
                    deletejob(jobs, job->pid);
                else if(WIFSTOPPED(status))
                {
                    job->state = ST;
                }
            }
        }
    }
    return;
}
示例#10
0
文件: tsh.c 项目: sanha/SP2015
/*
 * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever
 *     the user types ctrl-z at the keyboard. Catch it and suspend the
 *     foreground job by sending it a SIGTSTP.
 */
void sigtstp_handler(int sig)
{
	if (verbose) printf ("sigtstp_handler: entering\n");

	/* send stop signal to foreground process and it's entire group */
	pid_t pid = fgpid(jobs);
	if (getjobpid (jobs, pid) && verbose) printf ("sigtstp_handler: Job [%d] (%d) stopped\n", pid2jid (pid), pid);
	if (verbose) printf ("sigtstp_handler: exiting\n");

	if (getjobpid (jobs, pid)) kill (-pid, sig);

	return;
}
示例#11
0
文件: tsh.c 项目: sanha/SP2015
/*
 * sigint_handler - The kernel sends a SIGINT to the shell whenver the
 *    user types ctrl-c at the keyboard.  Catch it and send it along
 *    to the foreground job.
 */
void sigint_handler(int sig)
{
	if (verbose) printf ("sigint_handler: entering\n");

	/* send interrupt signal to foreground process and it's entire group */
	pid_t pid = fgpid(jobs);
	if (getjobpid (jobs, pid) && verbose) printf ("sigint_handler: Job (%d) killed\n", pid);
	if (verbose) printf ("sigint_handler: exiting\n");
	
	if (getjobpid (jobs, pid)) kill (-pid, sig);

	return;
}
示例#12
0
/*
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.
 */
void sigchld_handler(int sig) {
    int status;         // Status
    pid_t pid;          // pid
    struct job_t *pjob; // Pointer to job

    do {
    // Following directions from the link in the README
        pid = waitpid(-1, &status, WNOHANG|WUNTRACED); // Using WNOHANG as spoken about in class
        if (pid > 0) {
            if (WIFSTOPPED(status)) {
            // If stopped
                if ((pjob = getjobpid(jobs, pid)) != NULL) {
                // get job and change state
                    pjob->state = ST; // changing state
                    printf("Job [%d] (%d) stopped by signal 20\n", pjob->jid, pjob->pid);
                } else {
                // Job was invalid
                    printf("sigchld_handler: getjobpid error\n");
                    exit(1);
                }
            } else if (WIFSIGNALED(status)) {
                // TODO: Find the link for the second tutorial
                if ((pjob = getjobpid(jobs, pid)) != NULL) {
                    printf("Job [%d] (%d) terminated by signal 2\n", pjob->jid, pjob->pid);
                    if (!deletejob(jobs, pid)) { // Delete job
                        printf("sigchld_handler: deletejob error\n");
                        exit(1);
                    }
                } else {
                    printf("sigchld_handler: getjobpid error\n");
                    exit(1);
                }
            } else if (WIFEXITED(status)) {
                if (!deletejob(jobs, pid)) {
                    // DELETE JOB
                    printf("sigchld_handler: deletejob error\n");
                    exit(1);
                }
            } else {
                printf("Unknown waitpid\n");
                exit(1);
            }
        } else if (pid == -1 && errno == EINTR) {
            continue;
        } else {
            break;
        }
    } while (1);
    return;
}
示例#13
0
/*
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv)
{
	struct job_t *jd;
	int temp;


	if(!strcmp(argv[0], "bg")){    //bg command
		if(argv[1][0] == '%'){
			temp=argv[1][1];
			jd=getjobjid(jobs, temp-48);  //get job id based on %input
			if(jd==NULL)
				printf("%s: No such job\n",argv[1]);}
		else{
			temp=atoi(argv[1]);
			jd=getjobpid(jobs, temp);   //get job id based on input
			if(jd==NULL)
				printf("(%d): No such process\n",temp);}

		printf("[%d] (%d) %s",jd->jid,jd->pid,jd->cmdline);
		kill(jd->pid,SIGCONT);  //send SIGCONT signal to process
		jd->state=BG;

	}

	if(!strcmp(argv[0], "fg")){    //fg command
		if(argv[1][0] == '%'){
			temp=argv[1][1];
			jd=getjobjid(jobs, temp-48);   //get job id based on %input
			if(jd==NULL)
				printf("%s: No such job\n",argv[1]);}
		else{
			temp=atoi(argv[1]);
			jd=getjobpid(jobs, temp);    //get job id based on input
			if(jd==NULL)
				printf("(%d): No such process\n",temp);}

		if(jd!=NULL){
			waitfg(jd->pid);
			kill(jd->pid,SIGCONT);    //send sigcont to process
			if(jd->state!=ST)
			  deletejob(jobs,jd->pid);  //delete the job after termination


		}

	}

    return;
}
示例#14
0
文件: tsh.c 项目: RoseySoft/tsh
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.  
 */
void sigchld_handler(int sig) 
{
    pid_t child_pid;                                                                //Stores the child pid
    int status;                                                                     //Status variable

    while((child_pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0){               //Get the child pid in the loop
        struct job_t *jd = getjobpid(jobs, child_pid);                              //Get job detail of the child
        if(!jd){                                                                    //If no job
            printf("((%d): No such child", child_pid);                              //Throw error
            return;
        }

        if(WIFSTOPPED(status)){                                                     //If stopped
            jd->state = ST;                                                         //Change state of job to stopped
            printf("Job [%d] (%d) stopped by signal 20\n",jd->jid, child_pid);      //print the message
        }

        else if(WIFSIGNALED(status)){                                               //If signalled
            deletejob(jobs, child_pid);                                             //Delete job from jobs list
            printf("Job [%d] (%d) terminated by signal 2\n", jd->jid, child_pid);
        }

        else if(WIFEXITED(status)){                                                 //If exited
            deletejob(jobs, child_pid);                                             //Delete from jobs list
        }

        else{                                                                       //If nothing
            unix_error("waitpid error");                                            //throw error
        }
    }
    return;
}
示例#15
0
文件: tsh.c 项目: wwiiiii/CS230-KAIST
void sigchld_handler(int sig) 
{
    pid_t pid = 0;
    struct job_t *nowjob = 0;
    int status;
    while((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0)//handle all stopped or terminated children
    {
        if(WIFEXITED(status))
        {
         //   printf("pid [%d] terminated normally\n",pid);
            deletejob(jobs,pid);
        }
        else if(WIFSIGNALED(status))
        {
            printf("Job [%d] (%d) terminated by signal %d\n",pid2jid(pid),pid,WTERMSIG(status));
            deletejob(jobs,pid);
        }
        else if(WIFSTOPPED(status))
        {
            printf("Job [%d] (%d) stopped by signal %d\n", pid2jid(pid), pid, WSTOPSIG(status));
            nowjob = getjobpid(jobs,pid);
            nowjob->state = ST;
        }
    }
    if((errno != ECHILD) && (errno != 0)) 
    {
        unix_error("waitpid error");
    }   
        
    
    return;
}
示例#16
0
文件: tsh.c 项目: wwiiiii/CS230-KAIST
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
    int jobid = -1;
    pid_t pid = -1;
    struct job_t *nowjob;
    //error messages
    if(argv[1] == NULL)
    {
        if(!strcmp(argv[0],"fg"))
            puts("fg command requires PID or %jobid argument");
        else if(!strcmp(argv[0],"bg"))
            puts("bg command requires PID or %jobid argument");
        return;
    }

    if((argv[1][0] != '%') && (!(('0'<=argv[1][0]) && (argv[1][0]<='9'))))
    {
        if(!strcmp(argv[0],"fg"))
            puts("fg: argument must be a PID or %jobid");
        else if(!strcmp(argv[0],"bg"))
            puts("bg: argument must be a PID or %jobid");
        return;
    }
    //decide whether jid or pid
    if(argv[1][0] == '%')
    {
        jobid = atoi(&argv[1][1]);
        nowjob = getjobjid(jobs,jobid);
    }
    else
    {
        pid = (pid_t)atoi(argv[1]);
        nowjob = getjobpid(jobs,pid);
    }
    
    if(nowjob == NULL)
    {
        if(argv[1][0] == '%')
            printf("%%%d: No such job\n",jobid);
        else
            printf("(%d): No such process\n",(int)pid);
        return;
    }
    //////////////

    if(!strcmp(argv[0],"bg"))
    {
        nowjob->state = BG;
        printf("[%d] (%d) %s",nowjob->jid,nowjob->pid,nowjob->cmdline);
        if(kill(-(nowjob->pid), SIGCONT)<0) unix_error("kill error");
    }
    else if(!strcmp(argv[0],"fg"))
    {
        nowjob->state = FG;
//        printf("[%d] (%d) %s\n",nowjob->jid,nowjob->pid,nowjob->cmdline);
        if(kill(-(nowjob->pid), SIGCONT)<0) unix_error("kill error");
        waitfg(nowjob->pid);
    }
    return;
}
示例#17
0
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU signal. The 
 *     handler reaps all available zombie children, but doesn't wait 
 *     for any other currently running children to terminate.  
 */
void 
sigchld_handler(int sig) 
{
    pid_t pid;
    int status;
    struct job_t *job;
    int old_err = errno;

    while((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0 ) {
        if(WIFSTOPPED(status)) {
            job = getjobpid(job_list, pid);
            //Assume that pointer job is not NULL
            safe_printf("Job [%d] (%d) stopped by signal %d\n", job->jid, job->pid, WSTOPSIG(status));
            job->state = ST;
        }
        else if(WIFSIGNALED(status)) {
            safe_printf("Job [%d] (%d) terminated by signal %d\n", pid2jid(pid), pid, WTERMSIG(status));
            deletejob(job_list,pid);
        }
        else if(WIFEXITED(status)) 
            deletejob(job_list,pid);
    }

    if( pid < 0 && errno != ECHILD && errno != EINTR ) {
        safe_printf("waitpid error: %s\n", strerror(errno));
        _exit(1);
    }

    errno = old_err;
    return;
}
示例#18
0
/* id2job - parse the id and get job */
struct job_t * id2job(struct cmdline_tokens *tok, int argc) {
    struct job_t *job_ins = NULL;
    int job_id;
    int p_id;

    if ((tok -> argv[argc - 1][0]) == '%') {
        /* Start with %, parse it as jid */
        job_id = atoi(tok -> argv[argc - 1] + 1); /* Skip % */
        if ((job_ins = getjobjid(job_list, job_id)) == NULL) {
            printf("%%%d: No such job\n", job_id);
        }
    } else if (isdigit(tok -> argv[argc - 1][0])) {
        /* Start with number, parse it as pid */
        p_id = atoi(tok -> argv[argc - 1]);
        if ((job_ins = getjobpid(job_list, p_id)) == NULL) {
            printf("(%d): No such process\n", p_id);
        }
    } else {
        if (BUILTIN_BG == (tok -> builtins)) {
            printf("bg: argument must be a pid or %%jobid\n");
        } else if (BUILTIN_FG == (tok -> builtins)) {
            printf("fg: argument must be a pid or %%jobid\n");
        }
    }

    return job_ins;
}
示例#19
0
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU signal. The 
 *     handler reaps all available zombie children, but doesn't wait 
 *     for any other currently running children to terminate.  
 */
void 
sigchld_handler(int sig) 
{
  int status;
  pid_t pid; 

  while((pid = waitpid(-1, &status, WUNTRACED | WNOHANG)) > 0)
  {
  
    // If child exited normally, delete job from list
    if(WIFEXITED(status))
      deletejob(job_list, pid);

    // If child terminated because of uncaught signal, delete job from list
    else if(WIFSIGNALED(status))
    {
      printf("Job [%d] (%d) terminated by signal %d\n", 
	     pid2jid(pid), pid, WTERMSIG(status));
      
      deletejob(job_list, pid);
    }

    // If child was stopped change status to ST
    else if(WIFSTOPPED(status))
    {     
      printf("Job [%d] (%d) stopped by signal %d\n",
	     pid2jid(pid), pid, WSTOPSIG(status));

      getjobpid(job_list, pid) -> state = ST;
    }
  }

  return;

}
示例#20
0
/*
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 * a child job terminates (becomes a zombie), or stops because it
 * received a SIGSTOP or SIGTSTP signal. The handler reaps all
 * available zombie children, but doesn't wait for any other
 * currently running children to terminate.
 */
void sigchld_handler(int sig)
{
	// Jung driving now

	int status;
	pid_t pid;
	struct job_t *job;
	const int STDOUT = 1;
	/* check either status of children or return if no child zombied */
	while ((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0) {

		job = getjobpid(jobs, pid);

		if (WIFSTOPPED(status)) { /* stopped or ctrl+z */
			job->state = ST;
			char buffer[100];
			sprintf(buffer, "Job [%d] (%d) stopped by signal %d\n", job->jid, job->pid, WSTOPSIG(status));
			write(STDOUT, buffer, strlen(buffer));
		} 
		else {
			if (WIFSIGNALED(status)) { /* terminated or ctrl+c */
				char buffer[100];
				sprintf(buffer, "Job [%d] (%d) terminated by signal %d\n", job->jid, job->pid, WTERMSIG(status));
				write(STDOUT, buffer, strlen(buffer));
			}
			deletejob(jobs, pid); /* delete job in all other cases */
		}
	}
	return;

	// end of Jung driving, Kyung driving now
}
示例#21
0
/*
 * eval - Evaluate the command line that the user has just typed in
 *
 * If the user has requested a built-in command (quit, jobs, bg or fg)
 * then execute it immediately. Otherwise, fork a child process and
 * run the job in the context of the child. If the job is running in
 * the foreground, wait for it to terminate and then return. Note:
 * each child process must have a unique process group ID so that our
 * background children don't receive SIGINT (SIGTSTP) from the kernel
 * when we type ctrl-c (ctrl-z) at the keyboard.
 */
void eval(char *cmdline)
{
	// Kyung and Jung drove here

	/* Outline taken from Bryant & O'Hall page 735 */

	/* variables*/
	char *argv[MAXARGS];
	char buf[MAXLINE];
	int bg;
	pid_t pid;
	struct job_t *addedjob;
	sigset_t mask; /* for signals */
	sigemptyset(&mask);
	sigaddset(&mask, SIGCHLD);

	strcpy(buf,cmdline); /* parse command line */
	bg = parseline(buf,argv);

	/**************************
	 * evaluates command line
	 **************************/
	if(argv[0] == NULL)
		return;
	if(!builtin_cmd(argv))
	{ /* built-in command */
		sigprocmask(SIG_BLOCK, &mask, NULL);

		pid = fork();
		if(pid < 0) { /* fork error handling */
			unix_error("Fork error");
		}
		else if(pid==0) { /* child */
			setpgid(0, 0);
			sigprocmask(SIG_UNBLOCK, &mask, NULL);
			if(execve(argv[0], argv,environ) < 0) {
				printf("%s: Command not found\n", argv[0]);
				exit(1);
			}
		}
		else { /* parent - not a build-in command */
			if(bg) { /* run in background */
				sigprocmask(SIG_UNBLOCK, &mask, NULL);
				addjob(jobs, pid, BG, cmdline);
				addedjob = getjobpid(jobs,pid);
				printf("[%d] (%d) %s", addedjob->jid, addedjob->pid, addedjob->cmdline);
			}
			else { /* run in foreground */
				sigprocmask(SIG_UNBLOCK, &mask, NULL);
				addjob(jobs, pid, FG, cmdline);
				waitfg(pid);
			}
		}
	}
	return;

	/* done with code excerpt/outline */

	// end of Kyung and Jung driving
}
示例#22
0
文件: tsh.c 项目: pwwpche/ICS-SE12
/*
 * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever
 *     the user types ctrl-z at the keyboard. Catch it and suspend the
 *     foreground job by sending it a SIGTSTP.
 */
void sigtstp_handler(int sig)
{
    pid_t fg_pid = fgpid(jobs);
    if(fg_pid == 0)
        return ;
#ifdef DEBUG_SIGTSTP
    printf("--------------SIGTSTP-----------------\n");
    printf("fg_pid = %d\n",fg_pid);
    listjobs(jobs);

#endif

	struct job_t* fg_job = getjobpid(jobs, fg_pid);
	printf("Job [%d] (%d) stopped by signal %d\n", fg_job->jid, fg_job->pid, sig);
	fg_job->state = ST;
	kill(-fg_pid, SIGTSTP);

#ifdef DEBUG_SIGTSTP
    printf("after kill");
    listjobs(jobs);
    printf("--------------------------------------\n");
#endif
    return;

}
示例#23
0
文件: tsh.c 项目: pwwpche/ICS-SE12
/*
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP or SIGTSTP signal. The handler reaps all
 *     available zombie children, but doesn't wait for any other
 *     currently running children to terminate.
 */
void sigchld_handler(int sig)
{
#ifdef DEBUG_SIGTSTP
    printf("--------------SIGCHLD-----------------\n");
    listjobs(jobs);
fflush(stdout);
#endif
    pid_t pid;
    int status;
    while((pid = waitpid(-1, &status, WNOHANG|WUNTRACED)) > 0){
#ifdef DEBUG_SIGTSTP
    printf("pid = %d\n", pid);
    printf("WIFEXITED(status) = %d\n",WIFEXITED(status));
#endif
        if(WIFSTOPPED(status)){
            getjobpid(jobs, pid)->state = ST;
            continue;
        }
        deletejob(jobs, pid);
    }
#ifdef DEBUG_SIGTSTP
    printf("pid=%d\n",pid);
    listjobs(jobs);
    printf("---------------------------------------\n");
    fflush(stdout);
#endif
    return;
}
示例#24
0
文件: tsh.c 项目: vaibhav-495/Shell
void sigchld_handler(int sig)
{
        int status;
        pid_t pid=0;
        struct job_t* job;
        while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0){
        job=getjobpid(jobs,pid);
        if(WIFEXITED(status))
            deletejob(jobs,pid);
        else {
            if(WIFSIGNALED(status))
            {
            if(WTERMSIG(status)==2) {
                printf("Job [%d] (%d) terminated by signal 2\n",job->jid,pid);
                deletejob(jobs,pid);
            }
            }
        if(WIFSTOPPED(status)){
            job->state=ST;
            printf("Job [%d] (%d) stopped by signal 20\n",job->jid,pid);
        }
        }
    
        }
        return;
}
示例#25
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{

    struct job_t * job;
    job = NULL;

    if (argv[1] == NULL) {
         // Missing arguments
         printf("%s command requires PID or %%jobid argument\n", argv[0]);
         fflush(stdout);
         return;
    }

    if (isdigit(*argv[1])) {
        // Check if the second argument is a digit
        job = getjobpid(jobs, atoi(argv[1]));
        if (!job) {
            printf("(%s): No such process\n", argv[1]);
            fflush(stdout);
            return;
        }
    } else if (strlen(argv[1]) > 1 && argv[1][0] == '%') {
        // Check if the second argument is %number (e.g. %5)
        if (isdigit(argv[1][1])) {
            // Make sure that the second character is a digit
            job = getjobjid(jobs, atoi(argv[1]+1));
            if (!job) {
                printf("%s: No such job\n", argv[1]);
                fflush(stdout);
                return;
            }
        }
    }

    if (job == NULL) {
        // If the job is null, report invalid argument and stop
        printf("%s: argument must be a PID or %%jobid\n", argv[0]);
        fflush(stdout);
        return;
    }

    if (!strcmp(argv[0], "fg")) {
        if (Kill(-job->pid, SIGCONT) == 0) {
            job->state = FG;
            // since sigcont will just run the program in the background, 
            // we need to explicitly tell the shell
            // to wait for it to complete
            waitfg(job->pid);
        }
    } else if (!strcmp(argv[0], "bg")) {
        // Restart job but do not wait for the job (job is in background)
        printf("[%i] (%i) %s", job->jid, job->pid, job->cmdline);	
        fflush(stdout);
        if (Kill(-job->pid, SIGCONT) == 0) {
            job->state = BG;
        }
    }
    fflush(stdout);
    return;
}
示例#26
0
/*
 *fg_job - restart a stopped job and put it to foreground
 */
void fg_job(struct cmdline_tokens* tok)
{
	pid_t pid;
	struct job_t* job;
	int jid;
	sigset_t mask;
	sigemptyset(&mask);
	int argc=tok->argc;

	if(tok->argv[argc-1][0]=='%')  //recognizing the process by job ID
	{
		jid=atoi(tok->argv[argc-1]+1);
		job=getjobjid(job_list,jid);
		pid=job->pid;
	}else{                         //recognizing the process by process ID
	
		pid=atoi(tok->argv[argc-1]);
		job=getjobpid(job_list,pid);
	}

	job->state=FG;
	
	kill(pid,SIGCONT);

    /* since the job state is changed to foreground, 
    the parent process shall wait*/     
	while(fgpid(job_list))
	{
       sigsuspend(&mask);
	}

}
示例#27
0
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU signal. The 
 *     handler reaps all available zombie children, but doesn't wait 
 *     for any other currently running children to terminate.  
 */
void 
sigchld_handler(int sig) 
{
    pid_t cpid;
    int status;
    struct job_t* job;
    sigset_t mask,prev;
    //the reason why i dn not use the wrapped function
    //is that i need the return value
    while ((cpid = waitpid(-1, &status,WNOHANG|WUNTRACED))>0) {
        //prepare the mask
        Sigfillset(&mask);
        //block the signal because  i want to change something
        Sigprocmask(SIG_BLOCK, &mask, &prev);
        //get the job by the pid
        job = getjobpid(job_list, cpid);
        //STP by any signal
        //change thet status and print msg
        if (WIFSTOPPED(status)) {
            printf("Job [%d] (%d) stopped by signal %d\n",job->jid, cpid, WSTOPSIG(status));
            job->state = ST;
        }
        //terminate by signal
        //delete the job and print msg
        else if (WIFSIGNALED(status)){
            printf("Job [%d] (%d) terminated by signal %d\n",job->jid, cpid, WTERMSIG(status));
            deletejob(job_list, cpid);
        }
        //terminate normally
        //just delete the job from the job list
        else
            deletejob(job_list, cpid);        
    }
    return;
}
示例#28
0
文件: tsh.c 项目: kuoliu/15213
/* Execute the built-in background command */
void bgjob(struct cmdline_tokens *tokens_ptr){
    struct job_t *job_ptr = NULL;
    int argc = tokens_ptr->argc;
    char **argv = tokens_ptr->argv;
    int jid, pid;
    if(argv[argc - 1][0] == '%') {
        /* if job id is given */
        jid = atoi(argv[argc - 1] + 1);
        job_ptr = getjobjid(job_list, jid);
                
        if(job_ptr == NULL){
            fprintf(stderr, "Error: job with jid %d does not exist\n", jid);
            return ;
        }
    } else{
        /* if process id is given */
        pid = atoi(argv[argc - 1]);
        job_ptr = getjobpid(job_list, pid);
                
        if(job_ptr == NULL){
            fprintf(stderr, "Error: job with pid %d does not exist\n", pid);
            return ;
        }
    }
    if(job_ptr->state == ST){
        /* update the status, send SIGCONT signal and print information of the job*/
        job_ptr->state = BG;
        kill(job_ptr->pid, SIGCONT);
        printf("[%d] (%d) %s\n", job_ptr->jid, job_ptr->pid, job_ptr->cmdline);
    }
}
示例#29
0
文件: tsh.c 项目: vaibhav-495/Shell
/*
 * sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever
 *     the user types ctrl-z at the keyboard. Catch it and suspend the
 *     foreground job by sending it a SIGTSTP.
 */
void sigtstp_handler(int sig)
{
    struct job_t *job=getjobpid(jobs,fgpid(jobs));
    if(job!=NULL)
    kill(-fgpid(jobs),SIGTSTP);
    return;
}
示例#30
0
文件: tsh.c 项目: kuoliu/15213
/* 
 * sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
 *     a child job terminates (becomes a zombie), or stops because it
 *     received a SIGSTOP, SIGTSTP, SIGTTIN or SIGTTOU signal. The 
 *     handler reaps all available zombie children, but doesn't wait 
 *     for any other currently running children to terminate.  
 */
void sigchld_handler(int sig) {
    int status;
    pid_t pid;
    
    while((pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
        if(WIFEXITED(status)) {
            /* if a child job terminated normally */
            deletejob(job_list, pid);

        } else if(WIFSIGNALED(status)) {
            /* if a child job terminated by signal */
            printf("Job [%d] (%d) terminated by signal %d\n",
                pid2jid(pid), pid, WTERMSIG(status));
            deletejob(job_list, pid);

        } else if(WIFSTOPPED(status)) {
            /* if a child job is stopped, we should also update its status */
            printf("Job [%d] (%d) stopped by signal %d\n",
                pid2jid(pid), pid, WSTOPSIG(status));
            getjobpid(job_list, pid) -> state = ST;
        }
    }
        
    return;
}