Cory Petkovsek wrote:

> "eldump -? 2>&1 | more"
> 
> I figure this means take standard error(2) and merge it with standard
> out(1).  Right?

Right.

> Here are some experiments I ran:
> $ prog 1>d 1>j
> 
> stdout went to j
> d is empty

But note that d was created. (-:

> $ prog 1>d 2>&1 1>j
> 
> stdout went to j
> stderr went to d
> 
> How many streams are there?  Can I do something like
> $ prog 1>&4 4>&3 1>j 3>&5  5>&2

In the normal case, there are three:

        0 = stdin
        1 = stdout
        2 = stderr

But a program can create more.

Let's say you had this script.

        $ cat njturtles
        

> Can I fork a stream?  Maybe like:
> $ prog 1>&3>&4 3>file1 4>file2

Use tee(1) to fork.

> What other tricks can I do with streams?  Can I take stdout and route it in
> to stdin, thus making a superconducter inside my shell?

Heh, heh.  I like the term, "superconductor".

I don't see a way to write a pipe loop using shell syntax.  But it's
easy enough to do using C.  Here's superconductor.c.

    #include <stdio.h>
    #include <sys/fcntl.h>
    #include <unistd.h>

    void child(int pipends[2], char *argv[], char *envp[])
    {
        char *child_argv[2];

        if (dup2(pipends[O_RDONLY], 0) != 0) { /* stdin now comes from pipe */
            perror("child dup2 stdin");
            exit(1);
        }
        if (dup2(pipends[O_WRONLY], 1) != 1) { /* stdout now goes into pipe */
            perror("child dup2 stdout");
            exit(1);
        }
        close(pipends[0]);
        close(pipends[1]);
        child_argv[0] = "/bin/cat";
        child_argv[1] = NULL;

        execve(child_argv[0], child_argv, envp);
        perror("child execve");
        exit(1);
    }

    void parent(int pipends[2], char *argv[], char *envp[])
    {
        if (dup2(pipends[O_WRONLY], 1) != 1) { /* parent stdout goes into pipe */
            perror("parent dup2 stdout");
            exit(1);
        }
        close(pipends[0]);
        close(pipends[1]);
        argv[0] = "/bin/cat";

        execve("/bin/cat", argv, envp);
        perror("parent execve");
        exit(1);
    }

    int main(int argc, char *argv[], char *envp[])
    {
        int pipends[2];
        pid_t childpid;

        if (pipe(pipends)) {
            perror("pipe");
            exit(1);
        }
        childpid = fork();
        if (childpid < 0) {
            perror("fork");
            exit(1);
        }
        if (childpid == 0)
            child(pipends, argv, envp);
        else
            parent(pipends, argv, envp);
        return 0;                               /* never reached */
    }

Run it under strace and give it a single line of input.

        echo foo | strace -f ./superconductor

Hours of fun for the whole family!

-- 
Bob Miller                              K<bob>
kbobsoft software consulting
http://kbobsoft.com                     [EMAIL PROTECTED]

Reply via email to