Long story short, I can't get piping to work under *nix. Not being the most experienced developer with *nix, I figured I'd ask you guys to help me out a little.

I am trying a very simple thing. Basically I want to capture the output of the "printenv" command and print it to the console.
The problem is that the parent process blocks waiting for input from the child which has long since terminated. I don't know how to make it work.

This is the code I am using:
Code:
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>

typedef struct pipe
{
	int read, write;
} pipe_t;

const int _stdin = 0;
const int _stdout = 1;
const int _stderr = 2;

void create_pipe(pipe_t* pipe_)
{
	int tmp[2];
	pipe(tmp);
	pipe_->read = tmp[0];
	pipe_->write = tmp[1];
}

void close_pipe(pipe_t* pipe)
{
	close(pipe->read);
	close(pipe->write);
}

int main()
{
	pipe_t printenv, sort;

	create_pipe(&printenv);
	if (fork() == 0) // printenv
	{
		sleep(2);
		puts("I'm the child program!");
		dup2(printenv.write, _stdout);
		close_pipe(&printenv);
		execlp("printenv", NULL);
	}
	else
	{
		puts("I'm the parent process! Now reading from child output!");
		char buf[2048];
		ssize_t size = 0;
		while (size = read(printenv.read, buf, sizeof(buf)))
		{
			printf("OK! Got output from child process! Size = %u\n", size);
		}
		puts("Parent process is now terminating!");
	}
	close_pipe(&printenv);

	return 0;
}
The output I am getting is:
OK! Got output from child process! Size = 2048
OK! Got output from child process! Size = 144

Then it hangs.
Speaking of which, I don't know the type of ssize_t nor what type specifier would be the right for printf in that case. Hence why I've just put %u.
I don't know if there are any constants in some header for the file descriptors for stdin, stdout and stderr, either. Everywhere I look, they just use hardcoded constants, which is stupid.

Any information would be highly appreciated.
(I might probably be doing one or more things wrong.)
Thanks.