diff --git a/CMakeLists.txt b/CMakeLists.txt index 0211974..effea3f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,16 +64,17 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin") message(STATUS "Darwin detected") set(METER_SOURCES "osx/memory.cc" "osx/cpu.cc" "osx/load.cc") elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - message("FreeBSD detected") - message(WARNING "FreeBSD is still experimental!") - set(METER_SOURCES "bsd/memory_freebsd.cc" "bsd/cpu.cc" "bsd/load.cc") + message(STATUS "FreeBSD detected") + set(METER_SOURCES "freebsd/memory.cc" "freebsd/cpu.cc" "freebsd/load.cc") elseif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD") + # OpenBSD Stuff Here message(STATUS "OpenBSD detected") - message(FATAL_ERROR - "OpenBSD is not supported! See bsd/openBSD.txt for more info") - set(METER_SOURCES "bsd/memory_openbsd.cc" "bsd/cpu.cc" "bsd/load.cc") + set(METER_SOURCES "openbsd/memory.cc" "openbsd/cpu.cc" "openbsd/load.cc") + if(CMAKE_SYSTEM_VERSION VERSION_LESS 5.7) + add_definitions(-DOPENBSD_WORKAROUND=1) + endif() else() - message(FATAL_ERROR "Cannot be compiled on this system" ) + message(FATAL_ERROR "Cannot be compiled on this system") endif() # set common source files diff --git a/CONTRIBUTING b/CONTRIBUTING.rst similarity index 94% rename from CONTRIBUTING rename to CONTRIBUTING.rst index cc345ce..70c89f5 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING.rst @@ -49,6 +49,8 @@ You'll need to follow the subsequent rules in order to get your code merged: * Put vim modeline as the first line of file header * Use the lower-case for CMake commands * Do not add trailing whitespace + You can use this bash script to strip unnecessary whitespaces: + http://git.io/z_GA3A .. _`submit a pull request`: https://github.com/thewtex/tmux-mem-cpu-load/compare/ .. _Allman: http://en.wikipedia.org/wiki/Indent_style#Allman_style diff --git a/README.rst b/README.rst index 90d885d..6757332 100644 --- a/README.rst +++ b/README.rst @@ -47,7 +47,7 @@ Installation Dependencies ------------ -Currently, Linux and Mac OSX are supported. +Currently, Linux, Mac OSX, FreeBSD and OpenBSD are supported. Building ~~~~~~~~ diff --git a/bsd/memory_openbsd.cc b/bsd/memory_openbsd.cc deleted file mode 100644 index a391cac..0000000 --- a/bsd/memory_openbsd.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap - * - * Copyright 2012 Matthew McCormick - * Copyright 2013 Justin Crawford - * Copyright 2015 Pawel 'l0ner' Soltys - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c -// Based on: Apple.cpp for load_string/mem_string and apple's documentation - -#error ToDo: OpenBSD. This file is incomplete and likely will not compile if you remove this error (it is here to tell you it's unfinished) - -#include -#include -#include - -#include "getsysctl.h" -#include "memory.h" -#include "luts.h" -#include "conversions.h" - -std::string mem_string( bool use_colors = false ) -{ - // These values are in bytes - int64_t total_mem = 0; - int64_t used_mem = 0; - int64_t unused_mem = 0; - int32_t inactive_mem = 0; - int32_t active_mem = 0; - int32_t free_mem = 0; - int32_t wired_mem = 0; - int32_t page_size = 0; - int32_t cache_mem = 0; - std::ostringstream oss; - - // Get total physical memory, page size, and some other needed info - GETSYSCTL( "hw.realmem", total_mem ); - GETSYSCTL( "hw.pagesize", page_size ); - - GETSYSCTL( "vm.stats.vm.v_free_count", free_mem ); - GETSYSCTL( "vm.stats.vm.v_inactive_count", inactive_mem ); - GETSYSCTL( "vm.stats.vm.v_cache_count", cache_mem ); - GETSYSCTL( "vm.stats.vm.v_wire_count", wired_mem ); - - // Get all memory which can be allocated - //unused_mem = (inactive_mem + cache_mem + free_mem) * page_size; - used_mem = ( - static_cast( active_mem ) + static_cast( wired_mem ) + - static_cast( inactive_mem ) ) * static_cast( page_size ); - - if( use_colors ) - { - oss << mem_lut[( 100 * used_mem ) / total_mem]; - } - - oss << convert_unit( used_mem, MEGABYTES ) << '/' - << convert_unit( total_mem, MEGABYTES ) << "MB"; - - if( use_colors ) - { - oss << "#[fg=default,bg=default]"; - } - - return oss.str(); -} - diff --git a/bsd/openBSD.txt b/bsd/openBSD.txt deleted file mode 100644 index 4a7c804..0000000 --- a/bsd/openBSD.txt +++ /dev/null @@ -1,19 +0,0 @@ -About OpenBSD Port -================== - -I've decided not to do OpenBSD port. Some preparations has been made both -by myself and (mainly) by Justin Crawford, so finish it shouldn't be difficult. -Personally, after installing OpenBSD and trying to finish the port I've -discovered that g++ supplied by OpenBSD (version 5.7) doesn't support c++11. -This means we lose the ability to use to_string() and stoi() functions. I could -write replacements for them, or try to get c++11 working on OpenBSD. But I -decided not to. At least for the moment. - -I don't know OpenBSD, it's unfamiliar ground for me. And while FreeBSD was easy -to get into, I have found OpenBSD a little bit more difficult. - -So, no OpenBSD port for now. If you are OpenBSD user and know a little bit c++ -finishing the port should be easy (once you get C++11 working). - -l0ner - diff --git a/common/main.cc b/common/main.cc index 2937a39..e1bd9ba 100644 --- a/common/main.cc +++ b/common/main.cc @@ -34,12 +34,17 @@ #include "osx/cpu.h" #include "osx/memory.h" #include "osx/load.h" -#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) +#elif defined(__FreeBSD__) || defined(__NetBSD__) // BSD system #define BSD_BASED 1 - #include "bsd/cpu.h" - #include "bsd/load.h" - #include "bsd/memory.h" + #include "freebsd/cpu.h" + #include "freebsd/load.h" + #include "freebsd/memory.h" +#elif defined(__OpenBSD) + #define BSD_BASED 1 + #include "freebsd/cpu.h" + #include "freebsd/load.h" + #include "freebsd/memory.h" #else // assume linux system #include "linux/cpu.h" @@ -68,7 +73,7 @@ std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines, if( graph_lines > 0) { - oss << "["; + oss << " ["; oss << get_graph_by_percentage( unsigned( percentage ), graph_lines ); oss << "]"; } @@ -168,7 +173,7 @@ int main( int argc, char** argv ) return EXIT_FAILURE; } - std::cout << mem_string( use_colors ) << ' ' + std::cout << mem_string( use_colors ) << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' << load_string( use_colors ); diff --git a/bsd/cpu.cc b/freebsd/cpu.cc similarity index 99% rename from bsd/cpu.cc rename to freebsd/cpu.cc index 70e3560..403aea9 100644 --- a/bsd/cpu.cc +++ b/freebsd/cpu.cc @@ -51,7 +51,7 @@ float cpu_percentage( unsigned int cpu_usage_delay ) unsigned long long diff_nice = next_nice - current_nice; unsigned long long diff_idle = next_idle - current_idle; - return static_cast( diff_user + diff_system + diff_nice ) / - static_cast( diff_user + diff_system + diff_nice + diff_idle ) * + return static_cast( diff_user + diff_system + diff_nice ) / + static_cast( diff_user + diff_system + diff_nice + diff_idle ) * 100.0; } diff --git a/freebsd/cpu.h b/freebsd/cpu.h new file mode 100644 index 0000000..3840650 --- /dev/null +++ b/freebsd/cpu.h @@ -0,0 +1,31 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CPU_H_ +#define CPU_H_ + +#define CP_USER 0 +#define CP_NICE 1 +#define CP_SYS 2 +#define CP_INTR 3 +#define CP_IDLE 4 +#define CPUSTATES 5 + +float cpu_percentage( unsigned ); + +#endif diff --git a/bsd/getsysctl.h b/freebsd/getsysctl.h similarity index 91% rename from bsd/getsysctl.h rename to freebsd/getsysctl.h index 58f6860..aecd004 100644 --- a/bsd/getsysctl.h +++ b/freebsd/getsysctl.h @@ -27,14 +27,6 @@ #include #include -// CPU percentages stuff -#define CP_USER 0 -#define CP_NICE 1 -#define CP_SYS 2 -#define CP_INTR 3 -#define CP_IDLE 4 -#define CPUSTATES 5 - #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var)) static inline void getsysctl( const char *name, void *ptr, size_t len ) { diff --git a/bsd/load.cc b/freebsd/load.cc similarity index 100% rename from bsd/load.cc rename to freebsd/load.cc diff --git a/bsd/load.h b/freebsd/load.h similarity index 100% rename from bsd/load.h rename to freebsd/load.h diff --git a/bsd/memory_freebsd.cc b/freebsd/memory.cc similarity index 100% rename from bsd/memory_freebsd.cc rename to freebsd/memory.cc diff --git a/bsd/memory.h b/freebsd/memory.h similarity index 100% rename from bsd/memory.h rename to freebsd/memory.h diff --git a/openbsd/cpu.cc b/openbsd/cpu.cc new file mode 100644 index 0000000..fefc215 --- /dev/null +++ b/openbsd/cpu.cc @@ -0,0 +1,93 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include // usleep + +#include +#include + +#include "error.h" +#include "cpu.h" + +uint8_t get_cpu_count() +{ + int cpu_count = 1; // default to 1 + int mib[2] = { CTL_HW, HW_NCPU }; + size_t len = sizeof( cpu_count ); + + if( sysctl( mib, 2, &cpu_count, &len, NULL, 0 ) < 0 ) + { + error( "sysctl: error getting cpu count" ); + } + + return cpu_count; +} + +float cpu_percentage( unsigned int cpu_usage_delay ) +{ + int cpu_ctl[] = { CTL_KERN, KERN_CPTIME }; + + // on 64bit systems KERN_CPTIME gets reported as 64bit + // uint. Detect 64bit system and define array to hold the + // stats accordingly. + // NOTE: the following test may need to be extended to cover + // more 64bit platforms. +#if __x86_64__ || __ppc64__ + u_int64_t load1[CPUSTATES]; + u_int64_t load2[CPUSTATES]; +#else + u_int32_t load1[CPUSTATES]; + u_int32_t load2[CPUSTATES]; +#endif + + size_t size = sizeof( load1 ); + + // get cpu times + if( sysctl( cpu_ctl, 2, &load1, &size, NULL, 0 ) < 0 ) + { + error( "sysctl: error getting initial cpu stats" ); + } + + usleep( cpu_usage_delay ); + + // update cpu times + if( sysctl( cpu_ctl, 2, &load2, &size, NULL, 0 ) < 0 ) + { + error( "sysctl: error getting updated cpu stats" ); + } + + // Current load times + unsigned long long current_user = load1[CP_USER]; + unsigned long long current_system = load1[CP_SYS]; + unsigned long long current_nice = load1[CP_NICE]; + unsigned long long current_idle = load1[CP_IDLE]; + // Next load times + unsigned long long next_user = load2[CP_USER]; + unsigned long long next_system = load2[CP_SYS]; + unsigned long long next_nice = load2[CP_NICE]; + unsigned long long next_idle = load2[CP_IDLE]; + // Difference between the two + unsigned long long diff_user = next_user - current_user; + unsigned long long diff_system = next_system - current_system; + unsigned long long diff_nice = next_nice - current_nice; + unsigned long long diff_idle = next_idle - current_idle; + + return static_cast( diff_user + diff_system + diff_nice ) / + static_cast( diff_user + diff_system + diff_nice + diff_idle ) * + 100.0; +} diff --git a/openbsd/cpu.h b/openbsd/cpu.h new file mode 100644 index 0000000..5bb6e87 --- /dev/null +++ b/openbsd/cpu.h @@ -0,0 +1,34 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CPU_H_ +#define CPU_H_ + +#include + +#define CP_USER 0 +#define CP_NICE 1 +#define CP_SYS 2 +#define CP_INTR 3 +#define CP_IDLE 4 +#define CPUSTATES 5 + +float cpu_percentage( unsigned ); +uint8_t get_cpu_count(); + +#endif diff --git a/openbsd/error.h b/openbsd/error.h new file mode 100644 index 0000000..b4c6a7e --- /dev/null +++ b/openbsd/error.h @@ -0,0 +1,36 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BSD_ERROR_H_ +#define BSD_ERROR_H_ + +#include +#include +#include +#include // strerror + +inline void error( const char * error ) +{ + using std::cerr; + using std::endl; + + cerr << error << ": " << strerror( errno ) << endl; + exit( 23 ); +} + +#endif diff --git a/openbsd/load.cc b/openbsd/load.cc new file mode 100644 index 0000000..7c4a138 --- /dev/null +++ b/openbsd/load.cc @@ -0,0 +1,75 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include // getloadavg() +#include // floorf() +#include + +#include "cpu.h" +#include "load.h" +#include "luts.h" + +// Load Averages +std::string load_string( bool use_colors = false ) +{ + std::stringstream ss; + // Only get 3 load averages + const int nelem = 3; + double averages[nelem]; + // based on: opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c + + if( getloadavg( averages, nelem ) < 0) + { + ss << "0.00 0.00 0.00"; // couldn't get averages. + } + else + { + if( use_colors ) + { + // may not work + uint8_t cpu_count = get_cpu_count(); + + unsigned load_percent = static_cast( + averages[0] / cpu_count * 0.5f * 100.0f); + + if( load_percent > 100 ) + { + load_percent = 100; + } + + ss << load_lut[load_percent]; + } + + for( int i = 0; i < nelem; ++i ) + { + // Round to nearest, make sure this is only a 0.00 value not a 0.0000 + float avg = floorf( static_cast (averages[i] ) * 100 + 0.5 ) / 100; + ss << avg << " "; + } + + if( use_colors ) + { + ss << "#[fg=default,bg=default]"; + } + + } + + return ss.str(); +} diff --git a/bsd/cpu.h b/openbsd/load.h similarity index 89% rename from bsd/cpu.h rename to openbsd/load.h index ebc0e8e..f1bbc58 100644 --- a/bsd/cpu.h +++ b/openbsd/load.h @@ -16,9 +16,11 @@ * limitations under the License. */ -#ifndef CPU_H_ -#define CPU_H_ +#ifndef LOAD_H_ +#define LOAD_H_ -float cpu_percentage( unsigned ); +#include + +std::string load_string( bool ); #endif diff --git a/openbsd/memory.cc b/openbsd/memory.cc new file mode 100644 index 0000000..dc41c58 --- /dev/null +++ b/openbsd/memory.cc @@ -0,0 +1,118 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +// Ugly fix to compilation on OpenBSD 5.6 +// these need to be before include sys/mount.h +// and be in this exact order. Otherwise compiling on +// OpenBSD 5.6 will fail with missing NGROUPS define +// or missing gid_t typedefs +#ifdef OPENBSD_WORKAROUND +#include // typedefs +#include // missing NGROUPS +#include +#else +#include +#endif + +#include // VFS_* which we use to get cache +#include +#include // vmtotal struct + +#include "error.h" +#include "memory.h" +#include "luts.h" +#include "conversions.h" + +static int pageshift; + +#define pagesh(size) ((size) << pageshift) + +std::string mem_string( bool use_colors = false ) +{ + std::ostringstream oss; + + // These values are in bytes + int64_t total_mem = 0; + int64_t used_mem = 0; + int32_t free_mem = 0; + size_t size; + + // get page size + static int hw_pagesize[] = { CTL_HW, HW_PAGESIZE }; + int page_size = 0; + size = sizeof( page_size ); + if( sysctl( hw_pagesize, 2, &page_size, &size, NULL, 0 ) < 0 ) + { + error( "memory: error getting page size" ); + } + + // calculate how far we must shift the variables + pageshift = 0; + while( page_size > 1 ) + { + pageshift++; + page_size >>= 1; + } + + // get vm memory stats + static int vm_totalmem[] = { CTL_VM, VM_METER }; + struct vmtotal vm_total; + size = sizeof( vm_total ); + if( sysctl( vm_totalmem, 2, &vm_total, &size, NULL, 0 ) < 0 ) + { + error( "memory: error getting vm memory stats" ); + } + + // In case we need it, this gets the cached memory (bcstats.numbufpages) + static int vm_bcstats[] = { CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT }; + struct bcachestats bcstats; + size = sizeof( bcstats ); + if( sysctl( vm_bcstats, 3, &bcstats, &size, NULL, 0 ) < 0 ) + { + error( "memory: error getting cached memory size" ); + } + + // calculations based on conky openbsd port + used_mem = pagesh( vm_total.t_rm ); + free_mem = pagesh( vm_total.t_free ); + + // from nagios-memory plugin + used_mem -= pagesh( bcstats.numbufpages ); + free_mem += pagesh( bcstats.numbufpages ); + + // calculate total memory + total_mem = used_mem + free_mem; + + if( use_colors ) + { + oss << mem_lut[( 100 * used_mem ) / total_mem]; + } + + oss << convert_unit( used_mem, MEGABYTES ) + << '/' << convert_unit( total_mem, MEGABYTES ) << "MB"; + + if( use_colors ) + { + oss << "#[fg=default,bg=default]"; + } + + return oss.str(); +} diff --git a/openbsd/memory.h b/openbsd/memory.h new file mode 100644 index 0000000..3a123bb --- /dev/null +++ b/openbsd/memory.h @@ -0,0 +1,26 @@ +/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap + * + * Copyright 2012 Matthew McCormick + * Copyright 2015 Pawel 'l0ner' Soltys + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEMORY_H_ +#define MEMORY_H_ + +#include + +std::string mem_string( bool ); + +#endif