[
  {
    "path": ".gitignore",
    "content": "*.[oa]\n*~\n"
  },
  {
    "path": "README.md",
    "content": "# Introduction\nA simple simulation of shell in Linux for learning.\nA blog (in Chinese) of introduction and how to build it :http://www.cnblogs.com/wuyuegb2312/p/3399566.html\n\n# Usage\ntype\n\n　　make wshell\n\nfor wshell read input by fgets() or\n\n　　make wshell_r\n　　\n\nfor wshell with readline lib.It need to install libreadline5-dev first.\n\n\n## Attention\n\n　　Because of the lack of support for regular expressions , typing file's names such as \"*.c\" are not support.\n　　\n\n# File List\n### wshell.c\n　　main program\n\n### type_prompt.c\n　　print out the prompt of wshell including path,hostname\n\n### read_command.c\n　　read command input, and analyse the command and parameter(s).\n\n### builtin_command.c\n　　support some built-in command,such as exit,quit,about, and cd.\n\n### test.c\n　　a test program, helloworld, which can be executed in wshell.\n\n### parsing.c\n　　analyses user's input line and tell them to wshell.\n　　\n# Update log\n\n## 2015\n### 11.08\n    -Make the README.md be a real markdown file.\n    -Bug fix1:\n        Redirection operator \">>\" will append a file, not trunc it to 0-size.\nAs noted by [caiminfeng](http://www.cnblogs.com/caiminfeng/) .\n\n    -Bug fix2:\n        When inputed \"cd\", it would be core dump before.\nAs noted by [guokesong](https://github.com/guokesong) in [issues2](https://github.com/vvy/wshell/issues/2).\n\n## 2014\n### 05.14\n\n    -Bug fix:\n\n        In readline mode, the spaces alloced by readline() was freed only once.Now they are all freed in the end of read_command().\n\nAs noted by [xingfe123](http://home.cnblogs.com/u/614123/) \n\n \n\n### 04.14\n\n    -Bug fix:\n\n        Add handler of SIGCHLD. Earlier wshell would ignore the zombie process in background.\n\n        The handler only process the background process whose pid are saved in a array.\n\n     -Adjust some indents, although they are not errors.\n\n \n\n## 2013\n\n### 12.8\n\n    -Bug fix:\n\n        Output redirect function was not completed. '>' still is for make new file,but '>>' append to any file now.\n\n \n\n### 11.3\n    -Implemented a simple parsing function parse() to analyses the user input.\n    -Support I/O redirect, background running, and pipe. \n    -Bug fix:\n        Typing ctrl+d will normal exit wshell. before, segment fault when using readline lib.\n\n        Lack of free() somewhere, which may lead to memory leak.\n\n \n\n### 11.1\n    -Implemented some builtin command,such as exit/quit, about, and, cd.\n    -Bug fix:\n        Never free the memory of command and parameters before, which may cause memory leak.\n        To solve it, read_command() has been rewrited, and is more like the one in Linux.\n    -Rewrite read_command():\n        There is no need to malloc for command and parameters any more.\n        All these just are pointers now.\n    -Supply two versions:\n        Using readline lib and not.the former need installing readline lib.\n        Type \"make wshell_r\" to make the former,and \"make wshell\" for another.\n\n\n### 10.31\n    -Use execvp() instead of execve() to handle with commands like ls.\n    -Detect whether the shell is executed as root by geteuid()\n    -Bug fix:\n        execv()'s arg[0] usually is the name of command without path.\n        earlier version is not correct.\n    -Plan to do:\n        a built-in cd command.\n\n##10.16\n    -A shell with basic function: get input and execute the test program(hello world).\n\n\n# 简介\n为了学习而编写的Linux下shell的简单模拟实现。\n介绍如何一步一步编写该程序的博客：http://www.cnblogs.com/wuyuegb2312/p/3399566.html\n\n# 用法\n输入\n\n　　make wshell\n\n构建使用fgets()接收命令的wshell\n\n　　make wshell_r\n　　\n\n构建使用readline接收命令的wshell。需要安装libreadline5-dev或其他类似的库。\n\n\n## 注意\n\n　　由于不支持正则表达式，含有通配符如\"*.c\"这样的文件名是不支持的。\n    不存在的命令不会提示。\n　　\n\n# 文件列表\n### wshell.c\n　　主程序\n\n### type_prompt.c\n　　拼接当前路径、主机名的提示符。\n\n### read_command.c\n　　读取输入的命令，并分离出其中的参数。\n\n### builtin_command.c\n　　提供对基本内建命令的支持，含exit、quit、about、cd等。\n\n### test.c\n　　用来在wshell中执行的测试程序。\n\n### parsing.c\n　　分析用户输入（是否使用了管道、重定向、后台执行等）。\n　　\n# 更新记录\n\n## 2015\n### 11.08\n    -让README.md成为了真正的markdown文件\n    -调整部分缩进\n    -Bug修复1:\n        重定向符\">>\"将正确地在文件存在时做追加，而非把它变成0大小的文件。\n感谢[caiminfeng](http://www.cnblogs.com/caiminfeng/) 的指出。\n\n    -Bug修复2:\n       当输入不带参数的 `cd`时，会导致崩溃。\n感谢 [guokesong](https://github.com/guokesong) 在 [issues2](https://github.com/vvy/wshell/issues/2) 指出。\n\n## 2014\n### 05.14\n\n    -Bug修复:\n\n        在readline模式下, readline()申请的内存不会被释放。\n\n感谢[xingfe123](http://home.cnblogs.com/u/614123/) 指出。\n\n \n\n### 04.14\n\n    -Bug修复:\n\n        增加了SIGCHLD信号的处理器。较早版本的wshell不会处理后台的僵尸进程。\n\n        但是该处理器只会处理事先保存了pid的子进程。\n\n    -调整了不会导致错误的缩进。\n\n \n\n## 2013\n\n### 12.08\n\n    -Bug修复:\n\n        输出重定向尚未完成。 '>' 仍然会创建新文件，但是'>>'会往文件末尾追加。\n\n \n\n### 11.03\n    -实现了用于分析用户输入的函数parse()。\n    -支持输入输出重定向、管道、后台运行。\n    -Bug修复:\n        输入ctrl+d会正常退出wshell了。此前，在使用readline库时会段错误。\n\n        由于某处缺少free(), 会内存泄漏。\n\n \n\n### 11.01\n    -实现了一些内建命令，包括`exit` 、 `quit` 、 `about` 、 `cd`。\n    -Bug修复:\n        从未释放命令和参数的空间，导致内存泄漏。\n        重写read_command()以解决这个问题，现在的行为更像Linux的了。\n    -重写read_command():\n        现在没必要为command和parameter释放内存了，它们只是指针。\n    -提供了两个版本:\n        使用readline库和不使用的。前者需要事先安装这个库。\n        输入\"make wshell_r\"可以生成前者，而\"make wshell\"会生成后者。\n\n\n### 10.31\n    -用execvp()代替execve()处理 `ls` 这种命令。\n    -通过geteuid()判断shell是否执行在root用户下。\n    -Bug修复:\n        execv()'的arg[0]一般是不含路径的命令，上一个版本处理有误。\n    -下一步计划:\n        支持内建命令 `cd`。\n\n##10.16\n    -一个具有基本功能的shell: 获取输入并执行测试程序(hello world)."
  },
  {
    "path": "builtin_command.c",
    "content": "/*\n * =====================================================================================\n *       Filename:  builtin_command.c\n *    Description:  \n *        Version:  1.0\n *        Created:  2013.11.01 15h31m28s\n *         Author:  wuyue (wy), vvuyve@gmail.com\n *        Company:  UESTC\n * =====================================================================================\n */\n#include \"wshell.h\"\n\nint builtin_command(char *command, char **parameters)\n{\n\textern struct passwd *pwd;\n    if(strcmp(command,\"exit\")==0 || strcmp(command,\"quit\")==0)\n        exit(0);\n    else if(strcmp(command,\"about\") == 0)\n    {\n        printf(\"This is a simulation of shell (bash) in Linux.\\n\");\n        return 1;\n    }\n    else if(strcmp(command,\"cd\")==0)\n    {\n        char *cd_path = NULL;\n\n        if(parameters[1] == NULL)\n        //make \"cd\" to \"cd ..\" as in bash\n        {\n            parameters[1] = malloc(3 * sizeof(char));\n            parameters[1][0]= '.';\n            parameters[1][1]= '.';\n            parameters[1][2]= '\\0';\n        }\n        if(parameters[1][0] == '~')\n        {\n            cd_path = malloc(strlen(pwd->pw_dir)+strlen(parameters[1]));\n            //'~' makes length 1 more,but instead of '\\0'\n            if(cd_path == NULL)\n            {\n                printf(\"cd:malloc failed.\\n\");\n            }\n            strcpy(cd_path,pwd->pw_dir);\n            strncpy(cd_path+strlen(pwd->pw_dir),parameters[1]+1,strlen(parameters[1]));\n\t\t\t//printf(\"path with ~:\\n%s\\n\",cd_path);\n        }\n        else\n        {\n            cd_path = malloc(strlen(parameters[1]+1));\n            if(cd_path == NULL)\n            {\n                printf(\"cd:malloc failed.\\n\");\n            }\n            strcpy(cd_path,parameters[1]);\n        }\n        if(chdir(cd_path)!= 0)\n            printf(\"-wshell: cd: %s:%s\\n\",cd_path,strerror(errno));\n        free(cd_path);\n    }\n    return 0;\n}\n"
  },
  {
    "path": "makefile",
    "content": "wshell: wshell.h wshell.c type_prompt.c read_command.c builtin_command.c parsing.c test\n\tgcc wshell.c type_prompt.c read_command.c builtin_command.c parsing.c -o wshell\n\nwshell_r: wshell.h wshell.c type_prompt.c read_command.c builtin_command.c parsing.c test\n\tgcc wshell.c type_prompt.c read_command.c builtin_command.c parsing.c -o wshell -D READLINE_ON -I /usr/include -lreadline -ltermcap\n\ntest: test.c\n\tgcc test.c -o test\n\nclean:\n\trm -f wshell test\n"
  },
  {
    "path": "parsing.c",
    "content": "/*\n * =====================================================================================\n *       Filename:  parsing.c\n *    Description:  \n *        Version:  1.0\n *        Created:  2013.11.02 15h44min23s\n *         Author:  wuyue (wy), vvuyve@gmail.com\n *        Company:  UESTC\n * =====================================================================================\n */\n#include \"wshell.h\"\n\nint parse_info_init(struct parse_info *info)\n{\n    info->flag = 0;\n    info->in_file = NULL;\n    info->out_file = NULL;\n    info->command2 = NULL;\n    info->parameters2 = NULL;\n    return 0;\n}\n\nint parsing(char **parameters,int ParaNum,struct parse_info *info)\n{\n    int i;\n    parse_info_init(info);\n    if(strcmp(parameters[ParaNum-1],\"&\") ==0)\n    {\n        info->flag |= BACKGROUND;\n        parameters[ParaNum-1] = NULL;\n        ParaNum--;\n    }\n    for(i=0;i<ParaNum;)\n    {\n        if(strcmp(parameters[i],\"<<\")==0 || strcmp(parameters[i],\"<\")==0)\n        {\n            info->flag |= IN_REDIRECT;\n            info->in_file = parameters[i+1];\n            parameters[i] = NULL;\n            i+=2;\n        }\n        else if(strcmp(parameters[i],\">\")==0)\n        {\n            info->flag |= OUT_REDIRECT;\n            info->out_file = parameters[i+1];\n            parameters[i] = NULL;\n            i+=2;\n        }\n        else if(strcmp(parameters[i],\">>\")==0)\n        {\n            info->flag |= OUT_REDIRECT_APPEND;\n            info->out_file = parameters[i+1];\n            parameters[i] = NULL;\n            i+=2;\n        }\n        else if(strcmp(parameters[i],\"|\")==0)\n        {\n            char* pCh;\n            info->flag |= IS_PIPED;\n            parameters[i] = NULL;\n            info->command2 = parameters[i+1];\n            info->parameters2 = &parameters[i+1];\n            for(pCh = info->parameters2[0]+strlen(info->parameters2[0]);\n                    pCh!=&(info->parameters2[0][0]) && *pCh!='/';pCh--)\n                ;\n            if(*pCh == '/')\n                pCh++;\n            info->parameters2[0] = pCh;\n            break;\n        }\n        else\n            i++;\n    }\n#ifdef DEBUG\n\tprintf(\"\\nbackground:%s\\n\",info->flag&BACKGROUND?\"yes\":\"no\");\n\tprintf(\"in redirect:\");\n\tinfo->flag&IN_REDIRECT?printf(\"yes,file:%s\\n\",info->in_file):printf(\"no\\n\");\n\tprintf(\"out redirect:\");\n\tinfo->flag&OUT_REDIRECT?printf(\"yes,file:%s\\n\",info->out_file):printf(\"no\\n\");\n\tprintf(\"pipe:\");\n\tinfo->flag&IS_PIPED?printf(\"yes,command:%s %s %s\\n\",info->command2,info->parameters2[0],info->parameters2[1]):printf(\"no\\n\");\n#endif\n    return 1;\n}\n"
  },
  {
    "path": "read_command.c",
    "content": "/*\n * =====================================================================================\n *       Filename:  read_command.c\n *    Description:  \n *        Version:  1.0\n *        Created:  2013.10.21 14h12min24s\n *         Author:  wuyue (wy), vvuyve@gmail.com\n *        Company:  UESTC\n * =====================================================================================\n */\n#include \"wshell.h\"\n#ifdef READLINE_ON\n#include <readline/readline.h>\n#include <readline/history.h>\n#endif\n\n//return value: number of parameters\n//0 represents only command without any parameters\n//-1 represents wrong input\nint read_command(char **command,char **parameters,char *prompt)\n{\n#ifdef READLINE_ON\n    free(buffer);\n    buffer = readline(prompt);\n    if(feof(stdin)) {\n        printf(\"\\n\");\n        exit(0);\n    }\n\n#else\n    printf(\"%s\",prompt);\n    char* Res_fgets = fgets(buffer,MAXLINE,stdin);\n    if(Res_fgets == NULL)\n    {\n        printf(\"\\n\");\n        exit(0);\n    }\t\t\n#endif\n\n    if(buffer[0] == '\\0')\n        return -1;\n    char *pStart,*pEnd;\n    int count = 0;\n    int isFinished = 0;\n    pStart = pEnd = buffer;\n    while(isFinished == 0)\n    {\n        while((*pEnd == ' ' && *pStart == ' ') || (*pEnd == '\\t' && *pStart == '\\t'))\n        {\n            pStart++;\n            pEnd++;\n        }\n\n        if(*pEnd == '\\0' || *pEnd == '\\n')\n        {\n            if(count == 0)\n                return -1;\n            break;\n        }\n\n        while(*pEnd != ' ' && *pEnd != '\\0' && *pEnd != '\\n')\n            pEnd++;\n\n\n        if(count == 0)\n        {\n            char *p = pEnd;\n            *command = pStart;\n            while(p!=pStart && *p !='/')\n                p--;\n            if(*p == '/')\n                p++;\n            //else //p==pStart\n            parameters[0] = p;\n            count += 2;\n#ifdef DEBUG\n            printf(\"\\ncommand:%s\\n\",*command);\n#endif\n        }\n        else if(count <= MAXARG)\n        {\n            parameters[count-1] = pStart;\n            count++;\n        }\n        else\n        {\n            break;\n        }\n\n        if(*pEnd == '\\0' || *pEnd == '\\n')\n        {\n            *pEnd = '\\0';\n            isFinished = 1;\n        }\n        else\n        {\n            *pEnd = '\\0';\n            pEnd++;\n\t\t\tpStart = pEnd;\n        }\n    }\n\n    parameters[count-1] = NULL;\n\n#ifdef DEBUG\n    /*input analysis*/\n    printf(\"input analysis:\\n\");\n    printf(\"pathname:[%s]\\ncommand:[%s]\\nparameters:\\n\",*command,parameters[0]);\n    int i;\n    for(i=0;i<count-1;i++)\n        printf(\"[%s]\\n\",parameters[i]);\n#endif\n\n    return count;\n}\n"
  },
  {
    "path": "test.c",
    "content": "/*\n * =====================================================================================\n *       Filename:  test.c\n *    Description:  \n *        Version:  1.0\n *        Created:  2013.10.16 20h40m39s\n *         Author:  wuyue (wy), vvuyve@gmail.com\n *        Company:  UESTC\n * =====================================================================================\n */\n#include <stdio.h>\nint main()\n{\n    printf(\"Hello world!\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "type_prompt.c",
    "content": "/*\n * =====================================================================================\n *       Filename:  type_prompt.c\n *    Description:  \n *        Version:  1.0\n *        Created:  2013.10.16 20h18min28s\n *         Author:  wuyue (wy), vvuyve@gmail.com\n *        Company:  UESTC\n * =====================================================================================\n */\n//#include <sys/utsname.h>\n#include \"wshell.h\"\nconst int max_name_len = 256;\nconst int max_path_len = 1024;\n\nvoid type_prompt(char *prompt)\n{\n    extern struct passwd *pwd;\n    char hostname[max_name_len];\n    char pathname[max_path_len];\n    int length;\n    pwd = getpwuid(getuid());\n    getcwd(pathname,max_path_len);\n    if(gethostname(hostname,max_name_len)==0)\n        sprintf(prompt,\"[Wshell]%s@%s:\",pwd->pw_name,hostname);\n    else\n        sprintf(prompt,\"[Wshell]%s@unknown:\",pwd->pw_name);\n    //printf(\"pathname: %s,length:%d\\npw_dir:%s,length:%d\\n\",\n    //pathname,strlen(pathname),pwd->pw_dir,strlen(pwd->pw_dir));\n    length = strlen(prompt);\n    if(strlen(pathname) < strlen(pwd->pw_dir) || \n            strncmp(pathname,pwd->pw_dir,strlen(pwd->pw_dir))!=0)\n        sprintf(prompt+length,\"%s\",pathname);\n    else\n        sprintf(prompt+length,\"~%s\",pathname+strlen(pwd->pw_dir));\n    length = strlen(prompt);\n    if(geteuid()==0)\n        sprintf(prompt+length,\"#\");\n    else\n        sprintf(prompt+length,\"$\");\n    return;\n}\n\n//int main()\n//{\n//    type_prompt();\n//    return 0;\n//}\n"
  },
  {
    "path": "wshell.c",
    "content": "/*\n * =====================================================================================\n *       Filename:  wshell.c\n *    Description:  \n *        Version:  1.0\n *        Created:  2013.10.16 17h12min19s\n *         Author:  wuyue (wy), vvuyve@gmail.com\n *        Company:  UESTC\n * =====================================================================================\n */\n#include \"wshell.h\"\n#define TRUE 1\n#define MAXPIDTABLE 1024\n\npid_t BPTable[MAXPIDTABLE];\n\nvoid sig_handler(int sig)\n{\n    pid_t pid;\n    int i;\n    for(i=0;i<MAXPIDTABLE;i++)\n        if(BPTable[i] != 0) //only handler the background processes\n        {\n            pid = waitpid(BPTable[i],NULL,WNOHANG);\n            if(pid > 0)\n            {\n                printf(\"process %d exited.\\n\",pid);\n                BPTable[i] = 0; //clear\n            }\n            else if(pid < 0)\n            {\n\tif(errno != ECHILD)\n                    perror(\"waitpid error\");\n            }\n            //else:do nothing.\n            //Not background processses has their waitpid() in wshell.\n         }\n    return;\n}\n\nvoid proc(void)\n{\n    int status,i;\n    char *command = NULL;\n    char **parameters;\n    int ParaNum;\n    char prompt[MAX_PROMPT];\n    struct parse_info info;\n    pid_t ChdPid,ChdPid2;\n    parameters = malloc(sizeof(char *)*(MAXARG+2));\n    buffer = malloc(sizeof(char) * MAXLINE);\n    if(parameters == NULL || buffer == NULL)\n    {\n        printf(\"Wshell error:malloc failed.\\n\");\n        return;\n    }\n\t//arg[0] is command\n\t//arg[MAXARG+1] is NULL\n\n    if(signal(SIGCHLD,sig_handler) == SIG_ERR)\n        perror(\"signal() error\");\n\n    while(TRUE)\n    {\n        int pipe_fd[2],in_fd,out_fd;\n        type_prompt(prompt);\n        ParaNum = read_command(&command,parameters,prompt);\n        if(-1 == ParaNum)\n            continue;\n        ParaNum--;//count of units in buffer\n        parsing(parameters,ParaNum,&info);\n        if(builtin_command(command,parameters))\n            continue;\n        if(info.flag & IS_PIPED) //command2 is not null\n        {                \n            if(pipe(pipe_fd)<0)\n            {\n                printf(\"Wshell error:pipe failed.\\n\");\n                exit(0);\n            }\n        }  \n        if((ChdPid = fork())!=0) //wshell\n        {\n            if(info.flag & IS_PIPED)\n            {\n                if((ChdPid2=fork()) == 0) //command2\n                {\n                    close(pipe_fd[1]);\n                    close(fileno(stdin)); \n                    dup2(pipe_fd[0], fileno(stdin));\n                    close(pipe_fd[0]); \n                    execvp(info.command2,info.parameters2);\n                }\n                else\n                {\n                    close(pipe_fd[0]);\n                    close(pipe_fd[1]);\n                    waitpid(ChdPid2,&status,0); //wait command2\n                }\n            }\n\n            if(info.flag & BACKGROUND)\n            {\n                printf(\"Child pid:%u\\n\",ChdPid);\n                int i;\n                for(i=0;i<MAXPIDTABLE;i++)\n                    if(BPTable[i]==0)\n                        BPTable[i] = ChdPid; //register a background process\n                if(i==MAXPIDTABLE)\n                    perror(\"Too much background processes\\nThere will be zombine process\");                    \n            }\n            else\n            {          \n                waitpid(ChdPid,&status,0);//wait command1\n            } \n        }\n        else //command1\n        {\n\t\t\t\n            if(info.flag & IS_PIPED) //command2 is not null\n            {                \n                if(!(info.flag & OUT_REDIRECT) && !(info.flag & OUT_REDIRECT_APPEND)) // ONLY PIPED\n\t           {\n                    close(pipe_fd[0]);\n                    close(fileno(stdout)); \n                    dup2(pipe_fd[1], fileno(stdout));\n                    close(pipe_fd[1]);\n                }\n                else //OUT_REDIRECT and PIPED\n\t           {\n                    close(pipe_fd[0]);\n                    close(pipe_fd[1]);//send a EOF to command2\n                    if(info.flag & OUT_REDIRECT)\n    \t               out_fd = open(info.out_file, O_WRONLY|O_CREAT|O_TRUNC, 0666);\n                    else\n    \t               out_fd = open(info.out_file, O_WRONLY|O_APPEND|O_TRUNC, 0666);\n                    close(fileno(stdout)); \n                    dup2(out_fd, fileno(stdout));\n                    close(out_fd);\t        \n                }\n            }\n            else\n            {\n                if(info.flag & OUT_REDIRECT) // OUT_REDIRECT WITHOUT PIPE\n\t           {\n                    out_fd = open(info.out_file, O_WRONLY|O_CREAT|O_TRUNC, 0666);\n                    close(fileno(stdout)); \n                    dup2(out_fd, fileno(stdout));\n                    close(out_fd);\n                }\n                if(info.flag & OUT_REDIRECT_APPEND) // OUT_REDIRECT_APPEND WITHOUT PIPE\n\t           {\n                    out_fd = open(info.out_file, O_WRONLY|O_CREAT|O_APPEND, 0666);\n                    close(fileno(stdout)); \n                    dup2(out_fd, fileno(stdout));\n                    close(out_fd);\n                }\n            }\n            \n            if(info.flag & IN_REDIRECT)\n            {\n                in_fd = open(info.in_file, O_CREAT |O_RDONLY, 0666);\n                close(fileno(stdin)); \n                dup2(in_fd, fileno(stdin));\n                close(in_fd); \n            }\n            execvp(command,parameters);\n        }\n    }\n    free(parameters);\n\tfree(buffer);\n}\n\nint main() {\n    int i;\n    //init the BPTable\n    for(i=0;i<MAXPIDTABLE;i++)\n        BPTable[i] = 0;\n    proc();\n    return 0;\n}\n"
  },
  {
    "path": "wshell.h",
    "content": "/*\n * =====================================================================================\n *       Filename:  wshell.h\n *    Description:  \n *        Version:  1.0\n *        Created:  2013.10.16 20h15min26s\n *         Author:  wuyue (wy), vvuyve@gmail.com\n *        Company:  UESTC\n * =====================================================================================\n */\n#include <unistd.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <fcntl.h> \n#include <errno.h>\n#include <pwd.h>\n#include <signal.h>\n#include <sys/wait.h>\n#include <sys/types.h>\n#include <sys/stat.h> \n#define MAX_PROMPT 1024\n#define MAXLINE 4096 //the length of all args is ARG_MAX\n#define MAXARG 20\n\nstruct parse_info;\nstruct passwd *pwd;\nchar *buffer;\n\nvoid type_prompt(char*);\nint read_command(char **,char **,char*);\nint builtin_command(char *,char **);\nint parsing(char **,int,struct parse_info *);\nvoid proc(void);\nvoid sig_handler(int sig);\n\n\n\n#ifndef STRUCT_PARSE_INFO\n#define STRUCT_PARSE_INFO\n#define BACKGROUND \t\t\t1\n#define IN_REDIRECT \t\t2\n#define OUT_REDIRECT \t\t4\n#define OUT_REDIRECT_APPEND\t8\n#define IS_PIPED \t\t\t16\nstruct parse_info \n{\n    int flag;\n    char* in_file;\n    char* out_file;\n    char* command2;\n\tchar** parameters2;\n};\n#endif\n"
  }
]