/*    $Id: agent.c,v 1.6 1998/12/24 13:40:06 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, ls, masterok, agentlog, gap;

int err, msg, agt;

bcnu_load_agents ()
{
  char *ptr, *ptrb, line[BCNU_MESS], disflag[80];
  char minon[3], minoff[3], hron[3], hroff[3], hrs[30], freq[12], logfreq[12];
  FILE *fp;
  struct stat statbuf;
  int items, f, status, bcnu_agents_gap = gap;
  int aglines = 0;

  bcnu_agents_loaded = 0;
  bcnu_agents_enabled = 0;

  if ((fp = fopen (bcnucfg, "r")) == NULL)
    bcnu_error ("Can't open agent config file");
  while (fgets (line, BCNU_MESS, fp))
    {

      aglines++;
      if ((*line == '#') || (*line == '\n'))
	continue;
      if (bcnu_agents_loaded >= BCNU_MAX_AGENTS)
	{
	  bcnu_log ("max agents exceeded");
	  continue;
	}
      *bcnud_agent[bcnu_agents_loaded].agent_param = 0;

      items = sscanf (line, "%[^:]:%[^:]:%[^:]:%[0-9]:%[0-9]:%[^:]:%[^:\n]\n",
		      bcnud_agent[bcnu_agents_loaded].agent_type,
		      bcnud_agent[bcnu_agents_loaded].agent_name,
		      hrs, freq, logfreq, disflag,
		      bcnud_agent[bcnu_agents_loaded].agent_param);

      if (items < 6)
	{
	  sprintf (buf, "Invalid line(%d) in agents file", aglines);
	  bcnu_log (buf);
	  continue;
	}

      if (ckfile (bcnud_agent[bcnu_agents_loaded].agent_type))
	{
	  bcnu_log (buf);
	  continue;
	}
      if (ckfile (bcnud_agent[bcnu_agents_loaded].agent_name))
	{
	  bcnu_log (buf);
	  continue;
	}

      bcnud_agent[bcnu_agents_loaded].minutes_run = atoi (freq);
      bcnud_agent[bcnu_agents_loaded].minutes_log = atoi (logfreq);
      bcnud_agent[bcnu_agents_loaded].next_log = 0;

      if (strncasecmp (disflag, "e", 1) == 0)
	bcnud_agent[bcnu_agents_loaded].status = 1;
      else
	bcnud_agent[bcnu_agents_loaded].status = 0;

      sprintf (buf, "%s/%s", bcnuhome, bcnud_agent[bcnu_agents_loaded].agent_type);
      if (stat (buf, &statbuf) != 0)
	strcpy (bcnud_agent[bcnu_agents_loaded].agent_type, "agent");

      if (sscanf (hrs, "%[0-9].%[0-9]-%[0-9].%[0-9]\n", hron, minon, hroff, minoff) != 4)
	{
	  sscanf (hrs, "%[0-9]-%[0-9]\n", hron, hroff);
	  strcpy (minon, "0");
	  strcpy (minoff, "0");
	}
      bcnud_agent[bcnu_agents_loaded].min_on = atoi (minon);
      bcnud_agent[bcnu_agents_loaded].min_off = atoi (minoff);
      bcnud_agent[bcnu_agents_loaded].hr_on = atoi (hron);
      bcnud_agent[bcnu_agents_loaded].hr_off = atoi (hroff);

/* Stagger the agents at gap minute intervals to prevent bunching
 */
      bcnud_agent[bcnu_agents_loaded].next_run = bcnu_agents_gap;
      bcnu_agents_enabled += bcnud_agent[bcnu_agents_loaded].status;
      bcnu_agents_loaded++;
      bcnu_agents_gap += gap;
    }
  fclose (fp);

  sprintf (workbuf, "%d agents loaded, %d enabled, gap %d", bcnu_agents_loaded, bcnu_agents_enabled, gap);
  bcnu_log (workbuf);
}

agent_run (master)
     char *master;
{
  int run = 0;
  int disable = 0;
  int f, fstat;
  int blackout;
  int blackstrt = 0;
  int nowtime, ontime, offtime;
  char logfreq[12];

  char agentfile[80], agentenv[160], agentpenv[512];

  strcpy (agentfile, bcnuagent);

  bcnu_hour ();
  nowtime = (hour * 60) + mins;

  for (f = 0; f < bcnu_agents_loaded; f++)
    {
      blackout = 0;

      if (bcnud_agent[f].status != 0)

	{

/*
   printf("Status of %s is %d\n",bcnud_agent[f].agent_name,bcnud_agent[f].status);
   printf("Hour is %d start hr is %d end is %d\n",hour,bcnud_agent[f].hr_on,bcnud_agent[f].hr_off);
   printf("Mins is %d start min is %d end is %d\n",mins,bcnud_agent[f].min_on,bcnud_agent[f].min_off);
 */
	  ontime = (bcnud_agent[f].hr_on * 60) + bcnud_agent[f].min_on;
	  offtime = (bcnud_agent[f].hr_off * 60) + bcnud_agent[f].min_off;
	  if (ontime == offtime)
	    offtime++;

	  if ((nowtime >= ontime) && (nowtime < offtime))
	    {
	      if (bcnud_agent[f].status != 1)
		{
		  bcnud_agent[f].status = 1;
		  bcnud_agent[f].next_log = 0;
		  if (bcnud_agent[f].min_on == 0)
		    bcnud_agent[f].next_run = blackstrt += gap;
		  else
		    bcnud_agent[f].next_run = 0;

		  sprintf (workbuf, "%s blackout ended", bcnud_agent[f].agent_name);
		  bcnu_log (workbuf);
		}
	    }
	  else
	    {
	      if (bcnud_agent[f].status != -1)
		{
		  blackout = 1;
		  bcnud_agent[f].next_run = 0;
		  bcnud_agent[f].next_log = 0;
		  sprintf (workbuf, "%s blackout started", bcnud_agent[f].agent_name);

		  bcnu_log (workbuf);
		}
	    }
	}
      if (bcnud_agent[f].status > 0)
	{

	  bcnud_agent[f].next_run--;
	  if (bcnud_agent[f].next_run < 1)
	    {
	      run++;
	      switch (fork ())
		{
		case -1:	/* Can't fork, just exit. */
		  exit (1);
		case 0:	/* Child process comes here. */
		  close (ls);
		  signal (SIGALRM, SIG_IGN);
		  sprintf (agentfile, "%s/%s/%s", bcnuhome, bcnud_agent[f].agent_type, bcnud_agent[f].agent_name);
		  sprintf (agentenv, "BCNUHOME=%s", bcnuhome);
		  putenv (agentenv);
		  sprintf (logfreq, "%d", bcnud_agent[f].next_log);
		  if (blackout)
		    sprintf (agentpenv, "BCNUPARAM=blackout");
		  else
		    sprintf (agentpenv, "BCNUPARAM=%s", bcnud_agent[f].agent_param);
		  putenv (agentpenv);
		  if (debug || agentlog)
		    {
		      sprintf (workbuf, "Run (%s/%s) with %s",
			       bcnud_agent[f].agent_type, bcnud_agent[f].agent_name, agentpenv);
		      bcnu_log (workbuf);
		    }
		  if (execlp (agentfile, agentfile, master, bcnud_agent[f].agent_name, logfreq, NULL) == -1)
		    {
		      sprintf (workbuf, "Unable to run %s:%s",
			       bcnud_agent[f].agent_name, agentfile);
		      bcnu_log (workbuf);
		      sprintf (workbuf, "disable %s", bcnud_agent[f].agent_name);
		      bcnu_pipe_send (workbuf);
		    }
		  exit (0);
		default:	/* Daemon process comes here. */
		  if (blackout)
		    bcnud_agent[f].status = -1;
		  bcnud_agent[f].next_run = bcnud_agent[f].minutes_run;
		  if (bcnud_agent[f].next_log <= 0)
		    bcnud_agent[f].next_log = bcnud_agent[f].minutes_log;
		  else
		    bcnud_agent[f].next_log--;
		}
	    }
	}
    }

  return (run);
}
