top
and tail -f
are long-running programs (in fact, they never exit), so your strategy of reading the whole output and populating the the textbuffer with it obviously won't work.
Instead, you need to create an IO channel that watches what's going on with the pipe, hook the channel into the event loop, and append it to the text buffer as new output arrives. The minimalistic change to your program would be to rewrite the prepare
function like this:
static gboolean data_ready(GIOChannel *channel, GIOCondition cond, gpointer data)
{
FILE *fp = data;
char line[256];
if (fgets(line, sizeof line, fp)) {
gtk_text_buffer_get_end_iter (buffer, &iter);
gtk_text_buffer_insert (buffer, &iter, line, -1);
return TRUE;
}
else {
fclose(fp);
return FALSE;
}
}
void populate(){
FILE *fp = popen("top -b", "r");
GIOChannel *channel = g_io_channel_unix_new(fileno(fp));
g_io_add_watch(channel, G_IO_IN, data_ready, fp);
}