#include <stdio.h>
#include <kstat.h>
#include <sys/sysinfo.h>

void print_chain(kstat_ctl_t *kc)
{
 kstat_t *ksp;
 for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
   printf("Module: %s Class: %s Name: %s\n", ksp->ks_module, ksp->ks_class, ksp->ks_name);
 }
}

ulong numberOfCPUs(kstat_ctl_t *kc)
{
 ulong result=1;
 kstat_named_t *n_cpus;
 kstat_t *ksp_count;


 ksp_count = kstat_lookup(kc, "unix", 0, "system_misc"); 
 if (ksp_count != NULL) {
    kstat_read(kc, ksp_count, NULL);
    n_cpus = kstat_data_lookup(ksp_count, "ncpus");
    if (n_cpus != NULL) {
     result=n_cpus->value.ul;
   }
 } 


 return(result);
}

int main(int argc, char*argv[])
{
 kstat_ctl_t    *kc;
 kstat_t        *ksp;
 int            first=1;
 cpu_stat_t     cpu_stat;
 ulong          ncpus=1;
 ulong          (*cpu_state)[CPU_STATES];
 ulong          (*cpu_state_prev)[CPU_STATES];
 ulong          i,j;

 kc  = kstat_open();
 print_chain(kc);
 ncpus=numberOfCPUs(kc);  
 cpu_state = (ulong (*)[CPU_STATES]) calloc(ncpus, sizeof(*cpu_state));
 cpu_state_prev = (ulong (*)[CPU_STATES]) calloc(ncpus, sizeof(*cpu_state_prev));
 printf("Number of CPUs: %lu\n", ncpus);
 while(1) {
   for(i=0;i<ncpus;i++) {
     if ((ksp = kstat_lookup(kc, "cpu_stat", i, NULL)) != NULL) {
       if (kstat_read(kc, ksp, &cpu_stat) != -1) {
         for (j=0;j<CPU_STATES;j++) {
           cpu_state[i][j] = cpu_stat.cpu_sysinfo.cpu[j];
       }
       }
     }
   }
   if (!first) {
     for(i=0;i<ncpus;i++) {
       printf("CPU %lu: IDLE=%3lu%% USER=%3lu%% KERNEL=%3lu%% WAIT=%3lu%%\n", i, 
         cpu_state[i][CPU_IDLE]-cpu_state_prev[i][CPU_IDLE],
         cpu_state[i][CPU_USER]-cpu_state_prev[i][CPU_USER],
         cpu_state[i][CPU_KERNEL]-cpu_state_prev[i][CPU_KERNEL],
         cpu_state[i][CPU_WAIT]-cpu_state_prev[i][CPU_WAIT]);
     }
   }
   for(i=0;i<ncpus;i++) {
     for (j=0;j<CPU_STATES;j++) {
       cpu_state_prev[i][j] = cpu_state[i][j];
     }
   }
   first=0;
   sleep(1);
 }
 kstat_close(kc);
 exit(0);

}

