naval_ned
naval_ned

Reputation: 3

reading from a pipe in c and printing to stdout

I'm having some trouble reading from a pipe. Well not exactly. I'm reading fine its just the output is globbed up.

#include <sys/wait.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int pfd[2];

int main(void)
{
    pid_t   pid;
    int     status;
    char    readbuf[1024];
    int     bytes_read = 0;

    pipe(pfd);

    switch((pid = fork())) {
    case -1:
            perror("fork");
            break;
    case 0:
            /* child */
            close(pfd[0]);
            dup2(pfd[1], 1);        /* stdout */

            /* mkdir -p /home/edgar/testdir */
            chdir("/home/edgar/testdir");

            /* for file in a b c d e f g h i j k l m n o p q r s t u v w x y z;
             * do
             * touch $file
             * done
             */

            execl("/bin/ls", "ls", "-l", (char *)NULL);
            exit(1);
    default:
            /* parent */
            close(pfd[1]);
            dup2(pfd[0], 0);

            pid = wait(&status);
            /* get input back from ls */
            while ((bytes_read = read(pfd[0], readbuf, sizeof readbuf) > 0)) {
                    fprintf(stdout, "%s\n", readbuf);
            }

            printf("child exit status: %d\n", WEXITSTATUS(status));
    }
    return 0;
}

Here is an example of globbed up output:

laptop$ ./test1

-rw-r--r-- 1 edgar edgar 0 Jan 31 09:15 u

-rw-r--r-- 1 edgar edgar 0 Jan 31 09:15 v

-rw-r--r-- 1 edgar edgarp��

0 Jan 31 09:15 w -rw-r--r-- 1 edgar edgar 0 Jan 31 09:15 x

-rw-r--r-- 1 edgar edgar 0 Jan 31 09:15 y

-rw-r--r-- 1 edgar edgar 0 Jan 31 09:15 z

1 edgar edgar 0 Jan 31 09:15 d

-rw-r--r-- 1 edgar edgar 0 Jan 31 09:15 e

It read from a-v fine and then w-z is weird and then it started over at d. I added the extra newlines above for readability.

Upvotes: 0

Views: 3295

Answers (2)

naval_ned
naval_ned

Reputation: 3

This seems to have corrected the problem:

do {
        bytes_read = read(pfd[0], readbuf, sizeof(readbuf));
        readbuf[bytes_read] = '\0';
        printf("%s", readbuf);
    } while (bytes_read > 0);

Thanks for the assisstance.

Upvotes: 0

Chris Turner
Chris Turner

Reputation: 8142

What is one of the most important things to remember about strings in C? They're meant to be NUL terminated!

read doesn't add a NUL your string - it deals with chunks of raw data, so you have to do that yourself. This also means that you can't pass in the full size of the buffer as you'll need to leave space for the NUL to be added

       while ((bytes_read = read(pfd[0], readbuf, sizeof(readbuf)-1) > 0)) {
                readbuf[bytes_read]='\0';
                fprintf(stdout, "%s\n", readbuf);
       }

Upvotes: 2

Related Questions