/*
 * SysInfo
 *--------------------
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU GeneCPUral Public License as published by
 * the Free Software Foundation; either version 2 of the License, 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.
 */


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define DEFAULTUPDATETIME 3
#define PRGVERSION "0.0.2"
#define clrscr() printf("\x1B[2J") //define a clearscreen for linux
#define TRUE 1
#define FALSE 0 
#define CPU_WARNINGTEMP 75
#define SAVEFILE_PATH "/tmp/sysinfo.save"   // !!! take a look @ if setting file doesn't exist (search for ###bookmark1###)  




//===============================================DEKLARATIONS===============================================================

//deklarations of option-switch funktions


void switch_help(void);
void switch_verbose(void);
void switch_foobar(void);
void switch_version(void);
void switch_updatetime(void);
void switch_cputemp(void);
void switch_setWarnTemp(void);



//deklarations of output funktions
void head(void);
void uptime(void);
void kernel_v(void);
void memory(void);
void cputemp(void);
void cpumodel(void);
void save_custom_Variables(int var);
void get_custom_Variables(void);
void commit_GetCPUWarnTemp(void);
void cpu_load(void);

FILE *mem_file, *version_file, *kernel_file, *uptime_file, *cputemp_file, *cpumodel_file, *save_Variables_file,\
*get_Variables_file;


unsigned int CPU_WarningTemp = CPU_WARNINGTEMP;
unsigned int start      = FALSE;   //if set the main programm will start
unsigned int updatetime = DEFAULTUPDATETIME;
unsigned int old_kernel = FALSE;
unsigned int cputemp_flag = FALSE;
unsigned int cpumodel_check = TRUE;
unsigned int device_flag = 0;
unsigned int user_old=0, nice_old=0, system_old=0, idle_old=0, wa_old=0, hi_old=0, si_old=0;
//kommen später noch wech....
char cpumodel_save[50];
char GetCPUWarnTemp[35];



struct tm *tmnow;

//=================================================MAIN================================================================

int main(int argc, char **argv)
{

  if (argc > 1) // commited argument?
  {  
    unsigned int i;  
    for (i = argc; i > 1; i--)
    {
      int option_n = i-1;
      int x=11; //number of options -1
      
      char * const options[]={"--help","-h",\
                       "--foobar","-f",\
                       "--version","-v",\
                       "--updatetime","-u",\
                       "--cputemp","-ct",\
                       "--settemp","-st"};

      do
      {
        if((strcmp (argv[option_n],options[x]) == 0)||(0==x))
        {
          switch(x)
          {
            case 11: 
            case 10: switch_setWarnTemp();
                     break;
            case 9:
            case 8: switch_cputemp(); 
                    break;
            case 7:
            case 6: switch_updatetime(); 
                    break;
            case 5:
            case 4: switch_version();
                    break;
            case 3:
            case 2: switch_foobar();
                    break; 
            case 1:
            default: switch_help();
          }
	  
          x=-1; //all options checked (dropout...)
	
          if((1>=option_n)&&(0==start)) //if last option is read and the prgramm should not start
	  {
	    exit(0);      //Program exit
	  }
          else      
	  {
	    // empy else because dangling else problem
	  }
        }  
        else
        {
          x-=1;
        }
      }
      while(x > -1);
  
    } //END for
  } //END Arguments  
   
  
   clrscr();
   get_custom_Variables(); //Loding Setting-File
   
     
  while(1)
  {
  //drawing the output on screen
    head();
    kernel_v();
    memory();
    uptime();
    cpumodel();   
    if(TRUE == cputemp_flag)
    cputemp();
    cpu_load();
    
  //time between updates [default = 1]
    sleep(updatetime);
  
    clrscr();
  } //END while
   
  return 0;
} // END MAIN

//===================================================FUNCTIONS==================================================================

//SWITCH HELP output options
void switch_help(void)
{
  //drawing the help-menu
  printf("\n\n>>>sysinfo is a versatile infomonitor<<<\n");
  printf("  usage: sysinfo [option 0] [option 1]...[option n] \n\n");
  printf("  option          long option              meaning\n");
  printf("----------------------------------------------------------------------------------\n");
  printf("  -h, -?           --help                  shows this message\n");
  printf("  -v               --version               shows current Version\n");
  printf("  -f               --foobar                shows FooBar\n");
  printf("  -u               --updatetime            set new updatetime (default: %d sec)\n", DEFAULTUPDATETIME);
  printf("  -ct              --cputemp               shows CPU-Temp in °C (ACPI)\n");
  printf("  -st              --settemp               set CPU Warning Temperature (default: %d° C)\n", CPU_WARNINGTEMP);
} //END HELP



void switch_foobar(void)
{
  printf(">> foobar ;)\n");
} //END switch_foobar



void switch_version(void)
{
  printf(">> SysInfo Ver.: %s\n", PRGVERSION);
} //END switch_version


void switch_updatetime(void)
{
//printf("aktuell: %s   n = %i \n\n", argv[n], n); -> DEBUG
  printf("Please enter time (sec) between update: ");
  scanf("%i", &updatetime);
  start = TRUE;
} //END switch_updatetime

void switch_cputemp(void)
{
  cputemp_flag = TRUE;
  start = TRUE;
} //END switch_cputemp



void switch_setWarnTemp(void)
{
  printf("Please enter new CPU Warning Temperature in °C: ");
  scanf ("%d", &CPU_WarningTemp);
  printf("CPU Warning Temperature Set! (%d °C)\n", CPU_WarningTemp);
  start = TRUE;
  
  // Saving the custom CPU Warning Temperature
  save_custom_Variables(CPU_WarningTemp);
  
  
  
  
 }// END switch_setWarnTemp




void uptime(void)
{
  unsigned int uptime_unsorted = 0;
  unsigned char c;
  unsigned int DD;
  unsigned int HH;
  unsigned int MM;
//unsigned int SS; //uptime seconds
  
  uptime_file=fopen("/proc/uptime","r");

  if(NULL != uptime_file)
  {  
    while((c=fgetc(uptime_file))!= '.')
      {
        unsigned int i;
        i = atoi(&c);
        uptime_unsorted = (uptime_unsorted * 10) + i;
      }
  //SS = uptime_unsorted % 60; //seconds
    MM = uptime_unsorted / 60 % 60;
    HH = uptime_unsorted / 60 / 60 % 24;
    DD = uptime_unsorted / 60 / 60 / 24;
    fclose(uptime_file);
    printf("Uptime:\t\tdays %i, %02i:%02i\n",DD,HH,MM);
  }
  else
  {
    printf("Open file \"proc/uptime\" failed!\n");
  }

} //end UPTIME


void kernel_v(void)
{
  char Linux_v[35];
  kernel_file=fopen("/proc/sys/kernel/osrelease", "r");
  
  if(NULL != kernel_file)
  { 
    fgets(Linux_v, 35, kernel_file);
    printf("Linux:\t\t%s",Linux_v); 
    
    if(strstr(Linux_v, "2.6") == NULL )
      old_kernel = TRUE;
    
    fclose(kernel_file);
  }
  else
  {
    printf("Open file \"/proc/sys/kernel/osrelease\" failed!\n");
  }
} //END detect Kernel version and output


void memory(void)
{
  char MemTotal[35];
  char MemFree[35];
  mem_file=fopen("/proc/meminfo","r");
  
  if(NULL != mem_file)
  {
    if(old_kernel == TRUE)
    {
      unsigned char trash[100];
      unsigned int i;
      for(i=3; i>0 ; i--)
        fgets(trash, 100, mem_file);
      
    }
    
    fgets(MemTotal, 35, mem_file);
    fgets(MemFree, 35, mem_file);
    printf("%s",MemTotal);
    printf("%s",MemFree);
    fclose(mem_file);
  }
  else
  {
    printf("Open file \"/proc/meminfo\" failed!\n");
  }
}//END memory


void cputemp(void)
{ 
  char cputemp_string[35];
  char num[] ="0123456789";
  char cputemp_char;
  unsigned int temp = 0;
  unsigned int tempbegin;
  unsigned int tempend;
  unsigned int cputemp = 0;
  char path[45];
  
  if(1 > device_flag)
  {
    cputemp_file=fopen("/sys/bus/i2c/devices/0-0290/temp1_input", "r");
    if(NULL != cputemp_file)
    {
      device_flag = 1;
      fclose(cputemp_file);
    }
  
    cputemp_file=fopen("/proc/acpi/thermal_zone/ATF0/temperature", "r");
    if(NULL != cputemp_file)
    {
      device_flag = 2;
      fclose(cputemp_file);
    }
  
    cputemp_file=fopen("/proc/acpi/thermal_zone/THRM/temperature","r");
    if(NULL != cputemp_file)
    {
      device_flag =3;
      fclose(cputemp_file);
    }
  }//END if  
  switch (device_flag)
  {
    case 3: strncpy (path,"/proc/acpi/thermal_zone/THRM/temperature",sizeof(path));
            break;
    case 2: strncpy(path, "/proc/acpi/thermal_zone/ATF0/temperature", sizeof(path));
            break;
    case 1: break;
    default: printf("CPU-Temp:\tNo sensors found!\n");   
     
  }
  
  if(1 < device_flag)
  {
    cputemp_file=fopen(path, "r");
    fgets(cputemp_string, 35, cputemp_file);
    
  //strpbrk(cputemp, num);
  //temp = atoi(&cputemp);
       
    tempbegin = strcspn(cputemp_string, num);
    tempend = strcspn(cputemp_string, "C");
    
    int i = tempbegin;
    for (; i < (tempend-1); i++)
    {
      cputemp_char = cputemp_string[i];
      temp = (((int)cputemp_char)- 48);
      cputemp = (cputemp * 10) + temp;
    }
    
    //printf("%d", CPU_WarningTemp);
    
    if (cputemp < CPU_WarningTemp)
    {   
      printf("CPU-Temp:\t%d° C\n",cputemp);
      fclose(cputemp_file);
    }  
    else  
    {
      printf("CRITICAL CPU TEMPERATURE !!! (%d° C)\n", cputemp);
    } 
     
  }
  else if(1 == device_flag)
    {
      cputemp_file=fopen("/sys/bus/i2c/devices/0-0290/temp1_input", "r");
      fgets(cputemp_string, 7, cputemp_file);
      int i = 0;
      for( ;i < 5; i++)
      {
        cputemp_char = cputemp_string[i];
        temp = (((int)cputemp_char)- 48);
        cputemp = (cputemp * 10) + temp;
      }
      cputemp /= 1000;
      if (cputemp < CPU_WarningTemp)
      {   
        printf("CPU-Temp:\t%d° C\n",cputemp);
    
        fclose(cputemp_file);
      }  
      else  
      {
        printf("CRITICAL CPU TEMPERATURE !!! (%d° C)\n", cputemp);
        fclose(cputemp_file);
      }
    }
} //END cputemp
 

void cpumodel(void)
{
   
  if (cpumodel_check == TRUE) // already ascertained the model?
  {
    char cpumodel[50];
    char cpuinfo[50];
    char trash[100];
    int cpubegin;
  
  
  
    cpumodel_file=fopen("/proc/cpuinfo", "r");
  
    if(NULL != cpumodel_file)
    {
      int i;
      for (i = 4; i > 0; i--)
        fgets(trash, 100, cpumodel_file);
    
  
      fgets(cpuinfo, 50, cpumodel_file);
    
    
   
      fclose(cpumodel_file);
  
  
      
      cpubegin = strcspn( cpuinfo, ":") + 2;
      
  
  
      i = cpubegin; 
      for (; cpubegin < 50; cpubegin ++)
      {
        cpumodel[cpubegin - i] = cpuinfo[cpubegin];
	
      }
    
      printf("CPU-Model:\t%s", cpumodel);
         
    }
   
    else
    {
      fclose(cpumodel_file);
      printf("Open file \"/proc/cpuinfo\" failed!\n");
    }
    
    cpumodel_check = FALSE;
    strcpy(cpumodel_save , cpumodel); 
  }
  
  else
    printf("CPU-Model:\t%s", cpumodel_save);
    
    
}// END cpumodel


void head(void)
{
  time_t tnow;

  time(&tnow);
  tmnow = localtime(&tnow);  
  printf("\n%02d.%02d.%04d                 [SysInfo Ver.: %s]                     %02d:%02d \n", tmnow -> tm_mday,
                                                                                           tmnow -> tm_mon + 1,
                                                                                           tmnow -> tm_year + 1900,
                                                                                           PRGVERSION,
                                                                                           tmnow -> tm_hour,
                                                                                           tmnow -> tm_min);
  printf("==========================================================================\n\n");
} //END head



void save_custom_Variables(int var)
{  
 char CPUWarnTempSave[5];
 

 // creating a new plain setting-file
  system("rm -rf /tmp/sysinfo.save");
  system("touch /tmp/sysinfo.save");            /// ###bookmark1###       <---[!]
  
 //opening the file
  save_Variables_file=fopen(SAVEFILE_PATH, "w");
  
  
  
//---CPUWARNTEMP----

 //saving the CPU Warning Temperature in the Sysinfo-Settingfile
  fputs("CPU Warning Temp in °C: ", save_Variables_file );
  
 //converting int to string
  sprintf(CPUWarnTempSave, "%d", CPU_WarningTemp); 
 
  fputs(CPUWarnTempSave, save_Variables_file);
  fputs("\n", save_Variables_file);
    
//--END CPUWARNTEMP---- 
  
  
  
 //closing the setting-file   
  fclose(save_Variables_file);   
}// save_custom_Variables

void get_custom_Variables(void)
{
 
 int SettingsToGet = 1;  
 

 get_Variables_file=fopen("/tmp/sysinfo.save", "r");
 
 if(NULL != get_Variables_file)
 {
   
   fgets(GetCPUWarnTemp, 35, get_Variables_file );  //Get CPU Warning Temperature
   commit_GetCPUWarnTemp();
   
   
   
   // add anotherone 
 
   
   
   fclose(get_Variables_file);
 }
 else 
 {
   printf("No config-file found or config-file corrupt!\t\t\t\t\t\t\t[WARNING]\n* Please type \"sysinfo_config\" \
   to create a new config-file\n\n");
   
   //END PROGRAM
   exit(0);
 }
 
 
} 



void commit_GetCPUWarnTemp(void)
{
  unsigned int WarnTempbegin = 0;
  unsigned int i;
  unsigned int WarnTempend;
  unsigned char WarnTempChar; 
  unsigned int temp;
  unsigned int tempnew = 0;
  
  WarnTempbegin = strcspn( GetCPUWarnTemp, ":") + 2;
  WarnTempend = WarnTempbegin + 2;    // Two digits
 
  
  for (i = WarnTempbegin ; i < (WarnTempend); i++)
  {
    WarnTempChar = GetCPUWarnTemp[i];
    temp = (((int)WarnTempChar)- 48);
    tempnew = (tempnew * 10) + temp;
   }
  
   CPU_WarningTemp = tempnew;      
}

void cpu_load(void)
{
  FILE *stat;
  int user_new, nice_new, system_new, idle_new, wa_new, hi_new, si_new;
  int user = 0, nice = 0, system=0, idle=0, wa=0, hi=0, si = 0;
  char cpu[6];
  int i;
  
    stat=fopen("/proc/stat","r");
    fscanf(stat,"%s%d%d%d%d%d%d%d\n",cpu,&user_new,&nice_new,&system_new,&idle_new,&wa_new,&hi_new,&si_new);
    user = user_new - user_old;
    nice = nice_new - nice_old;
    system = system_new - system_old;
    idle = idle_new - idle_old;
    wa = wa_new - wa_old;
    hi = hi_new - hi_old;
    si = si_new - si_old;
    
    if(1 < updatetime)
    {
      user /= updatetime;
      nice /= updatetime;
      system /= updatetime;
      idle /= updatetime;
      wa /= updatetime;
      hi /= updatetime;
      si /= updatetime;
    }
    if(0 != user_old)
      printf("CPU-Load:\tuser:\t%2d\%\n\t\tsys:\t%2d\%\n\t\tnice:\t%2d\%\n\t\tidle:\t%2d\%\n",user,system, nice, idle);
//       printf("CPU-Load:\tuser:\t%d\%\tsys:\t%d\%\n\t\tnice:\t%d\%\tidle:\t%d\%\n\t\twa:\t%d\%\thi:\t%d\%\n\t\tsi:\t%d\% \n",user,system, nice, idle, wa, hi, si);
    user_old = user_new;
    nice_old = nice_new;
    system_old = system_new;
    idle_old = idle_new;
    wa_old = wa_new;
    hi_old = hi_new;
    si_old = si_new;
    fclose(stat);

    
  
  
}
