minishell 练习

参考:

https://blog.csdn.net/studyhardi/article/details/89763358

https://blog.csdn.net/OCTODOG/article/details/70942194

1、先是最简单的,能够执行并输出

#include <stdio.h>
#include <string.h>

#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <stdlib.h>

//https://blog.csdn.net/studyhardi/article/details/89763358
//https://blog.csdn.net/OCTODOG/article/details/70942194

char prefix[] = "MyShell> ";
char *argv[8+1];

void do_parse(char *buf){
	char *s = NULL;
	int i;
	s = strtok(buf," ");
	for(i=0;i<8&&s != NULL;i++){
		argv[i] = s;
		s = strtok(NULL," ");
	}
	argv[i] = NULL;
}

void do_execute(void){
	pid_t pid = fork();
	if(pid < 0){
		exit(1);
	}else if(pid == 0){
		execvp(argv[0],argv);
	}
	else{
		waitpid(pid,NULL,0);
	}
}

int main(){
	char buf[1024] = {0};
	for(;;){
		write(STDOUT_FILENO,prefix,strlen(prefix));

		scanf("%[^\n]%*c",buf);//https://blog.csdn.net/jeffasd/article/details/80705487

		do_parse(buf);
		do_execute();
	}
}

2、实现管道 |

#include <stdio.h>
#include <string.h>

#include <unistd.h>
#include <sys/wait.h>

#include <stdlib.h>

//https://blog.csdn.net/studyhardi/article/details/89763358
//https://blog.csdn.net/OCTODOG/article/details/70942194

char prefix[] =  "MyShell> ";
char* proc[8];
int proc_count=0;
char *argv[8][8+1];

void sighandle(int signum){
	//printf("recv %d signal, process %d\n",signum,getpid());
}

void do_parse(char *buf){
	char *s = NULL;
	int i,j;
	s = strtok(buf,"|");
	for(proc_count=0;proc_count<8&&s!= NULL;proc_count++){
		proc[proc_count] = s;
		s = strtok(NULL,"|");
	}

	for(i=0;i<proc_count;i++){
		s = strtok(proc[i]," ");
		for(j=0;j<8&&s!=NULL;j++){
			argv[i][j] = s;
			s = strtok(NULL," ");
		}
		argv[i][j] = NULL;
	}
}


void do_execute_child(pid_t parent_pid){
	int i;
	pid_t pid;
	
	for(i=0;i<proc_count;i++){
		int fd[2];
		pipe(fd);
		pid = fork();
		if(pid < 0){
			exit(1);
		}else if(pid == 0){
			close(fd[1]);
			dup2(fd[0],STDIN_FILENO);
		}else{
			close(fd[0]);
			dup2(fd[1],STDOUT_FILENO);
			execvp(argv[i][0],argv[i]);
		}
	}
	
	if(pid == 0){
		char buf[1024];
		int l;
		
		while( (l=read(STDIN_FILENO,buf,sizeof(buf))) > 0){
			write(STDOUT_FILENO,buf,l);
		}
		kill(parent_pid,SIGALRM);//由最后一个子程序唤醒曾曾曾曾曾...祖父
	}
	
	exit(0);
}

void do_execute(void){
	int i;
	pid_t pid;
	pid = fork();
	if(pid < 0){
		return;
	}else if(pid == 0){
		do_execute_child(getppid());
	}else{
		pause();//阻塞,等待唤醒
	}
}

int main(){
	signal(SIGALRM,sighandle);
	signal(SIGCHLD,SIG_IGN);
	char buf[1024] = {0};
	for(;;){
		write(STDOUT_FILENO,prefix,strlen(prefix));

		scanf("%[^\n]%*c",buf);//https://blog.csdn.net/jeffasd/article/details/80705487

		do_parse(buf);

		do_execute();
	}
}

3、实现重定向 >log 以及 2>&1

未完待续...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值