#include #include #include #include #include #include #include #include #include #include #include enum meminfo_row { meminfo_main = 0, meminfo_swap }; enum meminfo_col { meminfo_total = 0, meminfo_used, meminfo_free, meminfo_shared, meminfo_buffers, meminfo_cached }; unsigned read_total_main(void); /* * This code is slightly modified from the procps package. */ #define UPTIME_FILE "/proc/uptime" #define LOADAVG_FILE "/proc/loadavg" #define MEMINFO_FILE "/proc/meminfo" static char buf[300]; /* This macro opens FILE only if necessary and seeks to 0 so that successive calls to the functions are more efficient. It also reads the current contents of the file into the global buf. */ #define FILE_TO_BUF(FILE) { \ static int n, fd = -1; \ if (fd == -1 && (fd = open(FILE, O_RDONLY)) == -1) { \ fprintf(stdout, "ERROR: file %s, %s\r", FILE, strerror(errno)); \ close(fd); \ return 0; \ } \ lseek(fd, 0L, SEEK_SET); \ if ((n = read(fd, buf, sizeof buf - 1)) < 0) { \ fprintf(stdout, "ERROR: file %s, %s\r", FILE, strerror(errno)); \ close(fd); \ fd = -1; \ return 0; \ } \ buf[n] = '\0'; \ } #define SET_IF_DESIRED(x,y) if (x) *(x) = (y) /* evals 'x' twice */ int uptime(double *uptime_secs, double *idle_secs) { double up=0, idle=0; FILE_TO_BUF(UPTIME_FILE) if (sscanf(buf, "%lf %lf", &up, &idle) < 2) { fprintf(stdout, "ERROR: Bad data in %s\r", UPTIME_FILE); return 0; } SET_IF_DESIRED(uptime_secs, up); SET_IF_DESIRED(idle_secs, idle); return up; /* assume never be zero seconds in practice */ } int loadavg(double *av1, double *av5, double *av15) { double avg_1=0, avg_5=0, avg_15=0; FILE_TO_BUF(LOADAVG_FILE) if (sscanf(buf, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3) { fprintf(stdout, "ERROR: Bad data in %s\r", LOADAVG_FILE); return 0; } SET_IF_DESIRED(av1, avg_1); SET_IF_DESIRED(av5, avg_5); SET_IF_DESIRED(av15, avg_15); return 1; } /* The following /proc/meminfo parsing routine assumes the following format: [