Re: OT: capturing stdout & stderr to a GtkText
- From: Paul Davis <pbd Op Net>
- To: "Carlos A. Carnero Delgado" <texel rtvc com cu>
- Cc: gtk-list gnome org
- Subject: Re: OT: capturing stdout & stderr to a GtkText
- Date: Wed, 07 Feb 2001 18:56:48 -0500
>Currently, I have Perl embedded to process whatever the user types (yup,
>it's possible to enter anything that Perl digs as ok, and it will executed.)
>However, if I enter "print 2;" the Perl interpreter will print 2 but on a
>terminal. How can I capture the stdout and stderr output of an embedded
>program like Perl? If I can capture, it'll be no problem adding it to the
>GtkText.
you need to take control of exec-ing the sub-process so that you have
file descriptors corresponding to its stdin/out/err. typically, you
create a set of pipes with pipe(2) first, then you close&dup the file
descriptors for stdin, stdout, stderr. see below for an example of how
to do (most) this.
then use gdk_input_add() to get GTK's main loop to watch the relevant
file descriptors for data to read; your callback will be invoked when
there is data there, and you can then make whatever calls you wish to
display the messages in a GTK widget of some kind.
the end result is something like this (without any required error checking).
------------------------------------------------------------
int in[2], out[2], err[2];
char args[2];
pipe (in);
pipe (out);
pipe (err);
args[0] = "/usr/bin/perl";
args[1] = 0;
gdk_input_add (out[0], GDK_INPUT_READ, stdout_data_ready, NULL);
gdk_input_add (err[0], GDK_INPUT_READ, stderr_data_ready, NULL);
forkexec (args, NULL, in, out, err);
------------------------------------------------------------
--p
/*
Copyright (C) 1989/1994/1999 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
/*
Run a program with program name and args specified by argv, in the
environment specified by envp.
The exec'ed program uses inpipe[READ_DESC], outpipe[WRITE_DESC]
and errpipe[WRITE_DESC] as stdin, stdout, and stderr resp.
You can safely leave outpipe, inpipe & errpipe unspecified (NULL) if you
want the command to read/write from/to stdin/stdout/stderr. envp could just
be the environ extern that all C/C++ programs have access to, or it
could be some filtered version of it. This function doesn't care
what it is, but the cmd might (it might try to use $HOME for
example). I don't know if it can be a NULL pointer.
*/
#define READ_DESC 0
#define WRITE_DESC 1
pid_t forkexec (char **argv, char **envp,
int outpipe[2],
int inpipe[2],
int errpipe[2])
{
pid_t pid;
if ((pid = fork ()) == 0) {
/* In the child process */
if (inpipe) {
if (inpipe[READ_DESC] != 0) {
close (0);
if (dup (inpipe[READ_DESC]) < 0) {
return (-1);
}
}
if (inpipe[WRITE_DESC]) {
close (inpipe[WRITE_DESC]);
}
}
if (outpipe) {
if (outpipe[WRITE_DESC] != 1) {
close (1);
if (dup (outpipe[WRITE_DESC]) < 0) {
return (-2);
}
}
if (!errpipe) {
close(2);
if (dup (outpipe[WRITE_DESC]) < 0) {
return (-3);
}
}
if (outpipe[READ_DESC]) {
close (outpipe[READ_DESC]);
}
}
if (errpipe) {
if (errpipe[WRITE_DESC] != 1) {
close (2);
if (dup (errpipe[WRITE_DESC]) < 0) {
return (-4);
}
}
if (errpipe[READ_DESC]) {
close (errpipe[READ_DESC]);
}
}
/* do it */
execvp (argv[0], argv);
return (-3);
} else if (pid == -1) {
return (-5);
} else {
/* In the parent process */
if (outpipe && outpipe[WRITE_DESC]) {
close (outpipe[WRITE_DESC]);
outpipe[WRITE_DESC] = -1;
}
if (errpipe && errpipe[WRITE_DESC]) {
close (errpipe[WRITE_DESC]);
errpipe[WRITE_DESC] = -1;
}
}
return (pid);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]