📄 ysh.c
字号:
#include "ysh.h"
#include "extern.h"
char *envpath[10],buf[BUFSIZE],*input=NULL;
pid_t pid1=0;
int sig_flag=0,sig_z=0,history_number;
ENV_HISTORY envhis;
NODE *head,*end;
int main()
{
init_environ(); /*初始化环境变量,将查找路径至于envpath[]中,初始化history,和jobs的头尾指针*/
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;
history_number=envhis.end;
/********************设置signal信号********************/
struct sigaction action;
action.sa_sigaction=del_node;
sigfillset(&action.sa_mask);
action.sa_flags=SA_SIGINFO;
sigaction(SIGCHLD,&action,NULL);
// signal(SIGTSTP,ctrl_z);
signal(SIGTSTP,up_history);
/********************打印提示符************************/
path=get_current_dir_name();
printf("ysh@%s> ",path);
/********************获取用户输入**********************/
while ((c=getchar())==' ' || c=='\t'|| c==EOF)
; /*跳过空格等无用信息*/
while (c!='\n') {
buf[input_len++]=c;
c=getchar();
}
buf[input_len]='\0'; /*加上串结束符*/
/*分配动态存储空间,将命令从缓存拷贝到input中*/
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); /*管道命令*/
add_history(input);
free(input);
}else{
redirect(input,input_len); /*重定向命令*/
add_history(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); /*将指令或参数拷到arg中*/
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) {
add_history(input);
printf("Bye bye!\n");
free(input);
break;
}
/*history命令,显示history数组中保存的历史命令*/
if (strcmp(arg[0],"history")==0) {
add_history(input);
history_cmd();
free(input);
continue;
}
/*cd命令,改变当前路径*/
if (strcmp(arg[0],"cd")==0) {
add_history(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);/*将路径保存到arg[1]中*/
cd_cmd(arg[1]);/*cd_cmd()函数,改变路径到指定路径*/
free(input);
continue;
}
/*jobs命令,显示现有工作*/
if (strcmp(arg[0],"jobs")==0) {
add_history(input);
jobs_cmd(); /*jobs_cmd()函数,遍历链表,显示所有工作*/
free(input); continue;
}
/*bg命令,将作业放到后台执行*/
if (strcmp(arg[0],"bg")==0) {
add_history(input);
/*获取制定的作业号,作业号在%后*/
for (i=0;i<=input_len;i++) {
if (input[i]=='%')
break;
}
i++;
for (;i<=input_len;i++)
buf[j++]=input[i];
buf[j]='\0';
arg[1]=(char *) malloc(sizeof(char)*j);
strcpy(arg[1],buf); /*将作业号保存在arg[1]中*/
bg_cmd(atoi(arg[1])); /*bg_cmd命令,将指定作业放到后台运行*/
free(input);
continue;
}
/*fg命令,将作业放到前台执行*/
if (strcmp(arg[0],"fg")==0) {
add_history(input);
/*获取制定的作业号,作业号在%后*/
for (i=0;i<=input_len;i++) {
if (input[i]=='%')
break;
}
i++;
for (;i<=input_len;i++)
buf[j++]=input[i];
buf[j]='\0';
arg[1]=(char *) malloc(sizeof(char)*j);
strcpy(arg[1],buf); /*将作业号保存在arg[1]中*/
fg_cmd(atoi(arg[1])); /*fg_cmd命令,将指定作业放到后台运行*/
free(input);
continue;
}
/********************寻找命令文件***********************/
if (is_pr==0){/*非管道、重定向命令*/
/*在使用exec执行命令时,最后的参数必须是NULL指针,所以将其置空*/
arg[k]=(char *) malloc(sizeof(char));
arg[k]=NULL;
if (is_founded(arg[0])==0){ /*查找arg[0]中的命令是否存在*/
printf("This command is not founded!\n");
for (i=0;i<=k;i++)
free (arg[i]);
continue;
}
}
add_history(input);
/********************执行命令***************************/
if ((pid=fork())==0){ /*子进程*/
if (is_bg==1) /*若为后台命令,等待父进程增加节点*/
while (sig_flag==0) /*若sig_flag==0,等待父进程完成增加节点*/
/*等待父进程SIGUSR1信号,表示节点已加到链表中*/
signal(SIGUSR1,setflag); /*收到信号,setflag函数将sig_flag置一,以跳出循环*/ sig_flag=0; /*置零,为下一命令作准备*/
execv(buf,arg); /*执行命令*/
}else { /*父进程*/
pid1=pid; /*保存子进程进程号*/
if (is_bg==1) { /*后台命令*/
add_node(input,pid1);/*增加节点*/
kill(pid,SIGUSR1); /*向子进程发信号,表示节点已加进链表*/
pid1=0; /*pid1置零,为下一命令作准备*/
}
if (is_bg==0) /*前台命令*/
waitpid(pid,&status,0);
}
if (is_bg==1)
sleep(1); /*等待命令(如:ls &)输出后,再打印Shell提示符*/
for (i=0;i<k;i++) /*释放空间*/
free (arg[i]);
free(input);
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -