示例#1
0
int main(int argc, char **argv)
{
    int pid;
    sigset_t mask;

    Signal(SIGCHLD, handler);
    initjobs(); /* Initialize the job list */

    while (1) {
	Sigemptyset(&mask);
	Sigaddset(&mask, SIGCHLD); 
	Sigprocmask(SIG_BLOCK, &mask, NULL); /* Block SIGCHLD */
    
	/* Child process */
	if ((pid = Fork()) == 0) {
	    Sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Unblock SIGCHLD */
	    Execve("/bin/ls", argv, NULL);
	}

	/* Parent process */
	addjob(pid);  /* Add the child to the job list */
	Sigprocmask(SIG_UNBLOCK, &mask, NULL);  /* Unblock SIGCHLD */
    }
    exit(0);
}
示例#2
0
int
main(int argc, char **argv)
{
	int		i, nloop, signo;
	pid_t	childpid, parentpid;
	sigset_t	newmask;

	if (argc != 2)
		err_quit("usage: lat_sigwait <#loops>");
	nloop = atoi(argv[1]);

	Sigemptyset(&newmask);
	Sigaddset(&newmask, SIGUSR1);
	Sigprocmask(SIG_BLOCK, &newmask, NULL);		/* block SIGUSR1 */

	parentpid = getpid();
	if ( (childpid = Fork()) == 0) {
		for (i = 0; i < nloop; i++) {		/* child */
			Sigwait(&newmask, &signo);
			Kill(parentpid, SIGUSR1);
		}
		exit(0);
	}
		/* 4parent */
	Start_time();
	for (i = 0; i < nloop; i++) {
		Kill(childpid, SIGUSR1);
		Sigwait(&newmask, &signo);
	}
	printf("latency: %.3f usec\n", Stop_time() / nloop);
	exit(0);
}
示例#3
0
/* wait_fg_job - Use Sigsuspend to save some time :-) */
void wait_fg_job(int state) {
    sigset_t emptymask;
    Sigemptyset(&emptymask);
    while ((fgpid(job_list) != 0) && (FG == state)) {
        Sigsuspend(&emptymask);
    }
}
示例#4
0
int main(int argc, char **argv) 
{
    sigset_t mask, prev;

    Signal(SIGCHLD, sigchld_handler);
    Signal(SIGINT, sigint_handler);
    Sigemptyset(&mask);
    Sigaddset(&mask, SIGCHLD);

    while (1) {
        Sigprocmask(SIG_BLOCK, &mask, &prev); /* Block SIGCHLD */
        if (Fork() == 0) /* Child */
            exit(0);

        /* Wait for SIGCHLD to be received */
        pid = 0;
        while (!pid) 
            Sigsuspend(&prev);

        /* Optionally unblock SIGCHLD */
        Sigprocmask(SIG_SETMASK, &prev, NULL); 

        /* Do some work after receiving SIGCHLD */
        printf(".");
    }
    exit(0);
}
void sigio_dg_echo(int sockfd_arg, SA *pcliaddr, socklen_t clilen_arg)
{
    int i;
    const int on = 1;
    sigset_t zeromask, newmask, oldmask;

    sockfd = sockfd_arg;
    clilen = clilen_arg;

    for (i = 0; i < QSIZE; i++) { /* init queue of buffers */
        dg[i].dg_data = Malloc(MAXDG);
        dg[i].dg_sa = Malloc(clilen);
        dg[i].dg_salen = clilen;
    }
    iget = iput = nqueue = 0;

    Signal(SIGHUP, sig_hup);
    Signal(SIGIO, sig_io);
    Fcntl(sockfd, F_SETOWN, getpid());
    if (ioctl(sockfd, FIOASYNC, &on) < 0)
        err_sys("ioctl error");
    if (ioctl(sockfd, FIONBIO, &on) < 0)
        err_sys("ioctl error");

    Sigemptyset(&zeromask);
    Sigemptyset(&oldmask);
    Sigemptyset(&newmask);
    Sigaddset(&newmask, SIGIO); /* signal we want to block */

    Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
    for (;;) {
        while (nqueue == 0)
            sigsuspend(&zeromask);

        Sigprocmask(SIG_SETMASK, &oldmask, NULL);

        Sendto(sockfd, dg[iget].dg_data, dg[iget].dg_len, 0,
                dg[iget].dg_sa, dg[iget].dg_salen);

        if (++iget >= QSIZE)
            iget = 0;

        /* Block SIGIO */
        Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
        nqueue--;
    }
}
示例#6
0
// Initialise la gestion des signaux utilisées par le shell
// (assigne les handlers et prépare les bloquages)
void jobs_signals_init () {
    Signal(SIGCHLD, handler_sigchld);
    Signal(SIGINT, handler_sigint);
    Signal(SIGTSTP, SIG_IGN);

    Sigemptyset(&signals_to_block);
    Sigaddset(&signals_to_block, SIGCHLD);
}
示例#7
0
int main(int argc, char **argv)
{
	mqd_t mqd;
	void *buff;
	ssize_t n;
	sigset_t zeromask, newmask, oldmask;
	struct mq_attr attr;
	struct sigevent sigev;

	if (argc != 2)
		err_quit("Usage: nfs3 <name>");

	mqd = Mq_open(argv[1], O_RDONLY | O_NONBLOCK);
	Mq_getattr(mqd, &attr);
	buff = (void *)Malloc(attr.mq_msgsize);

	Sigemptyset(&zeromask);
	Sigemptyset(&newmask);
	Sigemptyset(&oldmask);
	Sigaddset(&newmask, SIGUSR1);

	Signal(SIGUSR1, sig_usr1);
	sigev.sigev_notify = SIGEV_SIGNAL;
	sigev.sigev_signo = SIGUSR1;
	Mq_notify(mqd, &sigev);

	for ( ; ; )
	{
		Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
		while (mqflag == 0)
			sigsuspend(&zeromask);
		mqflag = 0;

		Mq_notify(mqd, &sigev);
		while ((n = mq_receive(mqd, buff, attr.mq_msgsize, NULL)) >= 0)
		{
			printf("read %ld bytes\n", (long)n);
		}
		if (errno != EAGAIN)
			err_sys("mq_receive error");
		Sigprocmask(SIG_UNBLOCK, &newmask, NULL);
	}
	exit(0);
}
示例#8
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? */
    struct cmdline_tokens tok;
    sigset_t prev, mask_all;
    int state;
    pid_t pid;
    struct job_t *job_ins;

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

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

    /* Fig. 8.40 */
    if (!builtin_command(&tok)) {
        Sigemptyset(&mask_all);
        Sigaddset(&mask_all, SIGCHLD);
        Sigaddset(&mask_all, SIGINT);
        Sigaddset(&mask_all, SIGTSTP);
        Sigprocmask(SIG_BLOCK, &mask_all, &prev); /* Block at beginning */

        if ((pid = Fork()) == 0) { /* Child process */
            Sigprocmask(SIG_SETMASK, &prev, NULL); /* Unblock inside child */
	    Setpgid(0, 0); /* one proc and shell in pgrp */

	    open_dup2_in(tok.infile);
	    open_dup2_out(tok.outfile);
	    if (execve(tok.argv[0], tok.argv, environ) < 0) {
	        printf("%s: Command not found.\n", tok.argv[0]);
	        exit(0);
	    }
	}

        /* Parent process */

        state = bg ? BG : FG;
        addjob(job_list, pid, state, cmdline);
        job_ins = getjobpid(job_list, pid);

        Sigprocmask(SIG_SETMASK, &prev, NULL); /* Unblock 3 signals */

        if (bg) {
            printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
        } else {
            wait_fg_job(job_ins -> state);
        }
    }

    return;
}
示例#9
0
int
main(int argc, char **argv)
{
	mqd_t	mqd;
	void	*buff;
	ssize_t	n;
	sigset_t	zeromask, newmask, oldmask;
	struct mq_attr	attr;
	struct sigevent	sigev;

	if (argc != 2)
		err_quit("usage: mqnotifysig2 <name>");

		/* 4open queue, get attributes, allocate read buffer */
	mqd = Mq_open(argv[1], O_RDONLY);
	Mq_getattr(mqd, &attr);
	buff = Malloc(attr.mq_msgsize);

	Sigemptyset(&zeromask);		/* no signals blocked */
	Sigemptyset(&newmask);
	Sigemptyset(&oldmask);
	Sigaddset(&newmask, SIGUSR1);

		/* 4establish signal handler, enable notification */
	Signal(SIGUSR1, sig_usr1);
	sigev.sigev_notify = SIGEV_SIGNAL;
	sigev.sigev_signo = SIGUSR1;
	Mq_notify(mqd, &sigev);

	for ( ; ; ) {
		Sigprocmask(SIG_BLOCK, &newmask, &oldmask);	/* block SIGUSR1 */
		while (mqflag == 0)
			sigsuspend(&zeromask);
		mqflag = 0;		/* reset flag */

		Mq_notify(mqd, &sigev);			/* reregister first */
		n = Mq_receive(mqd, buff, attr.mq_msgsize, NULL);
		printf("read %ld bytes\n", (long) n);
		Sigprocmask(SIG_UNBLOCK, &newmask, NULL);	/* unblock SIGUSR1 */
	}
	exit(0);
}
示例#10
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)
{
    // Get memory for our parsed input
    char temp[MAXLINE];
    char** argv = (char**)temp;
    // Return if only newline
    if (strcmp(cmdline, "\n") == 0) {
        return;
    }
    // Parse the input
    int background = parseline(cmdline, argv);
    // Check if built in command
    if (builtin_cmd(argv) == 0) {
        // Not a built in command
        char* programName = argv[0];

        // Block sigchild signal
        sigset_t mask;
        Sigemptyset(&mask);
        Sigaddset(&mask, SIGCHLD);
        Sigprocmask(SIG_BLOCK, &mask, NULL);

        // Create a child process
        pid_t pid = Fork();

        // Unblock sichild signal
        Sigprocmask(SIG_UNBLOCK, &mask, NULL);
        if (pid == 0) {
            // Child
            // Assign it a new process group id
            setpgid(0,0);
            // Run the external program
            Execve(programName, argv, environ);
        }
        else {
            // Parent
            if (background == 0) {
                // Add it to the list
                addjob(jobs, pid, FG, cmdline);
                // Make the shell wait for the process in the fg
                waitfg(pid);
            }
            else {
                // Add it to the list
                addjob(jobs, pid, BG, cmdline);
                // Get the job id
                int jid = pid2jid(pid);
                // Print info on background job
                printf("[%d] (%d) %s", jid, pid, cmdline);
            }
        }
    }
    return;
}
示例#11
0
void dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
	int n;
	const int on = 1;
	char sendline[MAXLINE], recvline[MAXLINE + 1];
	fd_set rset;
	sigset_t sigset_alrm, sigset_empty;
	socklen_t len;
	struct sockaddr *preply_addr;

	preply_addr = (struct sockaddr *)Malloc(servlen);

	Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

	FD_ZERO(&rset);

	Sigemptyset(&sigset_empty);
	sigemptyset(&sigset_alrm);
	Sigaddset(&sigset_alrm, SIGALRM);

	Signal(SIGALRM, recvfrom_alarm);

	while (Fgets(sendline, MAXLINE, fp) != NULL)
	{
		Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

		Sigprocmask(SIG_BLOCK, &sigset_alrm, NULL);
		alarm(5);
		for ( ; ; )
		{
			FD_SET(sockfd, &rset);
			n = pselect(sockfd+1, &rset, NULL, NULL, NULL, &sigset_empty);
			if (n < 0)
			{
				if (errno = EINTR)
					break;
				else
					err_sys("pselect error");
			}
			else if (n != 1)
				err_sys("pselect error: returned %d", n);

			len = servlen;
			n = Recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);
			recvline[n] = 0; //null terminate
			printf("from %s: %s", (char *)Sock_ntop_host(preply_addr, len), recvline);
		}
	}
	free(preply_addr);
}
示例#12
0
/*
signal block by pselect,and pselect is atom operation
*/
void dg_cli(FILE *fp,int sockfd,const SA* pservaddr,socklen_t servlen){
	int n;
	const int on = 1;
	char sendline[MAXLINE+1],recvline[MAXLINE+1];
	fd_set rset;
	socklen_t len;
	sigset_t sigset_empty,sigset_alrm;
	struct sockaddr_in *preply_addr;
	preply_addr = Malloc(sizeof(struct sockaddr_in));
	FD_ZERO(&rset);
	Sigemptyset(&sigset_empty);
	Sigemptyset(&sigset_alrm);
	Sigaddset(&sigset_alrm,SIGALRM);
	Signal(SIGALRM,recvfrom_alrm);
	while(Fgets(sendline,MAXLINE,fp) != NULL){
		len = servlen;
		sendto(sockfd,sendline,strlen(sendline),0,pservaddr,len);
		Sigprocmast(SIG_BLOCK,&sigset_alrm,NULL);
		alarm(5);
		for(;;){
			FD_SET(sockfd,&rset);
			n = pselect(sockfd+1,&rset,NULL,NULL,NULL,&sigset_empty);
			if(n < 0){
				if(errno == EINTR)
					break;
				else
					err_quit("pselect error!");
			}else if(n != 1){
				err_quit("pselect error %d\n",n);
			}
			n = recvfrom(sockfd,recvline,MAXLINE,0,preply_addr,&len);
			recvlien[n] = 0;
			printf("from %s:%s\n",Sock_ntop_host(preply_addr,len),recvfrom);
		}
	}
}
/*
 * This helper function can handle the "fg" command
 * 1. Get the pid and jid.
 * 2. Set the job state to FG.
 * 3. Send the SIGCONT signal.
 * 4. Wait for the process because it is a foreground child process.
 */
void dofg(char **argv)
{
    pid_t pid;
    int jid;
    sigset_t mask;
    pid = getargvpid(argv);
    jid = pid2jid(pid);
    job_list[jid - 1].state = FG;
    tcsetpgrp(STDIN_FILENO, pid);
    Kill(pid, SIGCONT);
    Sigemptyset(&mask);
    while (fgpid(job_list)) {
        sigsuspend(&mask);
    }
}
示例#14
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? */
    struct cmdline_tokens tok;
    sigset_t mask_one, prev_one, mask_all;
    int state;
    pid_t pid;

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

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

    /* Fig. 8.40 */ 
    if (tok.builtins == BUILTIN_NONE) {
      Sigfillset(&mask_all);
      Sigemptyset(&mask_one);
      Sigaddset(&mask_one, SIGCHLD);
      Sigprocmask(SIG_BLOCK, &mask_one, &prev_one); /* Block SIGCHLD */
      
      if ((pid = Fork()) == 0) {
          Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
	  if (execve(tok.argv[0], tok.argv, environ) < 0) {
	      printf("%s: Command not found.\n", tok.argv[0]);
	      exit(0);
	  }
      }

      /* Parent process */
      Sigprocmask(SIG_BLOCK, &mask_all, NULL); /* Block all */
      state = bg ? BG : FG;
      addjob(job_list, pid, state, cmdline);
      Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
            
      if (state == BG) {
          printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
      }	else {
	
      }
      // Sigprocmask(SIG_SETMASK, &prev_one, NULL);
    }

    return;
}
示例#15
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 *argv[MAXARGS]; /* Argument list execve() */
    char buf[MAXLINE];   /* Holds modified command line */
    int bg;              /* Should the job run in bg or fg? */
    pid_t pid;           /* Process id */
    sigset_t mask;

    strcpy(buf, cmdline);
    bg = parseline(buf, argv);
    if (argv[0] == NULL) {
      return; /* Ignore empty lines */
    }

    if (!builtin_cmd(argv)) {
        /* Block SIGCHLD, SIGINT,	 
	and SIGSTP until the job to be run is on the list */
        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); // give the child a new group
            /* unblock signals for child */
            Sigprocmask(SIG_UNBLOCK, &mask, NULL); 
            if (execve(argv[0], argv, environ) < 0) {
                printf("%s: Command not found.\n", argv[0]);
                exit(0);
            }
        }

        addjob(jobs, pid, bg?BG:FG, cmdline);
        if (bg) {
            // Notify user that job is running in the background
            printf("[%i] (%i) %s", getjobpid(jobs, pid)->jid, pid, cmdline);
        }
	Sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Unblock signals */

        if (!bg) {
            /* Parent waits for foreground job to terminate */
            waitfg(pid);
        }
    }

    return;
}
示例#16
0
int main(int argc,char **argv)
{
	int i,j;
	pid_t pid;
	sigset_t newset;
	union sigval val;


	printf("SIGRTMIN = %d,SIGRTMAX = %d\n",(int) SIGRTMIN,(int )SIGRTMAX );

	if((pid=Fork())==0)
	{
		Sigemptyset(&newset);
		Sigaddset(&newset,SIGRTMAX);
		Sigaddset(&newset,SIGRTMAX-1);
		Sigaddset(&newset,SIGRTMAX-2);
		Sigprocmask(SIG_BLOCK,&newset,NULL);

		Signal_rt(SIGRTMAX,sig_rt);
		Signal_rt(SIGRTMAX-1,sig_rt);
		signal_rt(SIGRTMAX-2,sig_rt);

		sleep(6);

		Sigprocmask(SIG_UNBLOCK,&newset,NULL);
		sleep(3);
		exit(0);

	}

	sleep(3);
	for(i=SIGRTMAX;i>=SIGRTMAX-2;i--)
	{
		for(j=0;j<=2;j++)
		{
			val.sival_int=j;
			Sigqueue(pid,i,val);
			printf("sent signal %d, val= %d\n",i,j);


		}
	}
	exit(0);


}
示例#17
0
void
dg_cli(FILE *fp, int sockfd, const SA *pservaddr, socklen_t servlen)
{
	int				n;
	const int		on = 1;
	char			sendline[MAXLINE], recvline[MAXLINE + 1];
	sigset_t		sigset_alrm;
	socklen_t		len;
	struct sockaddr	*preply_addr;
 
	preply_addr = Malloc(servlen);

	Setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

	Sigemptyset(&sigset_alrm);
	Sigaddset(&sigset_alrm, SIGALRM);

	Signal(SIGALRM, recvfrom_alarm);

	while (Fgets(sendline, MAXLINE, fp) != NULL) {

		Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen);

		alarm(5);
		for ( ; ; ) {
			len = servlen;
			Sigprocmask(SIG_UNBLOCK, &sigset_alrm, NULL);
			n = recvfrom(sockfd, recvline, MAXLINE, 0, preply_addr, &len);
			Sigprocmask(SIG_BLOCK, &sigset_alrm, NULL);
			if (n < 0) {
				if (errno == EINTR)
					break;		/* waited long enough for replies */
				else
					err_sys("recvfrom error");
			} else {
				recvline[n] = 0;	/* null terminate */
				printf("from %s: %s",
						Sock_ntop_host(preply_addr, len), recvline);
			}
		}
	}
	free(preply_addr);
}
示例#18
0
文件: tsh.c 项目: fffxj/csapp
/* 
 * 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 *argv[MAXARGS]; /* Argument list execve() */
  char buf[MAXLINE];   /* Holds modified command line */
  int bg;              /* Should the job run in bg or fg? */
  pid_t pid;           /* Process id */

  sigset_t mask_all, mask_one, prev_one; /* Signal mask */
  Sigfillset(&mask_all);
  Sigemptyset(&mask_one);
  Sigaddset(&mask_one, SIGCHLD);

  strcpy(buf, cmdline);
  bg = parseline(buf, argv); 
  if (argv[0] == NULL)  
    return;   /* Ignore empty lines */

  if (!builtin_cmd(argv)) {
    Sigprocmask(SIG_BLOCK, &mask_one, &prev_one); /* Block SIGCHLD */
    if ((pid = Fork()) == 0) {       /* Child runs user job */
      Sigprocmask(SIG_SETMASK, &prev_one, NULL);  /* Unblock SIGCHLD */
      setpgid(0, 0);
      if (execve(argv[0], argv, environ) < 0) {
        printf("%s: Command not found\n", argv[0]);
        exit(0);
      }
    }
    if (!bg) {         /* Parent waits for foreground job to terminate */    
      Sigprocmask(SIG_BLOCK, &mask_all, NULL);
      addjob(jobs, pid, FG, cmdline);
      Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
      waitfg(pid);
    }
    else {             /* Background job */
      Sigprocmask(SIG_BLOCK, &mask_all, NULL);
      addjob(jobs, pid, BG, cmdline);
      printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
      Sigprocmask(SIG_SETMASK, &prev_one, NULL); /* Unblock SIGCHLD */
    }      
  }
  return;
}
示例#19
0
int
main(int argc, char **argv)
{
	int		signo;
	mqd_t	mqd;
	void	*buff;
	ssize_t	n;
	sigset_t	newmask;
	struct mq_attr	attr;
	struct sigevent	sigev;

	if (argc != 2)
		err_quit("usage: mqnotifysig4 <name>");

		/* 4open queue, get attributes, allocate read buffer */
	mqd = Mq_open(argv[1], O_RDONLY | O_NONBLOCK);
	Mq_getattr(mqd, &attr);
	buff = Malloc(attr.mq_msgsize);

	Sigemptyset(&newmask);
	Sigaddset(&newmask, SIGUSR1);
	Sigprocmask(SIG_BLOCK, &newmask, NULL);		/* block SIGUSR1 */

		/* 4establish signal handler, enable notification */
	sigev.sigev_notify = SIGEV_SIGNAL;
	sigev.sigev_signo = SIGUSR1;
	Mq_notify(mqd, &sigev);

	for ( ; ; ) {
		Sigwait(&newmask, &signo);
		if (signo == SIGUSR1) {
			Mq_notify(mqd, &sigev);			/* reregister first */
			while ( (n = mq_receive(mqd, buff, attr.mq_msgsize, NULL)) >= 0) {
				printf("read %ld bytes\n", (long) n);
			}
			if (errno != EAGAIN)
				err_sys("mq_receive error");
		}
	}
	exit(0);
}
示例#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, 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)
{
    /* Fig. 8.41 8.18 */
    int olderrno = errno;
    int status;
    pid_t p_id;
    struct job_t *job_ins;
    sigset_t prev, mask_all;

    Sigemptyset(&mask_all);
    Sigaddset(&mask_all, SIGCHLD);
    Sigaddset(&mask_all, SIGINT);
    Sigaddset(&mask_all, SIGTSTP);

    while((p_id = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
        /* Normally finish/exit */
        if (WIFEXITED(status)) {
          Sigprocmask(SIG_BLOCK, &mask_all, &prev); /* Block */
          deletejob(job_list, p_id);
          Sigprocmask(SIG_SETMASK, &prev, NULL); /* Unblock */
        } else if (WIFSIGNALED(status)) {
            /* Terminated by other signal */
            /* Order is fixed, otherwise it cause bugs. */
            printf("Job [%d] (%d) terminated by signal %d\n",
	          pid2jid(p_id), p_id, WTERMSIG(status));
            Sigprocmask(SIG_BLOCK, &mask_all, &prev); /* Block */
            deletejob(job_list, p_id);
            Sigprocmask(SIG_SETMASK, &prev, NULL); /* Unblock */
        } else if (WIFSTOPPED(status)) {
            /* Stopped by signal, need to modified the state to stopped */
            /* Order is fixed, otherwise it cause bugs. */
            printf("Job [%d] (%d) stopped by signal %d\n",
	          pid2jid(p_id), p_id, WSTOPSIG(status));
            job_ins = getjobpid(job_list, p_id);
            job_ins -> state = ST;
        }
    }

    errno = olderrno;
}
示例#21
0
文件: tsh.c 项目: RoseySoft/tsh
/* 
 * 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 *argv[MAXARGS];                                                        //arguments for execve()
    int bg;                                                                     //Determines whether the job will run in foreground or background
    pid_t pid;                                                                  //Contains the process id
    struct job_t *jd;
    sigset_t mask;                                                              //The signal set which has to be bloacked before adding the job to jobs

    bg = parseline(cmdline, argv);                                              //Copies contents of cmdline into argv and returns whether the job should run in background or foreground

    Sigemptyset(&mask);                                                         //Generate an empty signal set in mask
    Sigaddset(&mask, SIGCHLD);                                                  //Add SIGCHLD to the signal set to be blocked
    Sigaddset(&mask, SIGINT);                                                   //Add SIGINT to the signal set to be blocked
    Sigaddset(&mask, SIGTSTP);                                                  //Add SIGTSTP to the signal set to be blocked

    if(!builtin_cmd(argv)){                                                     //Checks whether command is built-in and executes it if yes, else enters if block
        Sigprocmask(SIG_BLOCK, &mask, NULL);                                    //Blocked the signal set
        if((pid = Fork()) == 0){                                                //Run user process in a child
            Sigprocmask(SIG_UNBLOCK, &mask, NULL);                              //Unblock the signal sets in child
            Setpgid(0,0);                                                       //New jobs should have new process ids else signal will kill shell also          
            if(execve(argv[0], argv, environ) < 0){                             //executes user command if successful
                printf("%s: Command not found.\n", argv[0]);                    //Throw error if execution unsuccessful
                exit(0);
            }
        }

        if(!bg){                                                                //If process is foreground, parent waits for the job to terminate
            addjob(jobs, pid, FG, cmdline);                                     //Add the process to jobs
            Sigprocmask(SIG_UNBLOCK, &mask, NULL);                              //Unblock the signal set afet adding the job
            waitfg(pid);                                                        //Parent waits for the foreground process to terminate}
        }

        else{                                                                   //If process is a background
            addjob(jobs, pid, BG, cmdline);                                     //Add the process to jobs
            Sigprocmask(SIG_UNBLOCK, &mask, NULL);                              //Unblock the signal set afet adding the job
            jd = getjobpid(jobs, pid);                                          //Get the jobpid
            printf("[%d] (%d) %s", jd->jid, jd->pid, jd->cmdline);              //Print the details of background job
        }
    }
    return;
}
示例#22
0
/*
 * builtin_fg_handler - Change a stopped or running
 * background job into a running foreground job
 */
void builtin_fg_handler(struct cmdline_tokens *tok) {
    /* TODO refactored */
    sigset_t prev, mask_all;

    Sigemptyset(&mask_all);
    Sigaddset(&mask_all, SIGCHLD);
    Sigaddset(&mask_all, SIGINT);
    Sigaddset(&mask_all, SIGTSTP);

    struct job_t *job_ins = id2job(tok, tok -> argc);

    /* Modify the status of candidate process, fire the signal */
    Sigprocmask(SIG_BLOCK, &mask_all, &prev); /* Block */
    job_ins -> state = FG;
    Sigprocmask(SIG_SETMASK, &prev, NULL); /* Unblock */

    Kill(job_ins -> pid, SIGCONT);

    /* Wait to stop */
    wait_fg_job(job_ins -> state);
}
示例#23
0
/*
 * builtin_bg_handler - Change a stopped background job
 * into a running background job
 */
void builtin_bg_handler(struct cmdline_tokens *tok) {
    /* TODO */
    sigset_t prev, mask_all;

    Sigemptyset(&mask_all);
    Sigaddset(&mask_all, SIGCHLD);
    Sigaddset(&mask_all, SIGINT);
    Sigaddset(&mask_all, SIGTSTP);
    struct job_t *job_ins = id2job(tok, tok -> argc);

    /* Fire the signal */
    if (ST == (job_ins -> state)) {
      Sigprocmask(SIG_BLOCK, &mask_all, &prev); /* Block */
      job_ins -> state = BG;
      Sigprocmask(SIG_SETMASK, &prev, NULL); /* Unblock */

        Kill(job_ins -> pid, SIGCONT);
        printf("[%d] (%d) %s\n",
          job_ins -> jid, job_ins -> pid, job_ins -> cmdline);
    }
}
示例#24
0
文件: util.c 项目: heapsters/shelldon
/*
 * waitfg - Block until process pid is no longer the
 *    foreground process
 */
void waitfg(pid_t pid)
{
    sigset_t mask, prev;

    Log("WAITFG [0]\n", 11);

    Sigemptyset(&mask);
    Sigaddset(&mask, SIGCHLD);

    Sigprocmask(SIG_BLOCK, &mask, &prev);

    Log("WAITFG [1]\n", 11);

    while (atomic_fggpid == pid) {
        Log("WAITFG [2]\n", 11);
        Sigsuspend(&prev);
    }

    Log("WAITFG [3]\n", 11);

    Sigprocmask(SIG_SETMASK, &prev, NULL);
}
示例#25
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? */
    struct cmdline_tokens tok;
    pid_t cpid ;    //child's pid
    sigset_t mask;
    sigset_t prev;
    int parseId;    //prepare for the jid or pid in the future
    int state;
    struct job_t* job;  //use for the fg or bg
    int infg = 0;   //default   STDIN
    int outfg = 1;  //default   STDOUT
    
    /* Create block signal */
    Sigemptyset(&mask);
    
    /* block int stp child signal with the block signal*/
    Sigaddset(&mask, SIGINT);
    Sigaddset(&mask, SIGTSTP);
    Sigaddset(&mask, SIGCHLD);
    
    /* Parse command line */
    bg = parseline(cmdline, &tok);
    
    if (bg == -1) /* parsing error */
        return;
    if (tok.argv[0] == NULL) /* ignore empty lines */
        return;
    
    /* When there is a redirect input or output
     ,  change the value infg and out fg to the file */
    if (tok.infile != NULL) {
        infg = Open(tok.infile, O_RDONLY, 0);
    }
    if (tok.outfile!=NULL) {
        outfg = Open(tok.outfile, O_WRONLY,0);
    }
    
/* There are 5 situations:
 1. Not a builtin command
 2. Quit
 3. list jobs
 4. builtin foreground jobs
 5. builtin background jobs
 */
    switch (tok.builtins) {
        case BUILTIN_NONE:
            //we need to fork and create a child process
            Sigprocmask(SIG_BLOCK, &mask, &prev);
            if ((cpid=Fork())==0) {
                //in the child process
                //we should unblock all signals
                Sigprocmask(SIG_UNBLOCK, &mask, NULL);
                cpid = getpid();
                //set child process group to avoid race condition
                setpgid(cpid,cpid);
                Sigprocmask(SIG_SETMASK, &prev, NULL);
                //set the in and out direction
                if(infg != 0){
                    Dup2(infg, 0);
                    Close(infg);
                }
                if (outfg != 1) {
                    Dup2(outfg, 1);
                    Close(outfg);
                }
                //process the outside command
                Execve(tok.argv[0], tok.argv, environ);
            }else{
                //in the parent process
                //determin whether it is a bg or fg
                if (bg==1) {
                    state = BG;
                }
                else{
                    state = FG;
                }
                //add the job to job list
                addjob(job_list, cpid, state, cmdline);
                //get the job from job list by pid
                job = getjobpid(job_list, cpid);
                //unblock all signal
                Sigprocmask(SIG_UNBLOCK, &mask, NULL);
                //use while to
                //set the shell wait until the job is stp or killed
                if(state == FG){
                    while (fgpid(job_list)!=0) {
                        Sigsuspend(&prev);
                    }
                }
                else{
                    //if bg, print the background job
                    printf("[%d] (%d) %s\n",job->jid, job->pid,cmdline);
                }
            }
            break;
        case BUILTIN_QUIT:
            //use the exit function
            exit(0);
            break;
        case BUILTIN_JOBS:
            //use the listjobs function
            listjobs(job_list, outfg);
            break;
        case BUILTIN_BG:
            //get the jid
            if (tok.argv[1][0]=='%') {
                parseId = atoi(&tok.argv[1][1]);
                job = getjobjid(job_list, parseId);
            }
            //or get the pid
            else if ((tok.argv[1][0] >= '0')&&(tok.argv[1][0]<='9')) {
                parseId = atoi(&tok.argv[1][0]);
                job = getjobpid(job_list, (pid_t)parseId);
            }
            printf("[%d] (%d) %s\n",job->jid, job->pid,job->cmdline);
            //set the job state to BG
            job->state = BG;
            //send SIGCONT
            Kill(-(job->pid), SIGCONT);
            break;
        case BUILTIN_FG:
            //get jid
            if (tok.argv[1][0]=='%') {
                parseId = atoi(&tok.argv[1][1]);
                job = getjobjid(job_list, parseId);
            }
            //get pid
            else if ((tok.argv[1][0] >= '0')&&(tok.argv[1][0]<='9')) {
                parseId = atoi(&tok.argv[1][0]);
                job = getjobpid(job_list, (pid_t)parseId);
            }
            //set the job state to FG
            job->state = FG;
            //send SIGCONT
            Kill(-(job->pid), SIGCONT);
            break;
        default:
            break;
    }
    
    return;
}
/* 
 * 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? */
    struct cmdline_tokens tok;
    pid_t pid;     /* if the pid is 0, it is the child. */
    int jid;       /* if the child runs in background, 
                      we should know the jid and print the infomation */

/*
 * Use new_mask to mask three signals.
 * Before the child process execve(), we should unblock these signals.
 * When it comes to parent process, we should set the old_mask set to
 * it after we add the job in job_list.
 */
    sigset_t new_mask, old_mask;

    /* Parse command line */
    bg = parseline(cmdline, &tok); 
/*
 * Maybe there are some more errors that we should return.
 * I did not meet them. If I met an error condition, I will
 * make an improvement as soon as possible.
 */
    if (bg == -1) return;               /* parsing error */
    if (tok.argv[0] == NULL)  return;   /* ignore empty lines */

/*
 * As it is said in the writeup, If the first word is a built-in command, the
 * shell immediately executes the command in the current process. Otherwise, 
 * the word is assumed to be the pathname of an executable program. In this 
 * case, the shell forks a child process, then loads and runs the program in
 * the context of the child.
 * 1. If it is a built-in command, builtinCommand function will handle it.
 * 2. If it is a executable program, the function returns 0.
 * 3. Then, we should block the signals before we fork a child.
 * 4. Put the child in a new process group.
 * 5. Set the I/O Redirection and make the signal default.
 * 6. Execute the program and exit.
 * 7. Add the job and unblock the signals in parent.
 * 8. If the child runs in foreground, wait for it.  
 */
    if (!builtinCommand(tok)) {
        Sigemptyset(&new_mask);
        Sigaddset(&new_mask, SIGCHLD);
        Sigaddset(&new_mask, SIGINT);
        Sigaddset(&new_mask, SIGTSTP);
        Sigprocmask(SIG_BLOCK, &new_mask, &old_mask);

        if (0 == (pid = Fork())) {
            int fdout, fdin;
            Setpgid(0, 0);
            dup2(fdout = getfd(OUT, tok.outfile), STDOUT_FILENO);
            dup2(fdin = getfd(IN, tok.infile), STDIN_FILENO);
            if (!bg) {
                tcsetpgrp(STDIN_FILENO, getpgrp());
            }
            Signal(SIGCHLD, SIG_DFL);
            Signal(SIGINT, SIG_DFL);
            Signal(SIGTSTP, SIG_DFL);
            Sigprocmask(SIG_UNBLOCK, &new_mask, NULL);
            if (execve(tok.argv[0], tok.argv, environ) < 0) {
                printf("%s: Command not found.\n", tok.argv[0]);
                exit(0);
            }
            if (STDOUT_FILENO != fdout) {
                close(fdout);
            }
            if (STDIN_FILENO != fdin) {
                close(fdin);
            }
            exit(0);
        }
        if (bg) {
            addjob(job_list, pid, BG, cmdline);
            Sigprocmask(SIG_SETMASK, &old_mask, NULL);
            jid = pid2jid(pid);
            printf("[%d] (%d) %s\n", jid, pid, cmdline);
        }
        else {
            addjob(job_list, pid, FG, cmdline);
            Sigprocmask(SIG_SETMASK, &old_mask, NULL);
/*
 * If the child runs in foreground, we should wait for it. I think it is
 * the most tricky thing in this shell lab. I test everything I know. Then,
 * I found the sigsuspend() function had the best performance.
 * 1. pause(). 
 *    It is the first way I think about. When I do manually from the
 *    command line, It is OK. However, when it comes to trace file, sometimes
 *    it is OK, sometimes it will cause an error.
 * 2. sleep(1), usleep(n), or something like these.
 *    Although Michael said that we cannot use sleep, I do not know what to do
 *    and what the performance is. So, I test it. When I ran it from the 
 *    command line, I could not find any wrong. When it comes to the trace 
 *    files, there are lots of errors. It seems that it is not a good way. -_-b
 * 3. sleep(0), sleep(0), sleep(0)...
 *    When I found the information in the Internet, someone said 3 or more 
 *    sleep(0) could be a good choice for wait. The fact is that it can pass
 *    a lot of trace files, but the performance is not stable. Also, I think 
 *    it will waste the CPU resource.
 * sigsuspend() is the only way that I found could pass the ./sdriver. If there
 * is annother better way, I will be very interested in it. If you would like 
 * to tell a better solution, I will be very happy.
 */
            while (fgpid(job_list)) {
                sigsuspend(&old_mask);
            }
        }
    }
    return;
}
示例#27
0
文件: tsh.c 项目: MyMiracle/Shell-Lab
/*
 * 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? */
    struct cmdline_tokens tok;

    /* Parse command line */
    bg = parseline(cmdline, &tok);
    if (bg == -1) return;               /* parsing error */
    if (tok.argv[0] == NULL)  return;   /* ignore empty lines */

    /* Built-in Command */
    if (tok.builtins!=BUILTIN_NONE){
      builtin_command(&tok);
      return;
      }

    /* Common tasks for both foreground and background */

    pid_t pid;
    sigset_t mask;
    Sigemptyset(&mask);
    Sigaddset(&mask, SIGCHLD);
    Sigaddset(&mask, SIGINT);
    Sigaddset(&mask, SIGTSTP);
    /* Block signal receving in parent */
    Sigprocmask(SIG_BLOCK, &mask, NULL);

    if ((pid=Fork())==0){
      /* Unblock signal receiving in child */
      Sigprocmask(SIG_UNBLOCK, &mask, NULL);
      /* Changes the child's process group from the shell's */
      Setpgid(0,0);

      /* Change the input and output file descriptors */
      IOredirection(&tok);

      Execve(tok.argv[0], tok.argv, environ);
      /* Command not found */
      printf("Executable file not found\n");
      exit(0);
    }

    /* Foreground job*/
    if (!bg){
      if (!addjob(job_list, pid, FG, cmdline))
	return;
      Sigprocmask(SIG_UNBLOCK, &mask, NULL);
      wait_for_fg(pid);
      return;
    }

    /* Background job */
    if (bg){
      if (!addjob(job_list, pid, BG, cmdline))
	return;
      Sigprocmask(SIG_UNBLOCK, &mask, NULL);
      printf("[%d] (%d) %s\n", pid2jid(pid), pid, cmdline);
    }
    return;
}
示例#28
0
文件: util.c 项目: heapsters/shelldon
/*
 * 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 (SIGSTP) from the kernel
 *    when we type ctrl-c (ctrl-z) at the keyboard.
 */
void eval(char *cmdline)
{
    char *argv[MAXARGS], buf[MAXLINE];
    int bg, status, state;
    volatile pid_t pid;
    int jid;
    sigset_t mask_all, mask_one, prev_one;

    Log("EVAL [0]\n", 9);

    strcpy(buf, cmdline);
    bg = parseline(buf, argv);

    if (argv[0] == NULL) {
        return;
    }

    Log("EVAL [1]\n", 9);

    if (builtin_cmd(argv)) {
        return;
    }

    Log("EVAL [2]\n", 9);

    Sigfillset(&mask_all);
    Sigemptyset(&mask_one);
    Sigaddset(&mask_one, SIGCHLD);

    Sigprocmask(SIG_BLOCK, &mask_one, &prev_one);

    pid = Fork();

    if (pid == CHILD) {
        Sigprocmask(SIG_SETMASK, &prev_one, NULL);
        Setpgid(0, 0);
        Log("EVAL [3]\n", 9);
        Execve(argv[0], argv, environ);
    }

    Sigprocmask(SIG_BLOCK, &mask_all, NULL);

    state = bg ? BG : FG;

    Log("EVAL [4]\n", 9);

    status = addjob(jobs, pid, state, cmdline);

    Log("EVAL [5]\n", 9);

    /* Stores jid while process has not been removed */
    jid = getjobpid(jobs, pid)->jid;

    atomic_fggpid = bg ? 0 : pid;

    Log("EVAL [5a]\n", 10);

    Sigprocmask(SIG_SETMASK, &prev_one, NULL);

    Log("EVAL [5b]\n", 10);

    /* Handle errors when generating a new job */
    if (!status) {
        return;
    }

    /* Parent waits for foreground job to terminate */
    if (!bg) {
        Log("EVAL [6]\n", 9);
        waitfg(pid);
    }
    else {
        Log("EVAL [7]\n", 9);
        printf("[%d] (%d) %s", jid, pid, cmdline);
    }
}
示例#29
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;
}