/*   $Id: process.c,v 1.9 2000/03/30 09:24:40 jap Exp $

 *    Copyright (c) 1998 John Phillips
 *
 *    You may distribute under the terms of the Artistic License
 *
 */

#include "bcnu.h"

extern struct bcnu_agent_def bcnud_agent[];
extern struct bcnu_msg_def bcnud_in;
extern char progname[];
extern char *id, *subver;
extern char starttime[];
extern char buf[], response[];
extern int s, masterok, fqdn;

int http = 0;
int err, msg, agt;

int bcnu_parse (buf, len)
     char *buf;
     int len;
{

  char *ptr, *ptrb;
  int items;
  char severity[5], time_logged[12], htype[4];

  buf[len] = 0;
  ptrb = buf;

  bcnud_in.host_type = HOST_ANY;
  bcnud_in.proto_version = 0;

  if (debug)
    printf ("buf=%s\n", buf);

  if (strncmp (ptrb, "GET", 3) == 0)
    {
      http = 1;
/* printf ("buf=(%s)\n",buf); */
      if (ptr = strchr (ptrb, ' '))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.msg_type, BCNU_MSG_AGT_HTTP);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ' '))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.bcnud_filename, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, '\r'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.agent_from, ptrb);
	  ptrb = ptr;
	}

      if (debug)
	{
	  printf ("type=%s\n", bcnud_in.msg_type);
	  printf ("afrom=%s\n", bcnud_in.agent_from);
	  printf ("file=%s\n", bcnud_in.bcnud_filename);
	}
      return TRUE;
    }
  if (*ptrb == 'V')
    {
      if (ptr = strchr (ptrb++, ':'))
	{
	  *ptr++ = 0;
	  bcnud_in.proto_version = atoi (ptrb);
	  ptrb = ptr;
	  if (debug)
	    printf ("bcnud_in.proto_version = %d\n", bcnud_in.proto_version);
	}
    }

  switch (bcnud_in.proto_version)
    {
    case 0:
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.msg_type, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  bcnud_in.severity = atoi (ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.host_for, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.host_from, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.agent_from, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  bcnud_in.time_logged = atol (ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.log_info, ptrb);
	  ptrb = ptr;
	}
      strcpy (bcnud_in.bcnud_filename, ptrb);
      break;
    case 1:
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.msg_type, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  bcnud_in.severity = atoi (ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.host_for, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  bcnud_in.host_type = atoi (ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.host_from, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.agent_from, ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  bcnud_in.time_logged = atol (ptrb);
	  ptrb = ptr;
	}
      if (ptr = strchr (ptrb, ':'))
	{
	  *ptr++ = 0;
	  strcpy (bcnud_in.log_info, ptrb);
	  ptrb = ptr;
	}
      strcpy (bcnud_in.bcnud_filename, ptrb);
      break;
    default:
      bcnu_error ("Unknown protocol version");
    }
  if (!fqdn)
    {
      if (ptr = strchr (bcnud_in.host_for, '.'))
	*ptr = 0;
    }
  if (debug)
    {
      printf ("type=%s\n", bcnud_in.msg_type);
      printf ("sever=%d\n", bcnud_in.severity);
      printf ("from=%s\n", bcnud_in.host_from);
      printf ("htype=%d\n", bcnud_in.host_type);
      printf ("for=%s\n", bcnud_in.host_for);
      printf ("afrom=%s\n", bcnud_in.agent_from);
      printf ("logged=%d\n", bcnud_in.time_logged);
      printf ("info=%s\n", bcnud_in.log_info);
      printf ("file=%s\n", bcnud_in.bcnud_filename);
    }
return TRUE;
}

int bcnu_process (hostname)
     char *hostname;
{
  int f;
  char agentmsg[80];
  int fstat, bytes;
  off_t fsize;
  char *mallocptr;
  int bufsz;
  long timevar;
  struct stat statbuf;
  char tmsg[30], lmsg[30];

  sprintf (response, "(%s)%s %s.%s, started at %s, %d requests\n%d agents loaded,%d enabled\n",
	   myhostname, id, BCNU_VER, subver, starttime, reqcnt, bcnu_agents_loaded, bcnu_agents_enabled);
  err = 0;
  msg = 0;
  agt = 0;
  bcnud_in.bcnud_file = 0;

  time (&bcnud_in.bcnud_time_logged);
  strcpy (bcnud_in.bcnud_host_from, hostname);

  if (debug)
    printf ("bcnu_process bcnu_in.msgtype (%s)\n", bcnud_in.msg_type);
  if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_PING) == 0)
    {
      return FALSE;
    }

  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_WIN32ALERT) == 0)
    {
      bcnu_register (hostname);
      return FALSE;
    }

  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_ERROR_LOG) == 0)
    {
      err++;
      bcnu_write_data ();
    }
  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_ERROR_FILE) == 0)
    {
      err++;
      bcnu_write_file (bcnud_in.host_from);
      bcnu_write_data ();
    }
  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_STATUS_LOG) == 0)
    {
      msg++;
      bcnu_write_data ();
    }
  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_STATUS_FILE) == 0)
    {
      msg++;
      bcnu_write_file (bcnud_in.host_from);
      bcnu_write_data ();
    }
  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_AGT_SHOW) == 0)
    {
      strcpy (buf, response);
      *response = 0;
      pump_data (strlen (buf));
      for (f = 0; f < bcnu_agents_loaded; f++)
	{

	  switch (bcnud_agent[f].status)
	    {
	    case 1:
	      sprintf (buf, "%-10s(%-6s)%-8s runs %-3d mins, next (run %-2d) (log %-2d) mins\n",
		       bcnud_agent[f].agent_name, bcnud_agent[f].agent_type, "enabled",
		       bcnud_agent[f].minutes_run, bcnud_agent[f].next_run, bcnud_agent[f].next_log);
	      break;
	    case 0:
	      sprintf (buf, "%-10s(%-6s)%-8s runs %-3d mins\n",
		       bcnud_agent[f].agent_name, bcnud_agent[f].agent_type, "disabled",
		       bcnud_agent[f].minutes_run);
	      break;
	    case -1:
	      sprintf (buf, "%-10s(%-6s)%-8s runs %-3d mins\n",
		       bcnud_agent[f].agent_name, bcnud_agent[f].agent_type, "blackout",
		       bcnud_agent[f].minutes_run);
	      break;
	    }
	  pump_data (strlen (buf));
	}
    }
  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_AGT_HTTP) == 0)
    {
      *response = 0;
      if (ckfile (bcnud_in.bcnud_filename))
	bcnu_error (buf);

      sprintf (buf, "%s/%s", bcnuhome, bcnud_in.bcnud_filename);

      if ((fstat = open (buf, O_RDONLY)) <= 0)
	{
	  sprintf (workbuf, "Can't open file (%s) to http get", buf);
	  bcnu_error (workbuf);
	}
      time (&timevar);
      if (stat (buf, &statbuf) != 0)
	bcnu_error ("can't stat file");
      strcpy (tmsg, ctime (&timevar));
      strcpy (lmsg, ctime (&statbuf.st_mtime));
      fsize = statbuf.st_size;

/*      printf ("File size of http file (%s) is %d\n", buf, fsize); 
 */
      sprintf (buf, "HTTP/1.0 200 OK\nDate: %sServer: %s/%s.%s\nContent-type: text/html\nContent-length: %d\nLast-modified: %s\n",
	       tmsg, id, BCNU_VER, subver, fsize, lmsg);

      if ((mallocptr = malloc (fsize + strlen (buf) + 1)) == NULL)
	bcnu_error ("Unable to malloc");

      strcpy (mallocptr, buf);

      bufsz = strlen (mallocptr);

      bytes = read (fstat, mallocptr + bufsz, fsize);
      if (send (s, mallocptr, bytes + bufsz, 0) != bytes + bufsz)
	{
	  bcnu_error ("http Connection aborted on error");
	}
      close (fstat);
      free (mallocptr);
    }
  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_AGT_GET) == 0)
    {
      *response = 0;
      if (ckfile (bcnud_in.bcnud_filename))
	bcnu_error (buf);
      sprintf (buf, "%s/%s", bcnuhome, bcnud_in.bcnud_filename);

      if ((fstat = open (buf, O_RDONLY)) <= 0)
	{
	  sprintf (workbuf, "Can't open file (%s) to get", buf);
	  bcnu_error (workbuf);
	}

      while (bytes = read (fstat, buf, BCNU_MESS))
	{
	  pump_data (bytes);
	}
      close (fstat);
    }
  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_AGT_SEND) == 0)
    {
      agt++;
      sprintf (response, "OK");
      bcnu_write_file (bcnud_in.host_from);
    }
  else if (strcasecmp (bcnud_in.msg_type, BCNU_MSG_AGT_RELOAD) == 0)
    {
      if (!masterok)
	{
	  sprintf (response, "%s unauthorised function %s\n", hostname, bcnud_in.msg_type);
	  bcnu_log (response);
	  return FALSE;
	}

      bcnu_pipe_send (BCNU_MSG_AGT_RELOAD);
      sprintf (response, "Agents reloaded by %s", hostname);
      bcnu_log (response);
    }
return TRUE;
}


int bcnu_write_file (hostname)
     char *hostname;
{
  int of, len, bytes;
  char otfile[80];

  if (ckfile (bcnud_in.bcnud_filename))
    bcnu_error (buf);
  if (err || msg || agt)
    {
      if (strlen (bcnud_in.bcnud_filename) == 0)
	sprintf (otfile, "%sfiles/%s.%d", bcnumsg, hostname, getpid ());
      else
	{
	  if (!masterok)
	    {
	      sprintf (response, "%s unauthorised function %s\n", hostname, bcnud_in.msg_type);
	      bcnu_log (response);
	      return FALSE;
	    }
	  sprintf (otfile, "%s/%s", bcnuhome, bcnud_in.bcnud_filename);
	}
    }

  strcpy (bcnud_in.bcnud_filename, otfile);
  bcnud_in.bcnud_file++;

  strcpy (response, "OK");
  if (debug)
    printf ("otfile=%s\n", otfile);
  if ((of = open (otfile, O_WRONLY | O_CREAT | O_TRUNC, 0755)) <= 0)
    {
      bcnu_error ("error on opening output file");
    }
  ack ();
  while (len = recv (s, buf, BCNU_MESS, 0))
    {
      if (debug)
	printf ("received %d bytes\n", len);
      if (len == -1)
	{
	  sprintf (buf, "error receiving file from %s", hostname);
	  bcnu_error (buf);
	}
      if (write (of, buf, len) == -1)
	bcnu_error ("error writing output file");

      ack ();
    }
  close (of);
}
