📄 ysh.c
字号:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <math.h>
#include <signal.h>
#include <stdlib.h>
#include "ysh.h"
int main()
{
initEnviron();
while(1)
{
char c,*arg[20];
int i=0,j=0,k=0,is_pr=0,is_bg=0,input_len=0,path,pid=0,status=0;
/*设置signal信号*/
struct sigaction action;
action.sa_sigaction=delNode;
sigfillset(&action.sa_mask);
action.sa_flags=SA_SIGINFO;
sigaction(SIGCHLD,&action,NULL);
signal(SIGTSTP,ctrl_z_cmd);
/*打印提示符*/
path=get_current_dir_name();
printf("ysh@%s> ",path);
/*获取用户输入*/
while((c=getchar())==' '||c=='\t'||c==EOF)
;
if(c=='\n')
continue;
while(c!='\n')
{
buf[input_len++]=c;
c=getchar();
}
buf[input_len]='\0';
input=(char *)malloc(sizeof(char)*(input_len+1));
strcpy(input,buf);
/*解析命令*/
/**管道命令和重定向命令**/
for(i=0,j=0,k=0;i<=input_len;i++)
if(input[i]=='<'||input[i]=='>'||input[i]=='|')
{
if(input[i]=='|')
{
pipel(input,input_len);
addHistory(input);
free(input);
}
else
{
redirect(input,input_len);
addHistory(input);
free(input);
}
is_pr=1;
break;
}
/**普通命令**/
if(is_pr==1)
continue;
for(i=0,j=0,k=0;i<=input_len;i++)
{
if(input[i]==' '||input[i]=='\0')
{
if(j==0)
continue;
else
{
buf[j++]='\0';
arg[k]=(char *)malloc(sizeof(char)*j);
strcpy(arg[k++],buf);
j=0;
}
}
else
{
if(input[i]=='&'&&input[i+1]=='\0')
{
is_bg=1;
continue;
}
buf[j++]=input[i];
}
}
/**内部命令**/
/***exit命令***/
if(strcmp(arg[0],"exit")==0)
{
addHistory(input);
printf("Bye!\n");
free(input);
break;
}
/***history命令***/
if(strcmp(arg[0],"history")==0)
{
addHistory(input);
history_cmd();
free(input);
continue;
}
/***cd命令***/
if(strcmp(arg[0],"cd")==0)
{
addHistory(input);
for(i=3,j=0;i<=input_len;i++)
buf[j++]=input[i];
buf[j]='\0';
arg[1]=(char *)malloc(sizeof(char)*j);
strcpy(arg[1],buf);
cd_cmd(arg[1]);
free(input);
continue;
}
/***jobs命令***/
if(strcmp(arg[0],"jobs")==0)
{
addHistory(input);
jobs_cmd();
free(input);
continue;
}
/***bg命令***/
if(strcmp(arg[0],"bg")==0)
{
addHistory(input);
for(i=0;i<=input_len;i++)
if(input[i]=='%')
break;
for(++i;i<=input_len;i++)
buf[j++]=input[i];
buf[j]='\0';
arg[1]=(char *)malloc(sizeof(char)*j);
strcpy(arg[1],buf);
bg_cmd(atoi(arg[1]));
free(input);
continue;
}
/***fg命令***/
if(strcmp(arg[0],"fg")==0)
{
addHistory(input);
for(i=0;i<=input_len;i++)
if(input[i]=='%')
break;
for(++i;i<=input_len;i++)
buf[j++]=input[i];
buf[j]='\0';
arg[1]=(char *)malloc(sizeof(char)*j);
strcpy(arg[1],buf);
fg_cmd(atoi(arg[1]));
free(input);
continue;
}
/*寻找命令文件*/
if(is_pr==0)
{
arg[k]=(char *)malloc(sizeof(char));
arg[k]=NULL;
if(isFounded(arg[0])==0)
{
printf("This command is not founded!\n");
for(i=0;i<=k;i++)
free(arg[i]);
continue;
}
}
addHistory(input);
/*执行命令*/
if((pid=fork())==0)
{
if(is_bg==1)
while(sig_flag==0)
signal(SIGUSR1,setFlag);
sig_flag=0;
execv(buf,arg);
}
else
{
pid1=pid;
if(is_bg==1)
{
addNode(input,pid1);
kill(pid,SIGUSR1);
pid1=0;
}
if(is_bg==0)
waitpid(pid,&status,0);
}
if(is_bg==1)
sleep(1);
for(i=0;i<k;i++)
free(arg[i]);
free(input);
}
return 0;
}
void initEnviron()
{
int fd,n,i;
char buf[80];
if((fd=open("ysh_profile",O_RDONLY,660))==-1)
{
printf("init environment variable error!\n");
exit(1);
}
while(n=getLine(fd,buf))
getEnviron(n,buf);
envhis.start=0;
envhis.end=0;
head=end=NULL;
}
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]==':')
{
buff[j++]='/';
buff[j]='\0';
p=(char *)malloc(sizeof(char)*(strlen(buff)+1));
strcpy(p,buff);
envpath[k++]=p;
envpath[k]=NULL;
j=0;
i++;
}
else
{
buff[j]=s[i];
j++;
i++;
}
}
}
else
fprintf(stderr,"No match");
}
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;
}
/*重定向的处理 */
int redirect(char *in,int len)
{
char *argv[20],*filename[20];
pid_t pid;
int i,j,k,fd_in,fd_out,is_in=-1,is_out=-1,num=0;
int is_back=0,status=0;
/*命令解析*/
for(i=0,j=0,k=0;i<=len;i++)
{
if(in[i]==' '||in[i]=='\t'||in[i]=='\0'||in[i]=='<'||in[i]=='>')
{
if(in[i]=='>'||in[i]=='<')
{
if(num<3)
{
num++;
if(in[i]=='<')
is_in=num-1;
else
is_out=num-1;
if(j>0&&num==1)
{
buf[j++]='\0';
argv[k]=(char *)malloc(sizeof(char)*j);
strcpy(argv[k],buf);
k++;
j=0;
}
}
else
{
printf("Error command!\n");
return 0;
}
}
if(j==0)
continue;
else
{
buf[j++]='\0';
if(num==0)
{
argv[k]=(char *)malloc(sizeof(char)*j);
strcpy(argv[k],buf);
k++;
j=0;
}
else
{
filename[status]=(char *)malloc(sizeof(char)*j);
strcpy(filename[status++],buf);
j=0;
}
}
}
else
{
if(in[i]=='&'&&in[i+1]=='\0')
{
is_back=1;
continue;
}
buf[j++]=in[i];
}
}
/*寻找命令文件*/
argv[k]=(char *)malloc(sizeof(char));
argv[k]=(char *)0;
if(isFounded(argv[0])==0)
{
printf("This command is not founded!\n");
for(i=0;i<=k;i++)
free(argv[i]);
return 0;
}
/*命令的执行*/
if((pid=fork())==0)
{
if(is_out!=-1)
{
if((fd_out=open(filename[is_out],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1)
{
printf("Can't open %s \n",filename[is_out]);
return 0;
}
}
if(is_in!=-1)
{
if((fd_in=open(filename[is_in],O_RDONLY,S_IRUSR|S_IWUSR))==-1)
{
printf("Can't open %s \n",filename[is_out]);
return 0;
}
}
if(is_out!=-1)
{
if(dup2(fd_out,STDOUT_FILENO)==-1)
{
printf("Redirect standard out error!\n");
exit(1);
}
}
if(is_in!=-1)
{
if(dup2(fd_in,STDIN_FILENO)==-1)
{
printf("Redirect standard in error!\n");
}
}
execv(buf,argv);
}
else
{
if(is_back==0)
waitpid(pid,&status,0);
}
/*释放空间*/
for(i=0;i<=k;i++)
free(argv[i]);
if(is_out!=-1)
{
free(filename[is_out]);
close(fd_out);
}
if(is_in!=-1)
{
free(filename[is_in]);
close(fd_in);
}
return 0;
}
/*管道的处理*/
int pipel(char *input,int len)
{
char *argv[10][30],*filename[10];
int i,j,k,is_bg=0;
int li_cmd=0,fd[10][1],pipe_in=-1,pipe_out=-1,flag=0;
pid_t pid;
/*命令解析*/
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)
{
argv[li_cmd][k]=(char *)malloc(sizeof(char)*j);
strcpy(argv[li_cmd][k],buf);
k++;
}
else
{
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++]=NULL;
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't open pipe!\n");
return 0;
}
}
/*寻找命令文件*/
for(i=0;i<li_cmd;i++)
{
if(isFounded(argv[i][0])==0)
{
printf("Can't found command!\n");
break;
}
if(i!=0)
pipe_in=fd[i-1][FD_READ];
else
pipe_in=NO_PIPE;
if(i!=li_cmd)
pipe_out=fd[i][FD_WRITE];
else
if(flag==1)
{
if((pipe_out=open(filename[0],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1)
{
printf("Can't 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 isFounded(char *cmd)
{
int k=0;
while(envpath[k]!=NULL)
{
strcpy(buf,envpath[k]);
strcat(buf,cmd);
if(access(buf,F_OK)==0)
return 1;
k++;
}
return 0;
}
/*history命令*/
void addHistory(char *inputcmd)
{
envhis.end=(envhis.end+1)%HISNUM;
if(envhis.end==envhis.start)
envhis.start=(envhis.start+1)%HISNUM;
strcpy(envhis.his_cmd[envhis.end],inputcmd);
}
void history_cmd()
{
int i,j=0;
if(envhis.start==envhis.end)
return;
else if(envhis.start<envhis.end)
{
for(i=envhis.start+1;i<=envhis.end;i++)
{
printf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
}
else
{
for(i=envhis.start;i<HISNUM;i++)
{
printf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
for(i=0;i<=envhis.end;i++)
{
printf("%d\t%s\n",j,envhis.his_cmd[i]);
j++;
}
}
}
/*cd命令*/
void cd_cmd(char *route)
{
if(route!=NULL)
if(chdir(route)<0)
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 addNode(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;
}
}
void delNode(int sig,siginfo_t *sip)
{
NODE *q,*p;
int id;
if(sig_z==1)
{
sig_z=0;
return;
}
id=sip->si_pid;
p=q=head;
if(head==NULL)
return;
while(p->pid!=id&&p->link!=NULL)
p=p->link;
if(p->pid!=id)
return;
if(p==head)
head=head->link;
else
{
while(q->link!=p)
q=q->link;
if(p==end)
{
end=q;
q->link=NULL;
}
else
q->link=p->link;
}
free(p);
return;
}
void setFlag()
{
sig_flag=1;
}
void ctrl_z_cmd()
{
NODE *p;
int i=1;
if(pid1==0)
return;
if(head!=NULL)
{
p=head;
while(p->pid!=pid1&&p->link!=NULL)
p=p->link;
if(p->pid==pid1)
strcpy(p->state,"stopped");
else
{
addNode(input,pid1);
strcpy(end->state,"stopped");
}
}
else
{
addNode(input,pid1);
strcpy(end->state,"stopped");
}
sig_z=1;
kill(pid1,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;
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);
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);
pid1=p->pid;
signal(SIGTSTP,ctrl_z_cmd);
kill(p->pid,SIGCONT);
waitpid(p->pid,NULL,0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -