/*****************************************************************************/
/* Copyright (c) 1998, David Paquet. All rights reserved.                    */
/* This file is free software; you can redistribute it and/or modify it      */
/* under the same terms as Perl itself.                                      */
/*****************************************************************************/

#include "os/aix.h"


char* OS_initialize() {
  
  struct CuAt*      obj;
  int               how_many;
  

  Sysmem = 0;

  /*
   * Get the real memory size via ODM
   *
   */


  if (odm_initialize() == 0) {
    obj = (struct CuAt*)getattr ("sys0", "realmem", 0, &how_many);
    Sysmem = atol(obj->value);
    odm_terminate();
  }

  else {
    printf("BIG PROLEM !\n");
  }
  
  Sysmem = Sysmem * 1024;


  /*
   * Get the page size in bytes
   *
   */
  
  PageSize = getpagesize();
  
  return NULL;
}


void OS_get_table() {
  int                  i, proc_nb;
  struct procinfo      pr_buff[MAX_PROCS];
  struct userinfo      uinfo;
  char                 format[F_FLAST + 1];
  char                 wchan[15], pctcpu[7], pctmem[7], state[10];
  char                 Args[MAXARGLN+1];
  struct timeval       now_tval;
  double               utime, stime, cutime, cstime, now;
  
  
  strcpy(format, Fullformat);
  
  proc_nb = getproc(pr_buff, MAX_PROCS, sizeof(struct procinfo));
  
  gettimeofday(&now_tval, (void *)NULL);
  now = (double)now_tval.tv_sec + (double) now_tval.tv_usec / 1000000.0;
  
  for(i=0; i<proc_nb; i++) {
    
    if ( pr_buff[i].pi_wchan != NULL ) {
      sprintf(wchan, "%p", pr_buff[i].pi_wchan);
    }
    
    if ( pr_buff[i].pi_stat == SNONE ) {
      continue;
    }
    
    
    switch (pr_buff[i].pi_stat){
    case SSLEEP :
      strcpy(state, SLEEP);
      break;
    case SRUN :
      strcpy(state, RUN);
      break;
    case SIDL :
      strcpy(state, IDLE);
      break;
    case SZOMB :
      strcpy(state, ZOMBIE);
      break;
    case SSTOP :
      strcpy(state, STOP);
      break;
    case SACTIVE :
      strcpy(state, ACTIVE);
      break;
    default:
      format[F_STAT] = 'S';
    }

    
    if ( state == ZOMBIE 
	 || getuser(&pr_buff[i], sizeof(struct procinfo),
		    &uinfo,      sizeof(struct userinfo) ) < 0 ) {
      
      bless_into_proc( Zombformat,
		       ZombFields,
		       pr_buff[i].pi_pid,
		       pr_buff[i].pi_ppid,
		       pr_buff[i].pi_sid,
		       pr_buff[i].pi_pgrp,
		       pr_buff[i].pi_uid,
		       pr_buff[i].pi_suid,
		       pr_buff[i].pi_pri,
		       pr_buff[i].pi_nice,
		       pr_buff[i].pi_cpu,
		       /* pr_buff[i].pi_stat, */
		       state,
		       pr_buff[i].pi_flag,
		       wchan,
		       pr_buff[i].pi_wtype,
		       pr_buff[i].pi_adspace,
		       pr_buff[i].pi_majflt,
		       pr_buff[i].pi_minflt,
		       pr_buff[i].pi_utime,
		       pr_buff[i].pi_stime,
		       pr_buff[i].pi_size );
      
      continue;
    } 
    
    /*
     * Command line args processing
     * 
     */

    Args[0] = '\0';

    if ( pr_buff[i].pi_flag & SKPROC ) {
      if ( pr_buff[i].pi_pid == 0 ) {
	strcpy(Args, "kproc (swapper)");
      }
      else {
	sprintf(Args, "kproc (%s)", uinfo.ui_comm);
      }
    }
    else {
      if (getargs(&pr_buff[i], sizeof(struct procinfo), Args, MAXARGLN) < 0) {
	sprintf(Args, "%s", uinfo.ui_comm);
      }
    }
    
    
    /*
     * Convert time values into seconds
     * 
     */

    
    utime = uinfo.ui_ru.ru_utime.tv_sec + 
            (double) uinfo.ui_ru.ru_utime.tv_usec / 1000000.0;
    
    stime = uinfo.ui_ru.ru_stime.tv_sec + 
            (double) uinfo.ui_ru.ru_stime.tv_usec / 1000000.0;

    cutime = uinfo.ui_cru.ru_utime.tv_sec + 
            (double) uinfo.ui_cru.ru_utime.tv_usec / 1000000.0;
    
    cstime = uinfo.ui_cru.ru_stime.tv_sec + 
            (double) uinfo.ui_cru.ru_stime.tv_usec / 1000000.0;

    /*
     * percentage calculation
     * 
     */
        
    pctcpu[0] = pctmem[0]= '\0';      
    
    sprintf( pctcpu, 
	     "%3.2f",
	     (utime + stime ) * 100 / ( now - uinfo.ui_start ) );
    
    if ( Sysmem == 0 ) {
      format[F_PRM] = 'S';
    }
    else {
      sprintf( pctmem,
	       "%3.2f",
	       (uinfo.ui_drss + uinfo.ui_trss) * PageSize * 100 / 
	       (float)Sysmem );
    }


    /*
     * Give it all to Perl
     * (we convert time values to hundredth of a second
     *  to keep in sync with the Linux version )
     */
    
    bless_into_proc( format,
		     FullFields,
		     pr_buff[i].pi_pid,
		     pr_buff[i].pi_ppid,
		     pr_buff[i].pi_sid,
		     pr_buff[i].pi_pgrp,
		     pr_buff[i].pi_uid,
		     pr_buff[i].pi_suid,
		     pr_buff[i].pi_pri,
		     pr_buff[i].pi_nice,
		     /* pr_buff[i].pi_cpu,  */
		     pctcpu,
		     /* pr_buff[i].pi_stat, */
		     state,
		     pr_buff[i].pi_flag,
		     wchan,
		     pr_buff[i].pi_wtype,
		     pr_buff[i].pi_adspace,
		     pr_buff[i].pi_majflt,
		     pr_buff[i].pi_minflt,
		     pr_buff[i].pi_size,
		     uinfo.ui_luid,
		     uinfo.ui_uid,
		     uinfo.ui_gid,
		     uinfo.ui_start,
		     (long) (utime  * 100),
		     (long) (stime  * 100),
		     (long) (cutime * 100),
		     (long) (cstime * 100),
		     uinfo.ui_tsize,
		     uinfo.ui_ttyp,
		     uinfo.ui_ttyd,
		     uinfo.ui_ttympx,
		     uinfo.ui_drss,
		     uinfo.ui_trss,
		     uinfo.ui_dvm,
		     /* uinfo.ui_prm,*/
		     pctmem,
		     Args ); 
    
  } 
  
}

