/* -------------------------------------------------------------------------- */
/*
                      NAME : misc.c
               DESCRIPTION : Various functions

                    AUTHOR : Heini Withagen
                    E-MAIL : heini@w4.nl
	          WWW-SITE : http://sparkie.riv.net/w4/index.html
                  CREATION : 21-08-1995
         LAST MODIFICATION : 30-08-1995

*/ 
/* -------------------------------------------------------------------------- */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <sys/file.h>
#include <unistd.h>
#include <signal.h>
#include "misc.h"
#include "conf.h"

static int lock_fd;

/* --------------------------------------------------------------------------- */

int init(void)
{
  /* program the alarm clock to prevent programs
     from hanging themself up */
  signal(SIGALRM, sig_alarm);
  alarm(ALARM_INTERVAL);

  lock_fd = creat(LOCK_FILE, 0600);
  if (lock_fd < 0)
    exit_with_http_error("Lock problem");

  /* get lock for the running version of the program */
  get_lock();
}

/* --------------------------------------------------------------------------- */

/* Function returns a random number with the specified width.
   If width = 0, an number with arbitrary width will be returned */

int random_number(int width)
{
  srand(time(NULL));
  if (width)
    return (( (double)rand()/(double)RAND_MAX ) * pow( 10.0, (double)width )); 
  else
    return rand();
}

/* --------------------------------------------------------------------------- */

/* alarm function is only reached if something went wrong */
   
void sig_alarm(int signo)
{
  errorlog("nph-count alarm activated, releasing lock; exiting");  
  release_lock();
  exit(0);
}

/* --------------------------------------------------------------------------- */

void get_lock(void)
{
  /* flock(lock_fd, LOCK_EX); */

#ifdef F_SETLKW
 
  struct flock lock;

  lock.l_type = F_WRLCK;
  lock.l_start = 0;
  lock.l_whence = SEEK_SET;
  lock.l_len = 0;

  fcntl(lock_fd, F_SETLKW, &lock); 
#endif
}

/* --------------------------------------------------------------------------- */

void release_lock(void)
{
  /* flock(lock_fd, LOCK_UN); */

#ifdef F_SETLKW

  struct flock lock;

  lock.l_type = F_UNLCK;
  lock.l_start = 0;
  lock.l_whence = SEEK_SET;
  lock.l_len = 0;

  fcntl(lock_fd, F_SETLK, &lock);
#endif
}

/* --------------------------------------------------------------------------- */

void exit_with_http_error(char *message)
{
  char str[64];

  sprintf(str, "HTTP/1.0 500 %s\n", message);
  fputs(str, stdout);
  release_lock();

  exit(1);
}

/* --------------------------------------------------------------------------- */

void errorlog(char *message)
{
  char str[32];
  time_t current_time = time(NULL);
  struct tm time_struct;
  FILE *fp;

  time_struct = *(localtime(&current_time));
  sprintf(str, "%s", asctime(&time_struct) );
  str[strlen(str)-1] = '\0';

#ifdef SERVER_ERROR_LOG
  fprintf(stderr, "[%s] nph-count: %s\n", str, message);
#endif

#ifdef FILE_ERROR_LOG
  if ( (fp = fopen(ERROR_FILE, "a")) )
  {
    fprintf(fp, "[%s] nph-count: %s\n", str, message);
    fclose(fp);
  }
#endif

}

/* --------------------------------------------------------------------------- */
