linux 编写自己的shell

// 已实现的功能:
// 1.普通的shell命令 例如:ls -la; vim smsh3.c
// 2.变量存储与替换   例如:set 显示所有的变量
//                         a=x;  x=who am i 添加变量或者修改变量的值
//                         echo $x;  $x     变量替换
// 3.简单的if..then ..fi 语句


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <ctype.h>

#define DFL_PROMPT ">"
#define MAXARGNUM  50
#define MAXSTRLEN  100
#define MAXVARS 100
#define FALSE   0
#define TRUE    1


extern char **environ;
static char **table;
static int  cur_len = 0;


enum states {NEUTRAL,WANT_THEN,THEN_BLOCK};
enum results {SUCCESS, FAIL};
static int if_state  = NEUTRAL;
static int if_result = SUCCESS;
static int last_stat = 0;

int    AddVar(char*);  // 添加,修改变量
int    FindVar(char*); // 变量替换
void   Load();         // 下载系统变量
void   List();         // 列出所有变量
int    Check(char*);   // 检测变量名是否合格

char*  VarReplace(char* ); // 变量替换
int    buildin_command(char*sbuf); // 内建命令
char** splitline(char*);   // 分拆字符串
void   setup();            // 设置
int    is_control_command(char*); 
int    do_control_command(char **);
int    ok_to_execute();
int    process(char**);
int    syn_err(char*);
void   fatal(char*,char*,int);
int    execute(char**);
void   freelist(char **);
char   *next_cmd(char *,FILE*);
void   *emalloc(size_t n);
void   *erealloc(void *p,size_t n);

// 主函数
int main(){
	char *cmdline = (char*)malloc(sizeof(char)*BUFSIZ);
	char **arglist;
	setup();
	Load();
	printf(">");
	while(fgets(cmdline,BUFSIZ,stdin)){
		if((arglist = splitline(cmdline)) != NULL){
			process(arglist);
		}
		printf(">");
	}
	return 0;
}

// 分拆字符串
char** splitline(char* strbuf){
	char **arglist=(char**)malloc(sizeof(char*)*MAXARGNUM);
	char *wordbuf = (char*)malloc(sizeof(char)*MAXSTRLEN);
	int wordlen=0,wordsnum=0;
	int start = 0,i = 0;
	int len = strlen(strbuf);
	while(isspace(strbuf[start])) start++;
	
	for(i = start;i<len;i++){
		if(isspace(strbuf[i])){
			wordbuf[wordlen]='\0';
			if(wordbuf[0] == '$'){
				wordbuf = VarReplace(wordbuf);
			}
			int l = strlen(wordbuf);
			arglist[wordsnum]=(char*)malloc(sizeof(char)*(l+1));
			strcpy(arglist[wordsnum],wordbuf);
			wordsnum++;
			wordlen = 0;
		}
		else wordbuf[wordlen++] = strbuf[i];
	}
	return arglist;
}

void setup(){
	signal(SIGINT,SIG_IGN);
	signal(SIGQUIT,SIG_IGN);
}

int process(char **args){
	int rv = 0;
	if(args[0] == NULL)
		rv = 0;
	else if(is_control_command(args[0]))
		rv = do_control_command(args);
	else if(ok_to_execute()){
		if(buildin_command(args[0]) ==  0)
			rv = execute(args);
	}
	return rv;
}

int ok_to_execute(){
	int rv = 1;
	if(if_state == WANT_THEN){
		syn_err("then expected");
		rv = 0;
	}
	else if(if_state == THEN_BLOCK && if_result == SUCCESS)
		rv = 1;
	else if(if_state == THEN_BLOCK && if_result == FAIL)
		rv = 0;
	return rv;
}

int is_control_command(char*s){
	return (strcmp(s,"if") == 0 ||
		strcmp(s,"then") == 0 ||
		strcmp(s,"fi") == 0);
}

int do_control_command(char**args){
	char *cmd = args[0];
	int rv = -1;
	if(strcmp(cmd,"if") == 0){
		if(if_state != NEUTRAL)
			rv = syn_err("if unexpected");
		else{
			last_stat = process(args+1);
			if_result = (last_stat == 0 ? SUCCESS : FAIL);
			if_state = WANT_THEN;
			rv = 0;
		}
	}
	else if(strcmp(cmd,"then") == 0){
		if(if_state != WANT_THEN)
			rv = syn_err("then unexpected");
		else{
			if_state = THEN_BLOCK;
			process(args+1);
			rv = 0;
		}
	}
	else if(strcmp(cmd,"fi") == 0){
		if(if_state != THEN_BLOCK)
			rv = syn_err("fi unexpected");
		else{
			if_state = NEUTRAL;
			rv = 0;
		}
	}
	else 
		fatal("internal error processing:",cmd,2);
}

void fatal(char *s1,char *s2,int n){
	fprintf(stderr,"Error:%s,%s\n",s1,s2);
	exit(n);
}

int syn_err(char* msg){
	if_state = NEUTRAL;
	fprintf(stderr,"syntax,error:%s\n",msg);
	return -1;
}

int execute(char *argv[]){
	int pid;
	int child_info = -1;
	if(argv[0] == NULL)
		return 0;
	if(strcmp(argv[0],"exit") == 0) exit(0);
	if((pid = fork()) == -1)
		perror("fork");
	else if(pid == 0){
		signal(SIGINT,SIG_DFL);
		signal(SIGQUIT,SIG_DFL);
		execvp(argv[0],argv);
		perror("cannot execute command");
		exit(1);
	}
	else{
		if(wait(&child_info) == -1)
			perror("wait");
		return child_info;
	}
}

void freelist(char **list){
	char **cp = list;
	while(*cp)
		free(*cp++);
	free(list);
}

char *next_cmd(char *prompt,FILE *fp){
	char *buf;
	int bufspace = 0;
	int pos = 0;
	int c;

	printf("%s",prompt);
	while((c = getc(fp)) != EOF){
		if(pos+1 >= bufspace){
			if(bufspace == 0)
				buf = (char*)emalloc(BUFSIZ);
			else
				buf = (char*)erealloc(buf,bufspace + BUFSIZ);
			bufspace += BUFSIZ;
		}
		if(c == '\n')
			break;
		buf[pos++] = c;
	}
	if(c == EOF && pos == 0) return NULL;
	buf[pos] = '\0';
	return buf;
}

void *emalloc(size_t n){
	void *rv;
	if((rv = malloc(n)) == NULL)
		fatal("out of memory","",1);
	return rv;
}

void *erealloc(void *p,size_t n){
	void *rv;
	if((rv = realloc(p,n)) == NULL)
		fatal("realloc() failed","",1);
	return rv;
}

int buildin_command(char *strbuf){
        if(strcmp(strbuf,"set") == 0){
                List();
                return TRUE;
        }
        else{
                char *cp = strchr(strbuf,'=');
                int rv = FALSE;
                if(cp!=NULL)
                        rv = AddVar(strbuf);
                return rv;
        }
        return FALSE;
}

void Load(){
	int size = 2;
	cur_len = 0;
	table = (char**)calloc(sizeof(char*),MAXVARS);
	for(;environ[cur_len];cur_len++){
	table[cur_len] = (char*)calloc(sizeof(char),strlen(environ[cur_len])+1);
		strcpy(table[cur_len],environ[cur_len]);
		if(cur_len>=MAXVARS)
		table = (char**)realloc(table,sizeof(char)*(MAXVARS)*size++);
	}
}

int AddVar(char *strbuf){
	if(!Check(strbuf)){
		printf("illegal name\n");
		return 0;
	}
	int pos = FindVar(strbuf);
	if(pos >= 0){
		table[pos]=(char*)calloc(sizeof(char),strlen(strbuf)+1);
		strcpy(table[pos],strbuf);
	}
	else{
		int len = strlen(strbuf);
		table[cur_len]=(char*)calloc(sizeof(char*),len+1);
		strcpy(table[cur_len],strbuf);
		cur_len++;
	}
	return 1;
}

int Check(char *name){
	if(isdigit(*name)) return 0;
	return 1;
}

void List(){
	int i;
	for(i=0;i<cur_len;i++)
		printf("%s\n",table[i]);
}

int FindVar(char *name){
	char *str1 = strchr(name,'=');
	*str1='\0';
	int i=0;
	int find=0;
	for(;i<cur_len;i++){
		char *str2=strchr(table[i],'=');
		*str2='\0';
		if(strcmp(name,table[i]) == 0){
			find =1;
			*str2='=';
			break;
		}
		*str2='=';
	}
	*str1='=';
	if(find) return i;
	else return -1;
}

// 变量替换
char*  VarReplace(char* strbuf){
	if(*strbuf == '$'){
		int i;
		for(i=0;i<cur_len;i++){
			char *var = strchr(table[i],'=');
			*var='\0';
			if(strcmp(table[i],strbuf+1) == 0){
				strbuf = (char*)calloc(sizeof(char),strlen(var+1)+2);
				strcpy(strbuf,var+1);
				*var='=';
				break;	
			}
			*var='=';
		}
	}
	return strbuf;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值