// ****************************************************************************
//  Project:        libguytools
// ****************************************************************************
//  Programmer:     Guy Voncken
//                  Police Grand-Ducale
//                  Service de Police Judiciaire
//                  Section Nouvelles Technologies
// ****************************************************************************
//  Module:         System information
// ****************************************************************************

// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
//
// This file is part of libguytools.
//
// libguytools 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 of the License, or
// (at your option) any later version.
//
// libguytools 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 libguytools. If not, see <http://www.gnu.org/licenses/>.

#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <cstdarg>

#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include <netinet/in.h>
#include <linux/if.h>

//#include <qapplication.h>
#include <qstring.h>

#include "toolconstants.h"
#include "toolglobalid.h"
#include "toolerror.h"
#include "toolsysinfo.h"

// ------------------------------------
//             Constants
// ------------------------------------

// ------------------------------------
//         Type definitions
// ------------------------------------


// ------------------------------------
//         Local variables
// ------------------------------------

static bool ToolSysInfoInitialized = false;

// ------------------------------------
//            Functions
// ------------------------------------

APIRET ToolSysInfoGetMacAddr (t_pToolSysInfoMacAddr pMacAddr)
{
   struct ifreq   Ifr;
   struct ifreq *pIfr;
   struct ifconf  Ifc;
   char   buf[1024];
   int    s, i, wr;
   bool   ok = false;

   s = socket(AF_INET, SOCK_DGRAM, 0);
   if (s==-1)
      return TOOLSYSINFO_ERROR_SOCKET;

   Ifc.ifc_len = sizeof(buf);
   Ifc.ifc_buf = buf;
   ioctl(s, SIOCGIFCONF, &Ifc);

   pIfr = Ifc.ifc_req;
   for (i = Ifc.ifc_len / sizeof(struct ifreq); --i >= 0; pIfr++)
   {
      strcpy (Ifr.ifr_name, pIfr->ifr_name);
      if (ioctl (s, SIOCGIFFLAGS, &Ifr) == 0)
      {
         if (! (Ifr.ifr_flags & IFF_LOOPBACK))
         {
            if (ioctl(s, SIOCGIFHWADDR, &Ifr) == 0)
            {
                ok = true;
                break;
            }
         }
      }
   }
   close(s);

   if (!ok)
      return TOOLSYSINFO_ERROR_NO_ADDR;

   bcopy (Ifr.ifr_hwaddr.sa_data, &pMacAddr->AddrVal[0], TOOLSYSINFO_MACADDRLEN_VAL);
   wr = 0;
   for (int i=0; i<TOOLSYSINFO_MACADDRLEN_VAL; i++)
      wr += sprintf(&pMacAddr->AddrStr[wr], "%02X", pMacAddr->AddrVal[i]);

   return NO_ERROR;
}

APIRET ToolSysInfoUname (QString &Uname)
{
   struct utsname name;

   if (uname (&name) == -1)
      return TOOLSYSINFO_ERROR_UNAME;

   Uname = QString(name.sysname) + " " + name.nodename + " " + name.release + " " + name.version + " " + name.machine;

   return NO_ERROR;
}


// ------------------------------
//     Module initialisation
// ------------------------------

APIRET ToolSysInfoInit (void)
{
   if (ToolSysInfoInitialized)
      return TOOLSYSINFO_ALREADY_INITIALISED;

   TOOL_CHK (TOOL_ERROR_REGISTER_CODE (ERROR_BASE_TOOL_SYSINFO))
   TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ALREADY_INITIALISED))
   TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_SOCKET))
   TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_NO_ADDR))
   TOOL_CHK (TOOL_ERROR_REGISTER_CODE (TOOLSYSINFO_ERROR_UNAME))

   ToolSysInfoInitialized = true;

   return NO_ERROR;
}

APIRET ToolSysInfoDeInit (void)
{
   return NO_ERROR;
}

