#include "parse.h"
#include <stdio.h>
#include <string.h>
#include "def.h"
#include "init.h"
#include "externs.h"
#include <sys/types.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <sys/wait.h>
#include <unistd.h>
#include "builtin.h"
void get_commend(int i);
void getname(char *name);
int check(const char *p);
void forkexec(int i);
void print_commend();
void shell_loop()
{
while(1)
{
printf("@minishell$ ");
fflush(stdout);
// getchar();
init();
if(read_commend())
break;
parse_commend();
// print_commend();
execute_commend();
}
printf("exit\n");
}
int read_commend()
{
if(fgets(cmdline,MAXLINE,stdin) == NULL)
return 1;
return 0;
}
int parse_commend()
{
//如果没命令输入
if(check("\n"))
return 0;
//如果是内部命令
if(builtin())
return 0;
//得第一条命令
get_commend(0);
//printf("%s\n",cmd[0].args[1]);
//判定是否有输入重定向
if(check("<"))
getname(infile);
//判断是否有管道
//int i = 1;
if(check("|"))
{
count++;
get_commend(count);
if(count == PIPENUM-1)
ERR_EXIT("over pipemax");
}
//判断是否有输出重定向
if(check(">"))
{
if(check(">"))
flag = 1;
getname(outfile);
}
//判断是否为后台作业
if(check("&"))
bground = 1;
//判断是否结束
if(check("\n"))
return count++; //返回命令条数
else
{
fprintf(stderr,"Commend line systax error\n");
return -1;
}
}
//获得第i+1条命令,放于结构体cmd中
void get_commend(int i)
{
int j = 0;
int flag_pra; //有没命令输入的标志
while(*cmdptr != '\0')
{
//除去空字符
while(*cmdptr == ' ' || *cmdptr =='\t')
cmdptr++;
cmd[i].args[j] = vpptr;
while(*cmdptr != '\n'
&& *cmdptr != '<' && *cmdptr != '>'
&& *cmdptr != '|' && *cmdptr != '&'
&& *cmdptr != '\0' && *cmdptr != ' '
&& *cmdptr != '\t')
{
*vpptr++ = *cmdptr++;
flag_pra = 1;
}
*vpptr++ = '\0';
switch(*cmdptr)
{
case ' ' :
case '\t':
j++;
flag_pra = 0;
break;
case '<':
case '>':
case '|':
case '&':
case '\n':
if(flag_pra == 0)
{
cmd[i].args[j] = NULL; //此时该指针指向的是以上那些字符中的某一个,不将其保存,应将其置空
// printf("%s\n",cmd[i].args[j]);
}
return;
default : //for '\0'
return;
}
}
}
void getname(char *name)
{
while(*cmdptr == ' ' || *cmdptr =='\t')
cmdptr++;
while (*cmdptr != '\0'
&& *cmdptr != ' '
&& *cmdptr != '\t'
&& *cmdptr != '>'
&& *cmdptr != '<'
&& *cmdptr != '|'
&& *cmdptr != '&'
&& *cmdptr != '\n')
{
*name++ = *cmdptr++;
}
*name = '\0';
}
int check(const char *p)
{
char *pp;
while(*cmdptr == ' ' || *cmdptr == '\t')
cmdptr++;
pp = cmdptr;
while(*p != '\0' && *p == *pp)
{
p++;
pp++;
}
if(*p =='\0')
{
//printf("%sgggg\n",p);
cmdptr = pp; //指针指向该字符的下个字符,即移过了该字符
return 1; //有该字符,返回1
}
return 0; //没有该字符,返回0
}
int execute_commend()
{
int i;
int fds;
int fd[2];
//pid_t pid;
if(count == 0)
return 0;
if(infile[0] != '\0')
{
if(open(infile,O_RDONLY) == -1)
{
printf("no such file.\n");
return 0;
}
else
cmd[0].infd = open(infile,O_RDONLY);
}
if(outfile[0] != '\0')
{
if(flag)
cmd[count-1].outfd = open(outfile,O_WRONLY | O_CREAT
| O_APPEND,0666);
else
cmd[count-1].outfd = open(outfile,O_WRONLY | O_CREAT
| O_TRUNC,0666);
}
//因为后台作业不会调用wait等待子进程推出
//为避免僵死进程,可以忽略SIGCHLD信号
if(bground == 1)
signal(SIGCHLD,SIG_IGN);
else
signal(SIGCHLD,SIG_DFL); //默认处理,接收子进程返回的值
for(i=0;i<count;i++)
{
//如果不是最后一条命令,则需要创建管道
if(i < count-1)
{
pipe(fd);
// printf("fd[1] = %d,fd[0] = %d\n",fd[1],fd[0]);
cmd[i].outfd = fd[1];
cmd[i+1].infd = fd[0];
}
forkexec(i);
// char buf[1024];
// read(cmd[i].outfd,buf,1024);
// printf("%s\n",buf);
if((fds = cmd[i].infd) != 0)
close(fds);
if((fds = cmd[i].outfd) != 1)
close(fds);
/* if(bground == 0)
{
while(wait(NULL) != lastpid)
;
}*/
}
if(bground == 0)
{
while(wait(NULL) != lastpid)
;
}
return 0;
}
void forkexec(int i)
{
pid_t pid;
pid = fork();
if(pid == -1)
ERR_EXIT("fork error");
else if(pid > 0)
lastpid = pid;
else if(pid == 0)
{
//bground=1时,将第一条简单命令的infd重定向
//当第一条命令试图从标准输入获取数据的时候立即返回EOF
if(cmd[i].infd == 0 && bground == 1)
cmd[i].infd = open("/dev/null",O_RDONLY);
//将第一个简单命令进程作为进程组组长
// if(i == 0)
// setpgid(0,0);
//子进程,重定向标准输入输出
if(cmd[i].infd != 0)
{
close(0);
dup(cmd[i].infd);
}
if(cmd[i].outfd != 1)
{
close(1);
dup(cmd[i].outfd);
}
int j;
for(j=3;j<1024; ++j)
close(j);
if(bground == 0)
{
signal(SIGINT,SIG_DFL);
signal(SIGQUIT,SIG_DFL);
}
execvp(cmd[i].args[0],cmd[i].args);
exit(EXIT_FAILURE);
}
}
void print_commend()
{
int i,j;
printf("count = %d\n",count);
if(infile[0] !='\0')
printf("infile = [%s]\n",infile);
if(outfile[0] !='\0')
printf("outfile = [%s]\n",outfile);
for(i=0;i<count;i++)
{
j = 0;
while(cmd[i].args[j] != NULL)
{
printf("[%s,j=%d]",cmd[i].args[j],j);
j++;
}
printf("\n");
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
shell环境.rar (16个子文件)
minishell
builtin.c 678B
def.h 486B
Makefile_parse 518B
parse.o 11KB
main.o 3KB
builtin.o 4KB
init.c 636B
init.o 6KB
externs.h 319B
init.h 71B
Makefile 190B
parse.c 5KB
minishell 21KB
parse.h 131B
main.c 389B
builtin.h 65B
共 16 条
- 1
资源评论
- wuming_4562013-11-23这个代码可以运行,还不错。
- 枸杞泡水2014-01-04还行吧,注释不够详细
- g2721651232014-06-10还不错,可以正常运行
CKJiang
- 粉丝: 14
- 资源: 8
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功