//
// free.c
// a new implementaion by Darren Kirby
// copyright 2005

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>

#define appname "d's free"
#define appversion "0.2"

int getfree(int C, int T, int BC) {
    struct meminfo {
        unsigned long int memtotal;
        unsigned long int memfree;
        unsigned long int buffers;
        unsigned long int cached;
        unsigned long int swapcached;
        unsigned long int active;
        unsigned long int inactive;
        unsigned long int hightotal;
        unsigned long int highfree;
        unsigned long int lowtotal;
        unsigned long int lowfree;
        unsigned long int swaptotal;
        unsigned long int swapfree;
        unsigned long int dirty;
        unsigned long int writeback;
        unsigned long int mapped;
        unsigned long int slab;
        unsigned long int commitlimit;
        unsigned long int committed_as;
        unsigned long int pagetables;
        unsigned long int vmalloctotal;
        unsigned long int mallocused;
        unsigned long int mallocchunk;
    };

    int i;
    struct meminfo minfo;
    char lines[35];
    char *line = lines;
    char memtype[15];
    long int value[23];

    FILE *memi;
    memi = fopen("/proc/meminfo", "r");
    if (!memi) {
        printf("open failed\n");
        return EXIT_FAILURE;
    }
    for (i = 0; i < 23; i++) {
        line = fgets(lines, 30, memi);
        sscanf(line, "%s%d kB", &memtype, &value[i]);
    }

    minfo = (struct meminfo) { value[0],  value[1],  value[2],  value[3],
                               value[4],  value[5],  value[6],  value[7],
                               value[8],  value[9],  value[10], value[11],
                               value[12], value[13], value[14], value[15], 
                               value[16], value[17], value[18], value[19],
                               value[20], value[21], value[22]};

    long int memused;
    long int used_minus_buffer;
    long int free_plus_buffer;
    int used_swap;

    memused = minfo.memtotal - minfo.memfree;
    used_minus_buffer = memused - (minfo.buffers + minfo.cached);
    free_plus_buffer = minfo.memfree + minfo.buffers + minfo.cached;
    used_swap = minfo.swaptotal - minfo.swapfree;

    printf("%18s %10s %10s %10s %10s %10s\n", "total","used","free","shared","buffers", "cached");
    printf("Mem:%14lu %10lu %10lu %10lu %10lu %10lu\n",
            fmt(minfo.memtotal,C), fmt(memused,C), fmt(minfo.memfree,C),
            // shared no longer computed...
            fmt(0,C), fmt(minfo.buffers,C), fmt(minfo.cached,C));

    (BC == 1) ? printf("-/+ buffers/cache: %10lu %10lu\n", fmt(used_minus_buffer,C), fmt(free_plus_buffer,C)) : printf("");
    printf("Swap: %12lu %10i %10lu\n", fmt(minfo.swaptotal,C), fmt(used_swap,C), fmt(minfo.swapfree,C));

    (T == 1) ? printf("Total: %11lu %10lu %10lu\n", fmt(minfo.memtotal + minfo.swaptotal,C), fmt(memused + used_swap,C),
                                                    fmt(minfo.memfree + minfo.swapfree,C)) : printf("");
    return 0;

}

fmt(unsigned long n, int C) {
    if (C == 2) {
        return n / 1024;
    } else if (C == 1) {
        return n * 1024;
    } else {
        return n;
    }
}

int showusage(void) {
    printf("usage: free [-b|-k|-m] [-o] [-t] [-s delay] [-V]\n \
            -b,-k,-m show output in bytes, KB, or MB\n \
            -o use old format (no -/+buffers/cache line\n \
            -t display total for RAM + swap\n \
            -s update every [delay] seconds\n \
            -V display version information and exit\n");

    return EXIT_FAILURE;
}

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

    int opt;
    int C = 0;   // -b, -k, or -m
    int P = 0;   // polling?
    int T = 0;   // print total?
    int BC = 1;  // display -/+ buffer/cache?
    int poll_interval;

    while ((opt = getopt(argc, argv, "bkmts:oV")) != -1) {
        switch(opt) {
            case 'b': C = 1; break;
            case 'm': C = 2; break;
            case 's': P = 1; poll_interval = atoi(optarg); break;
            case 'V': printf("%s version %s\n", appname, appversion); exit(0); break;
            case 't': T = 1; break;
            case 'o': BC = 0; break;
            default : showusage(); exit(1);
        }
    }

    if (P == 1) {
        while (1 == 1) {
            getfree(C,T,BC);
            printf("\n");
            sleep(poll_interval);
        }
    } else {
        getfree(C,T,BC);
        return EXIT_SUCCESS;
    }

}



syntax highlighted by Code2HTML, v. 0.9.1