功能如下:
(1)显示命令提示符%;
(2)获取用户输入指令;解析指令;寻找命令文件,执行指令;
(3)前一个命令完成后才继续显示命令提示符%,等待用户输入下一条命令;
(3)如果输入“exit”或“logout”,则退出shell.
(4)允许命令参数间有多个空格,也允许命令前后有空格
(5)支持输出重定向和管道功能。
void _spilt(char **argv,char *file,char **file_argv,char** pipeO,char** pipeI,char *cmdline)
/** 解析从命令行输入的字符串*/
void eval(char* cmdline)
/**执行命令*/
重定向实现:利用dup去改变标准输出文件描述符指向的文件
//核心代码:file是重定向输出的文件,即command > file
fd = open(file,O_WRONLY|O_CREAT|O_TRUNC,0777);
close(1);
dup(fd);
管道实现:利用pipe这个缓冲区(实际上可以当成是文件),然后利用dup改变标准输入和标准输出文件描述符指向的文件
//核心代码:改变标准输入和标准输出文件描述符指向的地方
pipe(pipe_fd);
dup2(pipe_fd[1],1);
dup2(pipe_fd[0],0);
程序所包含的知识:dup和文件描述符,pipe以及exec族(这里用execvp函数实现)还有fork,最后就是解析字符串了
源代码:
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXLINE 100
#define LEN 10
int isCDX = 0;
int isPipe = 0;
void _spilt(char **argv,char *file,char **file_argv,char** pipeO,char** pipeI,char *cmdline){
int i = 0, j = 0, cdx_argv, temp,pipe1,pipe2;
int k, len;
len = strlen(cmdline);
isCDX = 0;
isPipe = 0;
//解析shell
for(k = 0;k < len; k++){
if(cmdline[k] == ' '&& k == 0) continue; //去掉首个空格
else if(cmdline[k] == ' '&& cmdline[k-1] == ' ')continue; //去掉多个空格
else if(cmdline[k] == ' '){
//字符串尾
argv[i][j] = ';'=
j 0 ;++
i;}
elseif ([cmdline]k== '\n' && 0 k > && [ cmdline-k1]== ' ' )//字符串解析完多个空格后回车{
[
argv]i= NULL ;}
elseif ([cmdline]k== '\n' && == k 0 )//首个就是回车{
==
argv NULL ;}
elseif ([cmdline]k== '\n' )//字符串解析完成{
[
argv]i[]j= ';' ++;
i[]
argv=iNULL ; }else
//其他情况复制字符[{
]
argv[i]=j[ ] cmdline;k++;
j}}
//查找是否为重定向
for
(
=0temp ; <=; temp ++ i) tempif({
[]argv!=tempNULL ) if({
strcmp([]argv,temp)==">"0 ) =1{
isCDX ; strcpy(
,[file+argv1temp]);for(
=0cdx_argv ; <; cdx_argv ++ temp) cdx_argv[]{
file_argv=cdx_argv( char *) malloc(sizeof(char)*) ; MAXLINEstrcpy(
[]file_argv,cdx_argv[]argv)cdx_argv;}[
]
file_argv=cdx_argv( char *) malloc(sizeof(char)*) ; MAXLINE[]
file_argv=cdx_argvNULL ; break;
}else
continue; }}
if
(
==1isCDX ) return; //查找是否为管道for
(
=0temp ; <=; temp ++ i) tempif({
[]argv!=tempNULL ) if({
strcmp([]argv,temp"|")==0 ) =1{
isPipe ; for(
=0pipe1 ; <; pipe1 ++ temp) pipe1[]{
pipeO=pipe1( char *) malloc(sizeof(char)*) ; MAXLINEstrcpy(
[]pipeO,pipe1[]argv)pipe1;}[
]
pipeO=pipe1( char *) malloc(sizeof(char)*) ; MAXLINE[]
pipeO=pipe1NULL ; ++;
tempfor(
=0pipe2 ; <; temp ++ i) temp[]{
pipeI=pipe2( char *) malloc(sizeof(char)*) ; MAXLINEstrcpy(
[]pipeI,pipe2[]argv)temp;++;
pipe2}[
]
pipeI=pipe2( char *) malloc(sizeof(char)*) ; MAXLINE[]
pipeI=pipe2NULL ; }}
}
}
void
eval
( char*)char cmdline*{
[ ]argv;LEN//shell参数char[
] file;LEN//输出重定向文件char*
[ ]file_argv;LEN//输出重定向参数char*
[ ]pipeI;LEN//管道接受方command2char*
[ ]pipeO;LEN//管道输入方command1int,
; ipid_tfd,
; pidintpipePid[
2 pipe_fd];for(
=0i ; <; i ++ LEN) i[]{
argv=i( char *) malloc(sizeof(char)*) ; MAXLINE}_spilt
(
,,argv,file,file_argv,pipeO)pipeI;cmdlineif(
[0argv]==NULL)return;{
}else
if( strcmp("exit",[0argv])==0 || strcmp ( "logout",[0argv])==0 ) exit({
0);}else
if({
(=forkpid ( ))==0)// printf("我在子进程里\n");if{
(
)//输出重定向 isCDX // printf("我在重定向里\n");{
=
open
fd ( ,|file|O_WRONLY,O_CREAT0777O_TRUNC);close(
1);dup(
);fdif(
execvp([0argv],)<file_argv0 ) printf({
"%s:Command not found\n",[0argv]);exit(
0);}}
else
if( )//管道isPipe// printf("我在管道里\n");{
if
(
pipe()==pipe_fd- 1 )printf({
"Pipe error\n");exit(
0);}else
=fork{
pipePid ( );//在子进程里再创建子进程,这样父进程就不会退出了if(
==0pipePid ) dup2({
[1pipe_fd],1);if(
execvp([0pipeO],)<pipeO0 ) printf({
"%s:Command not found\n",[0pipeO]);exit(
0);}}
else
int;{
if status(
waitpid(,&pipePid,0status)<0 ) printf({
"waitfg : waitpid error\n");}else
dup2
({
[0pipe_fd],0);if(
execvp([0pipeI],)<pipeI0 ) printf({
"%s:Command not found\n",[0pipeI]);exit(
0);}}
}
}
}
else
//shell// printf("我在shell里\n");{
if
(
execvp([0argv],)<argv0 ) printf({
"%s:Command not found\n",[0argv]);exit(
0);}}
}
else
int;{
if status(
waitpid(,&pid,0status)<0 ) printf({
"waitfg: waitpid error\n");}else
printf({
"%d %s",,)pid;cmdline}}
}
return
;
}int
main
( )char[{
] cmdline;MAXLINEwhile(
1)printf({
"%%");fgets(
,,cmdlinestdinMAXLINE);if(
feof(stdin))exit( 0);eval(
);cmdline}return
0
; }
测试结果:
转载分享请注明转载处!!!
Allen_ZXJ
如果对你有帮助的话请点个赞再走呗
有什么问题也可以留言咨询噢
**
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)