📄 minish.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];
/*打开保存查找路径的mini_profile文件*/
if ((fd=open("mini_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 + -