Thread: programming unix shell piping problem

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    51

    programming unix shell piping problem

    Code:
    #include <stdio.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <sys/types.h> 
    #include <sys/wait.h> 
     
    enum 
    { 
        STDIN = 0, 
        STDOUT = 1, 
        STDERR = 2, 
        FD_READ = 0, 
        FD_WRITE = 1 
    }; 
     
    int main(int argc, char **argv, char **envp) 
    { 
        int fd[2]; 
        pid_t pid; 
        char *lessArg[] =  
        { 
            "/bin/less", 
            NULL 
        }; 
     
        char *lsArg[] = 
        { 
            "/bin/ls", 
            NULL 
        } 
     
        if(0 > pipe(fd)) 
        { 
            printf(%s \n", strerror(errno)); 
        } 
     
        if( pid = fork() ) // parent 
        { 
            waitpid(pid, NULL, 0); 
        } 
        else 
        { 
            dup2(fd[FD_WRITE], STDIN); 
            execve("/bin/ls", lsArg, envp); 
        } 
     
        if( pid = fork() ) // parent 
        { 
            waitpid(pid, NULL, 0); 
        } 
        else 
        { 
            dup2(fd[FD_READ], STDIN); 
            execve("/bin/less", lessArg, envp); 
        } 
         
        return 0; 
    }

    anyway, the code above, i'm having some trouble with. I've tried several things but i can't do what i want it to do.

    What the program does is, forks ls and pipes the result into less. less is to print it out to stdout. Now that all goes fine. It prints the output, but the problem is that i can't get back my stdin. I cant quit less or move in less. I'm shut out from the keyboard to control less.

    I've tried closing the file descriptors (fd) in the parent and still nothing.

    If i just use file redirection with dup2 it's all fine, just when i use the pipe file descriptors is when i run into problems

    thx

  2. #2
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    Well, the first problem I see is that you fail to close the file descriptors. Next, you redirect ls to STDIN when it should be STDOUT to pipe properly. Something more like this:
    Code:
    #include <stdio.h> 
    #include <unistd.h> 
    #include <errno.h> 
    #include <sys/types.h> 
    #include <sys/wait.h>
    
    enum
    {
        STDIN = STDIN_FILENO,
        STDOUT = STDOUT_FILENO,
        STDERR = STDERR_FILENO,
        FD_READ = 0,
        FD_WRITE = 1
    };
    
    int main(void)
    {
        pid_t pid;
        int fd[2];
    
        char *lessArg[] =  
        { 
            "/bin/less", 
            NULL 
        }; 
     
        char *lsArg[] = 
        { 
            "/bin/ls", 
            NULL 
        }
    
        if (pipe(fd) == -1) {
            perror("pipe -- main");
            return 1;
        }
    
        if ((pid = fork()) == 0) { /* ls is the child */
            if (dup2(fd[FD_WRITE], STDOUT) == -1)
                perror("child dup2 -- main");
            else if (close(fd[FD_READ]) == -1 || close(fd[FD_WRITE) == -1)
                perror("child close -- main");
            else
                execve("/bin/ls", lsArg, envp);
        }
    
        if (dup2(fd[FD_READ], STDIN) == -1) /* less is the parent */
            perror("parent dup2 -- main");
        else if (close(fd[FD_READ]) == -1 || close(fd[FD_WRITE]) == -1)
            perror("parent close -- main" );
        else
            execve("/bin/less", lessArg, envp);
    
        return 0;
    }
    My best code is written with the delete key.

  3. #3
    Registered User
    Join Date
    Aug 2003
    Posts
    51
    Thx for that prelude it works, but after looking at it there's one problem, the program doesn't fork before executing less.

    And now, i think i know the initial problem which is now what i need to solve.

    I think i am shut out of the input because less is still running in the background and the parent was what was running. ANd since the parent is waiting of the child to finish i wasn't able to do anything. The input was connected to the parent not the child (less).

    So now i need to have control of the child (less) then after less has finished, gain control to the parent.
    Last edited by Kyro; 08-28-2003 at 07:57 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. shell problem
    By ArXi in forum Linux Programming
    Replies: 2
    Last Post: 06-04-2009, 02:30 AM
  2. Running 'exec' twice in one UNIX shell script
    By Zughiaq in forum Tech Board
    Replies: 2
    Last Post: 05-03-2003, 12:04 AM
  3. unix shell
    By duffy in forum Tech Board
    Replies: 3
    Last Post: 10-16-2002, 03:11 AM
  4. UNIX File problem
    By DISGUISED in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 08-09-2002, 11:07 AM
  5. System.ini Shell Problems
    By (TNT) in forum Windows Programming
    Replies: 2
    Last Post: 08-26-2001, 01:05 PM