?? ysh.c
字號:
for (i=0,j=0,k=0;i<=len;i++) {
if (input[i]==' '||input[i]=='\t'||input[i]=='\0'||input[i]=='|'||input[i]=='>'||input[i]=='\n') {
if (input[i]=='|'||input[i]=='>') {
if (input[i]=='>') flag=1;
if (j>0) {
buf[j++]='\0';
argv[li_cmd][k]=(char *) malloc(sizeof(char)*j);
strcpy(argv[li_cmd][k],buf);
k++;
}
argv[li_cmd][k]=(char *) 0;
li_cmd++;
k=0;
j=0;
}
if (j==0)
continue;
else{
buf[j++]='\0';
if (flag==0) {/*flag==0命令中不含“>”、“<”重定向命令*/
argv[li_cmd][k]=(char *) malloc(sizeof(char)*j);
strcpy(argv[li_cmd][k],buf);
k++;
}else {/*flag==1命令中包含“>”、“<”重定向命令,重定向命令后為文件名*/
filename[0]=(char *) malloc (sizeof(char)*j);
strcpy(filename[0],buf);
}
}
j=0;
}else{
if (input[i]=='&'&&input[i++]=='\0'){/*帶后臺符號的命令*/
is_bg=1;
continue;
}
buf[j++]=input[i];
}
}
argv[li_cmd][k++]=(char *) 0;/*最后一參數置空*/
for (i=0;i<=10;i++) {/*初始化文件描述符*/
fd[i][FD_READ]=NO_PIPE;
fd[i][FD_WRITE]=NO_PIPE;
}
for (i=0;i<li_cmd;i++) {/*為命令建立相應的管道*/
if (pipe(fd[i])==-1) {
printf("Can not open pipe!\n");
return 0;
}
}
/*************************尋找命令文件,執行命令*************************/
for (i=0;i<=li_cmd;i++) {
if (is_founded(argv[i][0])==0) {
printf("Can not found command!\n");
break;
}
/*********將pipe_in指向到管道的讀端(第一條命令除外)***********/
if (i!=0)
pipe_in=fd[i-1][FD_READ];
else pipe_in=NO_PIPE;/*第一條命令除外*/
/*********將pipe_out指向到管道的寫端(最后一條命令除外)*********/
if (i!=li_cmd)
pipe_out=fd[i][FD_WRITE];
else
if (flag==1) {/*包含重定向命令*/
/*將pipe_out指向到文件*/
if ((pipe_out=open(filename[0],
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1){
printf ("Can not open %s \n",filename[0]);
break;
}
}else pipe_out=NO_PIPE;/*最后一條命令除外*/
if ((pid=fork())<0){
printf("Fork failed!\n");
return 0;
}
if (pid==0) {
if (pipe_in==NO_PIPE)
close(pipe_in);
if (pipe_out==NO_PIPE)
close(pipe_out);
if (pipe_out!=NO_PIPE) {
/*將標準輸出重定向到管道的寫端,
這樣該子進程的輸出就寫入管道了*/
dup2(pipe_out,1);
close(pipe_out);
}
if (pipe_in!=NO_PIPE) {
/*將標準輸入重定向到管道的讀端,
這樣管道的數據就可以被讀到了*/
dup2(pipe_in,0);
close(pipe_in);
}
execv(buf,argv[i]);
}else {
if (is_bg==0)
waitpid(pid,NULL,0);
close(pipe_in);
close(pipe_out);
}
}
return 0;
}
/**************************** 初始化函數 *****************************/
int getline(int fd,char *buf)/*按行讀取*/
{
int i=0;
char c;
while (read(fd,&c,1)){
buf[i++]=c;
if (c=='\n'){
buf[i-1]='\0';
return i;
}
}
return i;
}
void getenviron(int n,char *s)
{
int i=0,j=0,k=0;
char c,buff[80],*p;
while ((c=s[i])!='='){
buff[i++]=c;
}
buff[i++]='\0';
if (strcmp(buff,"PATH")==0){
while (s[i]!='\0'){
if (s[i]==':'){/*將以“:”分隔的查找路徑分別設置到envpath[]中*/
buff[j++]='/';
buff[j]='\0';
p=(char *) malloc(strlen(buff)+1);
strcpy(p,buff);
envpath[k++]=p;/*將路徑保存在envpath[k]中*/
envpath[k]=NULL;/*字符串尾置空*/
j=0;/*為下一個envpath[i]作準備*/
i++;
}else {
buff[j]=s[i];
j++;
i++;
}
}
}else fprintf(stderr,"No match");
}
void init_environ()
{
int fd,n,i;
char buf[80];
/*打開保存查找路徑的ysh_profile文件*/
if ((fd=open("ysh_profile",O_RDONLY,660))==-1)
{
printf("init environ variable error\n");
exit(1);
}
while (n=getline (fd,buf)){
getenviron(n,buf);/*getenviron()函數*/
}
envhis.start=0;/*初始化history循環數組*/
envhis.end=0; head=end=NULL;/*初始化jobs鏈表指針*/
}
/**************************** 查找命令文件函數 *****************************/
int is_founded(char *cmd)
{
int k=0;
while (envpath[k]!=NULL){/*查找路徑已在程序初始化時設定在envpath[i]中*/
strcpy(buf,envpath[k]);
strcat(buf,cmd);
if (access(buf,F_OK)==0) /*文件被找到*/
return 1;
k++;
}
return 0;
}
/**************************** history命令 *****************************/
void add_history(char *inputcmd)
{
envhis.end=(envhis.end+1)%HISNUM;/*end前移一位*/
if (envhis.end==envhis.start){/*end和start指向同一數組*/
envhis.start=(envhis.start+1)%HISNUM;/*start前移一位*/
}
strcpy(envhis.his_cmd[envhis.end],inputcmd);/*將命令復制到end指向的數組中*/
}
void history_cmd()
{
int i,j=0;
if (envhis.start==envhis.end)/*循環數組為空*/
return;
else if (envhis.start<envhis.end) {/*start<end時*/
for (i=envhis.start+1;i<=envhis.end;i++) {/*顯示start+1到end數組中的命令*/
printf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
}else {/*start>end時*/
for (i=envhis.start+1;i<HISNUM;i++) {/*顯示start+1到HISNUN數組中的命令*/
printf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
for (i=0;i<=envhis.end;i++) {/*顯示0到end數組中的命令*/
printf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
}
}
/**************************** cd命令 *****************************/
void cd_cmd(char *route)
{
if (route!=NULL) {/*路徑不為空*/
if (chdir(route)<0) {/*chdir()系統調用,達到改變當前路徑的目的*/
printf("cd;%s Error file or directory!\n",route);
}
}
}
/**************************** jobs命令 *****************************/void jobs_cmd(){ NODE *p; int i=1; p=head;
/*遍歷鏈表,顯示相關內容*/ if (head!=NULL) { /*鏈表不為空*/ do { printf("%d %d %s\t%s\n",i,p->pid,p->state,p->cmd); i++; p=p->link; }while (p!=NULL); } else printf("No jobs!\n");/*鏈表為空*/}
void add_node(char *input_cmd,int node_pid){ NODE *p; p=(NODE *) malloc(sizeof(NODE));/*申請新節點*/ p->pid=node_pid; /*設置節點信息*/ strcpy(p->cmd,input_cmd); /*保存命令信息*/ strcpy(p->state,"running"); /*設置工作狀態*/ p->link=NULL; if (head==NULL) {/*若鏈表為空*/ head=p; end=p; }else {/*鏈表不為空*/ end->link=p;/*將鏈表尾節點指針指向新節點*/ end=p;/*將end指向鏈表尾*/ }}
void del_node(int sig,siginfo_t *sip)/*刪除節點*/{ NODE *q,*p; int id;
/*當按下ctrl-z時,也會收到SIGCHLD信號,這種情況不刪除節點*/ if (sig_z==1) {sig_z=0;goto out;}
id=sip->si_pid;/*獲得發送SIGCHLD信號的進程的進程號*/ p=q=head; if (head==NULL) goto out;/*鏈表為空*/
/*遍歷鏈表找到相應節點*/ while (p->pid!=id&&p->link!=NULL)/*找到要刪除的節點p*/ p=p->link; if (p->pid!=id) {goto out;} if (p==head) {/*p為頭節點*/ head=head->link; }else { while(q->link!=p)/*找到p的前驅節點q*/ q=q->link; if (p==end) {/*p為尾節點*/ end=q; q->link=NULL; }else q->link=p->link; } free(p);out: return;}
void setflag(){ sig_flag=1;}/**************************** 前后臺切換命令 *****************************/void ctrl_z(){ NODE *p; int i=1; if (pid1==0) goto out;/*前臺沒有工作*/
/*改變鏈表中的相應節點的狀態*/ if (head!=NULL) {/*鏈表不為空*/ p=head;
/*遍歷鏈表,看該工作是否已經在鏈表中*/ while (p->pid!=pid1&&p->link!=NULL) p=p->link; if (p->pid==pid1) /*工作已在鏈表中*/ {strcpy(p->state,"stopped");} else {/*工作不在鏈表中*/ add_node(input,pid1);/*增加新節點*/ strcpy(end->state,"stopped");/*設置節點狀態*/ } }else {/*連標為空*/ add_node(input,pid1);/*增加新節點*/ strcpy(end->state,"stopped");/*設置節點狀態*/ } sig_z=1;/*sig_z標志置一,del_node()函數中不用刪除節點*/ kill(pid1,SIGSTOP);/*發送SIGSTOP信號給正在前臺運行的工作,將其停止*/ for (p=head;p->pid!=pid1;p=p->link)/*顯示提示信息*/ i++; printf("[%d]\t%s\t%s\n",i,end->state,end->cmd); pid1=0;out: return;}void bg_cmd(int job_num){ NODE *p; int i=0; p=head;
/*根據作業號,遍歷鏈表,找到指定節點*/ for (i=1;i<job_num;i++) p=p->link; kill(p->pid,SIGCONT);/*向對應工作發送SIGCONT信號,使其在后臺運行*/ strcpy(p->state,"running");/*修改對應節點狀態*/}void fg_cmd(int job_num){ NODE *p; int i=0; p=head;
/*根據作業號,遍歷鏈表,找到指定節點*/ for (i=1;i<job_num;i++) p=p->link; strcpy(p->state,"running");/*修改對應節點狀態*/ strcpy(input,p->cmd);/*將命令名復制到input中,為下一次按下ctrl-z作準備*/ pid1=p->pid;/*獲取該節點對應工作的進程號*/ signal(SIGTSTP,ctrl_z);/*設置signal()信號,為下一次按下ctrl-z作準備*/ kill(p->pid,SIGCONT);/*向對應工作發送SIGCONT信號,使其運行*/ waitpid(p->pid,NULL,0);/*父進程等待前臺進程的運行*/}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -