/* * 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; }
/* 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; }
/* * 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; }
/* * 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; }
/* * * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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 }
/* * 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); }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; } }
/* * 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; }
/* * 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]); }
/* * 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; }
/* * 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); } }
/* * 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; }
/* * 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); } } } }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }