⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 minish.c

📁 操作系统中的SHELL程序~在LINUX系统中也能运行
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -