【csapp lab】shell lab
/*
* eval - Evaluate the command line that the user has just typed in
*
* If the user has requested a built-in command (quit, jobs, bg or fg)
* then execute it immediately. Otherwise, fork a child process and
* run the job in the context of the child. If the job is running in
* the foreground, wait for it to terminate and then return. Note:
* each child process must have a unique process group ID so that our
* background children don't receive SIGINT (SIGTSTP) from the kernel
* when we type ctrl-c (ctrl-z) at the keyboard.
*/
void eval(char *cmdline)
{
char *argv[MAXARGS];
char buf[MAXLINE];
int bg;
pid_t pid;
sigset_t mask_child,mask_all,prev_all;
sigfillset(&mask_all);
sigemptyset(&mask_child);
sigaddset(&mask_child,SIGCHLD);
strcpy(buf,cmdline);
bg=parseline(buf,argv);
if(argv[0]==NULL)
return;
if(!builtin_cmd(argv)){
sigprocmask(SIG_BLOCK, &mask_child, &prev_all);
if((pid=fork())<0){
sigprocmask(SIG_SETMASK, &prev_all, NULL);
fprintf(stderr,"fork error: %s\n",strerror(errno));
exit(0);
}
else if(pid==0){ //child
setpgid(0,0);//last hint,很重要!!!
sigprocmask(SIG_SETMASK, &prev_all, NULL);
if(execve(argv[0],argv,environ)<0){
printf("%s: Command not found.\n",argv[0]);
exit(0);
}
}
//parent
sigprocmask(SIG_BLOCK, &mask_all, NULL);
addjob(jobs,pid,bg?BG:FG,cmdline);
sigprocmask(SIG_SETMASK, &prev_all, NULL);//csapp8.5.6
if(!bg){
flag=0;
//int status;
//if(waitpid(pid,&status,WUNTRACED)<0)
//unix_error("waitfg:waitpid error");
waitfg(pid);
//if(getjobpid(jobs, pid) && getjobpid(jobs, pid)->state != ST)
//deletejob(jobs, pid);
}
else{
// sigprocmask(SIG_SETMASK, &prev_all, NULL);
printf("[%d] (%d) %s",getjobpid(jobs, pid)->jid,pid,cmdline);}
}
return;
}
/*
* parseline - Parse the command line and build the argv array.
*
* Characters enclosed in single quotes are treated as a single
* argument. Return true if the user has requested a BG job, false if
* the user has requested a FG job.
*/
int parseline(const char *cmdline, char **argv)
{
static char array[MAXLINE]; /* holds local copy of command line */
char *buf = array; /* ptr that traverses command line */
char *delim; /* points to first space delimiter */
int argc; /* number of args */
int bg; /* background job? */
strcpy(buf, cmdline);
buf[strlen(buf)-1] = ' '; /* replace trailing '\n' with space */
while (*buf && (*buf == ' ')) /* ignore leading spaces */
buf++;
/* Build the argv list */
argc = 0;
if (*buf == '\'') {
buf++;
delim = strchr(buf, '\'');
}
else {
delim = strchr(buf, ' ');
}
while (delim) {
argv[argc++] = buf;
*delim = '\0';
buf = delim + 1;
while (*buf && (*buf == ' ')) /* ignore spaces */
buf++;
if (*buf == '\'') {
buf++;
delim = strchr(buf, '\'');
}
else {
delim = strchr(buf, ' ');
}
}
argv[argc] = NULL;
if (argc == 0) /* ignore blank line */
return 1;
/* should the job run in the background? */
if ((bg = (*argv[argc-1] == '&')) != 0) {
argv[--argc] = NULL;
}
return bg;
}
/*
* builtin_cmd - If the user has typed a built-in command then execute
* it immediately.
*/
int builtin_cmd(char **argv)
{
if(!strcmp(argv[0],"quit"))
exit(0);
if(!strcmp(argv[0],"jobs")){
listjobs(jobs);
return 1;
}
if(!strcmp(argv[0],"bg")||!strcmp(argv[0],"fg")){
do_bgfg(argv);
return 1;
}
return 0; /* not a builtin command */
}
/*
* do_bgfg - Execute the builtin bg and fg commands
*/
void do_bgfg(char **argv)
{
pid_t pid;
int jid;
struct job_t* job;
if(argv[1]==NULL){
printf("%s command requires PID or %%jobid argument\n",argv[0]);
return;
}
if(*argv[1]=='%'){
if(sscanf (argv[1],"%%%d",&jid)==0){
printf("%s: argument must be a PID or %%jobid\n",argv[0]);
return;
}
job=getjobjid(jobs, jid);
if(job)
pid=job->pid;
else {
printf("%s: No such job\n",argv[1]);
return;
}
}
else {
if(sscanf (argv[1],"%d",&pid)==0){
printf("%s: argument must be a PID or %%jobid\n",argv[0]);
return;
}
job=getjobpid(jobs,pid);
if(!job){
printf("(%s): No such process\n",argv[1]);
return;
}
}
if(!strcmp(argv[0],"fg")){
if(job-> state==ST)
kill(-pid,SIGCONT);
job->state=FG;
//int status;
//if(waitpid(pid,&status,WUNTRACED)<0)
//unix_error("waitfg:waitpid error");
waitfg(pid);}
if(!strcmp(argv[0],"bg")){
if(job->state==ST)
kill(-pid,SIGCONT);
job->state=BG;
printf("[%d] (%d) %s",job->jid,pid,job->cmdline);
}
return;
}
/*
* waitfg - Block until process pid is no longer the foreground process
*/
void waitfg(pid_t pid)
{
sigset_t mask_child,prev;
sigemptyset(&mask_child);
sigaddset(&mask_child,SIGCHLD);
sigprocmask(SIG_BLOCK,&mask_child,&prev);
while(getjobpid(jobs,pid)&&getjobpid(jobs,pid)->state==FG){
//while(pid==fgpid(jobs)){
// while(!flag){
sigsuspend(&prev);}//csapp8.5.7
///sigsuspend(&mask_empty);}
sigprocmask(SIG_SETMASK,&prev,NULL);
return;
}
/*****************
* Signal handlers
*****************/
/*
* sigchld_handler - The kernel sends a SIGCHLD to the shell whenever
* a child job terminates (becomes a zombie), or stops because it
* received a SIGSTOP or SIGTSTP signal. The handler reaps all
* available zombie children, but doesn't wait for any other
* currently running children to terminate.
*/
void sigchld_handler(int sig)
{
int olderrno=errno;
pid_t pid;
int status;
//ctermi=fgpid(jobs);
while((pid=waitpid(-fgpid(jobs),&status,WNOHANG|WUNTRACED))>0){//
//while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0){
//if(pid==fgpid(jobs)) flag=1;
if(WIFSTOPPED(status)){
printf("Job [%d] (%d) stopped by signal 20\n",getjobpid(jobs, pid)->jid,pid);
getjobpid(jobs, pid)-> state=ST;
//ctermi=pid;
}
else if(WIFSIGNALED(status)){
printf("Job [%d] (%d) terminated by signal 2\n",getjobpid(jobs, pid)->jid,pid);
deletejob(jobs, pid);
//ctermi=pid;
}
else if(WIFEXITED(status))
deletejob(jobs,pid);}
//pid=waitpid(-1,NULL,0);
//app_error("waitpid error");
//ctermi=pid;
errno=olderrno;
return;
}
/*
* sigint_handler - The kernel sends a SIGINT to the shell whenver the
* user types ctrl-c at the keyboard. Catch it and send it along
* to the foreground job.
*/
void sigint_handler(int sig)
{
pid_t fpid;
fpid=fgpid(jobs);
if(fpid){
kill(-fpid,sig);
}
return;
}
/*
* sigtstp_handler - The kernel sends a SIGTSTP to the shell whenever
* the user types ctrl-z at the keyboard. Catch it and suspend the
* foreground job by sending it a SIGTSTP.
*/
void sigtstp_handler(int sig)
{
pid_t fpid;
fpid=fgpid(jobs);
if(fpid>0){
kill(-fpid,SIGTSTP);
}
return;
}
/*********************
* End signal handlers
*********************/
相關文章
- CSAPP Cache LabAPP
- CSAPP Malloc LabAPP
- CSAPP-Lab03 Attack Lab 記錄APP
- csapp Lab1APP
- CSAPP-Lab04 Architecture Lab 深入解析APP
- CSAPP:Lab1 -DataLab 超詳解APP
- CSAPP 之 AttackLab 詳解APP
- CSAPP 之 CacheLab 詳解APP
- CSAPP 之 DataLab 詳解APP
- CSAPP 之 ShellLab 詳解APP
- CSAPP 之 BombLab 詳解APP
- CSAPP緩衝實驗buflabAPP
- CSAPP DATA LAB1————位運算APP
- csapp-bomblab(自信滿滿版)APP
- csapp-attacklab(完美解決版)APP
- 【CSAPP】以CTFer的方式開啟BufferLabAPP
- 深入理解計算機系統(CSAPP)bomblab實驗進階之nuclearlab——詳細題解計算機APP
- CSAPP二進位制炸彈實驗 bomb lab詳細解析APP
- MIT-6.828-JOS-lab5:File system, Spawn and ShellMIT
- 基於Jenkins + Gitlab + 蒲公英(附上shell指令碼)JenkinsGitlab指令碼
- mit6.828筆記 - lab5(下)- Spawn and ShellMIT筆記
- GitLab -IDEA整合gitlab(提交專案到gitlab)GitlabIdea
- csapp bomblab1—6+secret,較為全面,每個人的題不一樣。APP
- 【SEED Labs】DNS Rebinding Attack LabDNS
- Datalab
- 【SEED Labs】Public-Key Infrastructure (PKI) LabASTStruct
- bitnami gitlab 使用 gitlab-rails 命令GitlabAI
- GitLab CI持續整合-GitLab RunnerGitlab
- Calabash探索3-Calabash進階
- Gitlab管理之十八–使用Gitlab system hooksGitlabHook
- Wireshark Lab: HTTPHTTP
- gitlab使用Gitlab
- matlab技巧Matlab
- What is Scalability?
- Gitlab搭建Gitlab
- boom lab分析OOM
- matlab classdefMatlab
- geoshow in matlabMatlab