这个版本的Shell支持管道功能和I/O重定向.
下一个版本将增加对内建(buildins)命令的支持,如if ..then else等控制语句的支持.
-------------CODE-------------------
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#define OPEN_MAX 10
#define MAXNAME 100
#define FALSE 0
#define TRUE 1
#define MAXNAME 100
#define FALSE 0
#define TRUE 1
char *readcmd( FILE *fp ); //读入命令行字符串
char **getarg(char *argv); //把命令行字符串分解成字符数组指针
void getfile(char *name); //获得重定向文件名
void freearg(char **arg); //释放内存
char **getarg(char *argv); //把命令行字符串分解成字符数组指针
void getfile(char *name); //获得重定向文件名
void freearg(char **arg); //释放内存
char *buf; //存放用户输入的字符串
char *p; //指向buf的指针
int cmdnum; //记录命令个数
int pipefd[2]; //保存管道文件描述符
int wait_pid; //记录父进程PID
char infile[MAXNAME+1]; //输入重定向文件
char outfile[MAXNAME+1]; //输出重定向文件
int background; //记录命令是否在后台执行
int append; //记录是否写入文件末尾
struct cmd{
char ** argv; //命令行参数
int infd; //输入文件描述符
int outfd; // 输出文件描述符
}cmdline[BUFSIZ]; //命令行结构数组
char ** argv; //命令行参数
int infd; //输入文件描述符
int outfd; // 输出文件描述符
}cmdline[BUFSIZ]; //命令行结构数组
int main()
{
pid_t pid;
int status;
int i, fd;
{
pid_t pid;
int status;
int i, fd;
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_IGN); //处理中断(Ctrl-C)和推出(Ctrl-\)信号
signal(SIGQUIT, SIG_IGN); //处理中断(Ctrl-C)和推出(Ctrl-\)信号
printf("%% ");
while( (buf = readcmd(stdin)) != NULL ){
//-----------初始化-----------------
int k;
cmdnum = 0;
background = FALSE;
infile[0] = '\0';
outfile[0] = '\0';
append = FALSE;
for( k = 0; k < OPEN_MAX; k++ )
{
cmdline[k].infd = 0;
cmdline[k].outfd = 1;
}
{
cmdline[k].infd = 0;
cmdline[k].outfd = 1;
}
for( k = 3; k < OPEN_MAX; k++ )
close(k);
fflush(stdout); //清空输出缓冲区
close(k);
fflush(stdout); //清空输出缓冲区
p = buf;
//-----------计算命令个数并获得命令参数----------
for(i = 0; i <= cmdnum; i++)
cmdline[i].argv = getarg(buf);
if( infile[0] != '\0' )
cmdline[0].infd = open(infile, O_RDONLY);
if( outfile[0] != '\0' )
if( append == FALSE )
cmdline[cmdnum].outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
else
cmdline[cmdnum].outfd = open(outfile, O_WRONLY | O_CREAT | O_APPEND, 0666);
if( background == TRUE )
signal(SIGCHLD, SIG_IGN);
else
signal(SIGCHLD, SIG_DFL);
//-----------计算命令个数并获得命令参数----------
for(i = 0; i <= cmdnum; i++)
cmdline[i].argv = getarg(buf);
if( infile[0] != '\0' )
cmdline[0].infd = open(infile, O_RDONLY);
if( outfile[0] != '\0' )
if( append == FALSE )
cmdline[cmdnum].outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
else
cmdline[cmdnum].outfd = open(outfile, O_WRONLY | O_CREAT | O_APPEND, 0666);
if( background == TRUE )
signal(SIGCHLD, SIG_IGN);
else
signal(SIGCHLD, SIG_DFL);
//-----------执行命令行-------------
for(i = 0; i <= cmdnum; i++)
{
//-----------处理管道-------------
if( i < cmdnum )
{
pipe(pipefd);
cmdline[i+1].infd = pipefd[0];
cmdline[i].outfd = pipefd[1];
}
if ( pid = fork() )
wait_pid = pid;
else if ( pid == 0 ){
if( cmdline[i].infd == 0 && background == TRUE )
cmdline[i].infd = open("/dev/null", O_RDONLY);
if(cmdline[i].infd != 0)
{
close(0);
dup(cmdline[i].infd);
}
if(cmdline[i].outfd != 1)
{
close(1);
dup(cmdline[i].outfd);
}
if( background == FALSE )
{
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
}
for(i = 0; i <= cmdnum; i++)
{
//-----------处理管道-------------
if( i < cmdnum )
{
pipe(pipefd);
cmdline[i+1].infd = pipefd[0];
cmdline[i].outfd = pipefd[1];
}
if ( pid = fork() )
wait_pid = pid;
else if ( pid == 0 ){
if( cmdline[i].infd == 0 && background == TRUE )
cmdline[i].infd = open("/dev/null", O_RDONLY);
if(cmdline[i].infd != 0)
{
close(0);
dup(cmdline[i].infd);
}
if(cmdline[i].outfd != 1)
{
close(1);
dup(cmdline[i].outfd);
}
if( background == FALSE )
{
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
}
for( k = 3; k < OPEN_MAX; ++k)
close(k);
close(k);
execvp(cmdline[i].argv[0], cmdline[i].argv);
}
if(fd = cmdline[i].infd)
close(fd);
if((fd = cmdline[i].outfd) != 1)
close(fd);
}
if( background == FALSE )
while ( waitpid(pid, &status, 0) != wait_pid )
;
printf("%% ");
}
if(fd = cmdline[i].infd)
close(fd);
if((fd = cmdline[i].outfd) != 1)
close(fd);
}
if( background == FALSE )
while ( waitpid(pid, &status, 0) != wait_pid )
;
printf("%% ");
//-------释放内存-----------
for(i = 0; i <= cmdnum; i++)
freearg(cmdline[i].argv);
free(buf);
}
exit(0);
}
for(i = 0; i <= cmdnum; i++)
freearg(cmdline[i].argv);
free(buf);
}
exit(0);
}
void freearg(char **arg)
{
char **cp = arg;
while(*cp)
free(*cp++);
free(arg);
}
{
char **cp = arg;
while(*cp)
free(*cp++);
free(arg);
}
char *readcmd(FILE *fp)
{
char *buf;
int buflen = 0;
int i = 0;
int c;
while( (c = getc(fp)) != EOF ){
if( i +1 >= buflen ){
if( buflen == 0 ){
buf = (char*) malloc( BUFSIZ );
if( buf == NULL )
return NULL;
}
else{
buf = (char *)realloc(buf, buflen + BUFSIZ);
if( buf == NULL )
return NULL;
}
buflen += BUFSIZ;
}
if ( c == '\n' )
break;
buf[i++] = c;
}
break;
buf[i++] = c;
}
if( c == EOF && i == 0 )
return NULL;
buf[i] = '\0';
return buf;
return NULL;
buf[i] = '\0';
return buf;
}
char **getarg(char * argv)
{
char **args;
if( (args = (void *)malloc(BUFSIZ)) == NULL )
{
printf("out of memory\n");
return NULL;
}
int bufsize = sizeof(argv)/sizeof(argv[0]);
char argbuf[bufsize];
char *cp = argbuf;
char *end;
char *start = argbuf;
char * tempstr;
int len;
int i = 0;
{
char **args;
if( (args = (void *)malloc(BUFSIZ)) == NULL )
{
printf("out of memory\n");
return NULL;
}
int bufsize = sizeof(argv)/sizeof(argv[0]);
char argbuf[bufsize];
char *cp = argbuf;
char *end;
char *start = argbuf;
char * tempstr;
int len;
int i = 0;
while( *p != '\0' )
{
while( *p == ' ' || *p == '\t' )
p++; //去掉多余的空格
{
while( *p == ' ' || *p == '\t' )
p++; //去掉多余的空格
if( *p == '\0' )
break;
break;
if( *p == '|') //管道,使命令数加1
{
if( *(p+1) == ' ' )
p +=2; //跳过空格
else
p++;
cmdnum++;
break;
}
{
if( *(p+1) == ' ' )
p +=2; //跳过空格
else
p++;
cmdnum++;
break;
}
if( *p == '<' ) //输入重定向
{
if( *(p+1) == ' ' )
p +=2;
else
p++;
getfile(infile);
break;
}
{
if( *(p+1) == ' ' )
p +=2;
else
p++;
getfile(infile);
break;
}
if( *p == '>' ) //输出重定向
{
if( *(p+1) == ' ' )
p +=2;
else
p++;
if( *p == '>' ) //追加到文件末尾
{
if( *(p+1) == ' ' )
p +=2;
else
p++;
{
if( *(p+1) == ' ' )
p +=2;
else
p++;
if( *p == '>' ) //追加到文件末尾
{
if( *(p+1) == ' ' )
p +=2;
else
p++;
append = TRUE;
}
getfile(outfile);
break;
}
}
getfile(outfile);
break;
}
if( *p == '&' ) //后台执行命令
{
if( *(p+1) == ' ' )
p +=2;
else
p++;
background = TRUE;
break;
}
{
if( *(p+1) == ' ' )
p +=2;
else
p++;
background = TRUE;
break;
}
*cp++ = *p++;
if( *p == ' ' || *p == '\0' )
{
*cp = '\0';
end = cp;
len = end - start;
if( (tempstr = (char *)malloc(len + 1)) == NULL )
{
printf("out of memory\n");
return NULL;
}
strncpy(tempstr, start, len);
tempstr[len] = '\0';
if( i + 1 > BUFSIZ )
{
if( (args = (void *)realloc(args, BUFSIZ * 2)) == NULL )
{
printf("out of memory\n");
return NULL;
}
}
args[i++] = tempstr;
start = end;
if( *p == '\0')
break;
p++;
}
}
args[i] = NULL;
return args;
}
{
*cp = '\0';
end = cp;
len = end - start;
if( (tempstr = (char *)malloc(len + 1)) == NULL )
{
printf("out of memory\n");
return NULL;
}
strncpy(tempstr, start, len);
tempstr[len] = '\0';
if( i + 1 > BUFSIZ )
{
if( (args = (void *)realloc(args, BUFSIZ * 2)) == NULL )
{
printf("out of memory\n");
return NULL;
}
}
args[i++] = tempstr;
start = end;
if( *p == '\0')
break;
p++;
}
}
args[i] = NULL;
return args;
}
void getfile(char *name)
{
int i;
for( i = 0; i < MAXNAME; ++i )
{
if( *p == ' ' || *p == '|' || *p == '>' || *p == '\0' ||
*p == '<' || *p == '&' || *p == '\t' )
{
*name = '\0';
return;
}
else
*name++ = *p++;
}
*name = '\0';
}
{
int i;
for( i = 0; i < MAXNAME; ++i )
{
if( *p == ' ' || *p == '|' || *p == '>' || *p == '\0' ||
*p == '<' || *p == '&' || *p == '\t' )
{
*name = '\0';
return;
}
else
*name++ = *p++;
}
*name = '\0';
}
操作提示