//Sophie is driving void eval(char *cmdline) { char cmds[MAXLINE]; char *argv[MAXARGS]; int status; pid_t pid; strcpy(cmds, cmdline); parseline(cmds, argv); if(builtin_cmd(argv)) { if(strcmp(argv[0], "quit") == 0) { sigquit_handler(SIGQUIT); } } else { pid = fork(); if(pid == 0) { execve(argv[0], argv, environ); exit(-1); } else { waitpid(pid, &status, 0); } } 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; }
/* * 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; }
/* * eval - Evaluate the command line that the user has just typed in * * If the user has requested a built-in command (quit) * 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. */ 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 */ strcpy(buf, cmdline); bg = parseline(buf, argv); if (argv[0] == NULL) return; /* Ignore empty lines */ if (!builtin_cmd(argv)) {if ((pid = fork()) == 0) /* Child runs user job */ {if (execv(argv[0],argv) < 0) { printf("%s: Command not found.\n", argv[0]); exit(0); } } /* Parent waits for foreground job to terminate */ if (!bg) { int status; if (waitpid(pid, &status, 0) < 0) unix_error("waitfg: waitpid error"); } else printf("%d %s", 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) { // 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 }
/* * 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; }
/* * process_cmd * * 명령 라인을 인자 (argument) 배열로 변환한다. * 내장 명령 처리 함수를 수행한다. * 내장 명령이 아니면 자식 프로세스를 생성하여 지정된 프로그램을 실행한다. * 파이프(|)를 사용하는 경우에는 두 개의 자식 프로세스를 생성한다. */ void process_cmd(char *cmdline) { int argc; char *argv[MAXARGS]; // 명령 라인을 해석하여 인자 (argument) 배열로 변환한다. argc = parse_line(cmdline, argv); /* 내장 명령 처리 함수를 수행한다. */ if (builtin_cmd(argc, argv) == 0) { // 내장 명령 처리를 완료하고 리턴한다. return; } /* * 자식 프로세스를 생성하여 프로그램을 실행한다. */ // 프로세스 생성 // 자식 프로세스에서 프로그램 실행 // 파이프 실행이면 자식 프로세스를 하나 더 생성하여 파이프로 연결 // foreground 실행이면 자식 프로세스가 종료할 때까지 기다린다. 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; }
/* * 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 * 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; }
/* * 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; }
void eval(char *cmdline) { char buf[MAXLINE]; char *argv[MAXARGS]; int bg; int i; struct job *p; pid_t pid, tcpid; strcpy(buf, cmdline); bg = parseline(buf, argv); if (argv[0] == NULL) return; if (!builtin_cmd(argv)) { child_block(); if ((pid = Fork()) == 0) { child_unblock(); control_unblock(); if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) { printf("signal error\n"); exit(-1); } if (execve(argv[0], argv, environ) < 0) { printf("%s : Command not found.\n", argv[0]); exit(0); } } addjob(pid, cmdline); if (bg) { setpgid(pid, pid); p = selectjob(pid); printf("[%d] %d ", p->jid, p->pid); for (i = 0; p->argv[i] != NULL; i++) printf("%s ", p->argv[i]); printf("\n"); } else { forepid = pid; child_unblock(); printf("ready to fg_waitpid\n"); if (!sigsetjmp(env, 0)) { while (1) sleep(50); printf("u never see me\n"); } else printf("no fg_waitpid\n"); return; } child_unblock(); } 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) { // 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]; //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; }
/* * 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]; char buf[MAXLINE]; int bg; pid_t pid; sigset_t mask; strcpy(buf,cmdline); bg = parseline(buf,argv); if (argv[0] == NULL) return; if (!builtin_cmd(argv)) { sigemptyset(&mask); sigaddset(&mask,SIGCHLD); sigprocmask(SIG_BLOCK,&mask,NULL); if ((pid = fork()) < 0) { perror("fork"); exit(0); } else if (pid == 0) { sigprocmask(SIG_UNBLOCK,&mask,NULL); if (execvp(argv[0], argv) < 0) { printf("%s : Command not found.\n", argv[0]); exit(0); } } if (bg) addjob(jobs,pid,BG,buf); else addjob(jobs,pid,FG,buf); sigprocmask(SIG_UNBLOCK,&mask,NULL); if (!bg) { waitfg(pid); } else { printf("%d %s",(int)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) { /* the following code demonstrates how to use parseline --- you'll * want to replace most of it (at least the print statements). */ int i, bg, job_loc; char *argv[MAXARGS]; bg = parseline(cmdline, argv); if (bg) { // printf("background job requested\n"); } for (i=0; argv[i] != NULL; i++) { // printf("argv[%d]=%s%s", i, argv[i], (argv[i+1]==NULL)?"\n":", "); } if (builtin_cmd(&argv[0]) == 0){ return; }else{ int pid; sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, NULL); if((pid=fork())==0){ setpgid(0, 0); if(execvp(argv[0], argv)< 0){ printf("Command not found\n"); deletejob(jobs, pid); exit(0); } } if (!bg){ job_loc=addjob(jobs,pid,FG,cmdline); sigprocmask(SIG_UNBLOCK, &mask, NULL); waitfg(pid); } else{ job_loc=addjob(jobs,pid,BG,cmdline); printf("[%d] (%d) %s",job_loc, pid, cmdline); sigprocmask(SIG_UNBLOCK, &mask, NULL); } 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; pid_t pid; sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); bg=parseline(cmdline, argv); if(!builtin_cmd(argv)){ sigprocmask(SIG_BLOCK, &mask, 0); /* Fork */ if((pid=fork())<0){ unix_error("fork error"); return; } /* Child process */ else if(pid==0){ if(setpgid(0,0)<0) unix_error("setpgid error"); if (execvp(argv[0], argv) < 0) { printf("%s: Command not found. \n", argv[0]); exit(0); } } /* Parent process */ else{ if(bg==1){ addjob(jobs, pid, BG, cmdline); sigprocmask(SIG_UNBLOCK, &mask, 0); printf("[&d] (%d) %s", pid2jid(pid), pid, cmdline); } else{ addjob(jobs, pid, FG, cmdline); sigprocmask(SIG_UNBLOCK, &mask, 0); waitfg(pid); } } } return; }
void eval(char *cmdline) { char *argv[MAXARGS]; int argc = 0; int bg = parseline(cmdline, argv, &argc); pid_t pid = -1; sigprocmask(SIG_BLOCK,&maskchld,NULL); if(builtin_cmd(argv,argc)) return; if(bg) { pid = Fork(); if(pid==0) { setpgid(0,0); sigprocmask(SIG_UNBLOCK,&maskchld,NULL); Signal(SIGINT, SIG_DFL); Signal(SIGTSTP, SIG_DFL); if(execv(argv[0], argv) < 0) { printf("%s: Command not found\n",argv[0]); exit(0); } return; } addjob(jobs,pid,BG,cmdline); struct job_t* job = getjobpid(jobs,pid); printf("[%d] (%d) ", job->jid, job->pid); printf("%s", job->cmdline); sigprocmask(SIG_UNBLOCK,&maskchld,NULL); } else { pid=Fork(); if(pid==0){ setpgid(0,0); sigprocmask(SIG_UNBLOCK,&maskchld,NULL); Signal(SIGTSTP,SIG_DFL); Signal(SIGINT,SIG_DFL); if(execv(argv[0],argv) < 0){ printf("%s: Command not found\n",argv[0]); exit(0); } } addjob(jobs,pid,FG,cmdline); sigprocmask(SIG_UNBLOCK,&maskchld,NULL); waitfg(pid); return; } 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]; /* 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; }
/* * 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 = 0; pid_t pid; int status = 0; strcpy(buf, cmdline); bg = parseline(buf, argv); if(argv[0] == NULL){ return ; } #ifdef DEBUG_MSG_EVAL printf("cmdline is %s\n",cmdline); fflush(stdout); #endif if(!builtin_cmd(argv)){ sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, NULL); if((pid = fork()) == 0){ sigprocmask(SIG_UNBLOCK, &mask, NULL); setpgid(0,0); if(execve(argv[0], argv, environ) < 0){ printf("%s: Command not found\n", argv[0]); exit(0); } } if(!bg){ status = FG; addjob(jobs,pid,status, cmdline); sigprocmask(SIG_UNBLOCK, &mask, NULL); waitfg(pid); }else{ status = BG; addjob(jobs,pid,status, cmdline); printf("[%d] (%d) %s", getjobpid(jobs, pid)->jid, pid, cmdline); sigprocmask(SIG_UNBLOCK, &mask, NULL); } } 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; pid_t pid; strcpy(buf, cmdline); bg = parseline(buf, argv); if (!argv[0]) return; if (builtin_cmd(argv)) return; sigset_t mask, prev; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &prev); if ((pid = fork()) < 0) unix_error("fork error."); if (pid == 0) { sigprocmask(SIG_SETMASK, &prev, NULL); setpgid(0, 0); if (execve(argv[0], argv, environ) < 0) { printf("%s Command not found\n", argv[0]); exit(-1); } } int state = bg ? BG : FG; while(!addjob(jobs, pid, state, cmdline)) sigsuspend(&prev); sigprocmask(SIG_SETMASK, &prev, NULL); if (!bg) { waitfg(pid); } else { int jid = pid2jid(pid); 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]; // Parse command line. int isbg = parseline(cmdline, argv); pid_t pid; struct job_t *tmpjob; // Set sigset_t. sigset_t sig; sigemptyset(&sig); sigaddset(&sig, SIGCHLD); if( argv[0] == NULL ) // If input has no string, then return. return; if(!builtin_cmd(argv)) { // When cmdline is not builtin command. sigprocmask(SIG_BLOCK, &sig, NULL); // block SIGCHLD if( (pid = fork()) < 0) // When fork error occurs. return; else if( pid == 0 ) { //Child setpgid(0, 0); sigprocmask(SIG_UNBLOCK, &sig, NULL); // unblock SIGCHLD if(execve(argv[0], argv, environ) < 0) { // If command not found. printf("%s: Command not found\n", argv[0]); exit(0); } } else { // Parent if(isbg) { // When background addjob(jobs, pid, BG, cmdline); // Add to joblist(with state: BG) tmpjob = getjobpid(jobs, pid); printf("[%d] (%d) %s", tmpjob->jid, tmpjob->pid, tmpjob->cmdline); sigprocmask(SIG_UNBLOCK, &sig, NULL); // unblock SIGCHLD. } else { // foreground addjob(jobs, pid, FG, cmdline); // Add to joblist with state is FG. sigprocmask(SIG_UNBLOCK, &sig, NULL); // unblock SIGCHLD waitfg(pid); // wait foreground job. } } } 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. * 70 lines */ void eval(char *cmdline) { char * argv[MAXARGS]; char buf[MAXLINE]; int bg = 0; sigset_t mask; pid_t pid = 0; strcpy(buf, cmdline); bg = parseline(buf,argv); if(argv[0] == NULL) return; // ignore empty line if(!builtin_cmd(argv)) { 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 block"); pid = fork(); if (pid < 0) unix_error("fork error"); else if((pid == 0))//child process { if(setpgid(0,0) < 0) unix_error("setpgid error"); if(sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) unix_error("sigprocmask error unblock"); if(execve(argv[0],argv,environ) < 0)//run task { printf("%s: Command not found\n", argv[0]); exit(0); } } if(bg) { printf("[%d] (%d) %s",nextjid, pid, cmdline); addjob(jobs,pid,BG,cmdline); } else addjob(jobs,pid,FG,cmdline); if(sigprocmask(SIG_UNBLOCK, &mask, NULL)<0) unix_error("sigprocmask error unblock"); if(!bg) { waitfg(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]; memset(argv, 0, sizeof(void*) * MAXARGS); int bg = parseline(cmdline, argv); if(!argv[0]) return; if(builtin_cmd(argv)) return; //printf("%s\n", argv[0]); sigset_t mask,mask_all,prev_mask; sigemptyset(&mask); sigfillset(&mask_all); sigaddset(&mask,SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &prev_mask); pid_t pid = fork(); //Run the job in child process if(pid == 0) { setpgid(pid,pid); sigprocmask(SIG_SETMASK, &prev_mask, NULL); int result = execve(argv[0],argv,environ); if(result) { fprintf(stderr,"%s: Command not found\n", argv[0]); exit(0); } } //Parent process else { sigprocmask(SIG_BLOCK, &mask_all, NULL); if(bg) { addjob(jobs,pid,BG,cmdline); printf("[%d] (%d) %s", jobs->jid, pid, cmdline); sigprocmask(SIG_SETMASK, &prev_mask,NULL); } else{ addjob(jobs,pid,FG,cmdline); sigprocmask(SIG_SETMASK, &prev_mask, NULL); waitfg(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]; char buf[MAXLINE]; int bg; pid_t pid; sigset_t mask; strcpy(buf,cmdline); bg = parseline(buf, argv); if(argv[0] == NULL){ return; } if(!builtin_cmd(argv)){ //block SIGCHLD to avoid race condition sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, NULL); if((pid = fork()) == 0){ //unblock child sigprocmask(SIG_UNBLOCK, &mask, NULL); setpgid(0, 0); if(execve(argv[0], argv, environ ) < 0 ){ printf("%s: Command not found\n", argv[0]); exit(0); } }else{ if( pid < 0){ unix_error("Fork error"); return; } addjob(jobs, pid, bg + 1 , cmdline); if(bg){ printf("[%d] (%d) %s",pid2jid(pid),pid, cmdline); } //unblock parent sigprocmask(SIG_UNBLOCK, &mask, NULL); if(!bg){ waitfg(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]; char buf[MAXLINE]; int bg; pid_t pid; strcpy(buf,cmdline); bg=parseline(buf,argv); if(argv[0]==NULL) return; if(!builtin_cmd(argv)) { sigset_t mask; sigemptyset(&mask); sigprocmask(SIG_BLOCK,&mask,NULL); if((pid=fork())==0) { sigprocmask(SIG_UNBLOCK,&mask,NULL); if(execve(argv[0],argv,NULL)<0){ printf("%s: Command not found\n",argv[0]); exit(0); } } if(!bg) { if(setpgid(pid,pid)<0) unix_error("setpgid: setpgid error"); if(!addjob(jobs,pid,FG,buf)) app_error("addjob: addjob error"); sigprocmask(SIG_UNBLOCK,&mask,NULL); waitfg(pid); } else { if(setpgid(pid,pid)<0) unix_error("setpgid: setpgid error"); if(!addjob(jobs,pid,BG,buf)) app_error("addjob: addjob error"); sigprocmask(SIG_UNBLOCK,&mask,NULL); printf("[%d] (%d) %s",getjobpid(jobs,pid)->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];//argv will hold all of the parsed args pid_t pid; sigset_t mask; int background_job = parseline(cmdline, argv); //returns 1 if bg if(argv[0] == NULL){//no input return; } int builtin_job = builtin_cmd(argv); //returns 0 if not built in if(!builtin_job){ sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK,&mask,NULL); pid = fork(); if(pid == 0){ //child setpgid(0,0); sigprocmask(SIG_UNBLOCK,&mask,NULL); if(execvp(argv[0], argv) < 0){ printf("%s: Command not found.\n", argv[0]); exit(0); } } else{//parent if(background_job){ addjob(jobs, pid, BG, cmdline); printf("[%d] (%d) %s", pid2jid(pid), pid, cmdline); } else{ addjob(jobs, pid, FG, cmdline); } sigprocmask(SIG_UNBLOCK,&mask,NULL); if(!background_job){//wait until job is done waitfg(pid); //stuck } } } return; }