shell命令解释器.docx
《shell命令解释器.docx》由会员分享,可在线阅读,更多相关《shell命令解释器.docx(16页珍藏版)》请在冰豆网上搜索。
shell命令解释器
#include
#include
#include
#include
#include
#include
#include
char*stack[1000]={"/"};
intnum=1;
externchar**environ;
/*
内装式shell命令的函数声明:
*/
intlsh_cd(char**args);
intlsh_help(char**args);
intlsh_exit(char**args);
intlsh_pushd(char**args);
intlsh_popd(char**args);
intlsh_dirs(char**args);
intlsh_redirect1(char**args);
intlsh_redirect2(char**args);
intlsh_redirect3(char**args);
intlsh_redirect4(char**args);
intlsh_export(char**args);
intlsh_echo(char**args);
/*
装入的命令列表,紧随其后的是相应的功能。
*/
char*builtin_str[]={
"cd",
"help",
"exit",
"pushd",
"popd",
"dirs",
"export",
"echo"
};
int(*builtin_func[])(char**)={
&lsh_cd,
&lsh_help,
&lsh_exit,
&lsh_pushd,
&lsh_popd,
&lsh_dirs,
&lsh_export,
&lsh_echo
};
intlsh_num_builtins(){
returnsizeof(builtin_str)/sizeof(char*);
}
/*安装在内部的函数实现。
.*/
/**
@briefBultincommand:
changedirectory.
@paramargsListofargs.args[0]is"cd".args[1]isthedirectory.
@returnAlwaysreturns1,tocontinueexecuting.
@briefBultin命令:
改变目录。
@paramargs参数列表。
args[0]是“cd”。
args[1]是目录。
@return总是返回1,继续执行。
*/
intlsh_cd(char**args)
{
if(args[1]==NULL){
fprintf(stderr,"lsh:
expectedargumentto\"cd\"\n");
}else{
if(chdir(args[1])!
=0){
perror("lsh");
}
}
return1;
}
/**
@brief内置命令:
打印的帮助。
@paramargs参数列表。
不检查。
@return总是返回1,继续执行。
*/
intlsh_help(char**args)
{
inti;
printf("Typeprogramnamesandarguments,andhitenter.\n");
printf("Thefollowingarebuiltin:
\n");
for(i=0;iprintf("%s\n",builtin_str[i]);
}
printf("Usethemancommandforinformationonotherprograms.\n");
return1;
}
/**
@brief内置命令:
退出。
@paramargs参数列表。
不检查。
@return总是返回0,终止执行。
*/
intlsh_exit(char**args)
{
return0;
}
//pushd函数:
intlsh_pushd(char**args)
{
if(chdir(args[1])!
=0)
{
perror("lsh");
}
else
{
stack[num++]=get_current_dir_name();
inti=num-1;
while(i>=0)
{
printf("%s",stack[i]);
i--;
}
printf("\n");
}
return1;
}
//popd函数:
intlsh_popd(char**args)
{
if(num<2)
{
printf("popd:
directorystackempty!
\n");
return1;
}
num--;
chdir(stack[num]);
inti=num-1;
while(i>=0)
{
printf("%s",stack[i]);
i--;
}
printf("\n");
return1;
}
//dirs函数:
intlsh_dirs(char**args)
{
if(args[1]==0)
{
inti=num-1;
charm=stack[i];
stack[i]="/";
while(i>=0)
{
printf("%s",stack[i]);
i--;
}
printf("\n");
stack[num-1]=i;
return1;
}
else
{
if(strcmp(args[1],"-c")==0)
{
//memset(stack,0,sizeof(stack));
num=1;
}
if((strcmp(args[1],"-p")==0)&&(strcmp(args[2],"-v")==0))
{
intj=num-1;
while(j>=0)
{
printf("%d%s\n",num-1-j,stack[j]);
j--;
}
}
}
}
intfile1,file2;
//重定向1:
intlsh_redirect1(char**args)
{
file1=open(args[2],O_CREAT|O_RDWR);
file2=dup
(1);
dup2(file1,1);
close(file1);
lsh_launch(args);
dup2(file2,1);
//close(file2);
return1;
}
//重定向2:
intlsh_redirect2(char**args)
{
file1=open(args[2],O_CREAT|O_RDWR);
file2=dup
(2);
dup2(file1,2);
close(file1);
lsh_launch(args);
dup2(file2,2);
close(file2);
return1;
}
//重定向3:
intlsh_redirect3(char**args)
{
file1=open(args[2],O_CREAT|O_RDWR|O_APPEND);
file2=dup
(1);
dup2(file1,1);
close(file1);
lsh_launch(args);
dup2(file2,1);
close(file2);
return1;
}
//重定向4:
intlsh_redirect4(char**args)
{
file1=open(args[2],O_RDONLY|O_TRUNC);
file2=dup(0);
dup2(file1,0);
close(file1);
lsh_launch(args);
dup2(file2,0);
close(file2);
return1;
}
//export:
intlsh_export(char**args)
{
inti=0;
intbuf[100];
int*name;
int*value1;
int*value2;
int*value3;
if(args[1]==NULL)
{
while(environ[i]!
=NULL)
{
printf("%s\n",environ[i]);
i++;
}
}
else
{
strcpy(buf,args[1]);
name=strtok(buf,"=");
strtok(NULL,":
");
value1=getenv(name);
value2=strtok(NULL,":
");
value3=strcat(value1,value2);
setenv(name,value3,1);
}
return1;
}
intlsh_echo(char**args)
{
printf("%s:
%s\n",args[1]+1,getenv(args[1]+1));
return1;
}
/**
@brief启动程序,等待它终止。
@paramargs零终止的参数列表(包括程序)。
@return总是返回1,继续执行。
*/
intlsh_launch(char**args)
{
pid_tpid;
intstatus;
pid=fork();
if(pid==0){
//Childprocess
if(execvp(args[0],args)==-1){
perror("lsh");
}
exit(EXIT_FAILURE);
}elseif(pid<0){
//Errorforking
perror("lsh");
}else{
//Parentprocess
do{
waitpid(pid,&status,WUNTRACED);
}while(!
WIFEXITED(status)&&!
WIFSIGNALED(status));
}
return1;
}
/**
@brief执行shell内置或启动程序。
@paramargs零终止的参数列表。
@return1如果壳牌公司应该继续运行,如果它应该终止
*/
intlsh_execute(char**args)
{
inti;
/*if(args[1]!
=NULL)
if(strcmp(args[2],"|")==0)
{
returnpipe(args);
}*/
if(args[0]==NULL){
//Anemptycommandwasentered.
return1;
}
for(i=0;iif(strcmp(args[0],builtin_str[i])==0){
return(*builtin_func[i])(args);
}
}
if(args[1]!
=NULL)
if(strcmp(args[1],">")==0)
{
returnlsh_redirect1(args);
}
if(args[1]!
=NULL)
if(strcmp(args[1],"2>")==0)
{
returnlsh_redirect2(args);
}
if(args[1]!
=NULL)
if(strcmp(args[1],">>")==0)
{
returnlsh_redirect3(args);
}
if(strcmp(args[0],"cat")==0)
returnlsh_launch(args);
if(args[1]!
=NULL)
if(strcmp(args[2],"<")==0)
{
returnlsh_redirect4(args);
}
}
#defineLSH_RL_BUFSIZE1024
/**
@brief从stdin读取一行输入。
@return从stdin。
*/
char*lsh_read_line(void)
{
intbufsize=LSH_RL_BUFSIZE;
intposition=0;
char*buffer=malloc(sizeof(char)*bufsize);
intc;
if(!
buffer){
fprintf(stderr,"lsh:
allocationerror\n");
exit(EXIT_FAILURE);
}
while
(1){
//Readacharacter
c=getchar();
//IfwehitEOF,replaceitwithanullcharacterandreturn.
if(c==EOF||c=='\n'){
buffer[position]='\0';
returnbuffer;
}else{
buffer[position]=c;
}
position++;
//Ifwehaveexceededthebuffer,reallocate.
if(position>=bufsize){
bufsize+=LSH_RL_BUFSIZE;
buffer=realloc(buffer,bufsize);
if(!
buffer){
fprintf(stderr,"lsh:
allocationerror\n");
exit(EXIT_FAILURE);
}
}
}
}
#defineLSH_TOK_BUFSIZE64
#defineLSH_TOK_DELIM"\t\r\n\a"
/**
@briefSplitalineintotokens(verynaively).
@paramlineTheline.
@returnNull-terminatedarrayoftokens.
@brief直线分割成令牌(很天真)。
@param线。
@return以null结尾的标记数组)。
@brief从stdin读取一行输入。
@return从stdin。
*/
char**lsh_split_line(char*line)
{
intbufsize=LSH_TOK_BUFSIZE,position=0;
char**tokens=malloc(bufsize*sizeof(char*));
char*token,**tokens_backup;
if(!
tokens){
fprintf(stderr,"lsh:
allocationerror\n");
exit(EXIT_FAILURE);
}
token=strtok(line,LSH_TOK_DELIM);
while(token!
=NULL){
tokens[position]=token;
position++;
if(position>=bufsize){
bufsize+=LSH_TOK_BUFSIZE;
tokens_backup=tokens;
tokens=realloc(tokens,bufsize*sizeof(char*));
if(!
tokens){
free(tokens_backup);
fprintf(stderr,"lsh:
allocationerror\n");
exit(EXIT_FAILURE);
}
}
token=strtok(NULL,LSH_TOK_DELIM);
}
tokens[position]=NULL;
returntokens;
}
/**
@brief循环输入和执行它。
*/
voidlsh_loop(void)
{
char*line;
char**args;
intstatus;
charname[100];
charaddr[100];
do{
gethostname(name,sizeof(name));
printf("<%s>@<%s>:
<%s>$",getlogin(),name,getcwd(addr,sizeof(addr)));
line=lsh_read_line();
args=lsh_split_line(line);
status=lsh_execute(args);
free(line);
free(args);
}while(status);
}
/*
*@brief主要入口点。
*@param命令行参数个数参数计数。
*@paramargv参数向量。
*@return地位codeLoad配置文件,如果任何。
*/
intmain(intargc,char**argv)
{
//加载配置文件,如果有的话。
sigset_tsign;
sigemptyset(&sign);
sigaddset(&sign,SIGQUIT);
sigprocmask(SIG_BLOCK,&sign,NULL);
voidmy_handler(ints)
{
printf("Caughtsignal%d\n",s);
}
structsigactionsi;
si.sa_handler=my_handler;
sigemptyset(&si.sa_mask);
si.sa_flags=0;
sigaction(SIGINT,&si,NULL);
//运行命令循环。
lsh_loop();
//执行任何关闭/清理。
sigprocmask(SIG_UNBLOCK,&sign,NULL);
returnEXIT_SUCCESS;
}