diff -Naur busybox-1.13.3.orig/procps/free.c busybox-1.13.3/procps/free.c --- busybox-1.13.3.orig/procps/free.c 2009-02-26 12:47:35.000000000 +0100 +++ busybox-1.13.3/procps/free.c 2009-05-20 01:26:56.000000000 +0200 @@ -11,9 +11,107 @@ #include "libbb.h" +#if defined(__FreeBSD_kernel__) +#define BAD_OPEN_MESSAGE \ +"Error: /proc must be mounted\n" \ +" To mount /proc at boot you need an /etc/fstab line like:\n" \ +" /proc /proc proc defaults\n" \ +" In the meantime, run \"mount /proc /proc -t proc\"\n" + +#define MEMINFO_FILE "/proc/meminfo" +static int meminfo_fd = -1; + +static char buf[1024]; + +/* This macro opens filename 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(filename, fd) do{ \ + static int local_n; \ + if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) { \ + fputs(BAD_OPEN_MESSAGE, stderr); \ + fflush(NULL); \ + _exit(102); \ + } \ + lseek(fd, 0L, SEEK_SET); \ + if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \ + perror(filename); \ + fflush(NULL); \ + _exit(103); \ + } \ + buf[local_n] = '\0'; \ +}while(0) + +typedef struct mem_table_struct { + const char *name; /* memory type name */ + unsigned long *slot; /* slot in return struct */ +} mem_table_struct; + +static int compare_mem_table_structs(const void *a, const void *b){ + return strcmp(((const mem_table_struct*)a)->name,((const mem_table_struct*)b)->name); +} + +/* obsolete */ +unsigned long kb_main_shared; +/* old but still kicking -- the important stuff */ +unsigned long kb_main_buffers; +unsigned long kb_main_free; +unsigned long kb_main_total; +unsigned long kb_swap_free; +unsigned long kb_swap_total; +/* derived values */ +unsigned long kb_swap_used; +unsigned long kb_main_used; + +void meminfo(void){ + char namebuf[16]; /* big enough to hold any row name */ + mem_table_struct findme = { namebuf, NULL}; + mem_table_struct *found; + char *head; + char *tail; + static const mem_table_struct mem_table[] = { + {"Buffers", &kb_main_buffers}, // important + {"MemFree", &kb_main_free}, // important + {"MemShared", &kb_main_shared}, // important, but now gone! + {"MemTotal", &kb_main_total}, // important + {"SwapFree", &kb_swap_free}, // important + {"SwapTotal", &kb_swap_total}, // important + }; + const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct); + + FILE_TO_BUF(MEMINFO_FILE,meminfo_fd); + + head = buf; + for(;;){ + tail = strchr(head, ':'); + if(!tail) break; + *tail = '\0'; + if(strlen(head) >= sizeof(namebuf)){ + head = tail+1; + goto nextline; + } + strcpy(namebuf,head); + found = bsearch(&findme, mem_table, mem_table_count, + sizeof(mem_table_struct), compare_mem_table_structs + ); + head = tail+1; + if(!found) goto nextline; + *(found->slot) = strtoul(head,&tail,10); +nextline: + tail = strchr(head, '\n'); + if(!tail) break; + head = tail+1; + } + kb_swap_used = kb_swap_total - kb_swap_free; + kb_main_used = kb_main_total - kb_main_free; +} +#endif + int free_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int free_main(int argc, char **argv) { +#if defined(__linux__) /* "struct sysinfo" and "sysinfo(struct sysinfo*)" are Linux specific */ struct sysinfo info; sysinfo(&info); @@ -27,10 +125,10 @@ /* TODO: Make all this stuff not overflow when mem >= 4 Gib */ info.totalram/=info.mem_unit; info.freeram/=info.mem_unit; -#ifndef __uClinux__ +# ifndef __uClinux__ info.totalswap/=info.mem_unit; info.freeswap/=info.mem_unit; -#endif +# endif info.sharedram/=info.mem_unit; info.bufferram/=info.mem_unit; } else { @@ -38,10 +136,10 @@ /* TODO: Make all this stuff not overflow when mem >= 4 Gib */ info.totalram*=info.mem_unit; info.freeram*=info.mem_unit; -#ifndef __uClinux__ +# ifndef __uClinux__ info.totalswap*=info.mem_unit; info.freeswap*=info.mem_unit; -#endif +# endif info.sharedram*=info.mem_unit; info.bufferram*=info.mem_unit; } @@ -56,13 +154,33 @@ info.totalram-info.freeram, info.freeram, info.sharedram, info.bufferram); -#ifndef __uClinux__ +# ifndef __uClinux__ printf("%6s%13ld%13ld%13ld\n", "Swap:", info.totalswap, info.totalswap-info.freeswap, info.freeswap); printf("%6s%13ld%13ld%13ld\n", "Total:", info.totalram+info.totalswap, (info.totalram-info.freeram)+(info.totalswap-info.freeswap), info.freeram+info.freeswap); +# endif +#elif defined(__FreeBSD_kernel__) +# define S(X) ( ((unsigned long long)(X) << 10) >> shift) + const int shift = 10; + + meminfo(); + + printf(" total used free shared buffers\n"); + + printf("%-7s %10Lu %10Lu %10Lu %10Lu %10Lu\n", "Mem:", S(kb_main_total), + S(kb_main_used), S(kb_main_free), + S(kb_main_shared), S(kb_main_buffers)); + + printf("%-7s %10Lu %10Lu %10Lu\n", "Swap:", S(kb_swap_total), + S(kb_swap_used), S(kb_swap_free)); + + printf("%-7s %10Lu %10Lu %10Lu\n", "Total:", + S(kb_main_total + kb_swap_total), + S(kb_main_used + kb_swap_used), + S(kb_main_free + kb_swap_free)); #endif return EXIT_SUCCESS; }