?? 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 + -