2

I want to run: cat somefile | program > outputText in a UNIX system.

I have looked at many things such as pipe, using popen, dup2, etc; I am lost.

Basic code should be:

  • Read whatever output cat produces using program and do some magic, an then output the data into outputText.

Any advice please?

P.S. The files are binary files.

UPDATE:

I found this code that works with the prescribed command above... But it does things I don't want.

  1. How do I get rid of the sort? I tried erasing things, but then I get errors and the program doesn't run.
  2. Read data by cat as binary
  3. Output data to terminal as binary

Any tips please?

int main(void)
{
    pid_t p;
    int status;
    int fds[2];
    FILE *writeToChild;
    char word[50];

    if (pipe(fds) == -1)
    {
        perror("Error creating pipes");
        exit(EXIT_FAILURE);
    }

    switch (p = fork())
    {
        case 0: //this is the child process
            close(fds[1]); //close the write end of the pipe
            dup2(fds[0], 0);
            close(fds[0]);
            execl("/usr/bin/sort", "sort", (char *) 0);
            fprintf(stderr, "Failed to exec sort\n");
            exit(EXIT_FAILURE);

        case -1: //failure to fork case
            perror("Could not create child");
            exit(EXIT_FAILURE);

        default: //this is the parent process
            close(fds[0]); //close the read end of the pipe
            writeToChild = fdopen(fds[1], "w");
            break;
    }

    if (writeToChild != 0)
    {
        while (fscanf(stdin, "%49s", word) != EOF)
        {
            //the below isn't being printed.  Why?
            fprintf(writeToChild, "%s end of sentence\n", word);
        }
        fclose(writeToChild);
    }

    wait(&status);

    return 0;
}
10
  • 1
    Why would you use cat to pipe into it when you can just set the stdin of program to somefile? i.e., program < somefile > outputText
    – FatalError
    Commented Sep 19, 2014 at 2:10
  • My task specifies I must do it this way unfortunately.
    – raffaello
    Commented Sep 19, 2014 at 2:24
  • And the file read by cat is binary, and the output should be binary as well if possible.
    – raffaello
    Commented Sep 19, 2014 at 2:30
  • Do I need to have 2 files? One file does the piping? I noticed that many programs make calls to exec(), where they call a specific file, in my case that would be program? So pipe.c would call program.c and somehow take stdout from cat and place it into program.c???
    – raffaello
    Commented Sep 19, 2014 at 2:50
  • If you, as you say, is supposed to (homework?) run the program as cat somefile | program > output, then you're on the wrong track. Running the command like that makes the shell pipe the output from cat to the input of program. That's not the same as setting up a pipe inside your program. en.wikipedia.org/wiki/Redirection_(computing)#Piping
    – Henrik
    Commented Sep 19, 2014 at 5:47

2 Answers 2

1

This is my suggestion, as you wanted read and write binary files:

#include <stdio.h>

int main (void) {
    if (!freopen(NULL, "rb", stdin)) {
        return 1;
    }
    if (!freopen(NULL, "wb", stdout)) {
        return 1;
    }

    char buf[4];
    while (!feof(stdin)) {
        size_t numbytes = fread(buf, 1, 4, stdin);

        // Do something with the bytes here...

        fwrite(buf, 1, numbytes, stdout);
    }
}
4
  • That's what I just did :).. Took a while to figure out how to make stdout output binary. Wish I looked at this 20 min ago.
    – raffaello
    Commented Sep 19, 2014 at 6:49
  • The EOF check is out of order. You should check feof() after the fread() but before the fwrite(). Or just use the return value of fread().
    – FatalError
    Commented Sep 19, 2014 at 13:03
  • @FatalError From the fread man-page: "If an error occurs, or the end of the file is reached, the return value is a short item count (or zero)." I.e. numbytes holds the number of bytes actually read, even if EOF was reached. These bytes need to be written.
    – Henrik
    Commented Sep 19, 2014 at 13:07
  • @Henrik: +1 Yeah, now that I look more closely your code is correct. If the read fails to return any data it will call fwrite() with 0 bytes, so it won't actually write anything that's in buf.
    – FatalError
    Commented Sep 19, 2014 at 13:12
0

To be able to read the output (stdout) of cat, you don't need to pipe anything I found thanks to you guys! I got sidetracked with piping...

so if you run " cat somefile | program ", where somefile contains binary data... you will just see whatever somefile contains, reprinted on a terminal.

Thank you! Now I can finish writing my program.

/*program.c*/

int main()
{
    int i, num;

    unsigned char block[2];

    while ((num = fread(block, 1, 2, stdin)) == 2)
    {
        for(i = 0; i < 2; i++)
        {
            printf("%02x", block[i]);
        }
    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.