#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "vars.h"



int run_make_cache (char *config)
{
   char lock_file[ML_FILE_NAME],etmp[ML_ETMP],tmp[ML_FILE_NAME*2+5];
   struct flock lck;
   int fd,pid,status;

   // Set lock structure
   lck.l_type = F_WRLCK;
   lck.l_whence = 0;
   lck.l_start = 0L;
   lck.l_len = 0L;

   // Set lock file
   sprintf(lock_file,"%s/lock.file",redir[0]->ban_dir);
   #ifdef DEBUG_RUN_MAKE_CACHE
   fprintf(stderr,"lock file: %s\n",lock_file);
   #endif

   // Open lock file
   fd = open (lock_file, O_RDWR | O_CREAT,0600);
   if (fd < 0)
   {
    sprintf(etmp,"MAKE-CACHE: ERROR: Can't open file %s: %s\n",lock_file,strerror(errno));
    err_mes(etmp);
   }

   if (fcntl (fd, F_SETLK, &lck)<0)
   {
    // I not first, wait first finished
    err_mes("Waiting for make-cache finished");

    for (;;)
    {
      fcntl(fd, F_GETLK, &lck);
      if(lck.l_type==F_UNLCK) break;
      sleep(1);
    }

    err_mes("Make-cache finished detected, continue");
   }
   else
   {
     // I first, run make cache
     sprintf(etmp,"Run make-cache (%s)",VERSION);
     err_mes(etmp);

     //Fork
     pid=fork();
     if (pid<0)
      {
       err_mes("ERROR: Can't fork");
       exit(-1);
      }

     if (pid==0)
      { //child run make-cache
       if (execl(makecache,makecache,config,NULL)<0)
       {
        sprintf(tmp,"ERROR: Can't run \"%s %s\": %s\n",makecache,config, strerror(errno));
        err_mes(tmp);
        exit(-1);
       }
      }
      else
      {
       waitpid(pid,&status,0);
       if(WEXITSTATUS(status))
       {
        sprintf(tmp,"ERROR: make-cache finished abnormal.");
        err_mes(tmp);
        exit(-1);
       }
      }
      err_mes("Make-cache finished");

     // Unlock
      lck.l_type = F_UNLCK;

      if (fcntl (fd, F_SETLK, &lck)<0)
       {
        sprintf(etmp,"MAKE-CACHE: ERROR: fcntl return error: %s",strerror(errno));
        err_mes(etmp);
        exit(-1);
       }

   }

 close(fd);
 return(0);
}
