Esempio n. 1
0
void builtincont(struct cmdline_tokens *tok, int state){
  if (tok->argc < 2){
    // app_error("Usage: %s [%jid/pid]\n", tok->argv[0]);
    return;
  }
  pid_t pid;

  /* JID */
  if (tok->argv[1][0]=='%'){
    int jid = atoi((char *)(tok->argv[1] + sizeof(char)));
    pid = jid2pid(jid);
    if (!pid)
      app_error("No such jid \n");
  }
  else{
    /* PID case */
    pid = atoi(tok->argv[1]);
    if (!pid2jid(pid))
      app_error("No such pid \n");
  }
  /* Common to both JID & PID */
  Kill(-pid, SIGCONT);
  changestate(job_list, pid, state);
  if (state==BG){
    printf("[%d] (%d) %s\n", pid2jid(pid), pid,
	   getjobpid(job_list,pid)->cmdline);
  }

  if (state==FG){
    wait_for_fg(pid);
  }
}
Esempio n. 2
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, char **environ) 
{
	int bg;              /* should the job run in bg or fg? */
	struct cmdline_tokens tok;
	char* s;
	int jid, pid, state, fd1, fd2, fdstdin, fdstdout;
	sigset_t mask;
	struct job_t* job;
	
    	/* Parse command line */
   	 bg = parseline(cmdline, &tok); 
	
    	if (bg == -1) return;               /* parsing error */
    	if (tok.argv[0] == NULL)  return;   /* ignore empty lines */

	if (tok.infile != NULL) {
		fd1 = open(tok.infile, O_RDONLY, 0);
		if (fd1 == -1)
			app_error("open file fin error");
		fdstdin = dup(STDIN_FILENO);
		dup2(fd1, STDIN_FILENO);
	}
	if (tok.outfile != NULL) {
		fd2 = open(tok.outfile, O_WRONLY, 0);
		if (fd2 == -1)
			app_error("open file fout error");
		fdstdout = dup(STDOUT_FILENO);
		dup2(fd2, STDOUT_FILENO);
	}

	if (tok.builtins != BUILTIN_NONE) {
		if (tok.builtins == BUILTIN_QUIT)
			exit(0);
		else if (tok.builtins == BUILTIN_JOBS)
			listjobs(job_list, 1);
		else if (tok.builtins == BUILTIN_BG 
			|| tok.builtins == BUILTIN_FG) {
			s = tok.argv[1];
			pid = jid = -1;
			if (s[0] == '%') {
				sscanf(&s[1], "%d", &jid);
				pid = jid2pid(jid);
			}
			else {
				sscanf(s, "%d", &pid);
				jid = pid2jid(pid);
			}
			if (jid == -1 || pid == -1)
				app_error("fail to get pid or jid");
			job = getjobpid(job_list, pid);
			job->state = tok.builtins == BUILTIN_FG ? FG : BG;
			kill(pid, SIGCONT);
			waitjobpid(pid, job->state, job->cmdline);
		}
	}
	else {
		sigemptyset(&mask);
		sigaddset(&mask, SIGCHLD);
		sigaddset(&mask, SIGINT);
		sigaddset(&mask, SIGTSTP);
		sigprocmask(SIG_BLOCK, &mask, NULL);
		if ((pid = fork()) == 0) {	//Child runs user job
			setpgid(0, 0);
			sigprocmask(SIG_UNBLOCK, &mask, NULL);
			if (execve(tok.argv[0], tok.argv, environ) < 0) {
				printf("%s: Command not found.\n", tok.argv[0]);
			return;
			}
		}
		else {
			state = bg ? BG : FG;
			addjob(job_list, pid, state, cmdline);
			sigprocmask(SIG_UNBLOCK, &mask, NULL); 
			waitjobpid(pid, state, cmdline);
		}
	}

	if (tok.infile != NULL) {
		close(fd1);
		dup2(fdstdin, STDIN_FILENO);
	}
	if (tok.outfile != NULL) {
		close(fd2);
		dup2(fdstdout, STDOUT_FILENO);
	}
	return;
}
Esempio n. 3
0
void do_bgfg(char **argv)
{
    if(!argv[1]) { //Checks if there is a argument with the command
        printf("%s command requires PID or %% jobid argument\n", argv[0]);
        return;
    }

    int pid;

    if(argv[1][0] == '%') { // Checks if it is a jobid argument

        char* argStr = argv[1] + 1; //cuts the % sign from the argument
        int jid;
        sscanf(argStr, "%d", &jid); //convert the string to int

        if(!isStrDigits(argStr, argv)) { //check if the string is a number
            return;
        }

        if(getjobjid(jobs, jid) == NULL) { //check if the job exists
            printf("%%%d: No such job \n", jid);
            return;
        }

        pid = jid2pid(jid);
    }
    else {

        char* argStr = argv[1];
        sscanf(argStr, "%d", &pid); //convert string to int

        if(!isStrDigits(argStr, argv)) { //check it the string is a number
            return;
        }
        if(getjobpid(jobs, (pid_t) pid) == NULL) { //check if the job exists

            printf("(%d): No such process \n", pid);
            return;
        }
    }

    kill(-pid, SIGCONT);

    // If it is as fg process than wait for ot to finnish
    if (strcmp(argv[0], "fg") == 0) {

        getjobpid(jobs, pid)->state = FG; //job state changed to FG
        waitfg(pid);
        return;
    }

    getjobpid(jobs, pid)->state = BG; //job state changed to BG

    for (int i = 0; i < MAXJOBS; i++) {
        if (jobs[i].pid == pid) {
            printf("[%d] (%d) %s", pid2jid(pid), pid, jobs[i].cmdline);
        }
    }

    return;
}
Esempio n. 4
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) 
{
    int bg;              /* should the job run in bg or fg? */
    int job_state;      /* initial value of job BG or FG based on bg */
    int status;
    int check;
    struct cmdline_tokens tok;
    pid_t pid = -255;  // Initialzing to
    int jid = -255;   //  dummy values 
    sigset_t mask;      
    sigset_t mask2;      
    int flag = 0; //Used while processing "fg" built in command
    int infile_fd ; //file descriptor to be used for infile if specified in job 
    int outfile_fd ; //file descriptor to be used for outfile if specified in job

    //Get shell pid
    tsh_pid = getpid();

    //Intialize mask for blocked signal
    //Block SIGCHLD SIGINT SIGTSTP signals
    Sigemptyset(&mask);
    Sigemptyset(&mask2);
    Sigaddset(&mask,SIGCHLD);
    Sigaddset(&mask,SIGINT);
    Sigaddset(&mask2,SIGINT);
    Sigaddset(&mask,SIGTSTP);
    Sigaddset(&mask2,SIGTSTP);
    Sigprocmask(SIG_BLOCK,&mask,NULL);

    /* Parse command line */
    bg = parseline(cmdline, &tok); 

    if (bg == -1) return;               /* parsing error */
    if (tok.argv[0] == NULL)  return;   /* ignore empty lines */

    /* If tok is a BUILTIN shell command */
    if (tok.builtins != BUILTIN_NONE) {
        
       switch(tok.builtins) {                           

                           //Built in command quit :
                           //Send SIGKILL to all processes in shell
       case BUILTIN_QUIT : tsh_pid = getpid();
                           kill(-tsh_pid,SIGKILL);
                           break;

                           //List out all jobs when "jobs" called
                           //Also open output file if redirection specified and 
                           //redirect jobs output to the new file's descriptor

       case BUILTIN_JOBS :  if (tok.outfile != NULL) {
				    outfile_fd = open(tok.outfile , O_WRONLY);
				    listjobs(job_list,outfile_fd);
				    break;
			    }

			    else
				    listjobs(job_list,STDOUT_FILENO);
			    break;


			    // Parse job id or pid given with bg command
			    // Change state from ST to BG in job_list
			    // Send SIGCONT signal to job

       case BUILTIN_FG :   if(*(char *)(tok.argv[1]) == '%' ) {
				   jid = atoi( (((char *)(tok.argv[1])) + 1) ); 
				   pid = jid2pid(jid);
			   }
			   else {
				   pid = atoi(tok.argv[1]);
				   jid = pid2jid(pid);
			   }
			   change_job_state(job_list,pid,FG);
			   flag = 1;                            //flag set because we want to jump into else clause below 
			   // to process resumed job as a foreground job
			   Kill(-pid,SIGCONT);  
			   break;

			   //Parse job id or pid given with bg command
			   // Change state from ST to BG in job_list
			   // Send SIGCONT signal to job
       case BUILTIN_BG :   if(*(char *)(tok.argv[1]) == '%' ) {
				   jid = atoi( (((char *)(tok.argv[1])) + 1) ); 
				   pid = jid2pid(jid);
			   }
			   else {
				   pid = atoi(tok.argv[1]);
				   jid = pid2jid(pid);
			   }
			   printjob(pid,STDOUT_FILENO);
			   change_job_state(job_list,pid,BG);
			   Kill(-pid,SIGCONT);
			   break;
       case BUILTIN_NONE : break;
       default : break;

       }

    }


    //If tok is a external program to be run by shell 
    else if ((tok.builtins == BUILTIN_NONE) || (flag == 1)) {

	    if (flag == 1) 
		    bg = 0;

	    if(!bg)
		    job_state = FG;
	    else
		    job_state = BG;




	    //Child process   
	    if ((pid = Fork()) == 0) {

		    setpgid(0,0);  //Start process in new group     
		    Signal(SIGINT,  SIG_DFL);   /* ctrl-c from child handled by parent's sigchld */

		    addjob(job_list,getpid(),job_state,cmdline); 

		    // If input/output redirection specified open given file and point STDIN/STDOUT descriptor
		    // to new file's file descriptor
		    if (tok.infile != NULL) {
			    infile_fd = open(tok.infile , O_RDONLY);
			    dup2(infile_fd,STDIN_FILENO);   
		    }

		    if (tok.outfile != NULL) {
			    outfile_fd = open(tok.outfile , O_WRONLY);
			    dup2(outfile_fd,STDOUT_FILENO);   
		    }

		    //Unblock masks inherited from parent process
		    //and execute program using exec
		    Sigprocmask(SIG_UNBLOCK,&mask,NULL);
		    Execve(tok.argv[0],tok.argv,environ); 

	    }


	    //Parent process
	    //Add child to job list and unblock signal,also set fg_pid if job is foreground job	    
	    addjob(job_list,pid,job_state,cmdline); 
	    if(!bg)
		    fg_pid = pid;
	    Sigprocmask(SIG_UNBLOCK,&mask2,NULL); 

	    //Until foreground process terminates SIGCHLD functionality is done here , SIGINT and SIGTSTP are handled by handlers 
	    if(!bg) {

		    check = waitpid(pid,&status,WUNTRACED);
		    if ((check<0) && (errno!=ECHILD)) 
			    unix_error("waitfg : wait pid error\n");

		    if ((check == pid) && WIFSTOPPED(status)){
			    print_sigtstp_job(job_list,pid,SIGTSTP,STDOUT_FILENO);          //Print message that job was stopped by SIGSTP signal 

			    //Change stopped job state in list to ST (stopped) 
			    change_job_state(job_list,pid,ST);
			    return;
		    }

		    if ((check == pid) && (WIFSIGNALED(status)))
			    print_sigint_job(job_list,pid,WTERMSIG(status),STDOUT_FILENO);       //Print message that job/pid was terminated by a signal 


		    deletejob(job_list,pid);
		    Sigprocmask(SIG_UNBLOCK,&mask,NULL); 

	    }

	    else {
		    Sigprocmask(SIG_UNBLOCK,&mask,NULL); 
		    printjob(pid,STDOUT_FILENO);
	    }



    }

    return;
}