linux c语言实现cd,Linux 用C语言实现简单的shell(2)

/*author:Samsons

date:2015.4.28

1)对于shell指令采用结构体存储,方便管道的切割与执行;

2)采用strtok_r对于指令进行了更加合理的切割;

3)增加了多管道处理;

4)处理了一些简单的异常问题,包括文件路径问题,空行问题,指令错误等。*/#include#include#include#include#include#include#include

#define MAX 100

#define LEN 100

//shell指令单个管道结构体

structcmd_list{int argc; //单个管道参数个数

char *argv[MAX];

};struct cmd_list *cmdv[MAX]; //shell指令

int num;//shell管道个数//执行外部命令

void execute(char *argv[])

{interror;

error=execvp(argv[0],argv);if (error==-1) printf("failed!\n");

exit(1);

}//切分单个管道

void split_cmd(char *line)

{struct cmd_list * cmd = (struct cmd_list *)malloc(sizeof(structcmd_list));

cmdv[num++] =cmd;

cmd->argc = 0;char *save;char *arg = strtok_r(line, "\t", &save);//切分空格

while(arg)

{

cmd->argv[cmd->argc] =arg;

arg= strtok_r(NULL, "\t", &save);

cmd->argc++;

}

cmd->argv[cmd->argc] =NULL;

}//切分管道

void split_pipe(char *line)

{char *save;char * cmd = strtok_r(line, "|", &save);while(cmd) {

split_cmd(cmd);

cmd= strtok_r(NULL, "|", &save);

}

}//执行管道命令

void do_pipe(intindex)

{if (index == num - 1)

execute(cmdv[index]->argv);int fd[2];

pipe(fd);//创建管道,0读,1写

if (fork() == 0)

{

dup2(fd[1], 1);

close(fd[0]);

close(fd[1]);

execute(cmdv[index]->argv);

}

dup2(fd[0], 0);

close(fd[0]);

close(fd[1]);

do_pipe(index+ 1);

}//执行内部指令

int inner(char *line)

{char *save,*tmp[MAX];chart[LEN],p[LEN];

strcpy(t,line);char *arg = strtok_r(line, "\t", &save);//切分空格

int i=0;while(arg) {

tmp[i]=arg;

i++;//记录命令个数

arg = strtok_r(NULL, "\t", &save);

}

tmp[i]=NULL;if (strcmp(tmp[0],"exit")==0)//exit

{

exit(0);return 1;

}else

if (strcmp(tmp[0],"pwd")==0)//pwd

{charbuf[LEN];

getcwd(buf,sizeof(buf));//得到当前路径

printf("Current dir is:%s\n",buf);return 1;

}else

if (strcmp(tmp[0],"cd")==0)//cd

{charbuf[LEN];if (chdir(tmp[1])>=0)

{

getcwd(buf,sizeof(buf));

printf("Current dir is:%s\n",buf);

}else{

printf("Error path!\n");

}return 1;

}else return 0;

}//输入重定向

void cat_in(char *q)

{char t[30];intfd;if (q[0]==‘

{

strcpy(t,q+1);

fd=open(t,O_RDONLY);

cmdv[0]->argv[cmdv[0]->argc-1]=NULL; //默认重定向为参数的最后一个

cmdv[0]->argc--;if (fd==-1)

{

printf("file open failed\n");return;

}

dup2(fd,0);

close(fd);

}

}//输出重定向

void cat_out(char *q)

{char t[30];intfd;if (q[0]==‘>‘)

{

strcpy(t,q+1);

cmdv[num-1]->argv[cmdv[num-1]->argc-1]=NULL;

cmdv[num-1]->argc--;

fd=open(t,O_CREAT|O_RDWR,0666); //0666为权限

if (fd==-1)

{

printf("file open failed\n");return;

}

dup2(fd,1);

close(fd);

}

}intmain()

{inti,pid;charbuf[LEN],p[LEN];while (1)

{

fgets(buf,LEN,stdin);//读入shell指令

if (buf[0]==‘\n‘) continue;

buf[strlen(buf)-1]=‘\0‘;

strcpy(p,buf);intinner_flag;

inner_flag=inner(buf);//内置指令执行

if (inner_flag==0)

{

pid=fork();//建立新的进程

if (pid==0)

{

split_pipe(p);//管道的切割//默认输入输出重定向都是最后一个参数,输入时第一个管道,输出是最后一个管道

if (cmdv[0]->argv[cmdv[0]->argc-1]!=NULL)

{charq[LEN];

strcpy(q,cmdv[0]->argv[cmdv[0]->argc-1]);

cat_in(q);//输入重定向

}if (cmdv[num-1]->argv[cmdv[num-1]->argc-1]!=NULL)

{charq[LEN];

strcpy(q,cmdv[num-1]->argv[cmdv[num-1]->argc-1]);

cat_out(q);//输出重定向

}

do_pipe(0);//执行管道

exit(0);

}

waitpid(pid,NULL,0);

}

}return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值