Artifact [5a09c67ddb]

Artifact 5a09c67ddbb1054463032213e57687f09cd4db1a:


/*
   A colorful `free' clone with graphs and such.

   -- Roy Keene [200819992000] rkeene@suspend.net

    Bug 230819992230: freecolor segfaults if swapping is off. (fixed,
			reported by shammack@goldinc.com).
   Warn 260919991600: Warning about returning a local variable fixed (
                                 Jakob Erikson <jakov@quicknet.se>).
  Annoy 270819990700: Made the code for the "-o" option neater.
    Bug 270819990700: Fixed support for unknown options 
                             (Rene <renec@zorro.pangea.ca)
  Annoy 270819990800: Fixed display of buffed and cached memmory. 
   				(Rene <renec@zorro.pangea.ca)
  Annoy 270819991030: Fixed the ugly bargraph(), now its less ugly, but
   			but still not very good.
  Annoy 270819992100: Fixed the (less) ugly bargraph(), now it doesnt look
                            so bad.
Feature 161019991640: Added Total Free/Total Used to "-t" option.
   
*/
/*
 *  
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following condition
 *  is met:
 *  1. Redistributions of source code must retain the following disclaimer,
 *     and this list of conditions.
 * 
 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *  INCLUDING, BUT NOT LIMITED TO, THE  IMPLIED WARRANTIES OF MERCHANTABILITY
 *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 *  JUHA PIRKOLA OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */


#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if defined(HAVE_LIBSTATGRAB) && !defined(HAVE_LIBSTATGRAB_H)
#undef HAVE_LIBSTATGRAB
#endif

#ifndef HAVE_LIBSTATGRAB
#include <linux/kernel.h>
#include <sys/sysinfo.h>
#include <linux/sys.h>
#ifndef PROC_MEMINFO
#define PROC_MEMINFO "/proc/meminfo"
#endif
#else
#include <statgrab.h>
#endif
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef NO_GETOPT
#include <getopt.h>
#endif
#define BARLEN 35
#define HEADERLEN 14
#define VERSION "0.8.6"


extern char *optarg;
extern int optind, opterr, optopt;

void bargraph(float percent, float secondper, char marks[BARLEN+HEADERLEN],int usefull) {
  char percentone[BARLEN], percenttwo[BARLEN], remain[BARLEN];
  unsigned int numberofmarks, numofmarkstwo, remainnum;
  numberofmarks=(int) ((float) (BARLEN*(percent/100)));
  if (!usefull) numofmarkstwo=(int) ((float) (BARLEN*(secondper/100))); else numofmarkstwo=(BARLEN-numberofmarks);
  remainnum=BARLEN-(numberofmarks+numofmarkstwo);
  memset(percentone, '#', numberofmarks);
  memset(percenttwo, '%', numofmarkstwo);
  memset(remain, '.', remainnum);
  percentone[numberofmarks]=0;
  percenttwo[numofmarkstwo]=0;
  remain[remainnum]=0;
  sprintf(marks,"%s\033[1;31m%s\033[1;37m%s",percentone, percenttwo, remain);
  return;
}

#ifndef HAVE_LIBSTATGRAB
/*
  Extracted alot from sysinfo.c (part of the procps package?) by
  Michael K. Johnson <johnsonm@redhat.com>
*/
unsigned long get_meminfo(char searchfor[12]) {
  FILE *fd;
  unsigned long value=0, results=0;
  char buffer[256]; /* Paranoia, reallly big buffer. */
  char feildname[12];
  if ((fd=fopen(PROC_MEMINFO, "r"))==NULL) return(0);
  while (!feof(fd)) {
    fgets(buffer, sizeof(buffer), fd);
    sscanf(buffer,"%11s%lu",feildname,&value);
    if (strcmp(feildname,searchfor)==0) results+=(value*1024);
  }
  fclose(fd);
  return(results);
}
#endif

int main(int argc, char *argv[]) {
  float percentram, percentswap, percentbuffer, percentused, percentfree;
  float ramfree, ramtotal, swapfree, swaptotal, doloop=0, cachedbuffer, totaltotal;
  char realbarchart[BARLEN+HEADERLEN], swapbarchart[BARLEN+HEADERLEN], totalbarchart[BARLEN+HEADERLEN];
  int i, divisor=1024, dototals=0, doold=0, linestoup=2;
  unsigned long meminfo_cached;
#ifndef HAVE_LIBSTATGRAB
  struct sysinfo sinfo;

  meminfo_cached=get_meminfo("Cached:");
#else
  mem_stat_t *mem_stats=NULL;
  swap_stat_t *swap_stats=NULL;
  struct systeminfo_st {
    unsigned long totalram;  /* Total usable main memory size */
    unsigned long freeram;   /* Available memory size */
    unsigned long sharedram; /* Amount of shared memory */
    unsigned long bufferram; /* Memory used by buffers */
    unsigned long totalswap; /* Total swap space size */
    unsigned long freeswap;  /* swap space still available */
  } sinfo;

  statgrab_init();

#ifdef HAVE_STATGRAB_DROP_PRIVILEGES
  /* Drop setuid/setgid privileges. */
  if (statgrab_drop_privileges() != 0) {
    perror("Error. Failed to drop privileges");
    return 1;
  }
#endif

#endif
#ifdef NO_GETOPT
  for (i=1;i<argc;i++) {
    if (argv[i][0]=='-') {
      switch(argv[i][1]) {
        case 's' : 
           if (argc>(i+1)) { doloop=atof(argv[i+1]); i++; }
           break;
#else
  while ((i=getopt(argc, argv, "obkmVs:t")) != -1) {
  if (i=='?') { printf("usage: %s [-b|-k|-m] [-o] [-t] [-s delay] [-V]\n",argv[0]); return(1); }
    switch(i) {
        case 's' : 
           doloop=atof(optarg);
           break;
#endif
        case 'b' : divisor=1; break;
        case 'k' : divisor=1024; break;
        case 'm' : divisor=1048576; break;
        case 'V' : printf("freecolor version %s\n", VERSION); return(0);
        case 't' : dototals=1; linestoup++; break;
        case 'o' : doold=1; linestoup++; break;
#ifdef NO_GETOPT
        default  : printf("%s: illegal option -- %c\n",argv[0],argv[i][1]); printf("usage: %s [-b|-k|-m] [-t] [-s delay] [-V]\n",argv[0]); return(1);
      }
    }
  }
#else
  	}
  }
#endif
  while(1) {
#ifndef HAVE_LIBSTATGRAB
    sysinfo(&sinfo);
#else
  if(((mem_stats=get_memory_stats()) == NULL) || (swap_stats=get_swap_stats()) == NULL) {
    printf("Couldn't get memory information, exiting.\n");
    return(-1);
  }
  meminfo_cached=mem_stats->cache;
  sinfo.totalram=mem_stats->total;
  sinfo.freeram=mem_stats->free;
  sinfo.sharedram=0;
  sinfo.bufferram=0;
  sinfo.totalswap=swap_stats->total;
  sinfo.freeswap=swap_stats->free;
#endif
    ramtotal=sinfo.totalram;
    cachedbuffer=sinfo.bufferram+meminfo_cached;
    ramfree=sinfo.freeram;
    swapfree=sinfo.freeswap;
    swaptotal=sinfo.totalswap;
    totaltotal=(sinfo.totalram+sinfo.totalswap);
    percentram=(float) ((ramfree / ramtotal)*100);
    percentbuffer=(float) ((cachedbuffer/ramtotal)*100);
    percentfree=(float) (((sinfo.freeram+sinfo.freeswap+meminfo_cached+sinfo.bufferram)/totaltotal)*100);
    percentused=(int) (100-((int) percentfree));
    if (!(swaptotal==0)) { percentswap=(float) ((swapfree/swaptotal)*100); } else { percentswap=0; }
    bargraph(percentswap,0,swapbarchart,0);
    bargraph(percentram,percentbuffer,realbarchart,0);
    bargraph((int) percentfree,(int) percentused,totalbarchart,1);
    if (!doold) {
      printf("Physical  : \033[1;30m[\033[1;32m%s\033[1;30m]\033[1;37m %i\033[0;31m%%\033[0m\t(%i/%i)\n", realbarchart ,(int) (percentram+percentbuffer), (int) (ramfree+cachedbuffer)/divisor, (int) ramtotal/divisor);
      printf("Swap      : \033[1;30m[\033[1;32m%s\033[1;30m]\033[1;37m %i\033[0;31m%%\033[0m\t(%i/%i)\n",swapbarchart ,(int) percentswap,(int) swapfree/divisor, (int) swaptotal/divisor);
      if (dototals) 
      printf("Total     : \033[1;30m[\033[1;32m%s\033[1;30m]\033[1;37m \033[0m(%i=%i+%i)\n", totalbarchart, (int) (sinfo.totalram+sinfo.totalswap)/divisor,(int) ((sinfo.freeram+sinfo.freeswap)/divisor), (int) ((totaltotal-((sinfo.freeram+sinfo.freeswap+cachedbuffer)))/divisor));
    } else {
      printf("             total       used       free     shared    buffers     cached\n");
      printf("Mem:  %12lu %10lu %10lu %10lu %10lu %10lu\n",(sinfo.totalram/divisor), (sinfo.totalram-sinfo.freeram)/divisor, (sinfo.freeram/divisor), (sinfo.sharedram/divisor), (sinfo.bufferram/divisor), (((unsigned long) cachedbuffer)/divisor)); 
      printf("Swap: %12lu %10lu %10lu\n",(sinfo.totalswap/divisor), ((sinfo.totalswap-sinfo.freeswap)/divisor), (sinfo.freeswap/divisor));
      if (dototals) printf("Total: %11lu = (%8lu (used) + %8lu (free))\n",(long) totaltotal/divisor,(((long) totaltotal)-((sinfo.freeram+sinfo.freeswap)))/divisor,(sinfo.freeram+sinfo.freeswap+((unsigned long) cachedbuffer))/divisor);
    }
    if (doloop==0) { return(0); } else { usleep(doloop*1000000); printf("\033[%iA",linestoup); }
  }
  return(0);
}