如何创建|在一个人自己的壳?

时间:2015-11-13 16:15:42

标签: shell

我实际上在做自己的shell。

我做了以下特殊字符:

int commande(int fin, int fout, char * com, char * param, int * bg){
// execute a command
(ex. ls –l)
int symbole;
char *mot;
pid_t pid;
symbole = parsing();
switch(symbole){
    case 0: // NL
    case 1: // ;
    case 2: // &
    case 3: // <
    case 4: // >
    case 5: // | (Here I have some issues when I try to redirect  the output of a command).

    (correspond à ctrl+D)
    case 10:// Mot
    default:
}
return;
}

但是当我有两个跟随自己的指令时,我有一些问题要在输出管道时重定向输出“|”。事实上,我已经尝试了以下有效的操作:

>myShell ps > fich
>myShell ls -l | wc -l 

但不是这一个:

>myShell ls -l | wc -l >file

这里是专门开发的两个案例。我认为问题出现在案例5而不是案例4中,因为我尝试过的第一个命令(我在上面给你看过)。

        case 4:                                // SYMBOLE : >
            if(output==0){
                output=1;
                execute=1;
                for (l=0;l<10;l++){
                    eltsoutput[l]=eltsCommande[l];
                }
            }
            break;
        case 5:                                // SYMBOLE : |
            //if(tube==0){
                /*for (l=0;l<10;l++){
                    eltstube[l]=eltsCommande[l];
                }*/
                p2=fork();
                if(p2==0){
                    if(tube==0){
                        freopen( "fichtmp", "w", stdout );
                        execvp(eltsCommande[0], eltsCommande);
                    }
                    return(0);
                }
                else{    if(background==0){            // SANS MOD BG ATTENDRE FIN FILS
                        waitpid(p2, NULL, 0);
                    }
                    tube=1;                
                    execute=1;    
                }

            break;

你能帮我找到一种方法,用|同时执行两个命令并允许他们的结果转到文件?

在我的shell中,案例是在使用指令“;”重定向的情况下工作:

                }else if(output==1){               
                    close(1);
                    int filew = creat(eltsCommande[0], 0644);
                    execvp(eltsoutput[0], eltsoutput);

也许我应该使用这段代码来实现它?

1 个答案:

答案 0 :(得分:1)

查看NetBSD /bin/sh source code,我看到以下管道实现:

static int
sh_pipe(int fds[2])
{
        int nfd;

        if (pipe(fds))
                return -1;

        if (fds[0] < 3) {
                nfd = fcntl(fds[0], F_DUPFD, 3);
                if (nfd != -1) {
                        close(fds[0]);
                        fds[0] = nfd;
                }
        }

        if (fds[1] < 3) {
                nfd = fcntl(fds[1], F_DUPFD, 3);
                if (nfd != -1) {
                        close(fds[1]);
                        fds[1] = nfd;
                }
        }
        return 0;
}

evalpipe使用2个文件描述符调用此函数:

STATIC void
evalpipe(union node *n)
{
        struct job *jp;
        struct nodelist *lp;
        int pipelen;
        int prevfd;
        int pip[2];

        TRACE(("evalpipe(0x%lx) called\n", (long)n));
        pipelen = 0;
        for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
                pipelen++;
        INTOFF;
        jp = makejob(n, pipelen);
        prevfd = -1;
        for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
                prehash(lp->n);
                pip[1] = -1;
                if (lp->next) {
                        if (sh_pipe(pip) < 0) {
                                if (prevfd >= 0)
                                        close(prevfd);
                                error("Pipe call failed");
                        }
                }
                if (forkshell(jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) {
                        INTON;
                        if (prevfd > 0) {
                                close(0);
                                copyfd(prevfd, 0, 1);
                                close(prevfd);
                        }
                        if (pip[1] >= 0) {
                                close(pip[0]);
                                if (pip[1] != 1) {
                                        close(1);
                                        copyfd(pip[1], 1, 1);
                                        close(pip[1]);
                                }
                        }
                        evaltree(lp->n, EV_EXIT);
                }
                if (prevfd >= 0)
                        close(prevfd);
                prevfd = pip[0];
                close(pip[1]);
        }
        if (n->npipe.backgnd == 0) {
                exitstatus = waitforjob(jp);
                TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
        }
        INTON;
}
在evaltree中的switch语句中调用evalpipe,如下所示:

    case NPIPE:
            evalpipe(n);
            do_etest = !(flags & EV_TESTED);
            break;

...由evalloop中的无限循环调用,并渗透树直到它到达eval函数。我希望这会有所帮助。