ftp.nice.ch/pub/next/graphics/3d/geomview.1.4.1.s.tar.gz#/Geomview/src/lib/oogl/util/ppopen.c

This is ppopen.c in view mode; [Download] [Up]

/*
 * int ppopen(char *pgm,  FILE **frompgm, FILE **topgm)
 * int ppclose(FILE *fromcmd, FILE *tocmd)
 *
 * Like popen(), but hooks up both input and output FILE pointers to a program.
 * The "program" may be any valid /bin/sh command.
 * ppopen() returns the program's process id if successful, else 0.
 * If successful, ``*frompgm'' and ``*topgm'' are filled in with FILE *'s
 *
 * Take care when using this; deadlock is possible if the program writes a
 * large amount of data (> about 8K bytes) to its output while you're still
 * writing to its input.
 *
 * Typical usage might be:
 * FILE *frompgm, *topgm;
 * ppopen("polymerge", &frompgm, &topgm);
 * GeomFSave(g, topgm, "polymerge");
 * gg = GeomFLoad(frompgm, "polymerged data");
 * ppclose(topgm, frompgm);
*/


#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

static int npps = 0;
static unsigned short *pps;

int
ppopen(char *cmd, FILE **frompgm, FILE **topgm)
{
  struct pipe { int r, w; } pfrom, pto;
  int i, pid;
  

  /* create the communication pipes */
  pfrom.r = pfrom.w = -1;
  if(pipe(&pfrom) < 0 || pipe(&pto) < 0) {
    perror("Can't make pipe");
    close(pfrom.r); close(pfrom.w);
    return 0;
  }

  switch(pid = fork()) {
  case -1:
	perror("Can't fork");
	return 0;

  case 0: {
	static char rats[] = "Can't exec external module: ";
	close(pfrom.r);
	close(pto.w);
	dup2(pto.r, 0);
	dup2(pfrom.w, 1);
	execl("/bin/sh", "sh", "-c", cmd, NULL);

	write(2, rats, sizeof(rats)-1);
	perror(cmd);
	exit(1);
      }
  }

  close(pto.r);
  close(pfrom.w);
  *frompgm = fdopen(pfrom.r, "r");
  *topgm = fdopen(pto.w, "w");
  if(pfrom.r < npps) {
    int newsize = (pfrom.r + 10)*sizeof(pps[0]);
    npps = pfrom.r + 10;
    pps = (unsigned short *) (pps ? realloc(pps, newsize) : malloc(newsize));
    bzero(&pps[npps], newsize - npps*sizeof(pps[0]));
    pps[pfrom.r] = pid;
  }
  return pid;
}

ppclose(FILE *frompgm, FILE *topgm)
{
  union wait w;
  unsigned int fd;
  int pid;

  if(frompgm == NULL) return -1;
  if(topgm) fclose(topgm);
  fd = fileno(frompgm);
  fclose(frompgm);
  if(fd < npps && pps[fd] != 0) {
	pps[fd] = 0;
	while((pid = wait(&w)) != pps[fd] && pid > 0)
	    ;
  }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.