Exemple #1
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];
	/* int ground = parseline(cmdline, (char **)&argv); */
	char buf[MAXLINE];      // Holds modified command line
	strcpy(buf, cmdline);
	int ground = parseline(buf, argv);

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

	if (!builtin_cmd((char **)&argv)) {
		sigset_t mask;
		sigemptyset(&mask);
		sigaddset(&mask, SIGCHLD);
		sigprocmask(SIG_BLOCK, &mask, NULL);
		pid_t pid = __fork();

		if (pid != 0) {
			addjob(jobs, pid, ground ? BG : FG, cmdline);
			sigprocmask(SIG_UNBLOCK, &mask, NULL);
			if (!ground) waitfg(pid);
			else printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
		} else {
			__setpgid(0, 0);
			sigprocmask(SIG_UNBLOCK, &mask, NULL);
			if (execve(argv[0], argv, environ) < 0) {
				printf("%s: Command not found\n", argv[0]);
				exit(0);
			}
		}
	}

	return;
}
Exemple #2
0
/* do_fg - Execute the builtin fg command */
void
do_fg(char **argv) 
{
  struct job_t * job;
  pid_t pid;

  if (verbose)
    printf("do_fg: entering\n");

  job = treat_argv(argv);
 
  job->jb_state = FG;

  pid = jobs_fgpid();
  assert(kill(-pid, SIGCONT) != -1);

  if (verbose)
    printf("do_fg: sigcont %d \n", pid);


  waitfg(pid);

  if (verbose)
    printf("do_fg: exiting\n");

  return;
}
Exemple #3
0
/* 
 * 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;
}
Exemple #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) 
{
    char *argv[MAXARGS];
    int isBG = parseline(cmdline, argv);
    if (argv[0] == NULL) return;
    if (builtin_cmd(argv)) return;

    sigset_t allset;
    sigfillset(&allset);

    sigprocmask(SIG_BLOCK, &allset, NULL);
    pid_t childpid = fork();
    if (childpid == -1) unix_error("fork failed");
    if (childpid == 0) {
        sigprocmask(SIG_UNBLOCK, &allset, NULL);
        if (setpgid(0, 0) == -1)  unix_error("setpgrp failed");
        if (execv(argv[0], argv) == -1) unix_error("execv failed");
    } 

    if (isBG) {
        addjob(jobs, childpid, BG, cmdline);
        printjob(jobs, childpid);
        sigprocmask(SIG_UNBLOCK, &allset, NULL);
    } else {
        addjob(jobs, childpid, FG, cmdline);
        sigprocmask(SIG_UNBLOCK, &allset, NULL);
        waitfg(childpid);
    }

    return;
}
Exemple #5
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 h
 *         * ave 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];
	int bg = parseline(cmdline, argv);
	pid_t pid;
	struct job_t *jb;
	sigset_t mask;
	if (argv[0] == NULL) return;	//Ignoring the empty lines
	if (!builtin_cmd(argv)) {
	sigprocmask(SIG_BLOCK,&mask, NULL);
		if((pid = fork()) == 0)	{
			
		sigprocmask(SIG_UNBLOCK,&mask,NULL);
		setpgid(0,0);
			if(execv(argv[0],argv)<0){
				printf("%s : Command not found!! \n" , argv[0]);
				exit(0);
			}
		}
			
		if(!bg) {
			addjob(jobs,pid,FG,cmdline);
			sigprocmask(SIG_UNBLOCK,&mask,NULL);	
			waitfg(pid);
			
		}
		else{
			addjob(jobs,pid,BG,cmdline);
			sigprocmask(SIG_UNBLOCK,&mask,NULL);	
			jb = getjobpid(jobs,pid);
			printf("[%d] (%d)  %s", jb->jid, jb->pid,jb->cmdline);
		}
	}
	return;
}
/* 
 * 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;
}
Exemple #7
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]; /* argv for execve() */
    int bg;
    pid_t pid;

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

    if(!builtin_cmd(argv))
    {
        if((pid = fork()) < 0) unix_error("eval(): fork() error");

        if(pid == 0) /* child runs user job */
	{
            if(setpgid(0,0) < 0) unix_error("eval(): setpgid() error");

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

	addjob(jobs,pid,(bg == 1 ? BG : FG),cmdline);

	sigprocmask(SIG_UNBLOCK,&mask,NULL);

	if(!bg) waitfg(pid);
	else printf("[%d] (%d) %s",pid2jid(pid),pid,cmdline);
    }

    return;
}
Exemple #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) 
{
  
	char *argv[MAXARGS];
	int bg=parseline(cmdline,argv);
        int  p=builtin_cmd(&argv[0]);
	int childpid;
	bg++;                //because the background process is defined as  2 and foreground as 1
        sigset_t set;
        sigemptyset(&set);
        sigaddset(&set,SIGCHLD);
        sigaddset(&set,SIGINT);
        sigaddset(&set,SIGTSTP);
        if(!p)
        {       
                if((childpid=fork())==0)
		{
			setpgid(0,0); //Changing group id
			execve(argv[0], argv, NULL);
                        printf("Command not found\n");//If incase there is no command
		        exit(0);
		}
                else
		{    
			sigprocmask(SIG_BLOCK,&set,NULL); //masking if incase child executes first
		        addjob(jobs,childpid,bg,cmdline);
                        sigprocmask(SIG_UNBLOCK,&set,NULL);//remove mask
                        if(bg==1) 
                        	waitfg(childpid);
	           	else
                   		printf("[%d] (%d) %s",pid2jid(childpid),childpid,cmdline);
                }
	}
	return;
}
Exemple #9
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
    struct job_t *job = NULL;
    if (argv[1] == NULL) {
        printf("%s command requires PID or %%jobid argument\n", argv[0]);
        return;
    }
    if (argv[1][0] == '%') job = getjobjid(jobs, atoi(argv[1] + 1));
    else job = getjobpid(jobs, atoi(argv[1]));
    if (job == NULL) {
        printf("%s: argument must be a PID or %%jobid\n", argv[0]);
        return ;
    }

    if (job->state == ST) {
        if (kill(-job->pid, SIGCONT) == -1) unix_error("kill failed");
    }
    if (strcmp(argv[0], "fg") == 0) {
        if (job->state != FG) {
            job->state = FG;
        }
        waitfg(job->pid);
    }
    return;
}
Exemple #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)
{
	// 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
}
Exemple #11
0
/* 
	* do_bgfg - Execute the builtin bg and fg commands
	*/
void do_bgfg(char **argv) 
{
	if (argv[1] == NULL) {
		printf("%s command requires PID or %%jobid argument\n", argv[0]);
		return;
	}

	if (!isdigit(argv[1][0]) && argv[1][0] != '%') {
		printf("%s: argument must be a PID or %%jobid\n", argv[0]);
		return;
	}

	if (argv[1][0] == '%' ? 1 : 0) {
		if (getjobjid(jobs, atoi(&argv[1][1])) == NULL) {
			printf("%s: No such job\n", argv[1]);
			return;
		}
	} else {
		if (getjobjid(jobs, atoi(&argv[1][1])) == NULL) {
			printf("(%d): No such process\n", atoi(argv[1]));
			return;
		}
	}

	// This is my favourite code
	__kill(-getjobjid(jobs, atoi(&argv[1][1]))->pid, SIGCONT);
	getjobjid(jobs, atoi(&argv[1][1]))->state = strcmp(argv[0], "fg")==0?FG:BG;
	if (strcmp(argv[0], "fg")==0) waitfg(getjobjid(jobs, atoi(&argv[1][1]))->pid); else printf("[%d] (%d) %s", getjobjid(jobs, atoi(&argv[1][1]))->jid, getjobjid(jobs, atoi(&argv[1][1]))->pid, getjobjid(jobs, atoi(&argv[1][1]))->cmdline);
}
Exemple #12
0
/*
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv)
{
    struct job_t *j=NULL;

    /* Did the user provide bg or fg with an arguement? */
    if(argv[1] == NULL)
    {
        printf("%s command requires PID or %%jobid argument\n",argv[0]);
        return;
    }

    /* Is the argument a PID? */
    if(isdigit(argv[1][0]))
    {
        pid_t pid = atoi(argv[1]);
        if(!(j = getjobpid(jobs,pid)))
        {
            printf("(%d): No such process\n", pid);
            return;
	    }
    }
    else if(argv[1][0] == '%') /* Is the argument a JID? */
    {
        int jid = atoi(&argv[1][1]); /* argv[1][1] points past the '%' */

        if(!(j = getjobjid(jobs,jid)))
        {
	        printf("%s: No such job\n",argv[1]);
            return;
        }
    }
    else
    {
        printf("%s: argument must be a PID or %%jobid\n",argv[0]);
	    return;
    }

    if(!strcmp(argv[0],"bg"))
    {
        if(kill(-(j->pid),SIGCONT) < 0) unix_error("do_bgfg(): kill error");

        j->state =BG;
        printf("[%d] (%d) %s",j->jid,j->pid,j->cmdline);
    }
    else if(!strcmp(argv[0],"fg"))
    {
        if(kill(-(j->pid),SIGCONT) < 0) unix_error("do_bgfg(): kill error");

        j->state = FG;
	    waitfg(j->pid);
    }
    else
    {
        printf("do_bgfg(): internal error\n");
        exit(0);
    }

    return;
}
Exemple #13
0
/*
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv)
{

	if(!argv) return;
	int argc=0;
	int temp = 0;
	struct job_t* job = NULL;
	for(; argv[argc] != 0; argc++);
	if(argc != 2)
		{
			printf("fg command requires PID or %%jobid argument\n");
			return;
		}
	char* pid_or_jid = argv[1];
	if(pid_or_jid[0] != '%' && (pid_or_jid[0] > '9' || pid_or_jid[0] < '0'))
	{
		printf("fg: argument must be a PID or %%jobid\n");
		return;
	}

	if(pid_or_jid[0] == '%')
	{
		temp = atoi(pid_or_jid+1);
		job = getjobjid(jobs,temp);
		if(!job)
		{
			printf("%s: No such job\n", pid_or_jid);
			return;
		}
	}
	else
	{
		temp = atoi(pid_or_jid);
		job = getjobpid(jobs,temp);
		if(!job)
		{
			printf("(%d): No such process\n", temp);
		return;
		}
	}
	//foreground job
	if(!strcmp("fg", argv[0]))
	{
		kill(-job->pid,SIGCONT);
		job->state = FG;
		waitfg(job->pid);

	}
	//background job
	else if(!strcmp("bg", argv[0]))
	{
		printf("[%d] (%d) %s", job->jid, job->pid,job->cmdline);
		kill(-job->pid, SIGCONT);
		job->state = BG;
	}

    return;
}
Exemple #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.  
 *
 * Requires:
 *   "cmdline" is a NUL ('\0') terminated string with a trailing
 *   '\n' character.  "cmdline" must contain less than MAXARGS
 *   arguments.
 *
 * Effects:
 *   A built-in command is executed immediately. Otherwise, it attempts 
 *   to fork a child process and execute the job. If necessary, the 
 *   executable program is searched through the directories of the 
 *   search path. If not found, an error is thrown. If the job is
 *   running as a foreground job, it waits until completion.  
 */
static void
eval(const char *cmdline) 
{
	char *argv[MAXARGS];
	int bg = parseline(cmdline, argv);
	pid_t pid;
	sigset_t mask;
	
	// Checks command line is not empty.
	if (!argv[0]) {
		return;
	}

	// Checks that the command is not a built-in command.
	if(!builtin_cmd(argv)){
		sigemptyset(&mask);
		sigaddset(&mask, SIGCHLD);
		sigprocmask(SIG_BLOCK, &mask, NULL);

		// A child is forked. 
		pid = fork();
		if (pid == 0) {
			// Put child in new group whose ID is identical to child’s PID.
			setpgid(0, 0);
			sigprocmask(SIG_UNBLOCK, &mask, NULL);

			if (execve(argv[0], argv, environ) == -1) {
				int index = 0;
				// Run through directories in search path to execute program.
				while (argv[0][0] != '.' && index < directoryCount) {
					if (execve(strcat(directories[index],argv[0]), argv, environ) != -1) {
						break;
					}
					index++;
				}
				// Command not found.
				char *print;
				asprintf(&print, "%s: Command not found\n", argv[0]);
				sio_error(print);
			} 
		}
	

		if (bg == 0) {
			addjob(jobs,pid,FG,cmdline);
			sigprocmask(SIG_UNBLOCK, &mask, NULL);
			// Wait for foreground jobs to complete.
			waitfg(pid);
		}
		else {
			addjob(jobs,pid,BG,cmdline);
			sigprocmask(SIG_UNBLOCK, &mask, NULL);
			printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline); 
		}
	}
 
	return;
}
Exemple #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];
	char buf[MAXLINE];
	int bg;
	sigset_t mask;
	pid_t pid;
	
	strcpy(buf, cmdline);
	bg = parseline(buf, argv);
	if(argv[0] == NULL)
		return;

	if(!builtin_cmd(argv)){
		
		//block signal
		if(sigemptyset(&mask) < 0)
			unix_error("sigemptyset error");
		if(sigaddset(&mask, SIGCHLD) < 0)
			unix_error("sigaddset error");
		if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
			unix_error("sigprocmask error");

		if((pid = fork()) == 0){

			//set pid group to be the same as the current pid
			if(setpgid(0,0) < 0)
				unix_error("eval: set pid group error");

			//unblock siganl
			if(sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0)
				unix_error("sigprocmask error");

			//execute program
			if(execve(argv[0], argv, environ)<0){
				printf("%s: Command not found.\n", argv[0]);
				exit(1);
			}
		}
		
		if(!bg){
			addjob(jobs, pid, FG, cmdline);

			//unblock siganl
			if(sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0)
				unix_error("sigprocmask error");
			waitfg(pid);
		}else{
			addjob(jobs, pid, BG, cmdline);

			//unblock siganl
			if(sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0)
				unix_error("sigprocmask error");
			printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
		}
	}
    return;
}
Exemple #16
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* argvTask[MAXARGS]; // holds arguments for other calls
        pid_t npid; // new pid temp var
        sigset_t mask;
        parseline(cmdline, argvTask);
        if(builtin_cmd(argvTask)){}                 // check for a built in and runs immediately
        else // reaches for non-built in
        {
                sigemptyset(&mask);
                sigaddset(&mask, SIGCHLD);
                sigprocmask(SIG_BLOCK, &mask, NULL); // enable mask for parent
                if(parseline(cmdline, argvTask)) //checking if BG
                {
                        if(( npid = fork()) == 0) // child run in bg
                        {
                                sigprocmask(SIG_UNBLOCK, &mask, NULL); // unblock mask for child
                                setpgid(0,0);
                                if(execve(argvTask[0], argvTask, environ) < 0)
                                {
                                        //unix_error( argvTask[0]);
                                        printf("%s: Command not found \n",argvTask[0]);

                                        exit(0);
                                }
                        }
                        else // parent
                        {
                                addjob(jobs, npid,BG, cmdline); // add bg job to list and parent does not wait
                                printf( "[%d] (%d) %s", maxjid(jobs) , npid , cmdline);

                                sigprocmask(SIG_UNBLOCK, &mask, NULL); // unblock the parent
                        }
                }
                else // runs if FG
                {
                        if(( npid = fork()) == 0) // child run in fg
                        {
                                sigprocmask(SIG_UNBLOCK, &mask, NULL); // unblock child
                                setpgid(0,0);
                                if(execve(argvTask[0], argvTask, environ) < 0) // use exec call and check for error
                                {
                                        printf("%s: Command not found \n",argvTask[0]);
                                        exit(0);
                                }
                        }
                        else                 // parent
                        {
                                addjob(jobs, npid,FG,cmdline);        // adding the fg job to jobs list
                                sigprocmask(SIG_UNBLOCK, &mask, NULL); // unblock the parent

                                waitfg(npid);        //waiting for fg process to finish
                        }
                }
        }
  return;
}
Exemple #17
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];
    int bg = parseline(cmdline, argv);
    int rbic = builtin_cmd(argv);

    if (!rbic)
    {
        pid_t child = fork();
        //printf("forked\n");
        
        if (child)
        {      
            //PARENT    
            if (bg)
            {
                int ret = addjob(jobs, child, BG, cmdline); //returns an int
                if (ret)
                {
                    int jid = pid2jid(child);
                    printf("[%d] (%d) %s", jobs[jid-1].jid, jobs[jid-1].pid, jobs[jid-1].cmdline);
                }
                else
                {
                    printf("addjobfailed\n");
                }
            }
            else
            {
                int ret = addjob(jobs, child, FG, cmdline); //returns an int
                if (!ret)
                {
                    printf("addjobfailed\n");
                }
                waitfg(child);
            }
        }
        else if( child < 0 )
        {
            //ERROR
            exit(1); 
        }
        else
        {
            //CHILDS
            setpgid( 0, 0 );
            int rc = execv( argv[0], argv );
            if (rc == -1)
            {
                printf( "execv error %d\n", errno);
                exit(1);
            }
        }
    }
    return;
    
}
Exemple #18
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{   
    struct job_t *job;
    char *tmp;
    int jid;
    pid_t pid;

    tmp = argv[1];
    
    // if id does not exist
    if(tmp == NULL) {
        printf("%s command requires PID or %%jobid argument\n", argv[0]);
        return;
    }
    
    // if it is a jid
    if(tmp[0] == '%') {  
        jid = atoi(&tmp[1]); 
        //get job
        job = getjobjid(jobs, jid);
        if(job == NULL){  
            printf("%s: No such job\n", tmp);  
            return;  
        }else{
            //get the pid if a valid job for later to kill
            pid = job->pid;
        }
    } 
    // if it is a pid
    else if(isdigit(tmp[0])) { 
        //get pid
        pid = atoi(tmp); 
        //get job 
        job = getjobpid(jobs, pid); 
        if(job == NULL){  
            printf("(%d): No such process\n", pid);  
            return;  
        }  
    }  
    else {
        printf("%s: argument must be a PID or %%jobid\n", argv[0]);
        return;
    }
    //kill for each time
    kill(-pid, SIGCONT);
    
    if(!strcmp("fg", argv[0])) {
        //wait for fg
        job->state = FG;
        waitfg(job->pid);
    } 
    else{
        //print for bg
        printf("[%d] (%d) %s", job->jid, job->pid, job->cmdline);
        job->state = BG;
    } 
}
Exemple #19
0
/*
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv)
{
	struct job_t* job = NULL;
	sigset_t mask;
	int jid = 0;
    int fg = !strcmp(argv[0],"fg");
	if(argv[1] == NULL){
		printf("%s command requires PID or %%jobid argument\n", argv[0]);
		return;
	}
	//used to save a bit of repetition when returning after an error
	int done = 0;

	//SIGCHLD handler could delete the job before it is or read edited
	//giving us a seg fault so we must protect it while reading and editing state
	sigemptyset(&mask);
	sigaddset(&mask, SIGCHLD);
	sigprocmask(SIG_BLOCK, &mask, NULL);
	if(isdigit(argv[1][0])){
		pid_t pid = atoi(argv[1]);
		jid = pid2jid(pid);
		if(jid == 0){
			printf("(%d): No such process\n", pid);
			done = 1;
		}
	}else if(argv[1][0]=='%'){
		argv[1]++;
		jid = atoi(argv[1]);
		if(getjobjid(jobs, jid) == NULL){
			printf("%%%s: No such job\n", argv[1]);
			done = 1;
		}
	}else{
		printf("%s: argument must be a PID or %%jobid\n", argv[0]);
		done = 1;
	}
	if(done){
		sigprocmask(SIG_UNBLOCK, &mask, NULL);
		return;
	}
	job = getjobjid(jobs, jid);
	if(kill(-job->pid,SIGCONT) < 0){
		printf("Could not continue child process\n");
		sigprocmask(SIG_UNBLOCK, &mask, NULL);
		return;
	}
	//sets state to 1 if fg 2 if bg
	job->state = !fg + 1;
	if(fg){
		sigprocmask(SIG_UNBLOCK, &mask, NULL);
		waitfg(job->pid);
	}else{
		printf("[%d] (%d) %s",job->jid,job->pid, job->cmdline);	
		sigprocmask(SIG_UNBLOCK, &mask, NULL);
	}
    return;
}
Exemple #20
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
	struct job_t *job;
	int jid;
	pid_t pid;

	if (argv[1] == NULL)
	{
		printf("%s command requires PID or %%jobid argument\n", argv[0]);
		return;
	}
	
	if (argv[1][0] == '%')
	{
		jid = atoi(argv[1]+1);
		if (!(job = getjobjid(jobs, jid)))
		{
			printf("%s: No such job\n", argv[1]);
			return;
		}
	}
	else if (isdigit(argv[1][0]))
	{
		pid = atoi(argv[1]);
		if (!(job = getjobpid(jobs, pid)))
		{
			printf("(%d): No such process\n", pid);
			return;
		}	
	}	
	else
	{
		printf("%s: argument must be a PID or %%jobid\n", argv[0]);
		return;
	}
	
	if (kill(-(job->pid), SIGCONT) < 0)
	{
		if (errno != ESRCH)
			unix_error("do_bgfg error");
	}
	
	if (!strcmp("fg", argv[0]))
	{
		job->state = FG;
		waitfg(job->pid);
	}
	else if (!strcmp("bg", argv[0]))
	{
		printf("[%d] (%d) %s", job->jid, job->pid, job->cmdline);
		job->state = BG;
	}
	else
		printf("bg/fg error: %s\n", argv[0]);

}
Exemple #21
0
/*
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv)
{
    // Check if there's an argument
    if (argv[1] == NULL) {
        printf("%s command requires PID or %%jobid argument\n", argv[0]);
        return;
    }

    struct job_t* process = NULL;

    // Check if it's a pid or a jid
    if (argv[1][0] == '%') {
        // Check if the jid is valid
        if (strlen(argv[1]) == 1 || valid(&argv[1][1]) == 0) {
            printf("%s: argument must be a PID or %%jobid\n", argv[0]);
            return;
        }
        // Get the process
        process = getjobjid(jobs, atoi(&argv[1][1]));
        // Error handling
        if (process == NULL) {
            printf("%s: No such job\n", argv[1]);
            return;
        } 
    }
    else {
        // Check if the pid is valid
        if (valid(argv[1]) == 0) {
            printf("%s: argument must be a PID or %%jobid\n", argv[0]);
            return;
        }
        // Get the process
        process = getjobpid(jobs, (pid_t)atoi(argv[1]));
        if (process == NULL) {
            printf("(%s): No such process\n", argv[1]);
            return;
        }
    }

    // If the process is stopped send SIGCONT
    if (process->state == ST) {
        Kill(-(process->pid), SIGCONT);
    }
    // Check if program is bg or fg
    if (strcmp(argv[0], "bg") == 0) {
        process->state = BG;
        // Print job info
        printf("[%d] (%d) %s", process->jid, process->pid, process->cmdline);
    }
    else {
        process->state = FG;
        waitfg(process->pid);
    }
    return;
}
Exemple #22
0
/* 
 * 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);
    }
}
Exemple #23
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;
}
Exemple #24
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];
    //int to record for bg   
    int bg;         
    pid_t pid;      
    sigset_t mask;
    
    // parse the line
    bg = parseline(cmdline, argv);
    //check if valid builtin_cmd
    if(!builtin_cmd(argv)) { 
        
        // blocking first
        sigemptyset(&mask);
        sigaddset(&mask, SIGCHLD);
        sigprocmask(SIG_BLOCK, &mask, NULL);
        // forking
        if((pid = fork()) < 0){
            unix_error("forking error");
        }
        // child
        else if(pid == 0) {
            sigprocmask(SIG_UNBLOCK, &mask, NULL);
            setpgid(0, 0);
            //check if command is there
            if(execvp(argv[0], argv) < 0) {
                printf("%s: Command not found\n", argv[0]);
                exit(1);
            }
        } 
        // parent add job first
        else {
            if(!bg){
                addjob(jobs, pid, FG, cmdline);
            }
            else {
                addjob(jobs, pid, BG, cmdline);
            }
            sigprocmask(SIG_UNBLOCK, &mask, NULL);
            
            //if bg/fg
            if (!bg){
                //wait for fg
                waitfg(pid);
            } 
            else {
                //print for bg
                printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline);
            }
        }
    }
}
Exemple #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) 
{


    char *argv[MAXARGS];                            //args for execvp
    pid_t pid;
    sigset_t sSet;
    int stat;
    
    if (*cmdline == 10)
        return;
    else{
        stat= parseline(cmdline, argv);
        if (argv[0] == NULL)  
        return;   /* ignore empty lines */
        
        if(!builtin_cmd(argv)){ //If it is not a user command
        
        sigemptyset(&sSet);
        sigaddset(&sSet,SIGCHLD);
        sigprocmask(SIG_BLOCK, &sSet,NULL);
            

            if((pid = fork()) == 0) { /*Child runs user job*/
                setpgrp();
                sigprocmask(SIG_UNBLOCK, &sSet,NULL); /*Unblocked after setpgrp() because childpid should be set as group pid first without any interruption */
                int stat1=execvp(argv[0], argv);         //prints a message if execvp fails.
            if(stat1 < 0) { //If the command doesnot exists
                stat1=0;
                printf("%s: Command not found.\n",argv[0]);//prints a message if execvp fails.
                exit(0);                                 /*In case execvp fails then exit will get called.*/
            }
        }


        
        if(stat) {
                addjob(jobs, pid, BG, cmdline);       /* request for background job then job is added with BG state*/ 
                sigprocmask(SIG_UNBLOCK,&sSet,NULL);  /*unblocks signal after adding all jobs without any type of signal*/
                printf("[%d] (%d) %s",pid2jid(pid),pid,cmdline);
        }

        else
            {
                addjob(jobs, pid, FG, cmdline) ;
                sigprocmask(SIG_UNBLOCK,&sSet,NULL);/*unblocks signal after adding all jobs without any type of signal*/
                waitfg(pid);/*parent waits*/
            }
        }
    } 

  return;
}
Exemple #26
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
    char* p;
    int jobid;
    
      if(argv[1]==NULL)
      {
         printf("%s command requires PID or %%jobid argument\n",argv[0]);
         return;
      }
      if((p = strstr(argv[1],"%"))!=NULL)
      {
      	p++;
        jobid=atoi(p);
        if(getjobjid(jobs,jobid)!=NULL)     
		jobid=getjobjid(jobs,jobid)->pid;
        else
	{
		printf("%%[%d]: no such job\n",atoi(p));
		return;
        }
      }
      else if(isdigit(argv[1][0]))
      {
       
	jobid=atoi(argv[1]);    //argv[1] is the pid.
        if(getjobpid(jobs,jobid)==NULL)
	  {
	 	 printf("(%d) no such process\n",jobid);
                 return;
          }
      }
      else
        {
	         printf("%s: argument must be a PID or %%jobid\n",argv[0]);
                 return;
        }
      
      kill(-jobid,SIGCONT);    

      if(strcmp(argv[0],"fg")==0)
      {
      	getjobpid(jobs,jobid)->state=FG; 
        waitfg(jobid);
      }
     else
     {
        getjobpid(jobs,jobid)->state =BG;
        printf("[%d] (%d) %s",getjobpid(jobs,jobid)->jid,getjobpid(jobs,jobid)->pid,getjobpid(jobs,jobid)->cmdline);
     }
     return;
}
Exemple #27
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
    char *id = argv[1];
	if(id == NULL){//invalid input
		if(!strcmp(argv[0], "bg") )
			printf("bg command requires PID or %%jobid argument\n");
		else
			printf("fg command requires PID or %%jobid argument\n");
        return;
	}
	struct job_t *job;
    int jid;
    pid_t pid;
	
    //find job_t from the id
    if(id[0] == '%'){ //jid
       jid = atoi(&id[1]);
       job = getjobjid(jobs, jid);
       if(job == NULL){
          printf("%%%d: No such job\n", jid);
          return;
       }
    }
    else{ //pid
        pid = atoi(id);
        job = getjobpid(jobs,pid);
        if(job == NULL){
           printf("(%d): No such process\n", pid);
           return;
        }
    }

    //restart job by sending SIGCONT signal
    if(kill(- job->pid, SIGCONT) < 0){
        printf("Error with SIGCONT\n");
        return;
    }
	
	if(!strcmp(argv[0], "bg") ){
		printf("[%d] (%d) %s", job->jid, job->pid, job->cmdline);
        job->state = BG;
	}
	else if(!strcmp(argv[0], "fg") ){
        job->state = FG;
        waitfg(job->pid);
	}
    else{
        printf("There is an error with bg or fg\n");
    }
	
    return;  
}
Exemple #28
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
    struct job_t * p;
    char *ptr;
    int ret;
    if(argv[1]==NULL)    //No argument to fg or bg passed
      printf("%s command requires PID or %cjobid argument\n",argv[0],'%');
    else{
		if(*argv[1]=='%'){   //if job id passed
                                                     /* strtol returns integer in the argument passed and pointer to the string if present in it
                                                      * For eg. if argument is 1243gjgk, strtol returns 1243 and ptr points to "gjgk".
                                                      */
			ret=strtol(++argv[1],&ptr,10);
			if(*ptr!='\0'){   //an integer was passed
		  		printf("%s: argument must be a PID or %cjobid\n",argv[0],'%');
				return;
			}
                                                     else{
				p=getjobjid(jobs,ret);
				if(p==NULL){
			        	printf("%c%d No such job\n",'%',ret);
					return;
				}			
			}
		}
		else{   //Now for pid
		    ret=strtol(argv[1],&ptr,10);
	            if(*ptr!='\0'){
		    	printf("%s: argument must be a PID or %cjobid\n",argv[0],'%');
			return;
			}
		    else{
			        p = getjobpid(jobs, ret);
				if(p==NULL){
				   printf("(%d): No such process\n",ret);
				   return;
				}
			}
	     	}
	        kill(-(p->pid),SIGCONT);  //Send SIGCONT signal to the process group
		if(strcmp(*argv,"fg")==0){
                                                      p->state=FG; //change the state to FG
			    waitfg(p->pid); //wait for the foreground job
                                    }                
               	else{
			p->state=BG;	//change the state to BG		    
			printf("[%d] (%d) %s",p->jid,p->pid,p->cmdline);
                 }
	} 
	return;  
}
Exemple #29
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
    int jid = 0;
    pid_t pid;
/*handle 4 possible errors*/
    if (argv[1] == NULL) {
       printf("%s command requires PID or %%jobid argument\n", argv[0]);
       return;
    }
    if (argv[1][0] != '%' && !((argv[1][0])<='9' && argv[1][0]>='0')){
       printf("%s: argument must be a PID or %%jobid\n", argv[0]);
       return;
    }
    if (argv[1][0] == '%'){
       jid = atoi(argv[1]+1);
       struct job_t *now_job = getjobjid(jobs,jid);
       if (now_job == NULL){
          printf("%s: No such job\n", argv[1]);
          return;
       }
       pid = jobs[jid-1].pid;
    }
    else{
       char *str = (char *)malloc(strlen(argv[1])* sizeof (char));
       int i = 0;
       while (argv[1][i] != '\0' && (argv[1][i]<='9' && argv[1][i]>='0')){
	   str[i] = argv[1][i];
           i++;
       }
       str[i] = '\0';
       pid = atoi(str);
       jid = pid2jid(pid);
       struct job_t *now_job = getjobjid(jobs,jid);
       if (now_job == NULL){
          printf("(%s): No such process\n", argv[1]);
          return;
       }
    } 
/*handle bg & fg*/
    if (strcmp(argv[0],"bg") == 0){
       kill(-pid,SIGCONT);
       jobs[jid-1].state = BG;
       printf("[%d] (%d) %s", jid, pid, jobs[jid-1].cmdline);
    }
    if (strcmp(argv[0],"fg") == 0){
       kill(-pid,SIGCONT);
       jobs[jid-1].state = FG;
       waitfg(pid);
    }
    return;
}
Exemple #30
0
/* 
 * do_bgfg - Execute the builtin bg and fg commands
 */
void do_bgfg(char **argv) 
{
    struct job_t* jd = NULL;                                                        //Store the job details

    if( argv[1] == NULL ){                                                          //If no second argument
        printf("%s command requires PID or %%jobid argument\n", argv[0]);           //throw error
        return;
    }

    if(argv[1][0] == '%'){                                                          //If % then job id

        if(!isdigit(argv[1][1])){                                                   //If not a digit
            printf("%s: argument must be a pid or %%jobid\n", argv[0]);             //throw error
            return;
        }

        int jid = atoi( &argv[1][1] );                                              //Get the jid
        if( !( jd = getjobjid( jobs, jid ) ) ){                                     //If no such job with that jid
            printf( "%s: no such job\n", argv[1] );                                 //throw error
            return;
        }
    }

    else{                                                                           //If no % then pid

        if(!isdigit(argv[1][0])){                                                   //If not a digit
            printf("%s: argument must be a pid or %%jobid\n", argv[0]);             //throw error
            return;
         }

        pid_t pid = atoi( argv[1] );                                                //get the pid
        if( !( jd = getjobpid( jobs, pid ) ) ){                                     //if no such job with that pid
            printf( "(%s): no such process\n", argv[1]);                            //throw error
            return;
        }
    }

    Kill(-jd->pid, SIGCONT);                                                        //Send SIGCONT signal

    if( !strcmp( argv[0],"bg" ) ){                                                  //If background
        jd->state = BG;                                                             //Change job state to BG
        printf("[%d] (%d) %s",jd->jid,jd->pid,jd->cmdline);                         //print status
    }

    else {                                                                          //If foreground
        jd->state = FG;                                                             //Change job state to FG
        waitfg( jd->pid );                                                          //Wait for the job to finish
    }

    return;
}