/*简单的模拟shell,可以执行带一个输入重定向(或输出重定向或管道)命令,程序存在不完善之处,基本能用*/
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<dirent.h>
char command[100]; /*存放命令*/
char argv[50][50]; /*存放分解后的命令*/
int count; /*命令分解后的个数*/
/*枚举类型,依次表示一般命令,带输出重定向命令,带输入重定向命令,带管道命令*/
enum specify{NORMAL,OUT_REDIRECT,IN_REDIRECT,PIPE};
/*函数声明*/
int analysis_command();
int do_command();
int find_command(char *command);
/*主函数*/
int main()
{
while(1){
printf("$my_shell:");
command[0]=0;
gets(command);
if(!analysis_command())
continue;
do_command();
}
return 0;
}
/*解析命令*/
int analysis_command()
{
char *s=command;
int i=0,j=0,state=0;
strcat(command," ");
/*按空格为分隔符将命令分隔开来,存放在argv中*/
while(*s){
switch(state){
case 0:
if(!isspace(*s))
state=1;
else
s++;
break;
case 1:
if(isspace(*s)){
argv[i][j]='\0';
i++;
j=0;
state=0;
}else{
argv[i][j]=*s;
j++;
}
s++;
break;
}
}
count=i;
if(count==0)
return 0;
if(strcmp(argv[0],"logout")==0 || strcmp(argv[0],"exit")==0)
exit(0);
/*判断命令是否存在*/
if(!find_command(argv[0])){
puts("error:can't find command");
return 0;
}
return 1;
}
/*执行命令*/
int do_command()
{
int i,j;
char* file;
char* arg[50];
char* arg2[50];
int f=0,back_run=0;
int fd,pid,fd2,pid2;
enum specify type=NORMAL;
for(i=0;i<count;i++){
arg[i]=argv[i];
}
arg[i]=NULL;
if(strcmp(arg[count-1],"<")==0 || strcmp(arg[count-1],">")==0 || strcmp(arg[count-1],"|")==0){
printf("error:command error\n");
return 0;
}
for(i=0;i<count;i++){
if(strcmp(arg[i],"<")==0){
f++;
file=arg[i+1];
arg[i]=NULL;
type=IN_REDIRECT;
}else if(strcmp(arg[i],">")==0){
f++;
file=arg[i+1];
arg[i]=NULL;
type=OUT_REDIRECT;
}else if(strcmp(arg[i],"|")==0){
f++;
type=PIPE;
arg[i]=NULL;
for(j=i+1;j<count;j++){
arg2[j-i-1]=arg[j];
}
arg2[j-i-1]=NULL;
if(!find_command(arg2[0])){
printf("error:can't find command\n");
return 0;
}
}
}
if(strcmp(arg[count-1],"&")==0){
back_run=1;
arg[count-1]=NULL;
}
if(f>1){
printf("error:don't identify the command");
return 0;
}
pid=fork();
if(pid<0){
perror("fork error");
exit(0);
}else if(pid==0){/*在子进程里*/
switch(type){
case NORMAL:
execvp(arg[0],arg);
break;
case IN_REDIRECT:
fd=open(file,O_RDONLY);
dup2(fd,STDIN_FILENO);
execvp(arg[0],arg);
break;
case OUT_REDIRECT:
fd=open(file,O_WRONLY|O_CREAT|O_TRUNC,0666);
dup2(fd,STDOUT_FILENO);
execvp(arg[0],arg);
break;
case PIPE:
pid2=fork();
if(pid2==0){
fd2=open("tempfile",O_WRONLY|O_CREAT|O_TRUNC,0600);
dup2(fd2,STDOUT_FILENO);
execvp(arg[0],arg);
}else{
waitpid(pid2,NULL,0);
fd=open("tempfile",O_RDONLY);
dup2(fd,STDIN_FILENO);
execvp(arg2[0],arg2);
}
break;
}
}else{
if(!back_run)
waitpid(pid,NULL,0);
}
return 1;
}
/*查找命令*/
int find_command(char *command)
{
DIR *d;
struct dirent *ptr;
char temp[100];
char *dir;
/*获得环境变量*/
char *path=getenv("PATH");
/*分隔环境变量,且依次查找各个目录看命令是否存在*/
strcpy(temp,path);
dir=strtok(temp,":");
while(dir){
d=opendir(dir);
while((ptr=readdir(d)) != NULL)
if(strcmp(ptr->d_name,command) == 0){
closedir(d);
return 1;
}
closedir(d);
dir=strtok(NULL,":");
}
return 0;
}
|