/* cfengine for GNU
 
        Copyright (C) 1995
        Free Software Foundation, Inc.
 
   This file is part of GNU cfengine - written and maintained 
   by Mark Burgess, Dept of Computing and Engineering, Oslo College,
   Dept. of Theoretical physics, University of Oslo
 
   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

*/
 

/*********************************************************************/
/*                                                                   */
/*  TOOLKITS: "object" library                                       */
/*                                                                   */
/*********************************************************************/

#define INET

#include "cf.defs.h"
#include "cf.extern.h"
#include "../pub/global.h"
#include "../pub/md5.h"


/*******************************************************************/

GetNameInfo()

{ int i, found = false;
  char *sp,*sp2;
  time_t tloc;
  struct hostent *hp;
  struct sockaddr_in cin;
  
if (uname(&VSYSNAME) == -1)
   {
   perror("uname ");
   FatalError("cfengine: uname couldn't get kernel name info!!\n");
   }

for (sp = VSYSNAME.sysname; *sp != '\0'; sp++)
   {
   *sp = ToLower(*sp);
   }

for (sp = VSYSNAME.machine; *sp != '\0'; sp++)
   {
   *sp = ToLower(*sp);
   }


for (i = 0; CLASSATTRIBUTES[i][0] != '\0'; i++)
   {
   if (WildMatch(CLASSATTRIBUTES[i][0],VSYSNAME.sysname))
      {
      if (WildMatch(CLASSATTRIBUTES[i][1],VSYSNAME.machine))
         {
         if (WildMatch(CLASSATTRIBUTES[i][2],VSYSNAME.release))
            {
	    if (UNDERSCORE_CLASSES)
	       {
	       sprintf(VBUFF,"_%s",CLASSTEXT[i]);
	       AddClassToHeap(VBUFF);
	       }
	    else
	       {
               AddClassToHeap(CLASSTEXT[i]);
	       }
            found = true;
            break;
            }
         }
      else
         {
         Debug2("Cfengine: I recognize %s but not %s\n",VSYSNAME.sysname,VSYSNAME.machine);
         continue;
         }
      }
   }

if ((sp = malloc(strlen(VSYSNAME.nodename)+1)) == NULL)
   {
   FatalError("malloc failure in initialize()");
   }

strcpy(sp,VSYSNAME.nodename);
strcpy(VPREFIX,VSYSNAME.nodename); /* Temporary */

for (sp2=sp; *sp2 != '\0'; sp2++)  /* Truncate fully qualified name */
   {
   if (*sp2 == '.')
      {
      *sp2 = '\0';
      Debug("cfengine: INFO! Truncating fully qualified hostname %s to %s\n",VSYSNAME.nodename,sp);
      break;
      }

   if (!isalnum(*sp2))
      {
      *sp2 = '_';
      }
   }

AddClassToHeap(CanonifyName(sp));                 /* Unqualified host name comes first */
VDEFAULTBINSERVER.name = sp;

VSYSTEMHARDCLASS = (enum classes) i;


if ((tloc = time((time_t *)NULL)) == -1)
   {
   printf("Couldn't read system clock\n");
   }


CFSTARTTIME = tloc;

sprintf(VBUFF,"%s",ctime(&tloc));
AddTimeClass(VBUFF);


if (VERBOSE)
   {
   if (UNDERSCORE_CLASSES)
      {
      sprintf(VBUFF,"_%s",CLASSTEXT[i]);
      }
   else
      {
      sprintf(VBUFF,"%s",CLASSTEXT[i]);
      }

   if (ISCFENGINE)
      {
      printf ("GNU Configuration Engine - \n%s\n%s\n\n",VERSION,COPYRIGHT);
      }
   else
      {
      printf ("GNU Cfengine server daemon - \n%s\n%s\n\n",VERSION,COPYRIGHT);      
      }

   printf ("------------------------------------------------------------------------\n\n");
   printf ("Host name is: %s\n",VSYSNAME.nodename);
   printf ("Operating System Type is %s\n",VSYSNAME.sysname);
   printf ("Operating System Release is %s\n",VSYSNAME.release);
   printf ("Architecture = %s\n\n\n",VSYSNAME.machine);
   printf ("Using internal soft-class %s for host %s\n\n",VBUFF,VSYSNAME.nodename);
   printf ("The time is now %s\n\n",ctime(&tloc));
   printf ("------------------------------------------------------------------------\n\n");

   }

sprintf(VBUFF,"%d_bit",sizeof(long)*8);
AddClassToHeap(VBUFF);
Verbose("Additional hard class defined as: %s\n",VBUFF);

sprintf(VBUFF,"%s_%s",VSYSNAME.sysname,VSYSNAME.release);
for (sp = VBUFF; *sp != '\0'; sp++)
   {
   if (!isalnum(*sp))
      {
      *sp = '_';
      }
   }
AddClassToHeap(VBUFF);

Verbose("Additional hard class defined as: %s\n",VBUFF);

sprintf(VBUFF,"%s_%s",VSYSNAME.sysname,VSYSNAME.machine);
for (sp = VBUFF; *sp != '\0'; sp++)
   {
   if (!isalnum(*sp))
      {
      *sp = '_';
      }
   }
AddClassToHeap(VBUFF);

Verbose("Additional hard class defined as: %s\n",VBUFF);

sprintf(VBUFF,"%s_%s_%s",VSYSNAME.sysname,VSYSNAME.machine,VSYSNAME.release);
for (sp = VBUFF; *sp != '\0'; sp++)
   {
   if (!isalnum(*sp))
      {
      *sp = '_';
      }
   }

AddClassToHeap(VBUFF);
Verbose("Additional hard class defined as: %s\n",VBUFF);

sprintf(VBUFF,"%s_%s_%s_%s",VSYSNAME.sysname,VSYSNAME.machine,VSYSNAME.release,VSYSNAME.version);

for (sp = VBUFF; *sp != '\0'; sp++)
   {
   if (!isalnum(*sp))
      {
      *sp = '_';
      }
   }


if (strlen(VBUFF) < maxvarsize-2)
   {
   strcpy(VARCH,VBUFF);
   }
else
   {
   Verbose("cfengine internal: $(arch) overflows maxvarsize! Truncating\n");
   strcpy(VARCH,VSYSNAME.sysname);
   }

for (sp = VARCH; *sp != '\0'; sp++)
   {
   if (*sp == ' ')
      {
      *sp = '\0';   /* Truncate at first space */
      break;
      }

   if (!isalnum(*sp))
      {
      *sp = '_';
      }
   }

AddClassToHeap(VARCH);
Verbose("Additional hard class defined as: %s\n",VARCH);

if (! found)
   {
   FatalError("Cfengine: I don't understand what architecture this is!");
   }

strcpy(VBUFF,AUTOCONF_SYSNAME);

for (sp = VBUFF; *sp != '\0'; sp++)
   {
   if (!isalnum(*sp))
      {
      *sp = '_';
      }
   }

AddClassToHeap(VBUFF);
Verbose("\nGNU autoconf class from compile time: %s\n\n",VBUFF);
Verbose("  Careful with this - it might not be correct at run time if you have\n");
Verbose("  several OS versions with binary compatibilty!\n\n");

/* Get IP address from nameserver */

if ((hp = gethostbyname(VSYSNAME.nodename)) == NULL)
   {
   return;
   }
else
   {
   bzero(&cin,sizeof(cin));
   cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
   Verbose("Address given by nameserver: %s\n",inet_ntoa(cin.sin_addr));
   strcpy(VIPADDRESS,inet_ntoa(cin.sin_addr));
   }
}

/*********************************************************************/
/* TOOLKIT : files/directories                                       */
/*********************************************************************/

Repository(file)

char *file;

{ char buffer[bufsize];
  char node[maxlinksize];
  struct stat sstat, dstat;
  char *sp;
  struct Image dummy;
  short imagecopy;

if (!IMAGEBACKUP)
   {
   return true;
   }

if (IsItemIn(VREPOSLIST,file))
   {
   return true;
   }

PrependItem(&VREPOSLIST,file,NULL);

if (VREPOSITORY[0] == '\0' || HOMECOPY)
   {
   return false;
   }

Debug2("Repository(%s)\n",file);

strcpy (node,file);

buffer[0] = '\0';

for (sp = node; *sp != '\0'; sp++)
   {
   if (*sp == '/')
      {
      *sp = REPOSCHAR;
      }
   }

strcpy(buffer,VREPOSITORY);
AddSlash(buffer);

if (BufferOverflow(buffer,node))
   {
   printf("culprit: Repository()\n");
   return false;
   }

strcat(buffer,node);

MakeDirectoriesFor(buffer);

if (stat(file,&sstat) == -1)
   {
   Debug2("Repository file %s not there\n",file);
   return true;
   }

stat(buffer,&dstat);

imagecopy = IMAGEBACKUP;
IMAGEBACKUP = false;

dummy.server = "localhost";
dummy.inode_cache = NULL;
dummy.cache = NULL;

CheckForHoles(&sstat,&dummy);

if (CopyReg(file,buffer,sstat,dstat,&dummy))
   {
   IMAGEBACKUP = imagecopy;
   Verbose("cfengine: backed up to repository %s\n",buffer);
   return true;
   }
else
   {
   IMAGEBACKUP = imagecopy;
   return false;
   }
}

