[comp.windows.x.motif] Capturing Stdout/stderr to scrolling window

mrabin@ADS.COM (Marla Rabin) (03/07/91)

I'd like to be able to capture the stdout and stderr of some system
calls that I use (fork and exec), and print this output in my main
scrolling text window.
Douglas Young has an example of something like this in his
The X Window System Programming and Applications with Xt, 
OSF/MOTIF edition. (The xbc example, pages 156-166 in my edition).
However, when I make a few changes to his routines, they don't
work for me. The fork and exec runs the system call, but the stdout
output goes into never-never land. (I've put off redirecting stderr
for now for debugging purposes). Also, the routine that is supposed to
be called when anything appears in stdin (get_from_input below) never seems
to get called (I think this because inside that routine I write something to
stderr, and I never see that output when I run the program). I'm hoping someone
out there can spot my error(s) and help me solve this! Any help or suggestions
would be greatly appreciated!

I'm using Motif 1.1, X11R4, Sparcstation 1, SunOS Release 4.1.1

Code details:

In main, before realizing and main-looping I have the line:
	XtAddInput(fileno(stdin), XtInputReadMask, get_from_input, mainText);

where get_from_input is:

void
get_from_input(w, fid, id)
     Widget      w;
     int         *fid;
     XtInputId   *id;
{
  char  buf[BUFSIZ];
  int nbytes, i;

  extern void printToMain();

  fprintf(stderr, "in get\n");
  nbytes = read(*fid, buf, BUFSIZ);
  if (nbytes) {
    buf[nbytes] = '\0';
    printToMain(buf);
  }
}

The function that I'm using to run the system command is:

void
runCmd(cmd)
     char *cmd;
{
  int  to_parent[2];
  int  pid, status;

  pipe(to_parent);
  
  if (pid = fork(), pid == 0) {        /* in the child */
    const char *shell = (char *) getenv("SHELL");
    if (shell == NULL) shell = "/bin/sh";
    close(1);
    dup(to_parent[1]);                 /* redirect stdout */
    close(to_parent[0]);
    close(to_parent[1]);
    execl(shell, shell, "-c", cmd, NULL);
    exit(1);
  }
  else if (pid > 0) {                  /* in the parent */
    close(0);
    dup(to_parent[0]);                 /* redirect stdin */
    close(to_parent[0]);
    close(to_parent[1]);
    wait(&status);
  }
  else {                               /* error! */
    fprintf(stderr, "Couldn't fork process %s\n", cmd);
    exit(1);
  }
}  

Thanks in advance,
--marla
mrabin@ads.com

dbrooks@osf.org (03/07/91)

mrabin@ADS.COM (Marla Rabin) writes:
|> In main, before realizing and main-looping I have the line:
|> 	XtAddInput(fileno(stdin), XtInputReadMask, get_from_input, mainText);
|> 
|> where get_from_input is:
|> 
|> void
|> get_from_input(w, fid, id)
|>      Widget      w;
|>      int         *fid;
|>      XtInputId   *id;
|> {
|>   char  buf[BUFSIZ];
|>   int nbytes, i;
|> 
|>   extern void printToMain();
|> 
|>   fprintf(stderr, "in get\n");
|>   nbytes = read(*fid, buf, BUFSIZ);
			      ^^^^^^

Assuming the writer hasn't closed the pipe, this will block until
enough data is shoved across.  You'll have to do whatever SunOS offers
to perform a nonblocking read.

(Anyway, that's what occurred to me straight away.  I haven't looked
too closely at the mess of dup and close calls...)

-- 
David Brooks				dbrooks@osf.org
Systems Engineering, OSF		uunet!osf.org!dbrooks
"It's not easy, but it is simple."