Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c pipes, stdin/stdout and sort

Im trying to write a program that forks and sends sort (linux) some words to sort over stdin since sort without args will use stdin. Then collect the stdout from sort in the parent to output on parent's stdout.

Currently my program hangs. Could anyone lend a hand in explaining to me what is going wrong?

My code:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>


int main(int argc, char *argv[]){
    int fi[2];
    int fo[2];
    int oldstdin;
    int oldstdout;

    if (pipe(fi) == -1){
        exit(EXIT_FAILURE);
    }
    if (pipe(fo) == -1){
        exit(EXIT_FAILURE);
    }
    oldstdin = dup(STDIN_FILENO); /* Save current sdtin */
    oldstdout = dup(STDOUT_FILENO); /* Save current stdout */

    close(STDIN_FILENO);
    close(STDOUT_FILENO);


    if(dup2 (fo[0],STDIN_FILENO) == -1) /* Make the read end of out to be stdin */
        exit(EXIT_FAILURE);
    if(dup2 (fi[1],STDOUT_FILENO) == -1) /* Make the write end of in to be stdout */
        exit(EXIT_FAILURE);


    switch(fork()){
    case -1:
        exit(EXIT_FAILURE);
    case 0: /* CHILD */  
        close(fo[0]);
        close(fo[1]);
        close(fi[0]);
        close(fi[1]);
        execlp("sort","sort", (char *)NULL);
    default:
        break; /* fall through to parent */
    }

    char input[100];
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    dup2(oldstdin,STDIN_FILENO);
    dup2(oldstdout,STDOUT_FILENO);

    close(fo[0]); /* these are used by CHILD */
    close(fi[1]); /* "" */

    write(fo[1],"dino\nbat\nfish\nzilla\nlizard\0",27);
    input[read(fi[0], input,100)] = 0;
    printf("%s", input);
}
like image 813
Dacto Avatar asked Feb 01 '12 08:02

Dacto


1 Answers

I don't think sort expects stdin to be nul-terminated: it wouldn't be if redirected from a file.

It does however need to know when the input is complete (and won't emit anything until it is, so your read will block). Try closing fo[1] after writing to it.

Oh, and you can run this under strace -f to see what's happening, it will show you what both parent and child processes are doing.

like image 92
Useless Avatar answered Oct 22 '22 03:10

Useless