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

📄 ush.c

📁 一个在LINUX下运行的shell程序
💻 C
字号:
#include "ush.h"#include "ush-env.h"#include "ush-parse.h"#include "ush-prt.h"#include "ush-sig.h"#include "errno.h"#define MAXARG 20#define MAXFNAME 500#define MAXWORD  100#define BADFD -2static char* completeDir(char* path);static int invoke(int argc, char *argv[], int srcfd, char *srcfile,int dstfd, char *dstfile, BOOLEAN append,BOOLEAN bckgrnd);static void redirect(int srcfd, char *srcfile, int dstfd, char *dstfile,BOOLEAN append, BOOLEAN bckgrnd);static void waitfor(int pid);static BOOLEAN builtin(int argc, char *argv[], int srcfd, int dstfd);/////////////////////////////////////////////////////////////////// you should better not modify this function 						     ///////////////////////////////////////////////////////////////////int main(){				/* real shell */    char *prompt;    int pid, fd;    TOKEN term;    static TOKEN command();    static void waitfor();    ignoresig();    if (!EVinit())	fatal("can't initialize environment");    if ((prompt = EVget("PS2")) == NULL)	prompt = ">";    printf("%s", prompt);    while (1) {	term = command(&pid, FALSE, NULL);	if (term != T_AMP && pid != 0)	    waitfor(pid);	if (term == T_NL)	    printf("%s", prompt);	for (fd = 3; fd < 20; fd++)	    (void) close(fd);	/* ignore error */    }    return (0);}static TOKEN command(int *waitpid, BOOLEAN makepipe, int *pipefdp){				/* do simple cmd */    TOKEN token, term;    int argc, srcfd, dstfd, pid, pfd[2],fd;    char *argv[MAXARG + 1], srcfile[MAXFNAME], dstfile[MAXFNAME];    char word[MAXWORD], *malloc();    BOOLEAN append;       argc = 0;    srcfd = 0;    dstfd = 1;    while (1) {       	switch (token = gettoken(word)) {	case T_WORD:	    if (argc == MAXARG) {		fprintf(stderr, "Too many args\n");		break;	    }	    if ((argv[argc] = malloc(strlen(word) + 1)) == NULL) {		fprintf(stderr, "Out of argmemory\n");		break;	    }	    strcpy(argv[argc], word);	    argc++;	    continue;	case T_LT:	    if (makepipe) {		fprintf(stderr, "Extra<\n");		break;	    }	    if (gettoken(srcfile) != T_WORD) {		fprintf(stderr, "Illegal <\n");		break;	    }        //将重定向的fd读入,若是std I/O,则赋为BADFD        if((fd=atoi(word))!=0)            srcfd = fd;        else            srcfd = BADFD;	    continue;	case T_GT:        if (dstfd != 1) {		fprintf(stderr, "Extra > or >> \n");		break;	    }	    if (gettoken(dstfile) != T_WORD) {		fprintf(stderr, "Illegal > or >> \n");		break;	    }        //将重定向的fd读入,若是std I/O,则赋为BADFD        if((fd=atoi(word))!=0)            dstfd = fd;        else            dstfd = BADFD;	    	    append = FALSE;	    continue;	case T_GTGT:        if (dstfd != 1) {		fprintf(stderr, "Extra > or >>\n");		break;	    }	    if (gettoken(dstfile) != T_WORD) {		fprintf(stderr, "Illegal >or >>\n");		break;	    }        //将重定向的fd读入,若是std I/O,则赋为BADFD	    if((fd=atoi(word))!=0)            dstfd = fd;        else            dstfd = BADFD;	 	    append = TRUE;	    continue;	case T_BAR:	case T_AMP:	case T_SEMI:	case T_NL:	    argv[argc] = NULL;                if (token == T_BAR) {		if (dstfd != 1) {		    fprintf(stderr, "> or >> conflicts with |\n");		    break;		}		term = command(waitpid, TRUE, &dstfd);	    }	    else		term = token;	    if (makepipe) {		if (pipe(pfd) == -1)		    syserr("pipe");		*pipefdp = pfd[1];		srcfd = pfd[0];	    }                //处理$name的情况,将所有$开头的参数替换为同名环境变量的值        EVsubstitute(argc,argv);           if (term == T_AMP)            pid = invoke(argc, argv, srcfd,srcfile, dstfd, dstfile, append, TRUE);        else            pid = invoke(argc, argv, srcfd, srcfile, dstfd, dstfile,append, FALSE);	    if (token != T_BAR)		*waitpid = pid;	    if (argc == 0 && (token != T_NL || srcfd > 1))		fprintf(stderr, "Missing command\n");	    while (--argc >= 0)		free(argv[argc]);	    return (term);	case T_EOF:	    exit(0);	}    }}//////////////////////////////////////////////////////////// You must implement the invoke function 					//// return the process id									     ///////////////////////////////////////////////////////////static int invoke(int argc, char *argv[], int srcfd, char *srcfile,		  int dstfd, char *dstfile, BOOLEAN append,		  BOOLEAN bckgrnd)			      /* invoke simple command */{        if (argc == 0)	    return 0;    if(!builtin(argc,argv,srcfd,dstfd))    {        pid_t pid;        if ((pid = fork())<0)        {            syserror("fork failed.");        }        else if (pid == 0)        {            // 子进程,调用execvp.            // 如果需要重定向则调用重定向的方法            if(srcfd!=0||dstfd!=1)                redirect(srcfd,srcfile,dstfd,dstfile,append,bckgrnd);            if((execvp(completeDir(argv[0]),argv))<0)            {                syserror("execvp failed.");            }        }        else        {            // 父进程,只需返回pid,因为waitpid已经在main()中实现                        return pid;        }    }    else        return 0;    return 0;}//////////////////////////////////////////////////////////// You must implement the redirect function 					///////////////////////////////////////////////////////////static void redirect(int srcfd, char *srcfile, int dstfd, char *dstfile,		     BOOLEAN append, BOOLEAN bckgrnd){				/* I/O redirection */     int fd;     // 输入重定向     if(srcfd!=0)     {               fd = open(completeDir(srcfile),O_RDONLY|O_CREAT,0777);         if(fd>0)             if(srcfd<0)                 dup2(fd,STDIN_FILENO);             else                 dup2(fd,srcfd);         else            syserror("Open input file failed");         }     // 输出重定向     if(dstfd!=1)     {               if(append)             fd = open(completeDir(dstfile),O_WRONLY|O_CREAT|O_APPEND,0777);         else             fd = open(completeDir(dstfile),O_WRONLY|O_CREAT|O_TRUNC,0777);         if(fd>0)            if(dstfd<0)                dup2(fd,STDOUT_FILENO);            else                dup2(fd,dstfd);         else            syserror("Open output file failed");        }}static void waitfor(int pid){				/* wait for child */    int wpid, status;    while ((wpid = wait(&status)) != pid && wpid != -1)	statusprt(wpid, status);    if (wpid == pid)	statusprt(0, status);}//////////////////////////////////////////////////////////// You must implement the builtin function 	to do				//// the builtin command. 									//// Note :: the builtin command should not invoke the linux standard //// function.eg, cd should not invoke chdir						//// return true if a builtin command ,false other wise				////////////////////////////////////////////////////////////static BOOLEAN builtin(int argc, char *argv[], int srcfd, int dstfd)			      /* do built-in */{    char pwd[4] = "PWD";    int i,isPath;    char* dir;    DIR *testDir;    if (!strcmp(argv[0],"cd"))    {        // 如果只有cd,没有参数,则默认为HOME的目录。        if(argc==1)        {             dir = EVget("HOME");            EVset("PWD",dir);        }        else        {            if(strcmp(argv[1],".."))            {                dir = completeDir(argv[1]);                if(opendir(dir)!=NULL)                    EVset("PWD",dir);                                else                    syserror("cd command failed");               }            else            {                dir = EVget("PWD");                isPath = 0;                for(i = strlen(dir); i>0; i--)                {                    if(dir[i]=='/')                        break;                }                if(i!=0)                    dir[i] = '\0';                else                                    dir = "/\0";                                if(opendir(dir)!=NULL)                    EVset("PWD",dir);                                else                    syserror("cd command failed");               }        }        return TRUE;    }    else if (!strcmp(argv[0],"echo"))    {        for( i = 1; i < argc; i++)        {            printf("%s ", argv[i]);        }        printf("\n");        return TRUE;    }    else if (!strcmp(argv[0],"exit"))    {        exit(0);    }    else if (!strcmp(argv[0],"export"))    {        export(argc, argv);        return TRUE;    }    else if (!strcmp(argv[0],"pwd"))    {        printf("%s\n",EVget(pwd));        return TRUE;            }    else if (!strcmp(argv[0],"set"))    {        set(argc,argv);        return TRUE;    }    else if (!strcmp(argv[0],"unset"))    {        unset(argc,argv);        return TRUE;    }    else if (strchr(argv[0], '='))    {         asg(argc, argv);         return TRUE;    }               return FALSE;}// 将相对路径根据pwd的值转化为绝对路径(cd的实现需要)static char* completeDir(char* path){    char* comPath;    char* cd;    int totalLength;    if(path[0]=='/')        return path;   // 绝对路径,不需要转换。    else    {        cd = EVget("PWD");        totalLength = strlen(path) + strlen(cd);                // pwd + 相对路径 = 绝对路径        comPath = malloc(totalLength);        strcpy(comPath,cd);        strcat(comPath,"/");        strcat(comPath,path);        return comPath;    }}

⌨️ 快捷键说明

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