/* A colorful `free' clone with graphs and such. */ /* * Copyright (c) 2004, 2005, 2009, 2013, 2014 Roy Keene * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #if defined(HAVE_LIBSTATGRAB) && !defined(HAVE_LIBSTATGRAB_H) #undef HAVE_LIBSTATGRAB #endif #include #include #ifndef HAVE_LIBSTATGRAB #include #include #ifndef PROC_MEMINFO #define PROC_MEMINFO "/proc/meminfo" #endif #else #include #endif #include #include #include #include #ifndef NO_GETOPT #include #endif #define BARLEN 35 #define HEADERLEN 14 #define VERSION "0.9.2" extern char *optarg; extern int optind, opterr, optopt; struct freecolor_meminfo { uint64_t totalram; /* Total usable main memory size */ uint64_t freeram; /* Available memory size */ uint64_t sharedram; /* Amount of shared memory */ uint64_t bufferram; /* Memory used by buffers */ uint64_t cachedram; /* Memory used for I/O cache */ uint64_t totalswap; /* Total swap space size */ uint64_t freeswap; /* swap space still available */ }; void bargraph(double percent, double secondper, char marks[BARLEN + HEADERLEN + 1], int usefull) { char percentone[BARLEN + 1], percenttwo[BARLEN + 1], remain[BARLEN + 1]; unsigned int numberofmarks, numofmarkstwo, remainnum; numberofmarks=(int) ((double) (BARLEN * (percent / 100))); assert(numberofmarks <= BARLEN); if (!usefull) { numofmarkstwo = (int) ((double) (BARLEN * (secondper / 100))); } else { numofmarkstwo = (BARLEN - numberofmarks); } assert(numofmarkstwo <= BARLEN); remainnum = BARLEN - (numberofmarks + numofmarkstwo); assert(remainnum <= BARLEN); memset(percentone, '#', numberofmarks); memset(percenttwo, '%', numofmarkstwo); memset(remain, '.', remainnum); percentone[numberofmarks] = 0; percenttwo[numofmarkstwo] = 0; remain[remainnum] = 0; snprintf(marks, BARLEN + HEADERLEN + 1, "%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 */ unsigned long get_meminfo(char searchfor[12]) { FILE *fd; unsigned long value = 0, results = 0; char buffer[256]; char fieldname[12]; fd = fopen(PROC_MEMINFO, "r"); if (fd == NULL) { return(0); } while (!feof(fd)) { fgets(buffer, sizeof(buffer), fd); sscanf(buffer,"%11s%lu",fieldname,&value); if (strcmp(fieldname, searchfor) == 0) { results+=(value*1024); } } fclose(fd); return(results); } int get_all_meminfo(struct freecolor_meminfo *retval) { struct sysinfo sinfo; uint64_t meminfo_cached; uint64_t multiplier; meminfo_cached = get_meminfo("Cached:"); sysinfo(&sinfo); #ifdef HAVE_SYSINFO_MEM_UNIT multiplier = sinfo.mem_unit; #else multiplier = 1; #endif retval->totalram = sinfo.totalram * multiplier; retval->freeram = sinfo.freeram * multiplier; retval->sharedram = sinfo.sharedram * multiplier; retval->bufferram = sinfo.bufferram * multiplier; retval->totalswap = sinfo.totalswap * multiplier; retval->freeswap = sinfo.freeswap * multiplier; retval->cachedram = meminfo_cached; return(0); } #else int get_all_meminfo(struct freecolor_meminfo *retval) { static int init_called = 0; sg_mem_stats *mem_stats; sg_swap_stats *swap_stats; if (init_called == 0) { init_called = 1; sg_init(); #ifdef HAVE_STATGRAB_DROP_PRIVILEGES /* Drop setuid/setgid privileges. */ if (sg_drop_privileges() != 0) { perror("Error. Failed to drop privileges"); return(-1); } #endif } mem_stats = sg_get_mem_stats(); swap_stats = sg_get_swap_stats(); if (mem_stats == NULL || swap_stats == NULL) { return(-1); } retval->totalram = mem_stats->total; retval->freeram = mem_stats->free; retval->cachedram = mem_stats->cache; retval->sharedram = 0; retval->bufferram = 0; retval->totalswap = swap_stats->total; retval->freeswap = swap_stats->free; #ifdef HAVE_SG_FREE_MEM_STATS sg_free_mem_stats(mem_stats); #endif #ifdef HAVE_SG_FREE_SWAP_STATS sg_free_swap_stats(swap_stats); #endif return(0); } #endif int main(int argc, char **argv) { struct freecolor_meminfo sinfo; uint64_t cachedbuffer, divisor; double percentram, percentswap, percentbuffer, percentused, percentfree; double ramfree, ramtotal, swapfree, swaptotal, doloop, totaltotal; char realbarchart[BARLEN +HEADERLEN + 1], swapbarchart[BARLEN + HEADERLEN + 1], totalbarchart[BARLEN + HEADERLEN + 1]; int i, dototals, doold, linestoup; int gam_ret; /* Set defaults */ divisor = 1024; doold = 0; linestoup = 2; dototals = 0; doloop = 0; /* Get arguments */ #ifdef NO_GETOPT for (i=1;i (i+1)) { doloop=atof(argv[i+1]); i++; } break; #else while ((i=getopt(argc, argv, "obkmVs:t")) != -1) { switch(i) { case 's' : doloop=atof(optarg); break; #endif /* NO_GETOPT */ 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; case '?' : printf("usage: %s [-b|-k|-m] [-o] [-t] [-s delay] [-V]\n",argv[0]); return(1); 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); } } /* Display information */ while(1) { gam_ret = get_all_meminfo(&sinfo); if (gam_ret < 0) { fprintf(stderr, "Error getting memory information.\n"); return(1); } ramtotal = sinfo.totalram; ramfree = sinfo.freeram; swapfree = sinfo.freeswap; swaptotal = sinfo.totalswap; totaltotal = sinfo.totalram + sinfo.totalswap; cachedbuffer = sinfo.bufferram + sinfo.cachedram; percentram = (double) ((ramfree / ramtotal) * 100); percentbuffer = (double) ((cachedbuffer / ramtotal) * 100); percentfree = (double) (((sinfo.freeram + sinfo.freeswap + cachedbuffer) / totaltotal) * 100); percentused = (int) (100 - ((int) percentfree)); if (swaptotal!=0) { percentswap = (double) (( 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(%lu/%lu)\n", realbarchart, (int) (percentram + percentbuffer), (unsigned long) ((ramfree + cachedbuffer) / divisor), (unsigned long) (ramtotal / divisor) ); printf("Swap : \033[1;30m[\033[1;32m%s\033[1;30m]\033[1;37m %i\033[0;31m%%\033[0m\t(%lu/%lu)\n", swapbarchart, (int) percentswap, (unsigned long) (swapfree / divisor), (unsigned long) (swaptotal/divisor) ); if (dototals) { printf("Total : \033[1;30m[\033[1;32m%s\033[1;30m]\033[1;37m \033[0m(%lu=%lu+%lu)\n", totalbarchart, (unsigned long) ((sinfo.totalram + sinfo.totalswap) / divisor), (unsigned long) ((sinfo.freeram + sinfo.freeswap) / divisor), (unsigned long) ((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", (unsigned long) (sinfo.totalram / divisor), (unsigned long) ((sinfo.totalram - sinfo.freeram) / divisor), (unsigned long) (sinfo.freeram / divisor), (unsigned long) (sinfo.sharedram / divisor), (unsigned long) (sinfo.bufferram / divisor), (unsigned long) (cachedbuffer / divisor) ); printf("Swap: %12lu %10lu %10lu\n", (unsigned long) (sinfo.totalswap / divisor), (unsigned long) ((sinfo.totalswap - sinfo.freeswap) / divisor), (unsigned long) (sinfo.freeswap / divisor) ); if (dototals) { printf("Total: %11lu = (%8lu (used) + %8lu (free))\n", (unsigned long) (totaltotal / divisor), (unsigned long) ((((long) totaltotal) - ((sinfo.freeram+sinfo.freeswap))) / divisor), (unsigned long) ((sinfo.freeram+sinfo.freeswap+((unsigned long) cachedbuffer)) / divisor) ); } } if (doloop==0) { break; } usleep(doloop * 1000000); printf("\033[%iA", linestoup); } return(0); }