目的:
分享大家学习入门linux-c、熟悉shell命令执行,解析的过程
实现过程:
在linux的bashshell中执行我的应用程序,进入自己制作的shell界面(while循环),定制自己的shell提示符,通过fgets获得输入,并将所传入的参数写入一个指针数组中(整理参数),判断是不是空操作或exit(退出),如果不是再判断是不是重定向输入输出,或管道。最后通过fork创建子进程,调用execvp执行命令。最终程序能实现所有单linux命令,重定向输入输出,及管道(最多两层管道)。
内容(分为三个文件):
main.c
function.c
head.c
文档下载
main.c
#include "head.h"
#include "function.c"
int main(){
int ret,i,j,k=0;
pid_t pid;
char buf[ MAXLINE ];
while(1){
again:
print();
bzero(buf,MAXLINE);
fgets(buf,MAXLINE,stdin);//从stdin中输入MAXLINE到buf里面最后一个字符是\n(enter换行符)
if(buf[strlen(buf)-1]=='\n'){//将最后一个字符\n改为\0
buf[strlen(buf)-1]='\0';
}
// printf("%s\n",buf);
canshuzhengli(canshu,buf);//将所传入的参数用一个指针数组(*canshu[])来指向buf中的每个参数
if(*(canshu+0)==NULL){//没有输入,直接按下了enter
goto again;
}
if(strcmp(*(canshu+0),"exit")==0){//判断是不是输入了exit命令,是我们就直接退出
exit(1);
}
/*****************重定向输入,输出***************************************************/
if(*(canshu+1)!=NULL){
if((*(*(canshu+1)+0)==60)||(*(*(canshu+1)+0)==62)){//60==< 62==>
chongdingxiang(canshu);
goto again;
}
}
/******************管道命令*********************************************************/
for(i=0;*(canshu+i) != NULL;i++){
if(*(*(canshu+i)+0)=='|'){
guandao(canshu,i);
k=1000;
break;
}
printf("%d++++++++++\n",__LINE__);
}
if(k==1000){
printf("%d++++++++++\n",__LINE__);
goto again;
}
/**************输出指针数组*canshu[]中的每一个参数***********************************/
for(i=0;*(canshu+i) != NULL;i++){
printf("%s\n",*(canshu+i));
}
/*************创建子进程,用来执行和序********************************************/
if((pid=fork())<0){
perror("fork is failure!\n");
exit(1);
}else if(pid == 0){
if(execvp(*(canshu+0),canshu)<0){
perror(NULL);
exit(111);
}
}
if((pid=waitpid(pid,NULL,0))<0){
perror("fork is failure!\n");
exit(1);
}
}
return 0;
}
function.c
/*********************************************************************
********参数整理,将所有的参数都放在一个指针数组。ls -la /root********
********在指针数组的存放:"ls\0" "-la\0" "/root\0" "NULL" ********
**********************************************************************/
int canshuzhengli(char **ptr,char *buf){
while(*buf != '\0'){
*ptr=buf;
while(*buf != 32){//124==>管道字符;32==>空格
if(*buf=='\0'){
*++ptr=NULL;
return 0;
}
buf++;
}
*buf='\0';
buf++;
ptr++;
while(*buf == 32){
buf++;
}
}
*ptr = NULL;
return 0;
}
/**************打印提示符********************************************/
void print(){
int ret;
char *user;
char *dir;
char name[HOST_LEN];
bzero(name,sizeof(name));
if((ret = gethostname(name,sizeof(name)))<0){//获取主机名
perror("gethostname is failure!\n");
exit(1);
}
user=getlogin(); //获取登陆者名字
dir=(char *)get_current_dir_name(); //获取当前路径
printf("%s@%s##%s##%%",user,name,dir); //最终打印
}
/*****************输入输出重定向***********************************/
void chongdingxiang(char **canshu){
pid_t pidd,pid;
int fd;
if(*(*(canshu+1)+0) == 62){//输出重定向:目前只支持这种形式:ls > bb
pidd=fork();
if(pidd<0){
perror("chongdingxiang fork is failure!");
exit(1);
}else if(pidd==0){
if((fd=open(*(canshu+2),O_RDWR|O_CREAT|O_TRUNC,770))<0){
perror(">open is failure!");
exit(111);
}
if(dup2(fd,STDOUT_FILENO)<0){
perror(">dup2 is failure!");
exit(111);
}
if(execlp(*(canshu+0),*(canshu+0),NULL)<0){
perror(NULL);
exit(111);
}
}
if(pidd>0){
if(waitpid(pidd,NULL,0)<0){
perror("chongdingxiang waitpid is failure!");
exit(1);
}
}
}else{//wc < 1.c 输入重定向
pid=fork();
if(pid<0){
perror("chongdingxiang fork is failure!");
exit(1);
}else if(pid==0){
if((fd=open(*(canshu+2),O_RDWR))<0){
perror("open is failure!");
exit(111);
}
if(dup2(fd,STDIN_FILENO)<0){
perror(");
exit(111);
}
// printf("line:%d,canshu1:%s\n",__LINE__,*(canshu+0));
if(execlp(*(canshu+0),*(canshu+0),NULL)<0){
perror("+++++++");
exit(111);
}
// printf("line:%d,canshu1:%s\n",__LINE__,*(canshu+0));
}
if(pid>0){
if(waitpid(pid,NULL,0)<0){
perror("chongdingxiang < waitpid is failure!");
exit(1);
}
}
}
}
/***************************管道处理*************************************************/
int guandao(char **canshu,int i){
printf("++++++++++%d\n",__LINE__);
*(canshu+i)=NULL;
pid_t pid;
int ret,n;
int fd[2];
ret = pipe(fd);
if(ret<0){
perror("pipe is failure!");
return 1;
}
pid = fork();
if(pid < 0){
perror("fork is failure!");
return 1;
}
if(pid == 0){
printf("++++++++++%d\n",__LINE__);
close(fd[0]);
if(dup2(fd[1],STDOUT_FILENO)<0){
perror("| is dup2");
return 1;
}
if(execvp(*(canshu+0),canshu)<0){
perror("| is exe failure!");
return 1;
}
}
if(pid>0){
printf("++++++++++%d\n",__LINE__);
if(waitpid(pid,NULL,0)<0){
perror("| father waitpid is failure!");
return 1;
}
close(fd[1]);
if(dup2(fd[0],STDIN_FILENO)<0){
perror("| father dup2 is failure!");
return 1;
}
if(execvp(*(canshu+i+1),(canshu+i+1))<0){
perror("| father exe is failure!");
return 1;
}
}
printf("++++++++++%d\n",__LINE__);
return 0;
}
head.h
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 100
#define HOST_LEN 40
#define CANSHU_LEN 10
void print();
int guandao(char **canshu,int i);
int canshuzhengli(char **ptr,char *buf);
static char *canshu[ CANSHU_LEN ];