/*
 Distributed under the terms of the GNU General Public License v2
 $Header: $

 On Gentoo Linux the apache user has a shell of /bin/false and we dont
 want to give it a /bin/bash shell for security reasons, 
 so something like this is needed.

 This wrapper also does away with the every 5 min cronjob which is prone
 to errors if the previous run was not complete.

 20031019 -  <solar@gentoo.org>
 20040203 - small update.

*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/signal.h>
#include <sys/types.h>

#define CACTI_UID	81
#define CACTI_GID	81
#define CACTI_WORKDIR	"/home/httpd/htdocs/cacti/"
#define PHP_EXECUTABLE	"/usr/bin/php"

const int main(int argc, char **argv, char **envp)
{
   char *ARGV[] = { PHP_EXECUTABLE, "cmd.php", NULL };
   unsigned long tm[2];
   pid_t pid;

   if (access(PHP_EXECUTABLE, X_OK) != 0) {
      perror("access(" PHP_EXECUTABLE ", X_OK)");
      exit(EXIT_FAILURE);
   }

   if ((getuid() != 0) && (getuid() != CACTI_UID)) {
      fprintf(stderr,
	      "Invalid uid %d. This wrapper needs to be started by root or apache\n",
	      getuid());
      exit(EXIT_FAILURE);
   }

   /* Drop all privs */
   setregid(CACTI_GID, CACTI_GID);
   setreuid(CACTI_UID, CACTI_UID);

   /* verify we are running as correct user */
   if (getuid() != CACTI_UID) {
      fprintf(stderr,
	      "Invalid uid %d. This wrapper should be running as apache uid %d now but it seems not to be\n",
	      CACTI_UID, getuid());
      exit(EXIT_FAILURE);
   }

   if ((chdir(CACTI_WORKDIR)) != 0) {
      perror("chdir(" CACTI_WORKDIR ")");
      exit(EXIT_FAILURE);
   }

   /* If any arguments are passed lets not fork into the bg, otherwise we go 
    * into daemon mode. We could/should use getopt() or getopt_long() here. 
    */

   if (argc == 1) {
      /* go daemon */
      signal(SIGCHLD, SIG_IGN);
      if ((pid = fork()) != 0)
	 exit(EXIT_SUCCESS);

      setpgid(pid, pid);
      printf("Forked into the background pid[%d]\n", getpid());

      /* Close out the TERM */
      freopen("/dev/null", "r", stdin);
      freopen("/dev/null", "w", stdout);
      freopen("/dev/null", "w", stderr);
   }

   while (1) {
      /* track runtime.. */
      tm[0] = time(NULL);

      /* FIXME: system() is evil! */
      /* system("/usr/bin/php cmd.php"); */
      execve(PHP_EXECUTABLE, ARGV, envp);

      tm[1] = time(NULL);

      /* sleep the remainder of 5 mins */
      printf("sleep(%lu);\n", (5 * 60) - (tm[1] - tm[0]));
      sleep((5 * 60) - (tm[1] - tm[0]));
   }
   return 0;			/* never reached */
}
