I want to execute a program from my GTK+ application and get it's stdout output. After a little research I've turned to glibs GIOChannel. But I can't figure it out how can I detect the end of input. The only way I can think of is calling "wait_pid" with WNOHANG from my callback function, but somehow I think there's better way... Can anyone point me in the right direction?
That's what I have so far:
Code:
#include <glib.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
GIOChannel *io_channel_open(char *cmd[]);
gboolean cb_read_line(GIOChannel *io_channel, GIOCondition condition, gpointer data);
int main(int argc, char *argv[])
{
GMainLoop *main_loop;
GIOChannel *io_channel;
char *cmd[] = {"ls", "-lah", NULL};
io_channel = io_channel_open(cmd);
g_io_add_watch(io_channel, G_IO_IN, cb_read_line, NULL); /* Adds 1 reference...*/
g_io_channel_unref(io_channel); /* ... so we don't need this one, I think */
/* Main Loop */
main_loop = g_main_loop_new(NULL, TRUE);
g_main_loop_run(main_loop);
return 0;
}
/* Executes the program described by cmd[]
* and creates GIOChannel
*/
GIOChannel *io_channel_open(char *cmd[])
{
GIOChannel *io_channel;
pid_t child_pid;
int fd_pipe[2];
pipe(fd_pipe);
child_pid = fork();
if (child_pid == 0) {
close(fd_pipe[0]);
dup2(fd_pipe[1], STDOUT_FILENO);
execvp(cmd[0], cmd);
g_error("exec() failed!\n");
abort();
}
else {
close(fd_pipe[1]);
io_channel = g_io_channel_unix_new(fd_pipe[0]);
return io_channel;
}
}
/* Callback function to read and
* process the input
*/
gboolean cb_read_line(GIOChannel *io_channel, GIOCondition condition, gpointer data)
{
gchar *line_buf;
gsize length, terminator_pos;
g_io_channel_read_line(io_channel, &line_buf, &length, &terminator_pos, NULL);
g_print("%s", line_buf);
/* In _theory_ I should return FALSE to destroy this io_channel. */
return TRUE;
}
I'm using to compile:
Code:
gcc -Wall -o pipe_koe main.c `pkg-config --cflags --libs glib-2.0`