#1
  1. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95

    send EOF down pipe to STDIN


    this is a command interpreter, im trying to deal with piping the output of one command into the next, and all works cept slight problem. code,
    Code:
    //now execute command string process by process
                    while(y < nprocs){
                            //the index into the command vector of the start of the next command/process
                            x = cmd_indices[y++];
    
                            if( (cpid = fork()) == 0){      //child
                                    //check to see if stdout was piped from the last command
                                    //if it was then dup the read end of pipe to STDIN
                                    if(y >= 2){
                                            if(dup2(pipes[0], STDIN_FILENO) < 0){
                                                    perror("dup2");
                                                    return 1;
                                            }
                                    }
    
                                    //close read pipe and create arg vector
                                    close(pipes[0]);
                                    make_arg_vector(&x, (char ***)&cmd_vect, (char ***)&argv_vect);
    
                                    //pipe stdout to write end of pipe if this is a pipeline
                                    if( strcmp(cmd_vect[x], "|") == 0 ){
                                            if(dup2(pipes[1], STDOUT_FILENO) < 0){
                                                    perror("dup2");
                                                    return 1;
                                            }
                                            close(pipes[1]);
                                    }
    
                                    //execute and replace current process
                                    execvp(argv_vect[0], argv_vect);
    
                            }//end of child
    
                            //wait for the child to finish; error not fatal
                            if( (ccpid = waitpid(cpid, NULL, 0)) < 0)
                                    perror("waitpid");
                    }//process loop is the end of one command line
    the problem is that the next process in the pipeline(the one reading STDIN from the pipe) never gets an EOF sent down the pipe. so it hangs waiting on stdin after it outputs it's results for the first command. in case that isnt clear, my output is like this:
    msh-> ls -l
    total 60
    -rwxrwxr-x 1 oo7 oo7 14876 Oct 9 20:55 a.out
    drwxrwxr-x 29 oo7 oo7 4096 Sep 12 21:28 apps
    drwxrwxr-x 4 oo7 oo7 4096 Sep 23 16:38 exploits
    -rw------- 1 oo7 oo7 85 Oct 9 20:54 file
    drwxrwxr-x 3 oo7 oo7 4096 Oct 5 00:41 linux_docs
    drwxr-xr-x 2 oo7 oo7 4096 Oct 4 22:26 modules
    drwxr-xr-x 6 oo7 oo7 4096 Jul 7 21:38 programming
    drwxr-xr-x 4 oo7 oo7 4096 Oct 9 20:50 scrips
    -rw-rw-r-- 1 oo7 oo7 5250 Oct 9 20:55 shell.c
    drwxr-xr-x 8 oo7 oo7 4096 Sep 30 22:25 text_docs
    drwxrwxr-x 2 oo7 oo7 4096 Oct 9 19:03 tmp

    msh-> ls -l | cat
    total 60
    -rwxrwxr-x 1 oo7 oo7 14876 Oct 9 20:55 a.out
    drwxrwxr-x 29 oo7 oo7 4096 Sep 12 21:28 apps
    drwxrwxr-x 4 oo7 oo7 4096 Sep 23 16:38 exploits
    -rw------- 1 oo7 oo7 85 Oct 9 20:54 file
    drwxrwxr-x 3 oo7 oo7 4096 Oct 5 00:41 linux_docs
    drwxr-xr-x 2 oo7 oo7 4096 Oct 4 22:26 modules
    drwxr-xr-x 6 oo7 oo7 4096 Jul 7 21:38 programming
    drwxr-xr-x 4 oo7 oo7 4096 Oct 9 20:50 scrips
    -rw-rw-r-- 1 oo7 oo7 5250 Oct 9 20:55 shell.c
    drwxr-xr-x 8 oo7 oo7 4096 Sep 30 22:25 text_docs
    drwxrwxr-x 2 oo7 oo7 4096 Oct 9 19:03 tmp
    ////ahh im stuck now!!
    only Ctrl-C will kill me!
    now i've tried every(i think) possibility of closing pipes, and trying to send EOF down the pipes, but i think im missing something here. ? at what point should EOF be sent and in what manner?
  2. #2
  3. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244
    I am going to bed now, so that may be my problem, but I don't see you reading from and file descriptors. In anycase, I know that EOF is an int, not a char, are you sure you are passing things around as ints? If you are reading in as a char, you will truncate the bits that make it EOF and therefore will never get, nor sent it.

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  4. #3
  5. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    well that's b/c you dont do all that. that's the beautiful part. if they want to "|" output, you just do this:
    example, "ls | cat",
    *create a regular parent/child pipe set
    *make the write end of the pipe ls's stdout
    *execute the first command, ls
    *in next child, cat, make the read end of the pipe stdin
    *execute the next command, cat
    --then cat reads its stdin (the output of ls) and displays it, but now is the problem, it waits on stdin again. this is what strace looks like:
    --read command and fork
    read(0, "ls | cat\n", 1024) = 9
    fork() = 13633

    --dup pipe to stdout and exec ls
    [pid 13633] dup2(4, 1) = 1
    [pid 13633] execve("/usr/local/bin/ls", ["ls"],

    --ls writes output and exits; then a fork, dup pipe to stdin and cat exec's
    [pid 13633] write(1, "a.out\napps\nexploits\nfile\nlinux_d"..., 101) = 101
    fork() = 13634
    [pid 13634] dup2(3, 0) = 0
    [pid 13634] execve("/usr/local/bin/cat", ["cat"],

    --cat reads its stdin from the pipe and writes to stdout
    [pid 13634] read(0, "a.out\napps\nexploits\nfile\nlinux_d"..., 4096) = 101
    [pid 13634] write(1, "a.out\napps\nexploits\nfile\nlinux_d"..., 101) = 101

    --now it waits on stdin and i kill it!
    [pid 13634] read(0, <unfinished ...>
    make more sense now? ;)
    Last edited by infamous41md; October 9th, 2003 at 10:10 PM.
  6. #4
  7. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244
    Nope, still over my head. I bet trying to debug this is fun!

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw

IMN logo majestic logo threadwatch logo seochat tools logo