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

📄 shell.cpp

📁 这是一个linux下的Shell.有命令历史和命令提示
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// Shell.cpp: implementation of the Shell class.////////////////////////////////////////////////////////////////////////#include "Shell.h"#include "mystring.h"#include "synchro.h"#include <iostream>#include <iomanip>#include <string.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <dirent.h>#include <sys/types.h>#include <sys/stat.h>#include <fnmatch.h>#include <pwd.h>#include <sys/wait.h>#include <fcntl.h>#include <signal.h>using namespace std;static bool showStringArrayFlag = true;	//if more over, the sig_more_over is be called, and sig_more_over will set 							//showStringArrayFlag flase. then showStringArray will stop writing pipestatic void sig_more_over(int);		//the is a function that is called when a SIGPIPE signal is sended by os void sig_more_over(int signo)		{	if(signo == SIGPIPE);		showStringArrayFlag = false;}void showStringArray(char** buf);void showStringArrayWithMore(char** buf);void showStringArray(char** buf){	if(!buf)		return;	showStringArrayFlag = true;	char** temp = buf;	int i = 0;	cout.setf(ios::left, ios::adjustfield);	while(*temp)	{		if(showStringArrayFlag)		{			cout<<setw(40)<<(*temp);			if((++i)%3 == 0)				cout<<endl;			temp++;		}		else			break;	}	cout.unsetf(ios::left);	cout<<endl;}void showStringArrayWithMore(char** buf){	int pid[2];	int fid;							while ( 0 != pipe(pid));	while(-1 == (fid = fork()));	if(fid > 0)	{		int save = close(1);		dup(pid[1]);		close(pid[0]);		signal(SIGPIPE, sig_more_over);		showStringArray(buf);		close(1);		dup(save);		close(pid[1]);		wait(0);	}	else	{		close(pid[1]);		close(0);		dup(pid[0]);		execl("/bin/more", "/bin/more", 0);					//if more is invalid , I'll call less. if less is invalid.		execl("/usr/bin/less", "/usr/bin/less", 0);	}}//the special character string of loverconst char* Shell::spechar = "*?[-]!\\;'\"|&>";//flag for search file//ALL: 		 all file //DIR_:		 directory file//NORMALFILE:	 all file expect directory file 	const int  DIR_ = 4;						const int  NORMALFILE = 8;const int ALL = 0;	static	process_node* head = 0;			//the head point of the process list.static 	process_node* tail = 0;			//the tail point of the process liststatic  process_node* cur  = 0;		    //the current point of the process listvoid sig_chld(int signo){	if(signo == SIGCHLD && head) 	{		int status;		int pid;		pid = wait(&status);		cur = head;		while(cur->pro.id != pid )			cur = cur->next;				if(cur->pipe_read >= 0 && cur->readFlag)			close(cur->pipe_read);		if(cur->pipe_write >= 0 && cur->writeFlag)			close(cur->pipe_write);		process_node* temp;		process_node* temp1;		temp = head;		while(temp != cur)		{			if(temp->pipe_read >= 0 && temp->readFlag)				close(cur->pipe_read);			if(temp->pipe_write >= 0 && temp->writeFlag)				close(temp->pipe_write);			temp1 = temp;			temp = temp->next;			delete temp1;		}			head = cur->next;		if(cur->next == 0)		{			delete cur;			cur = tail = head = 0;		}	}}Shell::Shell () {	input     = 0;	command   = 0;	num_process_background = 0;	struct passwd* p;	p = getpwuid(getuid());		name_user = new char[strlen(p->pw_name) + 1];	strcpy(name_user,p->pw_name) ;	path_userhome = new char[strlen(p->pw_dir)+2];	strcpy(path_userhome,p->pw_dir);	strcat(path_userhome,"/");	//get the  current work directory	//getcwd() need a buffer  and  its size	//If the size is not bigger than the length of the dirctory	//It return zero	//so I must test the length  	int i = 1;	path_cur = (char*)malloc(64*i);	while(!getcwd(path_cur,64*i))	{		path_cur = (char*)realloc(path_cur,++i*(64));	}	path_cur = (char*)realloc(path_cur,strlen(path_cur)+2);	strcat(path_cur,"/");	if(chdir(path_cur))	{		cerr<<"Lover: beyond retrieve error! can't enter the user current directory"<<endl;		exit(1);	}				if(path_cur[0] == '/' && path_cur[1] == 0)	{		path_cur_last[0] = path_cur_last[1] = '/';		path_cur_last[2] = 0; 	}	else	{		for(i = strlen(path_cur) - 2; i >= 0 && path_cur[i] != '/'; i--){};		strcpy(path_cur_last,path_cur + i + 1);	}			char* work = new char[strlen("/bin/lover/") + strlen(name_user) + 1];	strcpy(work, "/bin/lover/");	strcat(work,name_user);		int fid;	if((fid = open(work,O_RDONLY|O_CREAT)) >= 0)	{		char a;		read(fid,&a,1);		tipchar = a;		close(fid);	}	else	{		if(0==getuid())			tipchar = '#';//the default tip char of root user is '#'		else			tipchar = '$';//the default tip char of normal is '$'	}	PATH.overffile(work);	delete work;		work = new char[strlen("/bin/lover/") + strlen(name_user) + strlen("commandbuf") + 1];	strcpy(work, "/bin/lover/");	strcat(work, name_user);	strcat(work, "commandbuf");	commandbuf.initffile(work);				//init commandbuf from the file 	delete work;						save = new struct termios[sizeof(struct termios)];	ioctl(0,TCGETS,save);	TELL_WAIT();	if(!isSynchroAble())	{		cerr<<"lover:  beyond retrieve error! signal system  error"<<endl;		exit(1);	}	setnonor();	signal(SIGCHLD, sig_chld);}//no overShell::~Shell () {	char* work = new char[strlen("/bin/lover/")+strlen(name_user) + 1];	strcpy(work,"/bin/lover/");	strcat(work,name_user);	int fid = open(work,O_WRONLY|O_TRUNC|O_CREAT);	if(fid >= 0)	{		write(fid,&tipchar,1);		write(fid,"\n",1);		PATH.show(fid);		close(fid);	}	delete work;	fresh();}//read from stdinvoid Shell::getinput_stdin(void){	show();	int size,i;	char* work;	char a;	input = 0;	do	{		a = scanf_(this->input,size,false);		if(a == KEYDOWN)		{			work = commandbuf.getCur();			commandbuf.devCur();			if(work != 0)			{				delete input;				input = new char[strlen(work) + 1];				strcpy(input,work);				delete work;				cursormove(KEYLEFT,size);				for(i = 0; i < size; i++)					write(1," ",1);				cursormove(KEYLEFT,size);				cout<<input<<flush;			}		}		else if(a == KEYUP)		{			work = commandbuf.getCur();			commandbuf.incCur();			if(work != 0)			{				delete input;				input = new char[strlen(work) + 1];				strcpy(input, work);				delete work;				cursormove(KEYLEFT,size);				for(i = 0; i < size; i++)					write(1," ",1);				cursormove(KEYLEFT,size);				cout<<input<<flush;			}		}		else if(a == '\t')//tab key		{			char** command_block;			int  num_block;			char echo;			blockchar(input, command_block, num_block);			if(num_block == 0)			{				echo = scanf_(input);				if(echo  == '\t')				{					List<char>* all = findAllExecFile("*");					if(all)					{						int num = all->getNum();						cout<<endl<<"Display all "<<num<<" posibilitees (y or n)"<<flush;						setnoecho();						setnonor();						do						{							echo = getch_();						}while(echo != 'n' &&  echo != 'N' && echo != 'y' &&  echo != 'Y');						if(echo == 'y' || echo == 'Y')						{							char** buf = all->getbuf_subdir();							showStringArrayWithMore(buf);							free__(buf);						}						cout<<endl;						return;					}				}				else					a = '\n';			}			else			{				char* work = new char[strlen(command_block[num_block - 1]) + 2];				strcpy(work, command_block[num_block - 1]);				strcat(work, "*");				free__(command_block, num_block);							List<char>* o;				if(num_block == 1)					o = findAllExecFile(work); 				else					o = findAll(work, ALL, true);				if(o && !(o->isempty()))				{					char* show = o ->getEqu();					if(show)					{						char* work_last = find_dirlast(work);						char* show_last = find_dirlast(show);						int len_s = strlen(show_last);						int len_w = strlen(work_last) - 1;						if(len_s > len_w)						{							cursormove(KEYLEFT, len_w);							cout<<show_last<<flush;//write(1, show_last, len_s);							size += len_s - len_w;							int size_old  = strlen(input); 							input = (char*)realloc(input, size + 1);							strcpy(input + size_old - len_w, show_last); 						}						else						{							char* temp = new char[strlen(input) + 1];							strcpy(temp, input);							char a = scanf_(input, size, false);							if(strcmp(temp, input) == 0 && a == '\t')							{								cout<<endl;								int num = o->getNum();								if(num < 100)								{									char** buf = o->getbuf_subdir();									showStringArray(buf);								}								else								{									cout<<endl<<"Display all "<<num<<" posibilitees (y or n)"<<flush;									setnoecho();									setnonor();									do									{										echo = getch_();									}while(echo != 'n' &&  echo != 'N' && echo != 'y' &&  echo != 'Y');									if(echo == 'y' || echo == 'Y')									{										char** buf = o->getbuf_subdir();										showStringArrayWithMore(buf);									}								}								this->show();								cout<<input<<flush;//write(1,input, strlen(input));							}						}					}				}			}					}	}while(a == KEYDOWN || a == KEYUP || a == '\t');	puts("");	cursormove(KEYLEFT,size);	if(input)		if(strlen(input))			commandbuf.inset(input);}//read  from filevoid Shell::getinput_file(void){	cout<<endl;	input = command_file.getCur();	while(input[0] == '#')	{		delete input;		input = command_file.getCur();	}}void Shell::load(int fid){	command_file.overffile(fid);	command_file.inset("exit", -1); 				//inset the exit command in the tail	command_file.reset();}bool Shell::getcommand(void){	//the start of input to  process.-1 only i = 0  for next input and return false	static int i = 0;					if(i < 0)	{		i = 0;		return false;	}	int start = i;	bool blockflag = (input[i] == '\'')?false:true;	delete command;	while(1)		{		if(input[i] == 0 || (input[i] == ';' && input[i-1] != TRAN_ABLE && blockflag))		{			command = new char[i-start + 1];			strncpy(command,input+start,i - start);			command[i-start] = 0;			//the last command 			//i = -1 to control the next call to return false			if(input[i] == 0)						i = -1;			else			{				i++;				while(input[i] != 0 && (input[i] == ' ' || input[i] == '\t')){i++;};				if(input[i] == 0)    					i = -1;			}			return true; 		}		if(input[i] == '\'' && (i == 0 || input[i-1] != TRAN_ABLE ))			blockflag = !blockflag;		i++;	}}void Shell::command_anslyse(void){	tranable(command);}//return value //0:  is  a normal lvoer command and execute it//1:  not a lover command//2:  exit command//-1: command_block is no validint  Shell::command_lover(char** command_block, int num_block){	if(num_block > 0)	{		char* work;		if(strcmp(command_block[0],"pwd") == 0)		{			_pwd();			return 0;		}		else if(strcmp(command_block[0],"cd") == 0)		{			if(num_block==1)//user only input "cd". enter the user's home diretory				_cd(this->path_userhome);			else			{				work = findFirst(command_block[1],DIR_);				if(!work)					cout<<"lover: cd: "<<command_block[1]<<": no the directory"<<endl;					else				{					_cd(work);					delete work;				}			}			return 0;		}		else if(strcmp(command_block[0],"path")==0)		{			if(num_block == 1)				PATH.show();			else			{				int i;				for(i = 1; i < num_block; i++)				{					if(strcmp(command_block[i],"-a") == 0)					{						for(int j = i+1; j < num_block && command_block[j][0] != '-'; j++)							{							work = findFirst(command_block[j],DIR_);							if(work)							{								addPath(work);								delete work;							}						}					}					if(strcmp(command_block[i],"-s") == 0)					{						for(int j = i+1; j < num_block && command_block[j][0] != '-'; j++)							{							work = findFirst(command_block[j],DIR_);							if(work)

⌨️ 快捷键说明

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