/* ************************************************************************
* Filename: main.c
* Description:
* Version: 1.0
* Created: 2010年09月20日 11时47分58秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME ()
* Company:
* ************************************************************************/
#include"my_shell.h"
char *argv[20];
int main()
{
while(1)
{
char cmd_buf[200]="";
char cur_dir[50];
int i = 0;
getcwd(cmd_buf, sizeof(cmd_buf));
printf("[%s@ %s]$",getenv("USER"),1+strrchr(cmd_buf, '/'));
// printf("[%s@ ]$",getenv("USER"));//打印提示符号。
fgets(cmd_buf, sizeof(cmd_buf), stdin);//获取字符串
cmd_buf[strlen(cmd_buf)-1]='/0'; //把最后一位'/n'变成字符串结束标志'/0'
if(cmd_buf[0]=='/0')
continue; //如果是输入回车的话,继续while循环
argv[i++]=strtok(cmd_buf, " ");
while((argv[i++]=strtok(NULL," "))!=NULL); //字符串按空格切割
//处理内部命令
if(infun(i-1, argv))
continue;
//处理外部命令
if(fork()==0) //创建子进程 调用execvp运行外部命令。
{
i=0;
while(argv[i]!=NULL)
{
if( strcmp(argv[i],"|")==0)
{
my_pipe(i);
}
i++;
}
execvp(argv[0],argv);
printf("command no found!/n");
exit(1);
}
wait(NULL); //父进程等待子进程结束。
/* ************************************************************************
* Filename: my_pipe.c
* Description:
* Version: 1.0
* Created: 2010年09月20日 11时47分58秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME ()
* Company:
* ************************************************************************/
#include "my_shell.h"
void my_pipe(int i)
{
pid_t pid;
int pipe_fd[2];
if(pipe(pipe_fd)<0)
{
perror("pipe");
exit(1);
}
if((pid=fork())==0)
{
argv[i]=NULL;
close(pipe_fd[0]); //关掉管道的读端
close(1);
dup2(pipe_fd[1],1); //标准输出重定向到管道的写端
execvp(argv[0],argv); //
}
else
{
close(pipe_fd[1]);
close(0);
dup2(pipe_fd[0],0); //标准输入重定向到管道的写端
execvp(argv[i+1],argv+i+1); //执行exec函数
perror("execvp more");
}
printf("my_pipe error/n");
}
}
return 0;
}
/* ************************************************************************
* Filename: shell_fun.c
* Description:
* Version: 1.0
* Created: 2010年09月20日 12时36分54秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#include"my_shell.h"
/***************************************************
*函数名 :int cd_fun(int argc, char *argv[])
*功能描述 :cd 命令处理函数
***************************************************/
static char OLD_DIR[MAX_DIR]="";
int cd_fun(int argc, char *argv[])
{
char *dir=argv[1];
char buf[MAX_DIR]="";
if(strcmp(argv[1], "-")==0)
{
strcpy(buf,OLD_DIR);
dir = buf;
}
else if(strcmp(argv[1], "~")==0)
{
dir = getenv("HOME");
}
getcwd(OLD_DIR,MAX_DIR);
chdir(dir); //跳到相应的目录
return 0;
}
/***************************************************
*函数名 :int exit_fun(int argc, char *argv[])
*功能描述 :exit 命令处理函数
***************************************************/
int exit_fun(int argc, char *argv[])
{
printf("ByeBye!/n");
exit(1);
}
/***************************************************
*函数名 :int test1_fun(int argc, char*argv[])
*功能描述 : test 命令处理函数
***************************************************/
int test1_fun(int argc, char*argv[])
{
printf("this is a test fun!/n");
return 0;
}
/***************************************************
*函数指针:用来指向内部命令的处理函数
***************************************************/
typedef int(*cmd_fun_t)(int argc, char *argv[]);
/* 内部命令结构体 */
typedef struct cmd_info
{
char *cmd_name; //内部命令名称
cmd_fun_t fun; //指向内部命令的处理函数
}CMD_STRUCT, pCMD_STRUCT;
/***************************************************
*内部命令及处理函数
***************************************************/
CMD_STRUCT cmd_list[]={
{"cd", cd_fun},
{"exit", exit_fun},
{"test1", test1_fun}
};//定义一个结构体数组。
/***************************************************
* 函数功能:是否为内部命令,如果是内部命令并进行处理
* 参数:
* int argc : 参数个数
* char *argv[]: 指向命令各个字段的指针数组
* 返回:
* 1 : 内部命令
* 0 : 外部命令
*****************************************************/
int infun(int argc, char *argv[])
{
int i = 0;
int cmd_num = sizeof(cmd_list)/sizeof(CMD_STRUCT);//为三
while(i<cmd_num) //从第一个开始比较。
{
//判断是否为内部命令
if(strcmp(cmd_list[i].cmd_name,argv[0])==0)
{ //如果是,则执行相应的处理函数
cmd_list[i].fun(argc, argv);
return 1;
}
i++;
}
return 0;
}
/* ************************************************************************
* Filename: my_pipe.h
* Description:
* Version: 1.0
* Created: 2010年09月20日 12时36分54秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#ifndef __MY_PIPE_INCLUDE_
#define __MY_PIPE_INCLUDE_
extern void my_pipe(int i);
#endif
/* ************************************************************************
* Filename: my_shell.h
* Description:
* Version: 1.0
* Created: 2010年09月20日 12时36分54秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#ifndef __MY_SHELL_INCLUDE_
#define __MY_SHELL_INCLUDE_
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include "my_pipe.h"
#include "shell_fun.h"
extern char *argv[20];
#endif
/* ************************************************************************
* Filename: shell_fun.h
* Description:
* Version: 1.0
* Created: 2010年9月20日 12时37分46秒
* Revision: none
* Compiler: gcc
* Author: YOUR NAME (),
* Company:
* ************************************************************************/
#ifndef _SHELL_FUN_H_
#define _SHELL_FUN_H_
//是否为内部命令,如果是内部命令并进行处理
//参数:
// int argc : 参数个数
// char *argv[]: 指向命令各个字段的指针数组
//返回:1(内部命令) 0(外部命令)
int infun(int argc, char *argv[]);
#define MAX_DIR 100
#endif //_SHELL_FUN_H_
----------------------------------------------Makefile----------------------------------------------------------------------
#README:
#Use "make" to generate "mysh" without debug info
#Use "make dmysh" to generate "dmysh" with debug info
OBJECT=main.o my_pipe.o shell_fun.o
OBJ=main.obj my_pipe.obj shell_fun.obj
CC=gcc
CFLAG=-O2
DEBUG=-DDEBUG -g
mysh: $(OBJECT) my_shell.h
$(CC) $(CFLAG) -o $@ $(OBJECT)
%.o:%.c
$(CC) -c $(CFLAG) -o $@ $<
###########################################
#just for debug
dmysh: $(OBJ) my_shell.h
$(CC) $(CFLAG) $(DEBUG) -o $@ $(OBJ)
%.obj:%.c
$(CC) -c $(CFLAG) $(DEBUG) -o $@ $<
##########################################
.PHONY:clean
clean:
@echo Clean...
@-rm *.o *.obj mysh dmysh -f