📄 shell.cpp
字号:
/*****************************************************************************/
/*作者:王伟*/
/*班级:自42*/
/*学号:2004011443*/
/*程序功能:模拟linux下shell环境,实现shell功能*/
/*日期:2007.6.1*/
/*****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define BUFFERSIZE 80
int main(void)
{
char *read_order(char *buffer); //从键盘中读取命令
char **order_name(const char *input); //返回每条命令
int pipel(char * input);
int pipe_number(const char *input);//统计管道数量
int redirect(char *input);//输入输出重定向
int order_number(const char *input); //统计命令数量,以;相隔
char *path,*buffer;
char *all_order,**every_order;
int i,pipe,k,number;
if((buffer=(char *)malloc(BUFFERSIZE*(sizeof(char))))==0)
{
printf("error! can't malloc enough space for buffer\n");
return (0);
}
while(1)
{
path=getcwd(NULL,0); //取得当前所在路径
printf("%s > $", path);
all_order=read_order(buffer); //读取命令
if(all_order==NULL)
continue;
number=order_number(all_order);
if (number<0)
continue;
every_order=order_name(all_order);
i=0;
while (i<number)
{
if(strlen(every_order[i])!=0)
{
k=pipe_number(every_order[i]); //是否有管道
if(k!=0)
pipel(every_order[i]);
else
redirect(every_order[i]); //输入输出重定向或普通命令
//for debug
//printf("%s\n",every_order[i]);
}
i++;
}
//释放申请的空间
for(i=0;i<number;i++)
free(every_order[i]);
free(every_order);
free(all_order);
free(path);
}
}
char **order_name(const char *input) //返回每条命令
{
int order_number(const char *input); //统计命令数量,以;相隔
int i,j,k,max_len;
char **order;
max_len=strlen(input);
k=order_number(input);
order=(char **)malloc(k*sizeof(char *));
for(i=0;i<k;i++)
{
order[i]=(char *)malloc((max_len+1)*sizeof(char));
order[i][0]='\0';
}
//分别取出被";"分割开的命令
k=0;
j=0;
for (i=0;i<=max_len;i++)
{
if (input[i]!=';')
{
order[k][j]=input[i];
j++;
}
else
{
order[k][j]='\0';
k++;
j=0;
}
}
//show the orders that are departed by ';'
/*for(i=0;i<k+1;i++)
printf("%s\n",order[i]);*/
return order;
}
int order_number(const char *input) //统计命令数量,以;相隔
{
int sum=0,i=0,len;
len=strlen(input);
while(i<len&&(input[i]==' '||input[i]==' '))
i++;
if(input[i]==';') //发生错误,出现;;
{
fprintf(stderr," syntax error near unexpected token: ;\n");
return -1;
}
if (i==len) //命令参数中只有空格或tab
return -1;
for (i=0;i<len;i++)
if(input[i]==';')
{
while(i<strlen(input)&&(input[i+1]==' '||input[i+1]==' '))
i++;
if(input[i+1]==';') //发生错误,出现;;
{
fprintf(stderr," syntax error near unexpected token: ;;\n");
return -1;
}
else
sum++;
}
sum=sum+1;
return sum;
}
int pipel(char * input)
{
int redirect(char *input);
int is_back(char *order); //分析是否为后台进程,并且将字符&去掉
int pipe_number(const char *input); //统计管道数量
int status,i,j,k,**fd,back=0,len;
char **order;
int *child;
back=is_back(input);
len=strlen(input);
k=pipe_number(input);
order=(char **)malloc((k+1)*sizeof(char *));
for(i=0;i<k+1;i++)
order[i]=(char *)malloc((len+1)*sizeof(char));
child=(int *)malloc((k+1)*sizeof(char *));
fd=(int **)malloc(k*sizeof(int *));
for(i=0;i<k;i++)
fd[i]=(int *)malloc(2*sizeof(int));
//分别取出被管道分割开的命令
k=0;
j=0;
for (i=0;i<=len;i++)
{
if (input[i]!='|')
{
order[k][j]=input[i];
j++;
}
else
{
order[k][j]='\0';
k++;
j=0;
}
}
//test
/*for(i=0;i<k+1;i++)
printf("%s\n",order[i]);*/
/*分析完毕*/
//create the pipe
for(i=0;i<k;i++)
if(pipe(fd[i]) == -1)
{
fprintf(stderr, "Open pipe error !\n");
//printf("Open pipe error !\n");
return 0;
}
//create the first child
i=0;
if((child[i]=fork())==0)
{
close(fd[i][0]);
if(fd[i][1] != STDOUT_FILENO)
{
// 将标准的输出重定向到管道的写入端,这样该子进程的输出就写入了管道
if(dup2(fd[i][1], STDOUT_FILENO) == -1)
{
fprintf(stderr, "Redirect Standard Out error !\n");
//printf("Redirect Standard Out error !\n");
return -1;
}
//关闭写入端
close(fd[i][1]);
}
redirect(order[i]);
exit(1); //child1 exit
}
else
{
//wait for child
waitpid(child[i],&status,0);
close(fd[i][1]);
}
i++;
while(i<k)
{
if ((child[i]=fork())==0)
{
if(fd[i][0] != STDIN_FILENO)
{
// 将标准的输入重定向到管道的读入端
if(dup2(fd[i-1][0], STDIN_FILENO) == -1)
{
fprintf(stderr, "Redirect Standard In error !\n");
//printf("Redirect Standard In Error !\n");
return -1;
}
close(fd[i-1][0]);
// 将标准的输出重定向到管道的写入端,这样该子进程的输出就写入了管道
if(dup2(fd[i][1], STDOUT_FILENO) == -1)
{
fprintf(stderr, "Redirect Standard Out error !\n");
//printf("Redirect Standard Out error !\n");
return -1;
}
close(fd[i][1]);
}
redirect(order[i]);
exit(1);
}
else
{
//wait for child
waitpid(child[i],&status,0);
close(fd[i][1]);
i++;
}
}
//create the last child
if((child[i] = fork()) == 0)
{
close(fd[i-1][1]);
if(fd[i-1][0] != STDIN_FILENO)
{
// 将标准的输入重定向到管道的读入端
if(dup2(fd[i-1][0], STDIN_FILENO) == -1)
{
fprintf(stderr, "Redirect Standard In error !\n");
//printf("Redirect Standard In Error !\n");
return -1;
}
close(fd[i-1][0]);
}
redirect(order[i]);
exit(1);
}
else if(back==0)
{
waitpid(child[i], NULL, 0);
close(fd[i-1][1]);
}
//释放申请的空间
for(i=0;i<k;i++)
free(fd[i]);
free(fd);
for(i=0;i<k+1;i++)
free(order[i]);
free(order);
free(child);
return 1;
/**************************************************/
}
int pipe_number(const char *input)//统计管道数量
{
int sum=0,i;
for (i=0;i<strlen(input);i++)
if(input[i]=='|')
sum++;
return sum;
}
void do_cd(char *argv[]) //专门用于cd命令
{
if(argv[1]!=NULL)
{
if(chdir(argv[1])<0)
switch(errno)
{
case ENOENT:
fprintf(stderr,"DIRECTORY NOT FOUND\n");
break;
case ENOTDIR:
fprintf(stderr,"NOT A DIRECTORY NAME\n");
break;
case EACCES:
fprintf(stderr,"YOU DO NOT HAVE RIGHT TO ACCESS\n");
break;
default:
fprintf(stderr,"SOME ERROR HAPPENED IN CHDIR\n");
}
}
}
int redirect(char *input) //重定向处理
{
char **analize(const char *input); //分析键入的命令,获取命令和参数并保存在arg中
char *is_file_exist(const char *order); //判断命令是否存在
void do_cd(char *argv[]); //专门用于cd命令
int number(const char *input); //分析命令和参数数量,来划分相应字符串
int is_back(char *order); //分析是否为后台进程,并且将字符&去掉
int pipe_number(const char *input); //统计管道数量
char *order_path,*real_order;
char *out_filename,*in_filename;
char **analized_order;
int len,status,i,j,k,back=0,fd_out,fd_in,flag_out=0,flag_in=0;
pid_t pid;
back=is_back(input);
len=strlen(input);
out_filename=(char *)malloc((len+1)*(sizeof(char)));
in_filename=(char *)malloc((len+1)*(sizeof(char)));
real_order=(char *)malloc((len+1)*(sizeof(char)));
//读取字符串中的命令,并存放于real_order中
for(i=0;i<len;i++)
{
if (input[i]!='>'&&input[i]!='<')
real_order[i]=input[i];
else
{
if (input[i]=='>')
flag_out=1;
if (input[i]=='<')
flag_in=1;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -