Re: How does one pipe output from process to text buffer?



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Thu, Dec 28, 2006 at 08:10:57PM -0500, Tony Freeman wrote:

[...]

Thanks!

I'm getting really close now!  Thanks for your help.

Glad it was useful. I'm keeping Zeeshan cc'ed -- he proposed using
libgtk. Many things apply whether you spawn a process or use a lib (but
tend to be easier with the lib; among other things you have less fds to
watch ;-)

Currently, I have the program doing what I want but for one thing ... it
freezes until all my ssh commands have returned.  Once control is
returned, all the notebook pages have all the proper ssh output
associated with it :-)

I'd like to be able to click on each notebook page as the ssh commands
are running, and be able to see real-time output being written.

This somehow smells like your app is waiting (or even spinning) in a
callback. You can easily distinguisch waiting and spining based on how
much CPU your process hogs :-)

Anyway ... 

This is what I have so far:

[...]

GPid pid;
gint stdout;
GIOChannel *gioout;
g_spawn_async_with_pipes( NULL, 
       ssh_command, 
       NULL, 
       G_SPAWN_SEARCH_PATH,
       NULL,
       NULL,
       &pid,
       NULL, &stdout, NULL,

Where does the subprocess get its input from? I don't think it'll be
doing anything useful this way. Maybe (just for testing purposes, and if
you want to get the subproces's putput part right first) you might want
to substitute the ssh command by some process which just procuces output
(e.g. a shell script with echoes constantly).

       NULL );
gioout = g_io_channel_unix_new(stdout);
g_io_channel_set_encoding(gioout, NULL, NULL);
g_io_add_watch(gioout, 
(G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_NVAL),
(GIOFunc)watch_out, 
textview);

[...]

Note ... if I replace G_SPAWN_SEARCH_PATH with NULL I get a compiler
error ... so I keep it at G_SPAWN_SEARCH_PATH.

Also ... it took me all day and night to finally brew up the combination
of (G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_NVAL).

IMHO GIO_IN should suffice -- but I haven't the docs here.

                                          I was under the die-hard
impression that I wanted to watch for G_IO_OUT (after all I want ssh
output), but it turns out I was thinking completely opposite of what
really needs to be thought?  Anyway, this combination finally started
putting output in the notebook text buffers.

The shell's output is *your* input :-) (note that your proces's
perspective is relevant here).


Here is the watch_out callback function:

gboolean watch_out (GIOChannel *channel, GIOCondition condition,
gpointer data)
{
GIOStatus status = G_IO_STATUS_NORMAL;
GtkTextView *textview;
GtkTextBuffer *buffer;
gchar buf[1024];
gchar *buftext;
gsize bytes_read;

/* set up pointers to our textbuffer */
textview = GTK_TEXT_VIEW((GtkWidget *)data);
buffer = gtk_text_view_get_buffer(textview);

/* send ssh output to our gui */
status = g_io_channel_read_chars(channel, buf, sizeof(buf), 
                                 &bytes_read, NULL);
buftext = g_strdup_printf("%s", buf); /*creates null-term str*/

No need for that. And besides, you are leaking mem. gtk_buffer_set_text
accepts a length param, if I remember correctly:

gtk_text_buffer_set_text(buffer, buftext, -1);

| if (bytes_read > 0) gtk_text_buffer_set_text(buff, buf, bytes_read);


/* decide if we should close the channel */
switch (status) {
     case G_IO_STATUS_NORMAL:
          return TRUE;
     default:
          return FALSE;
}
}


I've spent some time experiementing with the buf.  I've reduced it down
to 64 (buf[64]) ... when the application becomes un-frozen and I can
click around in the notebook pages, I see that only the last couple of
lines of ssh output has been written to the page.

It seems the buf[] is filling up with data and then being discarded
without writing that data to my textbuffer - until the end - at which
point it writes the data to the textbuffer as it dies away.

Sound reasonable?  How do I fix this?

The callback itself looks harmless to me. I'd expect the ssh subprocess
doing funny things when it doesn't get input.

Besides, an ssh wants a tty (or pty; it tries to set it in raw mode to
ask for a password). No idea what it'll do when fed via pipes. This is,
btw where Zeeshan's proposal to use libssh makes most sense (it makes
sense for other reasons as well).

The flag combination G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_NVAL looks a bit
strange to me.

I'd put my bet in spinning: your callback is being called too often and
there is nothing to read.

Maybe later more, when I have access to the doc

regards
- -- tomÃs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)

iD8DBQFFlKprBcgs9XrR2kYRAtb8AJ0TI8P05C6aCuMrZBHCbRWAf57ggACfafMu
kQ0kDofeXwtVKGOuF2I3/zs=
=yUNp
-----END PGP SIGNATURE-----




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]