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

📄 myshell.c

📁 用C++编写的Linux myshell
💻 C
字号:
#include<stdio.h>#include<signal.h>#include<unistd.h>#include<string>#include<iostream>#include<sys/types.h>#include<sys/wait.h>#include<fcntl.h>#include<sys/stat.h>using namespace std;void do_cd(char command[]){	int r=0;	char path[50];	strcpy(path,command+3); //取目录	if(path!=NULL)		r=chdir(path);	else cout<<"change dir error.\n";	if(r<0) cout<<"change dir error.\n";}void ex(char command[])  //以整行命令作为参数的exec函数,支持任意多个参数{	char c[50];	memset(c,'\0',50);   //初始化c	char *argv[50];   int i=0,j=0,k=0,s=0,f=0;	while(i<strlen(command))  //对输入的命令根据空格分割	{		if(s==0){              //去掉命令开头的空格			while(command[i]==' '){i++;continue;}  			s=1;		}		if(command[i]!=' '){c[k]=command[i];f=0;}		else{			if(f==1){i++;continue;}         //忽略连续空格			else{				argv[j]=(char *)malloc(50);  //分配内存空间				strcpy(argv[j],c);				j++;k=-1;				memset(c,'\0',50);           //初始化c;				f=1;			}		}		i++;k++;	}	if(f==0) //结尾没有空格	{		argv[j]=(char *)malloc(50);		strcpy(argv[j],c);		argv[j+1]=NULL;	}else argv[j]=NULL;  //结尾有空格	execvp(*argv,argv);	perror(command);     //命令输入错误处理	_exit(0);}void exr(char command[],int f,int p[])  //能处理重定向符号和管道符号的ex函数{	char *txt;	int w;	pid_t pid;	pid = fork();	if(pid==-1)                	   printf("failure!\n ");	else if(pid==0)          	{ 		if(f==1)		{			close(p[0]);            //关闭管道的读端			close(1);                    //关闭标准输出端子			dup(p[1]);				  //将stdout重定向到管道写端		} 		if(f==2)		{			close(p[1]);            //关闭管道的写端			close(0);                    //关闭标准输入端子			dup(p[0]);				  //将stdout重定向到管道读端		}                  		if(txt=strstr(command,"<"))     //如果有<则直接去掉		{			char in_file[20];			*txt='\0';			while(*(txt+1)==' ') txt++;  //去掉‘<’后的空格			char *s;			if(s=strstr(txt+1," ")) *s='\0';						strcpy(in_file,txt+1);			if(s!=NULL) strcat(command,s+1);			int fid2;			if((fid2=open(in_file,O_RDONLY))<0)    //打开用户指定文件,只读打开				fprintf(stderr,"%s ","open file error");			close(0);                 //关闭标准输入端子			dup(fid2);                //将文件in_file作为输入设备			close(fid2);              //关闭该文件的连接,释放资源锁让程序来对此 文件进行读写		}		if(txt=strstr(command,">"))		{			char out_file[20];			*(txt-1)='\0';               //将后面重定向部分的命令去掉			while(*(txt+1)==' ') txt++;  //去掉‘>’后的空格			strcpy(out_file,txt+1);      //取文件名			int filedes1;         if((filedes1=open(out_file,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))<0) //打开一个名为out_file的文件,只写打开,不存在则创建,文件表记为可读写        		fprintf(stderr,"%s ","open(creat) file error");    		close(1);         //关闭标准输出端子   		dup(filedes1);    //将文件out_file作为输出设备    		close(filedes1);  //关闭该文件的连接,释放资源锁让程序来对此 文件进行读写		}		ex(command);	}else{		wait(&w);		if(f==1)close(p[1]); //关闭管道写端		if(f==2)close(p[0]); //关闭管道读端	}}int main(int argc,char* argv[],char* env[]){   	cout<<"********************************************************\n";	cout<<"*                       myshell                        *\n";	cout<<"*                     write by hcy                     *\n";	cout<<"********************************************************\n";	char command[100];	pid_t pid;	int w;	while(1)	{		char *p,*t;		p=get_current_dir_name();   //取当前的工作目录		char path[100];		while(t=strstr(p,"/")){*t='0';strcpy(path,t+1);}  //取工作文件夹		cout<<"[hcy@localhost "<<path<<"]# ";             //打印提示信息  		cin.getline(command,100); 		if(strcmp(command,"show")==0)		{ 		              		pid = fork();            //克隆自己的进程给子进程, 其实就是copy堆栈区和数据给子进程   		if(pid==-1)              //返回为-1为失败  	   		printf("failure!\n ");			else if(pid==0)          //因为为了区分父进程与子进程区别,pid不同,子进程中的pid为0			{    	   	cout<<"The child process id is "<<getpid()<<endl;     //子进程的pid   	   	cout<<"The parent process id is "<<getppid()<<endl;   //父进程的pid				int i;				cout<<"\ncommand:";				for(i=0;i<argc;i++)   //输出命令行				{					cout<<argv[i]<<" ";				}				i=0;				cout<<"\n\n↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓环境变量↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓\n\n";     				while(env[i])  //输出所有环境变量				{					cout<<env[i]<<" ";					i++;				}				cout<<endl;				exit(0);       	  		}			else wait(&w);		}		else if(strcmp(command,"quit")==0)  //退出程序		{			cout<<"*************************quit***************************\n";			_exit(0);		} 		else if(strstr(command,"cd")==command) do_cd(command);  //如果命令以cd开头则执行do_cd      else               		{			char *txt;			int p[2];			if(txt=strstr(command,"|"))  //如果有管道符号|,则将前面的命令的输出保存在tmp中作为后面命令的输入			{				pipe(p);             //创建管道				char cmd1[100],cmd2[100];				*txt='\0';           //分割两条命令				strcpy(cmd1,command);				strcpy(cmd2,txt+1); 				exr(cmd1,1,p);               //执行前命令				exr(cmd2,2,p);               //执行后命令						}			else exr(command,0,p);		}	}}

⌨️ 快捷键说明

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