📄 tsh.c
字号:
*/void execute_cd(char **argv){ int index = strlen(argv[1]); int i = 0; char swap[128]; if(argv[1] == NULL){ chdir("/"); getcwd(prompt,128); }else if(argv[1][0] == '/'){ chdir(argv[1]); getcwd(prompt,128); }else if(!strcmp(argv[1],"../")){ getcwd(prompt,128); index = strlen(prompt) - 1; while(prompt[index]!='/') index--; strncpy(swap, prompt, index); chdir(swap); return; }else{ getcwd(prompt,128); strcat(prompt,"/"); strcat(prompt,argv[1]); chdir(prompt); } return;}/**makedir - build the dictory you wanted*/void makedir(char **argv){ int status; status = mkdir(argv[1]); if(status == 0) perror("Directory created!\n"); else perror("Unable to create the directory\n");}/**removedir - remove the dictory you have choosed*/void removedir(char **argv){ int status; status = rmdir(argv[1]); if(status == 0) perror("Directory removed!\n"); else perror("Unable to remove the directory!\n");}/* * do_bgfg - Execute the builtin bg and fg commands */void do_bgfg(char **argv, int output_fd) { struct job_t *job=NULL; if(argv[1]==NULL) /*bg\fg command without pid\jid*/ { printf("%s command requires PID or %%jobid argument\n",argv[0]); return; } if(argv[1][0]=='%') /*%jid is a jid*/ { int jid; jid=atoi(argv[1]+1); if((job=getjobjid(jobs, jid))==NULL) /*is the job found*/ { printf("%s NO such job\n",argv[1]); return; } } else{ if(!isdigit(*argv[1])) /*is the pid a digit*/ { printf("%s argument must be a PID or %%jobid\n",argv[0]); return; } pid_t pid=(pid_t)atoi(argv[1]); if((job=getjobpid(jobs, pid))==NULL) { printf("%s NO such process\n",argv[1]); return; } } kill(-(job->pid),SIGCONT); /*send a signal to the process and its child*/ if(!strcmp(argv[0],"bg")) { job->state=BG; /*change state*/ printf("[%d] (%d) %s",job->jid,job->pid,job->cmdline); } else { job->state=FG; /*change state*/ waitfg(job->pid,output_fd); /*wait the foreground process to terminate*/ } return;}/* * waitfg - Block until process pid is no longer the foreground process */void waitfg(pid_t pid, int output_fd){ struct job_t *job; job=getjobpid(jobs,pid); while((job!=NULL)&&job->state==FG) /*if process pid foreground*/ { sleep(1); } 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) { struct job_t *job; int status; int jid; pid_t pid; while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0) { job=getjobpid(jobs,pid); if(WIFSTOPPED(status)) /*if the job stopped by signal*/ { printf("Job [%d] (%d) stopped by signal %d\n",pid2jid(pid),pid,WSTOPSIG(status)); job->state=ST; /*change job state to stopped*/ } else if(WIFEXITED(status)) /*if the job terminated normally*/ { deletejob(jobs,pid); /*delete the job from job list*/ } else if(WIFSIGNALED(status)) /*if the job terminated by signal*/ { if((jid=job->jid)>0) printf("Job [%d] (%d) terminated by signal %d\n",jid,pid,WTERMSIG(status)); deletejob(jobs,pid); } } if(errno!=ECHILD&&errno!=EINTR) unix_error("waitpid error"); 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 pid; pid=fgpid(jobs); /*get the foreground job*/ if(!pid) /*if the foreground job exist*/ return; kill(-pid,SIGINT); /*send signal SIGINT to the foreground process and its cild*/ 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 pid; pid=fgpid(jobs); /*get the foreground job*/ if(!pid) return; kill(-pid,SIGTSTP); /*send signal SIGTSTP to the foreground process and its cild*/ return;}/********************* * End signal handlers *********************//*********************************************** * Helper routines that manipulate the job list **********************************************//* clearjob - Clear the entries in a job struct */void clearjob(struct job_t *job) { job->pid = 0; job->jid = 0; job->state = UNDEF; job->cmdline[0] = '\0';}/* initjobs - Initialize the job list */void initjobs(struct job_t *jobs) { int i; for (i = 0; i < MAXJOBS; i++) clearjob(&jobs[i]);}/* maxjid - Returns largest allocated job ID */int maxjid(struct job_t *jobs) { int i, max=0; for (i = 0; i < MAXJOBS; i++) if (jobs[i].jid > max) max = jobs[i].jid; return max;}/* addjob - Add a job to the job list */int addjob(struct job_t *jobs, pid_t pid, int state, char *cmdline) { int i; if (pid < 1) return 0; for (i = 0; i < MAXJOBS; i++) { if (jobs[i].pid == 0) { jobs[i].pid = pid; jobs[i].state = state; jobs[i].jid = nextjid++; if (nextjid > MAXJOBS) nextjid = 1; strcpy(jobs[i].cmdline, cmdline); if(verbose){ printf("Added job [%d] %d %s\n", jobs[i].jid, jobs[i].pid, jobs[i].cmdline); } return 1; } } printf("Tried to create too many jobs\n"); return 0;}/* deletejob - Delete a job whose PID=pid from the job list */int deletejob(struct job_t *jobs, pid_t pid) { int i; if (pid < 1) return 0; for (i = 0; i < MAXJOBS; i++) { if (jobs[i].pid == pid) { clearjob(&jobs[i]); nextjid = maxjid(jobs)+1; return 1; } } return 0;}/* fgpid - Return PID of current foreground job, 0 if no such job */pid_t fgpid(struct job_t *jobs) { int i; for (i = 0; i < MAXJOBS; i++) if (jobs[i].state == FG) return jobs[i].pid; return 0;}/* getjobpid - Find a job (by PID) on the job list */struct job_t *getjobpid(struct job_t *jobs, pid_t pid) { int i; if (pid < 1) return NULL; for (i = 0; i < MAXJOBS; i++) if (jobs[i].pid == pid) return &jobs[i]; return NULL;}/* getjobjid - Find a job (by JID) on the job list */struct job_t *getjobjid(struct job_t *jobs, int jid) { int i; if (jid < 1) return NULL; for (i = 0; i < MAXJOBS; i++) if (jobs[i].jid == jid) return &jobs[i]; return NULL;}/* pid2jid - Map process ID to job ID */int pid2jid(pid_t pid) { int i; if (pid < 1) return 0; for (i = 0; i < MAXJOBS; i++) if (jobs[i].pid == pid) { return jobs[i].jid; } return 0;}/* listjobs - Print the job list */void listjobs(struct job_t *jobs, int output_fd) { int i; char buf[MAXLINE]; for (i = 0; i < MAXJOBS; i++) { memset(buf, '\0', MAXLINE); if (jobs[i].pid != 0) { sprintf(buf, "[%d] (%d) ", jobs[i].jid, jobs[i].pid); if(write(output_fd, buf, strlen(buf)) < 0) { fprintf(stderr, "Error writing to output file\n"); exit(1); } memset(buf, '\0', MAXLINE); switch (jobs[i].state) { case BG: sprintf(buf, "Running "); break; case FG: sprintf(buf, "Foreground "); break; case ST: sprintf(buf, "Stopped "); break; default: sprintf(buf, "listjobs: Internal error: job[%d].state=%d ", i, jobs[i].state); } if(write(output_fd, buf, strlen(buf)) < 0) { fprintf(stderr, "Error writing to output file\n"); exit(1); } memset(buf, '\0', MAXLINE); sprintf(buf, "%s", jobs[i].cmdline); if(write(output_fd, buf, strlen(buf)) < 0) { fprintf(stderr, "Error writing to output file\n"); exit(1); } } } if(output_fd != STDOUT_FILENO) close(output_fd);}/****************************** * end job list helper routines ******************************//*********************** * Other helper routines ***********************//* * usage - print a help message */void usage(void) { printf("Usage: shell [-hvp]\n"); printf(" -h print this message\n"); printf(" -v print additional diagnostic information\n"); printf(" -p do not emit a command prompt\n"); exit(1);}/* * unix_error - unix-style error routine */void unix_error(char *msg){ fprintf(stderr, "%s: %s\n", msg, strerror(errno)); exit(1);}/* * app_error - application-style error routine */void app_error(char *msg){ fprintf(stderr, "%s\n", msg); exit(1);}/* * Signal - wrapper for the sigaction function */handler_t *Signal(int signum, handler_t *handler) { struct sigaction action, old_action; action.sa_handler = handler; sigemptyset(&action.sa_mask); /* block sigs of type being handled */ action.sa_flags = SA_RESTART; /* restart syscalls if possible */ if (sigaction(signum, &action, &old_action) < 0) unix_error("Signal error"); return (old_action.sa_handler);}/* * sigquit_handler - The driver program can gracefully terminate the * child shell by sending it a SIGQUIT signal. */void sigquit_handler(int sig) { if (verbose) printf("siquit_handler: terminating after receipt of SIGQUIT signal\n"); exit(1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -