⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parsecmd.l

📁 一个简单的shell
💻 L
字号:
%{#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/stat.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>extern char buf[];extern char* myptr;extern char* mylim;extern void display_history_list();extern void history_finish();static int my_yyinput(char* buf, int max);static int file_exist(const char* file, char* buffer);static void free_resource();static int do_exit(int, char**);static int do_export(int, char**);static int do_echo(int, char**);static int do_cd(int, char**);static int do_history(int, char**);static void add_arg(const char* xarg);static void add_simple_arg(const char* xarg);static void reset_args();static void do_list_cmd();static int do_pipe_cmd(int argc, char** argv);static int do_simple_cmd(int argc, char** argv, int prefd[], int postfd[]);#undef 	YY_INPUT#define YY_INPUT(b, r, ms) (r = my_yyinput(b, ms))char* argbuf[200];int argcnt = 0;typedef int (*buildin_cmd_handle)(int, char**);typedef struct{	const char* cmd;	buildin_cmd_handle handle;} CMD_ENTRY;const CMD_ENTRY buildin_cmd_table[] = {	{"exit", 	do_exit},	{"cd", 		do_cd},	{"echo", 	do_echo},	{"export", 	do_export},	{"history", do_history},	{0, 0}};%}%x		QUOTE%x		SINGQUOTEblank	[ \t]%%"\""			{BEGIN QUOTE;}<QUOTE>[^\n"]+	{add_arg(yytext);}<QUOTE>"\""		{BEGIN 0;}<QUOTE>\n		{BEGIN 0; do_list_cmd(); reset_args();}";"				{add_simple_arg(yytext);}">"				{add_simple_arg(yytext);}"<"				{add_simple_arg(yytext);}"|"				{add_simple_arg(yytext);}[^ \t\n|<>;"]+	{add_arg(yytext);}\n				{do_list_cmd(); reset_args();}.				;%%static buildin_cmd_handle get_cmd_handle(const char* cmd){	int i = 0;	while(buildin_cmd_table[i].cmd) {		if(strcmp(buildin_cmd_table[i].cmd, cmd) == 0)			return buildin_cmd_table[i].handle;		i++;	}	return 0;}static void free_resource(){	reset_args();}static int do_exit(int argc, char** argv){	int val = 0;	if(argc > 1)		val = atoi(argv[1]);	free_resource();	history_finish();	exit(val);	return 0;}static int do_cd(int argc, char** argv){	char* dir;	char cwd[100];	extern char lastdir[];	if(argc == 1) {		if(!(dir = getenv("HOME"))) {			printf("cd: %s\n", strerror(errno));			return -1;		}	} else if(argc == 2) {		if(strcmp(argv[1], "-") == 0) {			dir = lastdir;		} else if(strcmp(argv[1], "~") == 0) {			if(!(dir = getenv("HOME"))) {				printf("cd: %s\n", strerror(errno));				return -1;			}		} else			dir = argv[1];	} else {		printf("Usage: cd [dir]\n");		return -1;	}	getcwd(cwd, 99); 	if(chdir(dir) == -1) {		printf("cd: %s\n", strerror(errno));		return -1;	}	strcpy(lastdir, cwd);	return 0;}static int do_export(int argc, char** argv){	int i = 1;	char* p;	while(argv[i]) {		if((p = strchr(argv[i], '='))) {			*p = 0;			if(strpbrk(argv[i], "~`!@#$%^&*()-_+=|\\{}[];:'\"<>,.?/")) {				*p = '=';				printf("export: %s: not a valid indentifier\n", argv[i]);				i++;				continue;			} 			if(setenv(argv[i], p+1, 1) == -1) 				printf("export: %s\n", strerror(errno));			*p = '=';		}		i++;			}	return 0;}static int do_echo(int argc, char** argv){	int i = 1;	int j;	int argn = 0;	int arge = 0;	if(argv[1]) {		if(strcmp(argv[1], "-n") == 0) {			argn = 1;			i = 2;		} else if(strcmp(argv[1], "-e") == 0) {			arge = 1;			i = 2;		} else if((strcmp(argv[1], "-ne") == 0) || (strcmp(argv[1], "-en") == 0)) {			argn = arge = 1;			i = 2;		}	}	j = i;	while(argv[i]) {		if(i > j)			printf(" %s", argv[i]);		else 			printf("%s", argv[i]);		i++;	}	if(argn == 0)		printf("\n");		return 0;}int do_history(int argc, char** argv){	display_history_list();		return 0;}static void add_simple_arg(const char* arg){	argbuf[argcnt] = (char*)malloc(strlen(arg)+1);	strcpy(argbuf[argcnt], arg);	argcnt++;	argbuf[argcnt] = 0;}// $HOME// $$// $HOME$// $HOME$HOMEstatic void add_arg(const char* xarg){	char* arg;	char buf[200];	char xbuf[200];	int i,j,k;	int len = strlen(xarg);		k = 0;	for(i = 0; i < len; i++) {		if(xarg[i] == '$') {			if(xarg[i+1] == '$') {//$$,get pid				int pid = getpid();				sprintf(buf+k, "%d", pid);				k = strlen(buf);				i++;			} else if(xarg[i+1] == 0){//$ and end				buf[k] = '$';				k++;				break;			} else {//$HOME or $HOME$OTHER				for(j = i+1; j < len; j++) {					if(xarg[j] == '$') 						break;					xbuf[j-i-1] = xarg[j];				}				xbuf[j-i-1] = 0;				i = j-1;				if((arg = getenv(xbuf))) {					strcpy(buf+k, arg);					k += strlen(arg);				}			}					} else {			buf[k] = xarg[i];			k++; 		}	}	buf[k] = 0;	if(k > 0)		add_simple_arg(buf);}static int file_exist(const char* file, char* buffer){	int i = 0;	const char* p;	const char* path;	path = getenv("PATH");	p = path;	while(*p != 0) {		if(*p != ':')			buffer[i++] = *p;		else {			buffer[i++] = '/';			buffer[i] = 0;			strcat(buffer, file);			if(access(buffer, F_OK) == 0)				return 1;			i = 0;		}		p++;	}	return 0;}static void do_list_cmd(){	int i = 0;	int j = 0;	char* p;	while(argbuf[i]) {		if(strcmp(argbuf[i], ";") == 0) {//	 ;			p = argbuf[i];			argbuf[i] = 0;			do_pipe_cmd(i-j, argbuf+j);			argbuf[i] = p;			j = ++i;		} else			i++;	}	do_pipe_cmd(i-j, argbuf+j);}static int do_pipe_cmd(int argc, char** argv){	int i = 0;	int j = 0;	int prepipe = 0;	int prefd[2];	int postfd[2];	char* p;	while(argv[i]) {		if(strcmp(argv[i], "|") == 0) { // pipe			p = argv[i];			argv[i] = 0;			pipe(postfd); 		//create the post pipe			//be sure not close pipe in, otherwise whenever father write to this pipe,			//cause a Broken pipe.			//close(postfd[0]);	//father close pipe in						if(prepipe)					do_simple_cmd(i-j, argv+j, prefd, postfd);			else				do_simple_cmd(i-j, argv+j, 0, postfd);			argv[i] = p;			prepipe = 1;			prefd[0] = postfd[0];			prefd[1] = postfd[1];			j = ++i;		} else			i++;	}	if(prepipe)		do_simple_cmd(i-j, argv+j, prefd, 0);	else 		do_simple_cmd(i-j, argv+j, 0, 0);	return 0;}static int predo_for_redirect(int argc, char** argv, int* re){	int i;	int redirect = 0;		for(i = 1; i < argc; i++) {		if(strcmp(argv[i], "<") == 0) {			redirect = 1;			argv[i] = 0;			break;		} else if(strcmp(argv[i], ">") == 0) {			redirect = 2;			argv[i] = 0;			break;			}	}	if(redirect) {// need redirect stdin or stdout		if(argv[i+1]) {			int fd;			if(redirect == 2) {				if((fd = open(argv[i+1], O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) == -1) {					fprintf(stderr, "Open out %s failed\n", argv[i+1]);					return 1;				}				dup2(fd, STDOUT_FILENO);			} else {//redirect == 1				if((fd = open(argv[i+1], O_RDONLY, S_IRUSR|S_IWUSR)) == -1) {					fprintf(stderr, "Open in %s failed\n", argv[i+1]);					return 1;				}				dup2(fd, STDIN_FILENO);			}		} else {			fprintf(stderr, "Bad redirect, need more arg\n");			return 1;		}	}	if(re)		*re = redirect;	return 0;}static int do_simple_cmd(int argc, char** argv, int prefd[], int postfd[]){	int pid;	int status;	buildin_cmd_handle hd;	if(argc == 0)		return 0;	if(prefd == 0 && postfd == 0) {	// a very simple buitin command, not have pre and post pipe, father should do the	// builtin command itself.		if((hd = get_cmd_handle(argv[0]))) {			if(predo_for_redirect(argc, argv, 0))				return 1;			(*hd)(argc, argv);			return 0;		}	}		if((pid = fork()) == 0) {//child		// reset the signal INT handle to default		int redirect = 0;		signal(SIGINT, SIG_DFL);		if(predo_for_redirect(argc, argv, &redirect))			exit(1);				if(redirect != 1 && prefd) {//has a pre pipe, redirect stdin			close(prefd[1]);			if(prefd[0] != STDIN_FILENO) {	//			fprintf(stderr, "redirect stdin\n");				dup2(prefd[0], STDIN_FILENO);				close(prefd[0]);			}		}		if(redirect != 2 && postfd) {//has a post pipe, redirect stdout			close(postfd[0]);			if(postfd[1] != STDOUT_FILENO) {	//			fprintf(stderr, "redirect stdout\n");				dup2(postfd[1], STDOUT_FILENO);				close(postfd[1]);			}		}		if((hd = get_cmd_handle(argv[0]))) {			(*hd)(argc, argv);			exit(0);		}		char buffer[100];		if(file_exist(argv[0], buffer)) {	//		fprintf(stderr, "exec command %s\n", buffer);			execv(buffer, argv);		}		else {			fprintf(stderr, "-msh: %s: command not found\n", argv[0]);			exit(0);		}	}	waitpid(pid, &status, 0);	if(postfd) { // no		close(postfd[1]); // must close this fd here.	}	return 0;}static void reset_args(){	int i;	for(i = 0; i < argcnt; i++) {		free(argbuf[i]);		argbuf[i] = 0;	}	argcnt = 0;}static int my_yyinput(char* buf, int max){	int n;	n = (max < (mylim-myptr)) ? max : (mylim-myptr);	if(n > 0) {		memcpy(buf, myptr, n);		myptr += n;	}	return n;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -