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

📄 shell.c

📁 一个简单的shell,实现4个功能: (1)cd (2)pwd (3)pid (4)logout
💻 C
字号:
#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <unistd.h>#include <fcntl.h>#include <stdlib.h>#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include "ourhdr.h"
#include <string.h>
#include <dirent.h>

void sep_argu(int *argc,char *argv[],char *buf,int *numofcmd,int *cmd_offset);
int cmd_test(char *argv);
void my_chdir(char *path,char *argv[],int len,int start);
int in_cmd=-1;
int out_cmd=-1;
char *innercmd[MAXLINE]={"cd\0","logout\0","pwd\0","pid\0",NULL};
char *outercmd[MAXLINE]={NULL};
char ptr[MAXLINE];/*命令行数据结构*/typedef struct tagCommand{	char **argv;//参数	int argc;//文件名}COMD;void processcmd(COMD* pC, char* pBuf){	char *pchr = NULL;	char *pBegin = pBuf;	int n=1;	while ((pchr=strchr(pBegin, ' '))!=NULL)	{		pBegin=pchr+1;		while ((*pBegin)==' ')			pBegin++;		n++;	}	pC->argv=(char**)malloc(sizeof(char*)*(n+1));	pchr=NULL;	pBegin=pBuf;	int num=0;	while ((pchr=strchr(pBegin, ' '))!=NULL)	{		pC->argv[num]=(char*)malloc(sizeof(char)*(pchr-pBegin+1));		strncpy(pC->argv[num], pBegin, pchr-pBegin);		(pC->argv[num])[pchr-pBegin]='\0';		pBegin=pchr+1;		while ((*pBegin)==' ')			pBegin++;		num++;	}	pC->argv[num]=(char*)malloc(sizeof(char)*strlen(pBegin));	strcpy(pC->argv[num], pBegin);	num++;	pC->argv[num]=NULL;	pC->argc=num;}void fexec(COMD* pC, char* pBuf){		char *pchr = NULL;	char *paths = getenv("PATH");	char *pBegin = paths;	char **pDirs = NULL;	if ((pC->argv[0])[0]=='.' || (pC->argv[0])[0]=='/')	{		strcpy(pBuf, pC->argv[0]);		return;	}		int n=1;	while ((pchr=strchr(pBegin, ':'))!=NULL)	{		pBegin=pchr+1;		n++;	}	pDirs=(char**)malloc(sizeof(char*)*n);	pchr=NULL;	pBegin=paths;	int num=0;	while ((pchr=strchr(pBegin, ':'))!=NULL)	{		pDirs[num]=(char*)malloc(sizeof(char)*(pchr-pBegin+1));		strncpy(pDirs[num], pBegin, pchr-pBegin);		(pDirs[num])[pchr-pBegin]='\0';		pBegin=pchr+1;		num++;	}	pDirs[num]=(char*)malloc(sizeof(char)*strlen(pBegin));	strcpy(pDirs[num], pBegin);	num++;	int i=0;	for (i=0; i<num; i++)	{		strcpy(pBuf, pDirs[i]);		if ((pDirs[i])[strlen(pDirs[i])-1]!='/')			strcat(pBuf, "/");		strcat(pBuf, pC->argv[0]);		if (access(pBuf, F_OK)==0)		{			for (n=0; n<num; n++)			{				free(pDirs[n]);				pDirs[n]=NULL;			}			free(pDirs);			pDirs=NULL;			return;		}	}	for (n=0; n<num; n++)	{		free(pDirs[n]);		pDirs[n]=NULL;	}	free(pDirs);	pDirs=NULL;	pBuf[0]='\0';}int isbackgr(COMD* pC){	if ((pC->argv[pC->argc-1])[strlen(pC->argv[pC->argc-1])-1]=='&')	{		if (strlen(pC->argv[pC->argc-1])-1==0)		{			free(pC->argv[pC->argc-1]);			pC->argv[pC->argc-1]=NULL;			pC->argc--;		}		else			(pC->argv[pC->argc-1])[strlen(pC->argv[pC->argc-1])-1]='\0';		return 1;	}	return 0;}void redirinout(COMD* pC, int* piid){	int i=0;	int j=0;	for (i=0; i<pC->argc; i++)	{		if (pC->argv[i]!=NULL && (pC->argv[i])[0]=='<')		{			int fid;			char rname[100];			if ((pC->argv[i])[1]=='\0')			{				strcpy(rname, pC->argv[i+1]);				fid = open(rname, O_RDONLY);				if (fid==-1)				{					printf("Error opening input file!\n");					exit(2);				}				close(0);				dup(fid);				close(fid);				(pC->argv[i])[0]='\0';				(pC->argv[i+1])[0]='\0';				free(pC->argv[i]);				pC->argv[i]=NULL;				free(pC->argv[i+1]);				pC->argv[i+1]=NULL;			}			else				if ((pC->argv[i])[1]=='/' && (pC->argv[i])[2]=='\0')				{					close(0);					dup(piid[0]);					close(piid[1]);					(pC->argv[i])[0]='\0';					free(pC->argv[i]);					pC->argv[i]=NULL;				}				else				{					strcpy(rname, (pC->argv[i])+1);					fid = open(rname, O_RDONLY);					if (fid==-1)					{						printf("Error opening input file!\n");						exit(2);					}					close(0);					dup(fid);					close(fid);					(pC->argv[i])[0]='\0';					free(pC->argv[i]);					pC->argv[i]=NULL;				}		}		if (pC->argv[i]!=NULL && (pC->argv[i])[0]=='>')		{			int fid;			char rname[100];			if ((pC->argv[i])[1]=='\0')			{				strcpy(rname, pC->argv[i+1]);				fid = open(rname, O_WRONLY | O_CREAT);				if (fid==-1)				{					printf("Error accessing output file!\n");					exit(2);				}				close(1);				dup(fid);				close(fid);				(pC->argv[i])[0]='\0';				(pC->argv[i+1])[0]='\0';				free(pC->argv[i]);				pC->argv[i]=NULL;				free(pC->argv[i+1]);				pC->argv[i+1]=NULL;			}			else				if ((pC->argv[i])[1]=='/' && (pC->argv[i])[2]=='\0')				{					close(1);					dup(piid[1]);					close(piid[0]);					(pC->argv[i])[0]='\0';					free(pC->argv[i]);					pC->argv[i]=NULL;				}				else				{					strcpy(rname, (pC->argv[i])+1);					fid = open(rname, O_WRONLY | O_CREAT);					if (fid==-1)					{						printf("Error accessing output file!\n");						exit(2);					}					close(1);					dup(fid);					close(fid);					(pC->argv[i])[0]='\0';					free(pC->argv[i]);					pC->argv[i]=NULL;				}		}	}	for (i=0; i<pC->argc; i++)	{		int move=0;		for (j=0; j<pC->argc; j++)		{			if ((pC->argv[j])==NULL)			{				pC->argv[j]=pC->argv[j+1];				move=1;			}			if (move)			{				pC->argv[j]=pC->argv[j+1];			}		}	}}int* pipeinout(COMD* pC){	int i=0;	int* pipeid = NULL;	for (i=0; i<pC->argc; i++)	{		if (((pC->argv[i])[0]=='<' || (pC->argv[i])[0]=='>') && (pC->argv[i])[1]=='/')		{			pipeid = (int*)malloc(2*sizeof(int));			if (pipe(pipeid) == -1)			{				printf("Pipe creation error!\n");				exit(3);			}		}	}	return pipeid;}char* procpipe(char* pBuf){	char *pSecProc = NULL;	char *pchr = NULL;	if ((pchr=strchr(pBuf, '|'))!=NULL)	{		pchr--;		while ((*pchr)==' ')			pchr--;		pchr++;		(*pchr)='\0';		pchr++;		while ((*pchr)==' ')			pchr++;		if ((*pchr)=='|')			pchr++;		while ((*pchr)==' ')			pchr++;		pSecProc=(char*)malloc(sizeof(char)*1024);		strcpy(pSecProc, pchr);	}	return pSecProc;}int main(char *env[]){	char buf[MAXLINE];
	
	COMD execmd;
	COMD* pSecCom = NULL;
	execmd.argv=NULL;
	execmd.argc=0;
    char tmp;
	char *pSecP = NULL;
	char *argv[MAXLINE];
    char hostname[20];
    char path[MAXLINE]="~\0";
    char str[MAXLINE];
    int status;
    int i=0,j=0;
    int argc=0;
    int numofcmd=0;
    int cmd_offset[MAXLINE];
    int len=0;
    int ischdir=0;
    struct passwd *p1;
	pid_t pid;
    for(j=0;j<MAXLINE;j++)
	{
		argv[j]=(char *)malloc(sizeof(char)*MAXLINE);	
    }
    getcwd(ptr,MAXLINE);
    p1=getpwuid(getuid());
    gethostname(hostname,20);
    while(hostname[i]!='.')i++;
    hostname[i]='\0';
    printf("\n[%s@%s ~] shell:",p1->pw_name,hostname);
    while(1)
	{  
		while(fgets(buf,MAXLINE,stdin)!=NULL)
		{
			buf[strlen(buf)-1]='\0';
			sep_argu(&argc,argv,buf,&numofcmd,cmd_offset);
            for(i=0;i<numofcmd;i++)
			{
                in_cmd=-1;out_cmd=-1;
				cmd_test(argv[cmd_offset[i]]);
				ischdir=0;
				j=i+1;
				len=cmd_offset[j]-cmd_offset[i];
				if(in_cmd>=0)		/*call system function */
				{				
					switch(in_cmd)
					{
					case 0: 
						my_chdir(path,argv,len,cmd_offset[i]);
						ischdir=1;
						break;	
					case 1: 
						exit(0);
					case 2: 
						getcwd(str,MAXLINE);
						printf("%s\n",str);
						break;
					case 3: 
						printf("%d\n",getpid());
						break;
					default: 	
						break;	
					}
				}                   
				if(out_cmd>=0)			/*fork() and then call exec() to execue program*/
				{	
					if((pid=fork())<0)
						printf("fork error");
					else if(pid==0)
					{
						printf("exec");
						exit(0);
					}	
					if(waitpid(pid,&status,0)!=pid)
						printf("waitpid error");
				}		
				printf("\n[%s@%s %s] shell:",p1->pw_name,hostname,path);
			}
		}
		{
			do
			{
				if (execmd.argv!=NULL)
				{
					for (; execmd.argc>0; execmd.argc--)
					{
						free(execmd.argv[execmd.argc-1]);
						execmd.argv[execmd.argc-1]=NULL;
					}
					free(execmd.argv);
					execmd.argv=NULL;
				}
				printf(">");
				int i=0;
				while((tmp=getchar())!='\n')
				{
					buf[i]=tmp;
					i++;
				}
				buf[i]='\0';
				pSecP = procpipe(buf);
				if (pSecP!=NULL)
				{
					char *ad=" >/";
					strcat(buf, ad);
					char *ad2=" </";
					strcat(pSecP, ad2);
				}
				processcmd(&execmd, buf);
				if (i==0)
					continue;
				fexec(&execmd, buf);
				int bg=isbackgr(&execmd);
				if (pSecP!=NULL)
				{
					pSecCom = (COMD*)malloc(sizeof(COMD));
					pSecCom->argv=NULL;
					pSecCom->argc=0;
					processcmd(pSecCom, pSecP);
					fexec(pSecCom, pSecP);
					bg=isbackgr(pSecCom);
				}
				
				int* pipeID = NULL;
				if (strcmp(execmd.argv[0], "logout")!=0)
				{
					if (strcmp(buf, "")==0)
					{
						printf("Bad command or file name.\n");
						continue;
					}
					/*ready to execute*/
					int npid;
					pipeID = pipeinout(&execmd);
					if ((npid=fork())==0)
					{
						errno=0;
						redirinout(&execmd, pipeID);
						int status = execve(buf, execmd.argv, env);
						printf("Error executing specified file. (#%d)\n", errno);
						return 1;
					}
					else
					{
						if (pSecP==NULL)
						{
							if (!bg)
							{
								int status;
								wait(&status);
							}
							else
							{
								printf("Program ID#%d executed successful at background.\n", npid);
							}
						}
					}
					if (pSecP!=NULL)
					{
						if ((npid=fork())==0)
						{
							errno=0;
							redirinout(pSecCom, pipeID);
							int status = execve(pSecP, pSecCom->argv, env);
							printf("Error executing specified file. (#%d)\n", errno);
							return 1;
						}
						else
						{
							close(pipeID[0]);
							close(pipeID[1]);
							if (!bg)
							{
								int status;
								wait(&status);
							}
							else
							{
								printf("Program ID#%d executed successful at background.\n", npid);
							}
						}
					}
				}
				if (pSecP!=NULL)
				{
					sleep(1);
					free(pipeID);
					pipeID=NULL;
					free(pSecP);
					pSecP=NULL;
					free(pSecCom);
					pSecCom=NULL;
				}
	}while(strcmp(execmd.argv[0], "logout")!=0);
	
	if (execmd.argv!=NULL)
	{
		for (; execmd.argc>0; execmd.argc--)
		{
			free(execmd.argv[execmd.argc-1]);
			execmd.argv[execmd.argc-1]=NULL;
		}
		free(execmd.argv);
		execmd.argv=NULL;
	}
	}
	}
}

void sep_argu(int *argc,char *argv[],char *buf,int *numofcmd,int *cmd_offset)
{
	int i=0,j=0,p=0,k=0,num=1;
	cmd_offset[p++]=0;
	while(buf[j]!='\0')
	{
		if(buf[j]!=' '&&buf[j]==';')
		{
			++num;
			cmd_offset[p++]=i+1;
			strncpy(argv[i],buf+k,j-k);
			argv[i][j-k]='\0';
			i++;
			k=j+1;
		}	
		else if(buf[j]==' ')
		{
			strncpy(argv[i],buf+k,j-k);
			argv[i][j-k]='\0';
			i++;		
			k=j+1;
		}
		j++;  
	}
	strncpy(argv[i],buf+k,j-k+1);
	*argc=i;			/*num of all argument is stored into argc*/
	*numofcmd=num;			/*num of command is stored into numofcmd*/
}

int cmd_test(char *argv)
{
	int i=0;
	while(innercmd[i]!=NULL)
	{
		if(!strcmp(argv,innercmd[i])){in_cmd=i;return 0;}
		i++;
	}
	i=0;
	while(outercmd[i]!=NULL)
	{
		if(!strcmp(argv,outercmd[i++]))
		{
			out_cmd=i;
			return 0;
		}
	}
	return 1;
}

void my_chdir(char *path,char *argv[],int len,int start)
{
	int i=0;
	char *s="~\0";
	if(len>2)printf("the argument of command %s is unavailable",argv[start]);
	else {
		if(chdir(argv[++start])<0)
		{
			printf("chdir failed");
		}
					
		if(strcmp(ptr,getcwd(path,MAXLINE))==0)
			strcpy(path,s);
		else
		{
			i=strlen(path);
			if(i==1)strcpy(path,"/\0");
			else
			{
				while(path[i]!='/')i--;
				strncpy(path,path+i+1,strlen(path)-i+1);
			}
		}		
	}
}	

⌨️ 快捷键说明

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