[openbeos] Re: popen() alternatives

> I've been working on ZipOMatic lately, but now that I'm
> close to finishing it, I don't know how to kill the zip process,
> having started it with popen().
> 
> It does a lot, but as of yet, no zipping:
> http://www.kirilla.com/people/jonas/obos/ZipOMatic.zip
>
> I need to open a process (or multiple ones), read it's output,
> kill off the process if the user presses Stop, or otherwise wait
> for it to terminate.
> 
> And it needs to be thread-safe, so, IIRC, no fork()'ing.
> (there will be BLoopers around)

popen() use fork() :-)

However, the issue there is to get the forked process team id, so that 
you can 
kill it or wait his end.
Here's my own popen() implementation, called my_popen() ;-) :

-----8<--------------------------------
static FILE * my_popen
        (
        Arguments &     args,
        const char *    type,
        long *                  tid
        ) 
{ 
  int           p[2]; 
  FILE *        fp; 

  if (*type != 'r' && *type != 'w') 
    return NULL; 

  if (pipe(p) < 0) 
    return NULL; 

  if ((*tid = fork()) > 0) { /* then we are the parent */ 
    if (*type == 'r') { 
      close(p[1]); 
      fp = fdopen(p[0], type); 
    } else { 
      close(p[0]); 
      fp = fdopen(p[1], type); 
    } 

    return fp; 
  } else if (*tid == 0) {  /* we're the child */ 

    /* make our thread id the process group leader */ 
    setpgid(0, 0); 

    if (*type == 'r') { 
      fflush(stdout); 
          fflush(stderr);
      close(1); 
      if (dup(p[1]) < 0) 
        perror("dup of write side of pipe failed");
          close(2);
      if (dup(p[1]) < 0) 
        perror("dup of write side of pipe failed");
    } else { 
      close(0); 
      if (dup(p[0]) < 0) 
        perror("dup of read side of pipe failed"); 
    } 

    close(p[0]); /* close since we dup()'ed what we needed */ 
    close(p[1]); 

    execve(args[0], args, environ);

        printf("my_popen(): execve(%s) failed!\n", args[0]);
  } else {         /* we're having major problems... */ 
    close(p[0]); 
    close(p[1]); 
        printf("my_popen(): fork() failure!\n");
  } 

  return NULL; 
}
-----8<--------------------------------

Arguments is just a wrapping class around argv arrays... feel free to 
move back to classic string arrays.

Here how I use it in one of my pet project:

-----8<--------------------------------
Arguments cmd;
FILE *output;
long cmd_process_id;
bool cancel;
char line[1024];

cmd << "/boot/home/config/bin/cdrecord";
cmd << "dev=0,2,0";
cmd << "speed=4";
cmd << -v"
cmd << "/tmp/cd.img";

output = my_popen(cmd, "r", &cmd_process_id);
if (!output)
        return;

while ( ! feof(output) && ! ferror(output) )    {
  if ( cancel ) {
        kill(-cmd_process_id, SIGINT);          
        break;  
  };

  fgets(line, sizeof(line), output);
  
  // Do something with process output 
};

pclose(output);
------8<-----------------------------

To stop/resume the process, pass SIGSTOP/SIGCONT to kill() instead, it 
should works fine.

"Voilà".
Hope it could help...

-Phil


--
Fortune Cookie Says:

"This is a test of the Emergency Broadcast System.  If this had been an
actual emergency, do you really think we'd stick around to tell you?"


Other related posts: