#include <stdio.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <fcntl.h>

#define CMD "x-povray"
#define MAXLINE 2048

short attend=1;
char tmpn[32];
pid_t pov;

void attente(int s)
{
  signal(s,attente);
  if(s==SIGUSR1)
    attend=0;
}

void menage(int s)
{
  kill(pov,s);
  while(pov!=waitpid(-1,NULL,0));
  remove(tmpn);
  exit(0);
}

char *reconnaitre(char *b)
{
  int i;
  char *r;

  for(i=0;(b[i]==' ')||(b[i]=='\t');i++);
  if(strncmp("#external{",b+i,10))
    return(NULL);
  i+=10;
  r=b+i;
  for(i=0;(b[i]!='}')&&(b[i]!=0);i++);
  if(b[i]==0)
    return(NULL);
  b[i]=0;
  return(r);
}

int main(int argc,char **argv)
{
  char **fic,**cmd,*buf,*ext;
  int i,j,nfic=0,ncmd=0;
  int stdo;
  FILE *f,*p=NULL;
  short e;
  char c;

  fic=malloc(2*(argc+4)*sizeof(char *));
  buf=malloc(MAXLINE);
  if((fic==NULL)||(buf==NULL))
    return(2);
  cmd=fic+(argc+2);

  cmd[ncmd++]=CMD;
  for(i=1;i<argc;i++){
    if(strncasecmp("+i",argv[i],2)==0){
      if(argv[i][2]==0){
	if(i==argc-1)
	  return(3);
	fic[nfic++]=argv[++i];
      }else{
	fic[nfic++]=argv[i]+2;
      }
    }else{
      cmd[ncmd++]=argv[i];
    }
  }
  sprintf(tmpn,"/tmp/metapov.%d",getpid());
  cmd[ncmd++]="+I";
  cmd[ncmd++]=tmpn;
  cmd[ncmd++]=NULL;

  signal(SIGUSR1,attente);
  pov=fork();
  if(pov==0){
    while(attend)
      usleep(50000);
    execvp(CMD,cmd);
    return(0);
  }

  signal(SIGINT,menage);
  signal(SIGTERM,menage);
  close(STDOUT_FILENO);
  stdo=open(tmpn,O_WRONLY|O_CREAT|O_TRUNC,S_IREAD|S_IWRITE);
  dup2(stdo,STDOUT_FILENO);

  for(i=0;i<nfic;i++){
    f=fopen(fic[i],"rt");
    if(f==NULL){
      fprintf(stderr,"File %s not found and ignored.\n",fic[i]);
      continue;
    }
    j=0;
    e=1;
    while(e){
      c=fgetc(f);
      if(c==EOF){
	e=0;
	c='\n';
      }
      buf[j++]=c;
      if(c=='\n'){
	buf[j]=0;
	ext=reconnaitre(buf);
	if(ext==NULL){
	  if(p==NULL)
	    write(STDOUT_FILENO,buf,j);
	  else
	    fwrite(buf,1,j,p);
	}else{
	  if(strcmp("end",ext)==0){
	    if(p==NULL)
	      return(5);
	    pclose(p);
	    p=NULL;
	  }else{
	    p=popen(ext,"w");
	  }
	}
	j=0;
      }
    }
    fclose(f);
  }
  close(STDOUT_FILENO);

  kill(pov,SIGUSR1);
  while(pov!=waitpid(-1,NULL,0));
  remove(tmpn);

  return(0);
}
