/* files.c  --  The file holding all i/o functions required by Sigit..
   
   Copyright (C) Kenneth 'Redhead' Nielsen <redhead@diku.dk>
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

/* $Id: files.c,v 0.10 2001/08/13 16:43:00 redhead Exp $ */

#include "files.h" // #include "config.h"

/* just a small function used to create random numbers */

inline unsigned long int get_rand (unsigned long int max, unsigned short int verbose, unsigned short sys_log) 
{
  size_t res;
  time_t tim, c_start;
  if(max <= 0)
    return 0;
  logging(1, verbose, 4, sys_log, 0, "Who wants a Lesotho ?\n");
  c_start = clock();
  srandom(c_start);
  logging(2, verbose, 2, sys_log, 0, "[get_rand] Feeding srand() with bouderies, max: %d.\n", max);
  time(&tim);
  srandom(tim);
  logging(1, verbose, 2, sys_log, 0, "[get_rand] Charging srandom() to give us our random number.\n\t");
  res = random() % max;
  logging(0, verbose, 2, sys_log, 0, "*%d|%d*", (int) max, (int) res);
  logging(1, verbose, 3, sys_log, 0, "[get_rand] Returning with a normal inbound number.\n\t");
  return res;
}

/*
 * this is a function, which will take a integer, 
 * and from that make a unique hexa number. 
 * it is intentively to be called when you realy need a unique number
 * the buff should hold atleast 
 */
inline void create_hex(char buff[], unsigned short int verbose, unsigned short sys_log)
{
   /* creating a number which you cant
   * recreate in a million years or so.. 
   * unless the time on your computer 
   * is realy fucked.. 
   */
  static size_t counter = 0;
  size_t time_stamp = time(NULL);
  logging(2, verbose, 3, sys_log, 0, "Can time be NULL ??\n\t");
  counter++;
  logging(1, verbose, 2, sys_log, 0, "[create_hex] counter is: %d\n", counter);
  time_stamp += counter;
  logging(1, verbose, 2, sys_log, 0, "[create_hex] time_stamp is: %d\n\t", time_stamp);
  sprintf(buff, "%X", time_stamp);
  logging(0, verbose, 1, sys_log, 0, "-{%s}-",buff);
  logging(1, verbose, 4, sys_log, 0, "- ### Ceci nést pas un error. ### -\n");
}


/* a function to add all the signatures you need */
int add_sig(struct setting *conf)
{
  FILE* in_file;
  char buffer[LINE_SIZE +1];
  unsigned long int total = 0;
  unsigned int number, identifyer;
  conf->sig_n.ident[0] = '\0';
  logging(1, conf->verbose, 0, conf->sys_log, 1, ": Adding sig from file [%s].\n", conf->optarg_element);
  logging(0, conf->verbose, 1, conf->sys_log, 0, "\t[+");
  
  /*
    first we have the routine to read in the signature.. 
    (lets hope theres enough room for it in the NUM_LINES*LINE_SIZE)
     Lets hope fopen will return NULL if the file dosnt exist.
  */
  if( !(in_file = fopen(conf->optarg_element, "r")))
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Couldn't open file.\n");
      return CONF_MI;
    }
  /* else lets peek in the file, to see if it contains alot of signatures.. */
  if(!fgets(buffer, LINE_SIZE, in_file))
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : The file is empty.\n");
      return NO_READ;
    }
  if(buffer[0] == '@' && buffer[1] == '@')
    { 
      if(sscanf(buffer, "@@[Number: %d]--[Identifier: %X]@@\n", &number , &identifyer) == 2)
	sprintf(conf->sig_n.ident, "%X", identifyer);
      while(!feof(in_file))
	{
	  if(!fgets(buffer, LINE_SIZE, in_file))
	    {
	      logging(2, conf->verbose, 2, conf->sys_log, 0, "[add_sig] there was nothing more to read.\n");
	      continue; /* next time in the while this will get cought */
	    }
	  total += strlen(buffer); /* first time will allways have enough room */
	  logging(2, conf->verbose, 2, conf->sys_log, 0, "[add_sig] The total is: %d.\n", total);
	  strcpy(conf->sig_n.sig, buffer); /* we hope this is the first sig line */
	  logging(2, conf->verbose, 3, conf->sys_log, 0, "[add_sig] The buffer is containing {%s}.\n", buffer);
	  while(!feof(in_file))
	    { /* we recon theres gonna be no error once we made the first successfull read */
	      fgets(buffer, LINE_SIZE, in_file);
	      logging(0, conf->verbose, 1, conf->sys_log, 0, "+");
	      if(buffer[0] == '@' && buffer[1] == '@')
		{/* now we must assume, that the entire sig is gathered in sign */
		  if(set_sig(conf))
		    {
		      fclose(in_file);
		      return FAILURE;
		    }
		  conf->sig_n.sig[0] = '\0';
		  if(sscanf(buffer, "@@[Number: %d]--[Identifier: %X]@@\n", &number , &identifyer) == 2)
		    sprintf(conf->sig_n.ident, "%X", identifyer);
		  else
		    conf->sig_n.ident[0] = '\0';
		  total = 0;
		  continue; /* lets skip the rest of the loop */
		}
	      if((total += strlen(buffer)) < (NUM_LINES*LINE_SIZE -1))
		{
		  strncat(conf->sig_n.sig, buffer, strlen(buffer));
		}
	      else
		{
		  logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : The signature was longer than %d chars.\n", 
			NUM_LINES*LINE_SIZE);
		  fclose(in_file);
		  return EXCEEDED;
		}
	    }
	  total = 0;
	  logging(0, conf->verbose, 1, conf->sys_log, 0, "|");
	}
      logging(0, conf->verbose, 1, conf->sys_log, 0, "+]\n");
      logging(1, conf->verbose, 0, conf->sys_log, 1, "   DONE\n");
      fclose(in_file);
    }
  else
    { /* we only have one sig, so lets just put that in there.. */
      strncpy(conf->sig_n.sig, buffer, strlen(buffer));
      logging(2, conf->verbose, 3, conf->sys_log, 0, "[add_sig] The buffer is containing {%s}.\n", buffer);
      conf->sig_n.sig[strlen(buffer)] = '\0';
      while (fgets(buffer, LINE_SIZE, in_file) > 0)
	{
 	  logging(0, conf->verbose, 1, conf->sys_log, 0, "+");
 	  total += strlen(buffer);
	  logging(2, conf->verbose, 2, conf->sys_log, 0, "[add_sig] The total is: %d.\n", total);
	  if(total < NUM_LINES*LINE_SIZE)
	    {
	      strncat(conf->sig_n.sig, buffer, strlen(buffer));
	      continue;
	    }
	  else
	    {
	      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] :The signature was longer than %d chars.\n", 
		      NUM_LINES*LINE_SIZE);
	      fclose(in_file);
	      return EXCEEDED;
	    }
	  logging(0, conf->verbose, 1, conf->sys_log, 0, "|");
	}
      if(set_sig(conf))
	{
	  fclose(in_file);
	  return FAILURE;
	}
      logging(0, conf->verbose, 1, conf->sys_log, 0, "+]\n");
      logging(1, conf->verbose, 0, conf->sys_log, 1, "   DONE\n");
      fclose(in_file);
    }
  return SUCCESS;
}


/* well isnt this fun, lets get a signature by the number we now know.. */
int get_sig(struct setting *conf)
{
  FILE* out_file;

  logging(1, conf->verbose, 0, conf->sys_log, 1, "Getting sig from file: [%s]\n", conf->sig_file);
  logging(0, conf->verbose, 1, conf->sys_log, 0, "\t[+");

  if(!(out_file = fopen(conf->data_file, "rb")))
    { /* at this point we should be at the top of the file */
      /* some error happened */
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can not open file.\n");
      return CONF_MI;
    }
  if(!fread((void*) &(conf->cnt), sizeof(conf->cnt),1 ,out_file))
    {
      /* some error happened */
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : The file is empty.\n");
      fclose(out_file);
      return COUNT_MISS;
    }
  logging(0, conf->verbose, 1, conf->sys_log, 0, "+>%d<+", (int) ntohl(conf->cnt.count));
  /* now we know the max count, so lets get the random number for that */
  conf->c_num = get_rand(ntohl(conf->cnt.count) -2, conf->verbose, conf->sys_log);
  logging(0, conf->verbose, 1, conf->sys_log, 0, "+>%d<+", (int) conf->c_num);
  /* the lets search for that signature */
  if(fseek(out_file, conf->c_num*sizeof(conf->sig_n), SEEK_CUR) != 0)
    {
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't seek in file.\n");
      fclose(out_file);
      return SEEK_ERR;
    }
  /* lets read that signature we have now */
  if(!fread((void*) &(conf->sig_n), sizeof(conf->sig_n),1, out_file))
    {
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : The file is empty.\n");
      fclose(out_file);
      return NO_READ;
    }
  logging(0, conf->verbose, 1, conf->sys_log, 0, "+]\n");
  logging(1, conf->verbose, 0, conf->sys_log, 1, "   DONE\n");
  fclose(out_file);
  return SUCCESS;
}

/* 
 * this function is very simmular to the get_sig() 
 * it just writes in a loop what's in the database 
*/
	
int edit_data_file(struct setting *conf)
{
  char test_temp[NUM_LINES*LINE_SIZE +2], exec_line[LINE_SIZE +1], *editor; 
  size_t i = 1, pid, xpid;
  int waiter;
  FILE* in_file;
  FILE* out_file;
  logging(1, conf->verbose, 0, conf->sys_log, 1, "Getting sig from file: [%s].\n", conf->data_file);
  logging(1, conf->verbose, 0, conf->sys_log, 1, "Writing edit file  ");
  logging(0, conf->verbose, 1, conf->sys_log, 0, " [+");
  if(!(in_file = fopen(conf->data_file, "rb")))
    { /* at this point we should be at the top of the file */
      /* some error happened */
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can not open data file.\n");
      return CONF_MI;
    }
  if(!(out_file = fopen(conf->optarg_element, "w")))
    {
      /* at this point we should be at the top of the file */
      /* some error happened */
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can not open editing file: [%s]\n", conf->optarg_element);
      return CONF_MI;
    }
  if(!fread((void*) &(conf->cnt), sizeof(conf->cnt),1 ,in_file))
    {
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't read from file: [%s]\n", conf->data_file);
      /* some error happened */
      fclose(in_file);
      fclose(out_file);
      return COUNT_MISS;
    }
  logging(0, conf->verbose, 1, conf->sys_log, 0, "+>Total: %d<+", (int) ntohl(conf->cnt.count));
  /* now we know the max count, so lets get the random number for that */
  for(; i <= ntohl(conf->cnt.count) && !feof(in_file); i++)
    { 
      if(!fread((void*) &(conf->sig_n), sizeof(conf->sig_n),1, in_file))
	{
	  logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't read from file: [%s]\n", conf->data_file);
	  fclose(in_file);
	  fclose(out_file);
	  return NO_READ;
	}
      if(conf->delete && !strcasecmp(conf->sig_n.ident, conf->delete_sig))
	{
	  logging(2, conf->verbose, 0, conf->sys_log, 0, "Deleting Sig [%s]\n\t", conf->sig_n.ident);
	  if(conf->verbose > 4)
	    Mostly_Harmless(conf);
	  continue; /* hmm this was the signature we wanted to delete.. */
	}
      logging(0, conf->verbose, 1, conf->sys_log, 0, "+>%d<+", (int) i);
      if(0 < sprintf(test_temp,"%s", conf->sig_n.sig)) /* this is ugly.. totaly idiotic.. */
	{ /* but it is nesssary, if we want to have the correct number of signatures..*/
	  /* non the less.. it seems to remove the very last signature from the database */
	  if(!fprintf(out_file, "@@[Number: %d]--[Identifier: %s]@@\n", 
		      ntohl(conf->sig_n.count), conf->sig_n.ident))
	    {
	      logging(2, conf->verbose, 1, conf->sys_log, 0, "[ERROR] : Can't write to editing file.\n");
	      fclose(in_file);
	      fclose(out_file);
	      return FAILURE;
	    }
	  if(!fprintf(out_file, "%s", conf->sig_n.sig))
	    {
	      logging(2, conf->verbose, 1, conf->sys_log, 0, "[ERROR] : Can't write to editing file.\n");
	      fclose(in_file);
	      fclose(out_file);
	      return FAILURE;
	    }
	}
    }
  /* here we must be at the end of the out_put file.. Thus we create the last thing */
  if(!fprintf(out_file, "@@[O'lack atlast we've reached The End.]@@\n"))
    {
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't write to editing file.\n");
      fclose(in_file);
      fclose(out_file);
      return FAILURE;
    }
  logging(0, conf->verbose, 1, conf->sys_log, 0, "+]\n");
  logging(1, conf->verbose, 0, conf->sys_log, 1, "   DONE\n");
  fclose(in_file);
  fclose(out_file);
  if(conf->list || conf->delete)
    return SUCCESS;
  if ((!(editor = getenv("VISUAL")))
      && (!(editor = getenv("EDITOR")))
      ) {
    editor = DEFAULT_EDITOR;
  }
  
  switch (pid = fork()) {
  case -1:
    logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Creating fork()\n");
    return FAIL_FO;
  case 0:
    /* child */
    if (chdir("/tmp") < 0) {
      logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Couldn't change dir to /tmp\n");
      return FAILURE;
    } 
    if (strlen(editor) + strlen(conf->optarg_element) + 2 >= LINE_SIZE) {
 	  logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : The file length with the editor exceeded buffer length.\n");
	  return EXCEEDED;
    }
    sprintf(exec_line, "%s %s", editor, conf->optarg_element);
    execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", exec_line, NULL);
    logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Couldn't execute editor.\n");
    logging(1, conf->verbose, 4, conf->sys_log, 0, "Powered by: cat - ^D\n\t");
    logging(0, conf->verbose, 4, conf->sys_log, 0, "\t- Because editors are for whimps.\n");
    return FAILURE;
    /*NOTREACHED*/
  default:
    /* parent */
    break;
  }
  
  /* parent */
  xpid = wait(&waiter);
  if (xpid != pid) {
    logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : wrong PID (%d != %d) from \"%s\"\n", (int) xpid, (int) pid, editor);
    return FAILURE;
  }
  if (WIFEXITED(waiter) && WEXITSTATUS(waiter)) {
    logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : \"%s\" exited with status %d\n",
	    editor, WEXITSTATUS(waiter));
    return FAILURE;
  }
  if (WIFSIGNALED(waiter)) {
    logging(2, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : \"%s\" killed; signal %d (%score dumped)\n",
	    editor, WTERMSIG(waiter),
	    WCOREDUMP(waiter) ?"" : "no ");
    return FAILURE;
  }
  return SUCCESS;
}


/* 
   set sig will open the sigdatabase and add the signature to it..
*/

int set_sig(struct setting *conf)
{
  char touch_cmd[LINE_SIZE];
  FILE* out_file;
  int was_there = 1;
  conf->cnt.count = htonl(0);
  strcpy(conf->cnt.ver, VERSION);
  logging(0, conf->verbose, 1, conf->sys_log, 0, "<");
  if(strlen(conf->sig_n.sig) > NUM_LINES*LINE_SIZE)
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] :The signature was longer than %d chars.\n", 
	      NUM_LINES*LINE_SIZE);
      return EXCEEDED;
    }
  if(conf->sig_n.ident[0] == '\0')
    create_hex(conf->sig_n.ident, conf->verbose, conf->sys_log);
  if(access(conf->data_file, F_OK))
    { /* it must be the very first signature.. hence no file */
      logging(2, conf->verbose, 3, conf->sys_log, 0, "[set_sig] The signature file never existed, creating one.\n");
      sprintf(touch_cmd, "touch %s", conf->data_file);
      system(touch_cmd);
      was_there = 0;
    }
  logging(0, conf->verbose, 1, conf->sys_log, 0, "-");
  
  /* if the file allready exists, then there must be atleast one sig in it */
  /* we now return to the start of the file */
   if(!(out_file = fopen(conf->data_file, "rwb+")))
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR : Cant open file {%s} for adding a sig.\n", conf->data_file);
      return FAILURE;
    }
  if(fseek(out_file, 0, SEEK_SET) != 0)
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Cant seek in file.\n");
      fclose(out_file);
      return SEEK_ERR;
    }
  if(was_there)
    if(!fread((void*) &(conf->cnt), sizeof(conf->cnt),1, out_file))
      {
	logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't read from file. {%s}\n", conf->data_file);
	fclose(out_file);
	return NO_READ;
      }
  logging(0, conf->verbose, 1, conf->sys_log, 0, "-]%d[-", ntohl(conf->cnt.count));
  
  /* then we increase that, and stores the new value to the file */
  if(fseek(out_file, 0, SEEK_SET) != 0)
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't seek in file.\n");
      fclose(out_file);
      return SEEK_ERR;
    }
  conf->cnt.count = htonl(ntohl(conf->cnt.count) + 1);
  logging(0, conf->verbose, 1, conf->sys_log, 0, "-[%d]-", ntohl(conf->cnt.count));
  if(!fwrite((void*) &(conf->cnt), sizeof(conf->cnt),1, out_file))
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't write count to file {%s}.\n", conf->data_file);
      fclose(out_file);
      return WRITE_ERR;
    }
  conf->sig_n.count = conf->cnt.count;
  /* now we can search to the end of the file, and store the new signature */
  if(fseek(out_file, 0, SEEK_END) != 0)
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't seek in file.\n");
      fclose(out_file);
      return SEEK_ERR;
    }
  logging(0, conf->verbose, 1, conf->sys_log, 0, "-");
  if(!fwrite((void*) &(conf->sig_n), sizeof(conf->sig_n),1, out_file))
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't write signature to file. {%s}\n", conf->data_file);
      fclose(out_file);
      return WRITE_ERR;
    }
  logging(0, conf->verbose, 1, conf->sys_log, 0, ">");
  fclose(out_file);
  return SUCCESS;
}



int buffer_magic(char ch, char buffer[], 
		 int sig_write, 
		 int *l_count, 
		 int *prity_sig_count, 
		 int *line_count, 
		 int *buffer_count)
{
  FILE  *fp;
#ifdef LINUX
  int upt = 0, temp = 0, days = 0, hours = 0, min = 0;
#endif
  int counter = 0;
  char uname_buffer[LINE_SIZE +1], tmp[10];
  struct utsname unamebuf;
  struct tm *tm_set;
  time_t tim, t;
  /* to make sure, the garbage in memory
     isnt causing any problems.*/
  uname_buffer[0] = '\0';
  tmp[0] = '\0';
  uname(&unamebuf);  
  switch(ch)
    {
    case('t'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      break;
    case ('H'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      strcpy(uname_buffer, HOMEPAGE);
      uname_buffer[strlen(HOMEPAGE)] = '\0';
      *line_count = *line_count + strlen(HOMEPAGE);
      break; 
    case ('M'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      sprintf(uname_buffer, "%s", unamebuf.machine);
      uname_buffer[strlen(unamebuf.machine)] = '\0';
      *line_count = *line_count + strlen(unamebuf.machine);
      break;
    case('N'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      sprintf(uname_buffer, "%s", unamebuf.nodename);
      uname_buffer[strlen(unamebuf.nodename)] = '\0';
      *line_count = *line_count + strlen(unamebuf.nodename);
      break;
    case ('P'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      strcpy(uname_buffer, PACKAGE);
      uname_buffer[strlen(PACKAGE)] = '\0';
      *line_count = *line_count + strlen(PACKAGE);
      break; 
    case ('R'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      sprintf(uname_buffer, "%s", unamebuf.release);
      uname_buffer[strlen(unamebuf.release)] = '\0';
      *line_count = *line_count + strlen(unamebuf.release);
      break; 
    case ('S'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      sprintf(uname_buffer, "%s", unamebuf.sysname);
      uname_buffer[strlen(unamebuf.sysname)] = '\0';
      *line_count = *line_count + strlen(unamebuf.sysname);
      break;
    case ('T'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      tim = time(&t);
      tm_set = localtime(&tim);
      sprintf(uname_buffer, "%.2d:%.2d", tm_set->tm_hour, tm_set->tm_min);
      *line_count = *line_count + strlen(uname_buffer);
      break;
    case ('U'):
      /* I know the HP_UX havn't gotten the same /proc structure as Linux
	 There might be other architechtures suffering of the same*/
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;

#ifdef LINUX
      fp = fopen("/proc/uptime", "r");
      fscanf(fp, "%d %d", &upt, &temp);
      fclose(fp);
      days = upt/86400;
      upt = upt%86400;
      hours = upt/3600;
      upt = upt%3600;
      min = upt/60;
      tim = time(&t);
      tm_set = localtime(&tim);
      if(days >0)
	sprintf(uname_buffer, "%.2d:%.2d up %.2d days, ", tm_set->tm_hour, tm_set->tm_min, days);
      else
	sprintf(uname_buffer, "%.2d:%.2d up ", tm_set->tm_hour, tm_set->tm_min);
      sprintf(tmp, "%.2d:%.2d", hours, min);
      strcat(uname_buffer, tmp);
      *line_count = *line_count + strlen(uname_buffer);
#endif

      break;
    case ('V'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      strcpy(uname_buffer, VERSION);
      uname_buffer[strlen(VERSION)] = '\0';
      *line_count = *line_count + strlen(VERSION);
      break; 
    case ('%'):
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      strcpy(uname_buffer, "%");
      uname_buffer[1] = '\0';
      *line_count = *line_count +1;
      break;
    default:
      if(sig_write == 0)
	*l_count = *l_count +1;
      else
	*prity_sig_count = *prity_sig_count +1;
      break;
    }
  for(counter = 0; 
      *buffer_count < *line_count && 
	*buffer_count < LINE_SIZE && 
	uname_buffer[counter] != '\0'; 
      *buffer_count = *buffer_count +1, counter++)
      buffer[*buffer_count] = uname_buffer[counter];
     
    
  return SUCCESS;
}
/* 
 * This is the pretty printer.. 
 *
 */

int pretty_print(struct setting *conf)
{
  FILE *out_file;
  char ch, line_buff[LINE_SIZE +3], buffer[LINE_SIZE +3];
  int line_count = 0, last_line = 0, sig_write = 0, buffer_count = 0, longest_line = 0;  
  int prity_count = 0, sig_count = 0, l_count = 0, one_two = 0, started = 0, spaces, i;
  
  logging(1, conf->verbose, 0, conf->sys_log, 1, "Opening the fifo: [%s] for writing.\n", conf->sig_file);
  logging(0, conf->verbose, 1, conf->sys_log, 0, "\t[+");
  /* make the normal required "-- \n" as the first line of a sig. */
  if(!(out_file = fopen(conf->sig_file, "w")))
    {
      logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't open file {%s} for writing.\n", conf->sig_file);
      /* some error happened */
      return CONF_MI;
    }
  if(conf->slash)
    { /* if the user told, that the system dosnt put it in */
      if(!fwrite("-- \n", 4, 1, out_file))
	{
	  logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't write [-- \\n] to file {%s}.\n", conf->sig_file);
	  fclose(out_file);
	  return WRITE_ERR;
	}
      logging(0, conf->verbose, 2, conf->sys_log, 0, "++W -- \\n W++");
    }
  logging(0, conf->verbose, 2, conf->sys_log, 0, "++W Signature W++");
  logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Preparing to write signature number: %d.\n", conf->sig_n.count);
  if(strlen(conf->t_line) > 2)
    {
      logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Preparing to write t_line {%s} if it will fit.\n", conf->t_line);
      strncpy(line_buff, conf->t_line, LINE_SIZE);
      /* #### very dangerous, counting to -1, but if we should allready #### */
      /* #### print one line, then the counter will be 0 for the first  #### */
      /* ####               run through the prity buffer.               #### */
      prity_count--;
    }
  else
    { /* we need to avoid the sig_count to be -1, so we have the started flag */
      logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] No t_line to write, altering started flag.\n");
      started = 1;
      sig_write = 1;
      one_two++;
    }
  for( ; sig_write != 4 ; )
    { 
      logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Currently using sig_write setting {%d} in the process.\n", sig_write);
      
      /*
       * sig_write == 0  writing either top line or bottom line
       * sig_write == 1  writing presetting
       * sig_write == 2  writing signature
       * sig_write == 3  done writing signature
       * sig_write == 4  We've finished bottom line and its time to get out.
       */
      
      /* if its either the top line or the pre setting
	 we have the conversion chars to check */
      if(sig_write <= 1)
	{
	  logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Checking conversion chars.\n");
	  if(sig_write == 0)
	    ch = line_buff[l_count];
	  else
	    ch = conf->pritty[prity_count];
 	  if(ch == '%')
 	    {
	      if(sig_write == 0)
		l_count++;
	      else
		prity_count++;
	      if(sig_write == 0)
		ch = line_buff[l_count];
	      else
		ch = conf->pritty[prity_count];
	      
	      logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Calling buffer_magick() with [ch: %c, sig_write: %d, l_count: %d, prity_count: %d, line_count: %d, buffer_count: %d]\n",ch, sig_write, l_count, prity_count, line_count, buffer_count);
	      
	      buffer_magic(ch, buffer, 
			   sig_write, 
			   &l_count, 
			   &prity_count, 
			   &line_count, 
			   &buffer_count);
	      
	      logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Returning from buffer_magick() with [ch: %c, sig_write: %d, l_count: %d, prity_count: %d, line_count: %d, buffer_count: %d]\n",ch, sig_write, l_count, prity_count, line_count, buffer_count);
	      
	    }
	  if(sig_write == 0)
	    {
	      if(line_buff[l_count] != '\0' && 
		 line_count < LINE_SIZE && 
		 buffer_count < LINE_SIZE)
		{
		  if(line_buff[l_count] == '\n')
		    {
		      l_count++;
		      sig_write = 4;
		    }	      
		  else
		    {
		      buffer[buffer_count++] = line_buff[l_count++];
		      line_count++;
		      if(line_count >= LINE_SIZE)
			sig_write = 4;
		    }
		}
	      else 
		sig_write = 4;
	    }
	  else
	    {
	      if(strlen(conf->pritty) > 1)
		{ /* as long as theres something in the pritty, we just copy it to our buffer */
		  if(conf->pritty[prity_count] != '\n' && 
		     conf->pritty[prity_count] != '\0' && 
		     line_count < LINE_SIZE) 
		    {
		      buffer[buffer_count++] = conf->pritty[prity_count++];
		      line_count++;
		    } /* if its a \n we've reached its time to write the signature */
		  if(conf->pritty[prity_count] == '\n')
		    {
		      buffer[buffer_count++] = ' ';
		      buffer[buffer_count++] = ' ';
		      prity_count++;
		      last_line = line_count;
		      sig_write = 2;
		    } 
		  /* if we've reached this part, and yet there was more signature to write
		     then we just fill blanks for the remaining preset, so there won't be
		     some odd mengling of the signature.. */
		  
		  logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Filling the preset space with ' ' to accomplish smooth transformation.\n");
		  
		  if(conf->pritty[prity_count] == '\0')
		    {
		      line_count = 0;
		      for(i = 0; i <= last_line; i++)
			{ 
			  buffer[buffer_count++] = ' ';
			  line_count++;
			}
		      sig_write = 2;
		      /* making a slow ajustment to the normal line_size */
                      if(line_count <= 2)
                        last_line = 0;
                      else
			last_line = (line_count -2);
		    }
		} 
	      else
		sig_write = 2;
	    }  
	} /* now its time to write the signature part */
      if(sig_write == 2)
	{

	  if(conf->sig_n.sig[sig_count] != '\0' && 
	     line_count < LINE_SIZE)
	    { /* the '\n' will be added later */
	      if(conf->sig_n.sig[sig_count] == '\n')
		{
		  sig_count++;
		  sig_write = 3;
		}	      
	      else
		if(conf->sig_n.sig[sig_count] == '%' && conf->sig_n.sig[sig_count +1] == 'r')
		  {		  
		    if(!sig_count)
		      longest_line = LINE_SIZE -2;
		    else
		      if(conf->sig_n.sig[sig_count -1] != '\n')
			goto out;
		    sig_count += 2;
		    
		    /* removing any leading spaces in the signature */
		    while(conf->sig_n.sig[sig_count] == ' ' || conf->sig_n.sig[sig_count] == '\t')
		      sig_count++;
		    
		    for(spaces = 0; 
			(conf->sig_n.sig[sig_count + spaces] != '\n' &&
			 conf->sig_n.sig[sig_count + spaces] != '\0') &&
			  spaces < LINE_SIZE; spaces++)
		      /* just count what we need.. */ ;
		    
		    /* setting the spaces needed, to right place it */
		    if(longest_line - spaces > 0)
		      for(i = 0; i < longest_line - spaces - last_line && 
			    line_count + spaces < LINE_SIZE; i++)
			{
			  buffer[buffer_count++] = ' ';
			  line_count++;
			}
		    
		    
		  }
		else
		  { /* we just copy it into our buffer. The easiest way */
		  out:
		    buffer[buffer_count++] = conf->sig_n.sig[sig_count++];
		    line_count++;
		  }
	    }
	  else 
	    sig_write = 3;
	}/* thi is reached, if we have a full buffer to write.. */
      if(sig_write >= 3 || line_count >= LINE_SIZE)
	{
	  /* #### In order to correct the -1 in the prity_count #### */
	  if(prity_count == -1)
	    prity_count++;
	  else
	    {
	      if(conf->pritty[prity_count] != '\0')
		prity_count++;
	    } /* was it the bottom line we were writing ? */
	  if(sig_write == 4)
	    {
	      started = 1;
	      one_two++;
	      line_buff[0] = '\0';
	    }
	  else
	    {
	   logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Finding the last white space, where we can split the line.\n");

	      /* it must have been part of the signature and preset, 
		 so if were in the middle of a word, we better go back to a white space */
	      if(conf->sig_n.sig[sig_count] != '\0' && 
		 conf->sig_n.sig[sig_count] != '\n' && 
		 conf->sig_n.sig[sig_count] != ' ' && 
		 conf->sig_n.sig[sig_count] != '\t' && 
		 started &&
		 conf->sig_n.sig[sig_count -1] != '\n')
		for(; conf->sig_n.sig[sig_count] != ' ' && 
		      conf->sig_n.sig[sig_count] !='\n' && 
		      conf->sig_n.sig[sig_count] !='\t' && 
		      conf->sig_n.sig[sig_count] != '\0'; sig_count--, buffer_count--)
		  /* lets just count.. */ line_count--;
	      else /* it was the first line, so its OK to start searching for white spaces */
		started = 1;
	    }/* if theres nothing in the buffer, then why bother filling more */	
	  if(!buffer_count &&
	      conf->sig_n.sig[sig_count] == '\0' && 
	      conf->pritty[prity_count] == '\0')
	    sig_write = 4;
	  else
	    {/* write what we got so far */
	      if(started && conf->sig_n.sig[sig_count] == '\n')
		{
		  sig_count++;
		  /* this might be where the buffer[buffer_count] = '\n'; should be */
		}
	      buffer[buffer_count++] = '\n';
	      buffer[buffer_count] = '\0';
	      buffer_count = 0;

	      logging(2, conf->verbose, 3, conf->sys_log, 0, "[pretty_print] Writing signature part {%s} to the fifo.\n", buffer);

	      if(!fwrite(buffer, strlen(buffer), 1, out_file))
		{
		  logging(1, conf->verbose, 0, conf->sys_log, 1, "[ERROR] : Can't write signature to file.\n");
		  fclose(out_file);
		  return WRITE_ERR;
		}/* prepare for the writing of presetting next */
	      sig_write = 1;
	      if(sig_count > 1 && longest_line < line_count)
		longest_line = line_count;
	      line_count = 0;  
	    }
	  logging(0, conf->verbose, 1, conf->sys_log, 0, "++");
	  /* hmmm are we done writing the signature and should we select bottom line now ? */
	  if(conf->pritty[prity_count] == '\0' && conf->sig_n.sig[sig_count] == '\0')
	    {
	      if(line_buff[0] == '\0' && one_two > 1)
		sig_write = 4; /* if we allready are done with the bottom line we exit */
	      if(one_two == 1)
		{ /* if there has been just one (indicating top line ) go on */
		  if(strlen(conf->b_line) > 1) 
		    {/* if theres somethign inteh bottom lie we can write it */
		      sig_write = 0;
#ifdef LINUX
		      strncpy(line_buff, conf->b_line, LINE_SIZE);
#else
		      strcpy(line_buff, conf->b_line);
#endif
		      l_count = 0;
		    }
		  else /* else we might aswell exit.. */
		    sig_write = 4;
		}
	    }	
	}
    }
  logging(0, conf->verbose, 1, conf->sys_log, 0, "+]\n");
  logging(1, conf->verbose, 0, conf->sys_log, 1, "   DONE\n");
  logging(1, conf->verbose, 4, conf->sys_log, 0, "So Long and Thanks for all the Fish.\n");
  fclose(out_file);
  return SUCCESS;
}


/* hmmm lets hope people won't read this far in the file.. */

int _shine_on_you_crazy_diamond_(void){return(printf("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",10,34,84,104,101,32,98,97,110,100,32,105,115,32,106,117,115,116,32,102,97,110,116,97,115,116,105,99,44,10,32,116,104,97,116,32,105,115,32,114,101,97,108,121,32,119,104,97,116,32,73,32,116,104,105,110,107,46,10,32,45,79,104,32,98,121,32,116,104,101,32,119,97,121,44,32,119,104,105,99,104,32,111,110,101,32,105,115,32,80,105,110,107,32,63,34,10,9,45,32,45,32,80,105,110,107,32,70,108,111,121,100,32,45,32,72,97,118,101,32,65,32,67,105,103,97,114,46,10,10));}



syntax highlighted by Code2HTML, v. 0.9.1