📄 shell.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 + -