Merge pull request #13 from l0ner/master

Pull l0ner/master into upstream.
This commit is contained in:
Matt McCormick 2015-01-19 21:47:04 -05:00
commit ca82149c10
31 changed files with 1551 additions and 384 deletions

53
.gitignore vendored Normal file

@ -0,0 +1,53 @@
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
sysstat
tmux-mem-cpu-load
# CMake generated #
###################
CMakeFiles
Makefile
cmake_install.cmake
CMakeCache.txt
install_manifest.txt
version.h
config.h
CTestTestfile.cmake
DartConfiguration.tcl
# Packages #
############
# it's better to unpack this files and commit raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
*.swp
*.swo
*~

12
AUTHORS Normal file

@ -0,0 +1,12 @@
Original author and maintainer:
Mattherw McCormick
Contributors (in alphabetical order):
Justin Crawford <justin@pci-online.net>
krieiter <krieiter@gmail.com>
Mark Palmeri <mlp6@duke.edu>
Pawel 'l0ner' Soltys <pwslts@gmail.com>

@ -1,22 +1,92 @@
# 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.
#
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
if(COMMAND cmake_policy) if(COMMAND cmake_policy)
cmake_policy(VERSION 2.6) cmake_policy(VERSION 2.6)
endif(COMMAND cmake_policy) endif(COMMAND cmake_policy)
### General Package stuff
project( tmux-mem-cpu-load ) project( tmux-mem-cpu-load )
set(tmux-mem-cpu-load_VERSION_MAJOR 2)
set(tmux-mem-cpu-load_VERSION_MINOR 3)
set(tmux-mem-cpu-load_VERSION_PATCH 0)
#Compute full version string
set(tmux-mem-cpu-load_VERSION
${tmux-mem-cpu-load_VERSION_MAJOR}.${tmux-mem-cpu-load_VERSION_MINOR}.${tmux-mem-cpu-load_VERSION_PATCH})
# Check whether we have support for c++11 in compiler and fail if we don't
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-std=c++11" COMPILER_SUPPORTS_CXX11)
check_cxx_compiler_flag("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(FATAL_ERROR "
Compiler ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} has no C++11 support.")
endif()
# generate header file to handle version
configure_file(
"${PROJECT_SOURCE_DIR}/version.h.in" "${PROJECT_SOURCE_DIR}/version.h"
)
# set build type
if(NOT CMAKE_BUILD_TYPE) if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
FORCE) FORCE)
endif(NOT CMAKE_BUILD_TYPE) endif(NOT CMAKE_BUILD_TYPE)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}) # detect system type
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
message("Linux detected")
set(METER_SOURCES "linux/memory.cc" "linux/cpu.cc" "linux/load.cc")
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
# Mac OS X source setting will go here
message( "Darwin detected")
set(METER_SOURCES "osx/memory.cc" "osx/cpu.cc" "osx/load.cc")
elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
# FreeBSD STUFF HERE
message("FreeBSD detected")
message( WARNING "FreeBSD is still experimental!" )
set( METER_SOURCES "bsd/memory_freebsd.cc" "bsd/cpu.cc" "bsd/load.cc" )
elseif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
# OpenBSD Stuff Here
message( "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" )
else()
message( FATAL_ERROR "Cannot be compiled on this system" )
endif()
add_executable(tmux-mem-cpu-load tmux-mem-cpu-load.cpp) # set common source files
install(TARGETS tmux-mem-cpu-load set( COMMON_SOURCES "tmux-mem-cpu-load.cpp" "graph.cc" )
RUNTIME DESTINATION bin
) # add binary tree so we find version.h
include_directories("${PROJECT_BINARY_DIR}" )
add_executable(tmux-mem-cpu-load ${COMMON_SOURCES} ${METER_SOURCES})
install(TARGETS tmux-mem-cpu-load RUNTIME DESTINATION bin)
include( CTest ) include( CTest )
if( BUILD_TESTING ) if( BUILD_TESTING )
@ -26,17 +96,20 @@ if( BUILD_TESTING )
add_test( NAME no_arguments add_test( NAME no_arguments
COMMAND tmux-mem-cpu-load ) COMMAND tmux-mem-cpu-load )
add_test( NAME custom_interval
COMMAND tmux-mem-cpu-load -i 3 )
add_test( NAME no_cpu_graph
COMMAND tmux-mem-cpu-load -g 0 )
add_test( NAME colors add_test( NAME colors
COMMAND tmux-mem-cpu-load --colors ) COMMAND tmux-mem-cpu-load --colors )
add_test( NAME arguments
COMMAND tmux-mem-cpu-load --colors 1 4 )
add_test( NAME invalid_status_interval add_test( NAME invalid_status_interval
COMMAND tmux-mem-cpu-load -1 4 ) COMMAND tmux-mem-cpu-load -i -1 )
add_test( NAME invalid_graph_lines add_test( NAME invalid_graph_lines
COMMAND tmux-mem-cpu-load 1 -4 ) COMMAND tmux-mem-cpu-load --graph_lines -2 )
set_tests_properties( usage set_tests_properties( usage
invalid_status_interval invalid_status_interval

53
CONTRIBUTING Normal file

@ -0,0 +1,53 @@
============
Contributing
============
Want to improve the quality of tmux-mem-cpu-load code? Great! Here's a quick
guide:
1. Fork, then clone the repo:
git clone git@github.com:your-username/tmux-mem-cpu-load
2. Make your change. Add tests for your change.
3. See if it compiles and runs like it should.
4. Run tests to check if you didn't break anything:
make test
Push to your fork and `submit a pull request`_.
At this point you're waiting on us. We'll review your changes as soon as we can.
Before merging your changes we may request you to make some changes or
corrections.
Style guidelines
----------------
You'll need to follow the subsequent rules in order to get your code merged:
* Use Allman_ style for block braces.
* No space before `(`
* Add space after each `(` and before each `)`
* Use braces single line statements
* Don't use mixed case naming style, use underscores instead.
Bad example:
int myAwesomeVariable = 0;
doSomething( myAwesomeVariable );
Good example:
int my_awesome_variable = 0;
do_something( my_awesome_variable );
* Don't vertically align tokens on consecutive lines.
* If you break up an argument list, align the line to opening brace
* Use 2 space indentation (no tabs)
* Use spaces around operators, except for unary operators, such as `!`.
* Add LICENSE header in new files you create.
* Put vim modeline as the first line of file header
* Use the lower-case for CMake commands
.. _`submit a pull request`: https://github.com/thewtex/tmux-mem-cpu-load/compare/
.. _Allman: http://en.wikipedia.org/wiki/Indent_style#Allman_style

@ -53,7 +53,7 @@ Building
~~~~~~~~ ~~~~~~~~
* >= CMake_ -2.6 * >= CMake_ -2.6
* C++ compiler (e.g. gcc/g++) * C++ compiler with C++11 support (e.g. gcc/g++ >= 4.6)
Download Download
-------- --------
@ -106,9 +106,11 @@ Contributions from:
* Justin Crawford <justinc@pci-online.net> * Justin Crawford <justinc@pci-online.net>
* krieiter <krieiter@gmail.com> * krieiter <krieiter@gmail.com>
* Mark Palmeri <mlp6@duke.edu> * Mark Palmeri <mlp6@duke.edu>
* `Pawel 'l0ner' Soltys`_ <pwslts@gmail.com>
.. _tmux: http://tmux.sourceforge.net/ .. _tmux: http://tmux.sourceforge.net/
.. _CMake: http://www.cmake.org .. _CMake: http://www.cmake.org
.. _`project homepage`: http://github.com/thewtex/tmux-mem-cpu-load .. _`project homepage`: http://github.com/thewtex/tmux-mem-cpu-load
.. _`terminals with 256 color support`: http://misc.flogisoft.com/bash/tip_colors_and_formatting#terminals_compatibility .. _`terminals with 256 color support`: http://misc.flogisoft.com/bash/tip_colors_and_formatting#terminals_compatibility
.. _`Pawel 'l0ner' Soltys` : http://l0ner.github.io/

57
bsd/cpu.cc Normal file

@ -0,0 +1,57 @@
/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
*
* Copyright 2012 Matthew McCormick
* Copyright 2013 Justin Crawford <Justasic@gmail.com>
* 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
#include <sys/types.h>
#include <unistd.h> // usleep
#include "getsysctl.h"
#include "cpu.h"
float cpu_percentage( unsigned int cpu_usage_delay )
{
int32_t load1[CPUSTATES];
int32_t load2[CPUSTATES];
GETSYSCTL( "kern.cp_time", load1 );
usleep( cpu_usage_delay );
GETSYSCTL( "kern.cp_time", load2 );
// 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<float>( diff_user + diff_system + diff_nice ) /
static_cast<float>( diff_user + diff_system + diff_nice + diff_idle ) *
100.0;
}

24
bsd/cpu.h Normal file

@ -0,0 +1,24 @@
/* 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_
float cpu_percentage( unsigned );
#endif

59
bsd/getsysctl.h Normal file

@ -0,0 +1,59 @@
/*
* Copyright 2012 Matthew McCormick
* Copyright 2013 Justin Crawford <Justasic@gmail.com>
* 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
#ifndef BSD_METER_COMMON_H_
#define BSD_METER_COMMON_H_
#include <iostream>
#include <cerrno>
#include <sys/sysctl.h>
#include <sys/types.h>
// 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 )
{
size_t nlen = len;
if( sysctlbyname( name, ptr, &nlen, NULL, 0 ) == -1 )
{
std::cerr << "sysctl(" << name << "...) failed: " << strerror( errno )
<< std::endl;
exit( 23 );
}
if( nlen != len )
{
std::cerr << "sysctl(" << name << "...) expected "
<< static_cast<unsigned long>( len ) << " bytes, got "
<< static_cast<unsigned long>( nlen ) << " bytes\n";
//exit( 23 );
}
}
#endif

81
bsd/load.cc Normal file

@ -0,0 +1,81 @@
/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
*
* Copyright 2012 Matthew McCormick
* Copyright 2013 Justin Crawford <Justasic@gmail.com>
* 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
#include <sstream>
#include <string>
#include <stdlib.h> // getloadavg()
#include <cmath> // floorf()
#include <sys/types.h>
#include "getsysctl.h"
#include "load.h"
#include "../luts.h"
// Load Averages
std::string load_string( bool use_colors = false )
{
std::stringstream ss;
// Get only 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
int32_t cpu_count = 0;
GETSYSCTL( "hw.ncpu", cpu_count );
unsigned load_percent = static_cast<unsigned int>( 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<float>( averages[i] ) * 100 + 0.5 ) / 100;
ss << avg << " ";
}
if( use_colors )
{
ss << "#[fg=default,bg=default]";
}
}
return ss.str();
}

26
bsd/load.h Normal file

@ -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 LOAD_H_
#define LOAD_H_
#include <string>
std::string load_string( bool );
#endif

26
bsd/memory.h Normal file

@ -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 <string>
std::string mem_string( bool );
#endif

76
bsd/memory_freebsd.cc Normal file

@ -0,0 +1,76 @@
/* 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.
*/
// 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
#include <sstream>
#include <string>
#include <sys/types.h>
#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
int32_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 );
GETSYSCTL( "vm.stats.vm.v_active_count", active_mem );
// Get all memory which can be allocated
//unused_mem = (cache_mem + free_mem) * page_size;
used_mem = ( static_cast<int64_t>( active_mem ) +
static_cast<int64_t>( inactive_mem ) +
static_cast<int64_t>( wired_mem ) ) * static_cast<int64_t>( 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();
}

78
bsd/memory_openbsd.cc Normal file

@ -0,0 +1,78 @@
/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
*
* Copyright 2012 Matthew McCormick
* Copyright 2013 Justin Crawford <Justasic@gmail.com>
* 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 <sstream>
#include <string>
#include <sys/types.h>
#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<int64_t>( active_mem ) + static_cast<int64_t>( wired_mem ) +
static_cast<int64_t>( inactive_mem ) ) * static_cast<int64_t>( 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();
}

19
bsd/openBSD.txt Normal file

@ -0,0 +1,19 @@
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

35
conversions.h Normal file

@ -0,0 +1,35 @@
/* 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.
*/
enum
{
BYTES = 0,
KILOBYTES = 1,
MEGABYTES = 2,
GIGABYTES = 3
};
template <class T>
inline T convert_unit( T num, int to, int from = BYTES)
{
for(from; from < to; from++)
{
num /= 1024;
}
return num;
}

62
graph.cc Normal file

@ -0,0 +1,62 @@
/* 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 <string>
#include <cstring>
#include "graph.h"
std::string get_graph_by_percentage( unsigned value, unsigned len )
{
unsigned step = 0;
std::string bars;
unsigned bar_count = ( static_cast<float>(value) / 99.9 * len );
for( step; step < bar_count; step++ )
{
bars.append( "|" );
}
for( step; step < len; step++ )
{
bars.append( " " );
}
return bars;
}
std::string get_graph_by_value( unsigned value, unsigned max, unsigned len )
{
unsigned step = 0;
std::string bars;
unsigned bar_count = ( static_cast<float>( value / ( max - 0.1 ) ) * len );
for( step; step < bar_count; step++ )
{
bars.append( "|" );
}
for( step; step < len; step++ )
{
bars.append( " " );
}
return bars;
}

27
graph.h Normal file

@ -0,0 +1,27 @@
/* 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 GRAPH_H_
#define GRAPH_H_
#include <string>
std::string get_graph_by_percentage( unsigned, unsigned len = 10 );
std::string get_graph_by_value( unsigned, unsigned, unsigned len = 10 );
#endif

70
linux/cpu.cc Normal file

@ -0,0 +1,70 @@
/* 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 <string>
#include <fstream>
#include <unistd.h> // usleep
#include "cpu.h"
#include "../luts.h"
float cpu_percentage( unsigned cpu_usage_delay )
{
std::string line;
size_t substr_start = 0;
size_t substr_len;
// cpu stats
// user, nice, system, idle
// in that order
unsigned long long stats[4];
std::ifstream stat_file( "/proc/stat" );
getline( stat_file, line );
stat_file.close();
// skip "cpu"
substr_len = line.find_first_of( " ", 3 );
// parse cpu line
for( unsigned i=0; i < 4; i++ )
{
substr_start = line.find_first_not_of( " ", substr_len );
substr_len = line.find_first_of( " ", substr_start );
stats[i] = std::stoll( line.substr( substr_start, substr_len ) );
}
usleep( cpu_usage_delay );
stat_file.open( "/proc/stat" );
getline( stat_file, line );
stat_file.close();
// skip "cpu"
substr_len = line.find_first_of( " ", 3 );
// parse cpu line
for( unsigned i=0; i < 4; i++ )
{
substr_start = line.find_first_not_of( " ", substr_len );
substr_len = line.find_first_of ( " ", substr_start );
stats[i] = std::stoll( line.substr( substr_start, substr_len ) ) - stats[i];
}
return static_cast<float>( stats[0] + stats[1] + stats[2]) /
static_cast<float>( stats[0] + stats[1] + stats[2] + stats[3] ) * 100.0;
}

24
linux/cpu.h Normal file

@ -0,0 +1,24 @@
/* 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_
float cpu_percentage( unsigned );
#endif

70
linux/load.cc Normal file

@ -0,0 +1,70 @@
/* 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 <string>
#include <sstream>
#include <unistd.h> // sysconf()?
#include <sys/sysinfo.h>
#include <linux/kernel.h> // SI_LOAD_SHIFT
#include "load.h"
#include "../luts.h"
std::string load_string( bool use_colors = false )
{
std::ostringstream oss;
float f = static_cast<float>( 1 << SI_LOAD_SHIFT );
struct sysinfo sinfo;
sysinfo( &sinfo );
if( use_colors )
{
// Likely does not work on BSD, but not tested
unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN );
float recent_load = sinfo.loads[0] / f;
// colors range from zero to twice the number of cpu's
// for the most recent load metric
unsigned load_percent = static_cast< unsigned int >(
recent_load / number_of_cpus * 0.5f * 100.0f );
if( load_percent > 100 )
{
load_percent = 100;
}
oss << load_lut[load_percent];
}
// set precision so we get results like "0.22"
oss.setf( std::ios::fixed );
oss.precision( 2 );
oss << sinfo.loads[0] / f << " " << sinfo.loads[1] / f << " "
<< sinfo.loads[2] / f;
if( use_colors )
{
oss << "#[fg=default,bg=default]";
}
return oss.str();
}

26
linux/load.h Normal file

@ -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 LOAD_H_
#define LOAD_H_
#include <string>
std::string load_string( bool );
#endif

105
linux/memory.cc Normal file

@ -0,0 +1,105 @@
/* 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 <sstream>
#include <fstream>
#include <sys/sysinfo.h>
#include "memory.h"
#include "../luts.h"
#include "../conversions.h"
std::string mem_string( bool use_colors = false )
{
using std::string;
using std::ifstream;
using std::stoi;
std::ostringstream oss;
string line, substr;
size_t substr_start;
size_t substr_len;
unsigned int total_mem, used_mem;
/* Since linux uses some RAM for disk caching, the actuall used ram is lower
* than what sysinfo(), top or free reports. htop reports the usage in a
* correct way. The memory used for caching doesn't count as used, since it
* can be freed in any moment. Usually it hapens automatically, when an
* application requests memory.
* In order to calculate the ram that's actually used we need to use the
* following formula:
* total_ram - free_ram - buffered_ram - cached_ram
*
* example data, junk removed, with comments added:
*
* MemTotal: 61768 kB old
* MemFree: 1436 kB old
* MemAvailable ????? kB ??
* MemShared: 0 kB old (now always zero; not calculated)
* Buffers: 1312 kB old
* Cached: 20932 kB old
* SwapTotal: 122580 kB old
* SwapFree: 60352 kB old
*/
ifstream memory_info("/proc/meminfo");
while( getline( memory_info, line ) )
{
substr_start = 0;
substr_len = line.find_first_of( ':' );
substr = line.substr( substr_start, substr_len );
substr_start = line.find_first_not_of( " ", substr_len + 1 );
substr_len = line.find_first_of( 'k' ) - substr_start;
if( substr.compare( "MemTotal" ) == 0 )
{
// get total memory
total_mem = stoi( line.substr( substr_start, substr_len ) );
}
else if( substr.compare( "MemFree" ) == 0 )
{
used_mem = total_mem - stoi( line.substr( substr_start, substr_len ) );
}
else if( substr.compare( "Buffers" ) == 0 ||
substr.compare( "Cached" ) == 0 )
{
used_mem -= stoi( line.substr( substr_start, substr_len ) );
}
}
if( use_colors )
{
oss << mem_lut[(100 * used_mem) / total_mem];
}
// we want megabytes on output, but since the values already come as
// kilobytes we need to divide them by 1024 only once, thus we use
// KILOBYTES
oss << convert_unit(used_mem, MEGABYTES, KILOBYTES) << '/'
<< convert_unit(total_mem, MEGABYTES, KILOBYTES) << "MB";
if( use_colors )
{
oss << "#[fg=default,bg=default]";
}
return oss.str();
}

26
linux/memory.h Normal file

@ -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 <string>
std::string mem_string( bool );
#endif

75
osx/cpu.cc Normal file

@ -0,0 +1,75 @@
/*
* Copyright 2012 Matthew McCormick
* Copyright 2013 Justin Crawford <Justasic@gmail.com>
* 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 <mach/mach.h>
#include <unistd.h> // usleep()
#include "cpu.h"
// OSX or BSD based system, use BSD APIs instead
// See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h
// and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/
host_cpu_load_info_data_t _get_cpu_percentage()
{
kern_return_t error;
mach_msg_type_number_t count;
host_cpu_load_info_data_t r_load;
mach_port_t mach_port;
count = HOST_CPU_LOAD_INFO_COUNT;
mach_port = mach_host_self();
error = host_statistics(mach_port, HOST_CPU_LOAD_INFO,
( host_info_t )&r_load, &count );
if ( error != KERN_SUCCESS )
{
return host_cpu_load_info_data_t();
}
return r_load;
}
float cpu_percentage( unsigned int cpu_usage_delay )
{
// Get the load times from the XNU kernel
host_cpu_load_info_data_t load1 = _get_cpu_percentage();
usleep( cpu_usage_delay );
host_cpu_load_info_data_t load2 = _get_cpu_percentage();
// Current load times
unsigned long long current_user = load1.cpu_ticks[CPU_STATE_USER];
unsigned long long current_system = load1.cpu_ticks[CPU_STATE_SYSTEM];
unsigned long long current_nice = load1.cpu_ticks[CPU_STATE_NICE];
unsigned long long current_idle = load1.cpu_ticks[CPU_STATE_IDLE];
// Next load times
unsigned long long next_user = load2.cpu_ticks[CPU_STATE_USER];
unsigned long long next_system = load2.cpu_ticks[CPU_STATE_SYSTEM];
unsigned long long next_nice = load2.cpu_ticks[CPU_STATE_NICE];
unsigned long long next_idle = load2.cpu_ticks[CPU_STATE_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<float>( diff_user + diff_system + diff_nice ) /
static_cast<float>( diff_user + diff_system + diff_nice + diff_idle ) *
100.0;
}

23
osx/cpu.h Normal file

@ -0,0 +1,23 @@
/*
* 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_
float cpu_percentage ( unsigned );
#endif

89
osx/load.cc Normal file

@ -0,0 +1,89 @@
/*
* Copyright 2012 Matthew McCormick
* Copyright 2013 Justin Crawford <Justasic@gmail.com>
* 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 <string>
#include <sstream>
#include <fstream>
#include <cmath> // floorf()
#include <unistd.h>
#include <stdlib.h> // getloadavg()
#include "load.h"
#include "../luts.h"
std::string load_string( bool use_colors = false )
{
std::ostringstream oss;
// Both apple and BSD style systems have these api calls
// Only get 3 load averages
const int nelem = 3;
double averages[nelem];
// based on:
// http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c
if( getloadavg( averages, nelem ) < 0 )
{
oss << "0.00 0.00 0.00"; // couldn't get averages.
}
else
{
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<float>( averages[i] ) * 100 + 0.5 ) / 100;
oss << avg << " ";
}
}
std::string load_line( oss.str() );
oss.str( "" );
if( use_colors )
{
// Likely does not work on BSD, but not tested
unsigned number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN );
std::istringstream iss( load_line.substr( 0, 4 ) );
float recent_load;
iss >> recent_load;
// colors range from zero to twice the number of
// cpu's for the most recent load metric
unsigned load_percent = static_cast< unsigned int >(
recent_load / number_of_cpus * 0.5f * 100.0f );
if( load_percent > 100 )
{
load_percent = 100;
}
oss << load_lut[load_percent];
}
oss << load_line.substr( 0, 14 );
if( use_colors )
{
oss << "#[fg=default,bg=default]";
}
return oss.str();
}

25
osx/load.h Normal file

@ -0,0 +1,25 @@
/*
* 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 LOAD_H_
#define LOAD_H_
#include <string>
std::string load_string( bool );
#endif

76
osx/memory.cc Normal file

@ -0,0 +1,76 @@
/*
* Copyright 2012 Matthew McCormick
* Copyright 2013 Justin Crawford <Justasic@gmail.com>
* 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 <string>
#include <sstream>
#include <mach/mach.h>
#include <sys/sysctl.h> // for sysctl
#include "memory.h"
#include "../luts.h"
#include "../conversions.h"
std::string mem_string( bool use_colors )
{
std::ostringstream oss;
// These values are in bytes
int64_t total_mem;
int64_t used_mem;
int64_t unused_mem;
vm_size_t page_size;
mach_port_t mach_port;
mach_msg_type_number_t count;
vm_statistics_data_t vm_stats;
// Get total physical memory
int mib[2];
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
size_t length = sizeof( int64_t );
sysctl( mib, 2, &total_mem, &length, NULL, 0 );
mach_port = mach_host_self();
count = sizeof( vm_stats ) / sizeof( natural_t );
if( KERN_SUCCESS == host_page_size( mach_port, &page_size ) &&
KERN_SUCCESS == host_statistics( mach_port, HOST_VM_INFO,
( host_info_t )&vm_stats, &count ) )
{
unused_mem = ( int64_t )vm_stats.free_count * ( int64_t )page_size;
used_mem = ( ( int64_t )vm_stats.active_count +
( int64_t )vm_stats.inactive_count + ( int64_t )vm_stats.wire_count
) * ( int64_t )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();
}

26
osx/memory.h Normal file

@ -0,0 +1,26 @@
/*
* Copyright 2012 Matthew McCormick
* Copyright 2013 Justin Crawford <Justasic@gmail.com>
* 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 <string>
std::string mem_string( bool );
#endif

@ -1,4 +1,5 @@
/* /* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
*
* Copyright 2012 Matthew McCormick * Copyright 2012 Matthew McCormick
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -12,412 +13,156 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* */ */
#include <cstring> #include <cstring>
#include <fstream>
#include <iostream> #include <iostream>
#include <fstream>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <unistd.h> // sleep #include <cstdlib> // EXIT_SUCCESS, atoi()
#include <cmath> // for floorf #include <getopt.h> // getopt_long
#include <cstdlib> // EXIT_SUCCESS
// Apple specific. #include "version.h"
#if defined(__APPLE__) && defined(__MACH__) #include "graph.h"
// Mach kernel includes for getting memory and CPU statistics
# include <mach/vm_statistics.h>
# include <mach/processor_info.h>
# include <mach/mach_types.h>
# include <mach/mach_init.h>
# include <mach/mach_host.h>
# include <mach/host_info.h>
# include <mach/mach_error.h>
# include <mach/vm_map.h>
# include <mach/mach.h>
# include <sys/sysctl.h> // for sysctl
# include <sys/types.h> // for integer types
#endif
// if we are on a BSD system
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
// TODO: Includes and *BSD support
# define BSD_BASED 1
#endif
// Tmux color lookup tables for the different metrics. // Tmux color lookup tables for the different metrics.
#include "luts.h" #include "luts.h"
// Function declarations. #if defined(__APPLE__) && defined(__MACH__)
float cpu_percentage( unsigned int cpu_usage_delay ); // Apple osx system
std::string cpu_string( unsigned int cpu_usage_delay, #include "osx/cpu.h"
unsigned int graph_lines, #include "osx/memory.h"
bool use_colors = false ); #include "osx/load.h"
std::string mem_string( bool use_colors = false ); #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
std::string load_string( bool use_colors = false ); // BSD system
#define BSD_BASED 1
#include "bsd/cpu.h"
#include "bsd/load.h"
#include "bsd/memory.h"
#else
// assume linux system
#include "linux/cpu.h"
#include "linux/memory.h"
#include "linux/load.h"
#endif
std::string cpu_string( unsigned int cpu_usage_delay, unsigned int graph_lines,
#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__)) bool use_colors = false )
// OSX or BSD based system, use BSD APIs instead
// See: http://www.opensource.apple.com/source/xnu/xnu-201/osfmk/mach/host_info.h
// and: http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/
host_cpu_load_info_data_t _get_cpu_percentage()
{ {
kern_return_t error;
mach_msg_type_number_t count;
host_cpu_load_info_data_t r_load;
mach_port_t mach_port;
count = HOST_CPU_LOAD_INFO_COUNT;
mach_port = mach_host_self();
error = host_statistics(mach_port, HOST_CPU_LOAD_INFO, (host_info_t)&r_load, &count);
if (error != KERN_SUCCESS)
{
return host_cpu_load_info_data_t();
}
return r_load;
}
float cpu_percentage( unsigned int cpu_usage_delay )
{
// Get the load times from the XNU kernel
host_cpu_load_info_data_t load1 = _get_cpu_percentage();
usleep(cpu_usage_delay);
host_cpu_load_info_data_t load2 = _get_cpu_percentage();
// Current load times
unsigned long long current_user = load1.cpu_ticks[CPU_STATE_USER];
unsigned long long current_system = load1.cpu_ticks[CPU_STATE_SYSTEM];
unsigned long long current_nice = load1.cpu_ticks[CPU_STATE_NICE];
unsigned long long current_idle = load1.cpu_ticks[CPU_STATE_IDLE];
// Next load times
unsigned long long next_user = load2.cpu_ticks[CPU_STATE_USER];
unsigned long long next_system = load2.cpu_ticks[CPU_STATE_SYSTEM];
unsigned long long next_nice = load2.cpu_ticks[CPU_STATE_NICE];
unsigned long long next_idle = load2.cpu_ticks[CPU_STATE_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;
#else // Linux
float cpu_percentage( unsigned int cpu_usage_delay )
{
std::string stat_line;
size_t line_start_pos;
size_t line_end_pos;
unsigned long long current_user;
unsigned long long current_system;
unsigned long long current_nice;
unsigned long long current_idle;
unsigned long long next_user;
unsigned long long next_system;
unsigned long long next_nice;
unsigned long long next_idle;
unsigned long long diff_user;
unsigned long long diff_system;
unsigned long long diff_nice;
unsigned long long diff_idle;
std::istringstream iss;
std::ifstream stat_file("/proc/stat");
getline(stat_file, stat_line);
stat_file.close();
// skip "cpu"
line_start_pos = stat_line.find_first_not_of(" ", 3);
line_end_pos = stat_line.find_first_of(' ', line_start_pos);
line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
iss >> current_user >> current_nice >> current_system >> current_idle;
iss.clear();
usleep( cpu_usage_delay );
stat_file.open("/proc/stat");
getline(stat_file, stat_line);
stat_file.close();
// skip "cpu"
line_start_pos = stat_line.find_first_not_of(" ", 3);
line_end_pos = stat_line.find_first_of(' ', line_start_pos);
line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
line_end_pos = stat_line.find_first_of(' ', line_end_pos + 1);
iss.str( stat_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
iss >> next_user >> next_nice >> next_system >> next_idle;
iss.clear();
diff_user = next_user - current_user;
diff_system = next_system - current_system;
diff_nice = next_nice - current_nice;
diff_idle = next_idle - current_idle;
#endif // platform
return static_cast<float>(diff_user + diff_system + diff_nice)/static_cast<float>(diff_user + diff_system + diff_nice + diff_idle)*100.0;
}
std::string cpu_string( unsigned int cpu_usage_delay,
unsigned int graph_lines,
bool use_colors )
{
std::string meter( graph_lines + 2, ' ' );
meter[0] = '[';
meter[meter.length() - 1] = ']';
int meter_count = 0;
float percentage; float percentage;
//output stuff
std::ostringstream oss; std::ostringstream oss;
oss.precision( 1 ); oss.precision( 1 );
oss.setf( std::ios::fixed | std::ios::right ); oss.setf( std::ios::fixed | std::ios::right );
// get %
percentage = cpu_percentage( cpu_usage_delay ); percentage = cpu_percentage( cpu_usage_delay );
float meter_step = 99.9 / graph_lines;
meter_count = 1;
while(meter_count*meter_step < percentage)
{
meter[meter_count] = '|';
meter_count++;
}
if( use_colors ) if( use_colors )
{ {
oss << cpu_percentage_lut[static_cast<unsigned int>( percentage )]; oss << cpu_percentage_lut[static_cast<unsigned int>( percentage )];
} }
oss << meter;
if( graph_lines > 0)
{
oss << "[";
oss << get_graph_by_percentage( unsigned( percentage ), graph_lines );
oss << "]";
}
oss.width( 5 ); oss.width( 5 );
oss << percentage; oss << percentage;
oss << "%"; oss << "%";
if( use_colors ) if( use_colors )
{ {
oss << "#[fg=default,bg=default]"; oss << "#[fg=default,bg=default]";
} }
return oss.str(); return oss.str();
} }
void print_help()
std::string mem_string( bool use_colors )
{ {
std::ostringstream oss; using std::cout;
#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__)) using std::endl;
// OSX or BSD based system, use BSD APIs instead
cout << "tmux-mem-cpu-load v" << tmux_mem_cpu_load_VERSION << endl
#if defined(__APPLE__) && defined(__MACH__) << "Usage: tmux-mem-cpu-load [OPTIONS]\n\n"
// These values are in bytes << "Available options:\n"
int64_t total_mem; << "-h, --help\n"
int64_t used_mem; << "\t Prints this help message\n"
int64_t unused_mem; << "--colors\n"
vm_size_t page_size; << "\tUse tmux colors in output\n"
mach_port_t mach_port; << "-i <value>, --interval <value>\n"
mach_msg_type_number_t count; << "\tSet tmux status refresh interval in seconds. Default: 1 second\n"
vm_statistics_data_t vm_stats; << "-g <value>, --graph-lines <value>\n"
<< "\tSet how many lines should be drawn in a graph. Default: 10\n"
// Get total physical memory << endl;
int mib[2];
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
size_t length = sizeof(int64_t);
sysctl(mib, 2, &total_mem, &length, NULL, 0);
mach_port = mach_host_self();
count = sizeof(vm_stats) / sizeof(natural_t);
if (KERN_SUCCESS == host_page_size(mach_port, &page_size) &&
KERN_SUCCESS == host_statistics(mach_port, HOST_VM_INFO, (host_info_t)&vm_stats, &count))
{
unused_mem = (int64_t)vm_stats.free_count * (int64_t)page_size;
used_mem = ((int64_t)vm_stats.active_count +
(int64_t)vm_stats.inactive_count +
(int64_t)vm_stats.wire_count) * (int64_t)page_size;
}
// To kilobytes
#endif // Apple
// TODO BSD
used_mem /= 1024;
total_mem /= 1024;
#else // Linux
unsigned int total_mem;
unsigned int used_mem;
unsigned int unused_mem;
size_t line_start_pos;
size_t line_end_pos;
std::istringstream iss;
std::string mem_line;
std::ifstream meminfo_file( "/proc/meminfo" );
getline( meminfo_file, mem_line );
line_start_pos = mem_line.find_first_of( ':' );
line_start_pos++;
line_end_pos = mem_line.find_first_of( 'k' );
iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
iss >> total_mem;
used_mem = total_mem;
for( unsigned int i = 0; i < 3; i++ )
{
getline( meminfo_file, mem_line );
// accomodate MemAvailable potentially being in lines 2-4 of /proc/meminfo
// did this in a way to not break the original logic of the loop
if( mem_line.find("MemAvailable") == 0 )
{
i--;
}
else
{
line_start_pos = mem_line.find_first_of( ':' );
line_start_pos++;
line_end_pos = mem_line.find_first_of( 'k' );
iss.str( mem_line.substr( line_start_pos, line_end_pos - line_start_pos ) );
iss >> unused_mem;
used_mem -= unused_mem;
}
}
meminfo_file.close();
#endif // platform
if( use_colors )
{
oss << mem_lut[(100 * used_mem) / total_mem];
}
oss << used_mem / 1024 << '/' << total_mem / 1024 << "MB";
if( use_colors )
{
oss << "#[fg=default,bg=default]";
}
return oss.str();
} }
int main( int argc, char** argv )
std::string load_string( bool use_colors )
{ {
std::ostringstream oss; unsigned cpu_usage_delay = 990000;
short graph_lines = 10; // max 32767 should be enough
#if defined(BSD_BASED) || (defined(__APPLE__) && defined(__MACH__))
// Both apple and BSD style systems have these api calls
// Only get 3 load averages
int nelem = 3;
double averages[3];
// based on: http://www.opensource.apple.com/source/Libc/Libc-262/gen/getloadavg.c
if( getloadavg(averages, nelem) < 0 )
{
oss << "0.00 0.00 0.00"; // couldn't get averages.
}
else
{
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<float>(averages[i]) * 100 + 0.5) / 100;
oss << avg << " ";
}
}
std::string load_line( oss.str() );
oss.str( "" );
#else // Linux
std::ifstream loadavg_file( "/proc/loadavg" );
std::string load_line;
std::getline( loadavg_file, load_line );
loadavg_file.close();
#endif // platform
if( use_colors )
{
std::ifstream stat_file( "/proc/stat" );
std::string stat_line;
std::getline( stat_file, stat_line );
// Likely does not work on BSD, but not tested
unsigned int number_of_cpus = sysconf( _SC_NPROCESSORS_ONLN );
std::istringstream iss( load_line.substr( 0, 4 ) );
float recent_load;
iss >> recent_load;
// colors range from zero to twice the number of cpu's for the most recent
// load metric
unsigned int load_percent = static_cast< unsigned int >( recent_load / number_of_cpus * 0.5f * 100.0f );
if( load_percent > 100 )
{
load_percent = 100;
}
oss << load_lut[load_percent];
}
oss << load_line.substr( 0, 14 );
if( use_colors )
{
oss << "#[fg=default,bg=default]";
}
return oss.str();
}
int main(int argc, char** argv)
{
unsigned int cpu_usage_delay = 900000;
int graph_lines = 10;
bool use_colors = false; bool use_colors = false;
try
{
std::istringstream iss;
iss.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
std::string current_arg;
unsigned int arg_index = 1;
if( argc > arg_index )
{
if( strcmp( argv[arg_index], "--colors" ) == 0 )
{
use_colors = true;
++arg_index;
}
}
if( argc > arg_index )
{
iss.str( argv[arg_index] );
int status_interval;
iss >> status_interval;
if( status_interval < 1 )
{
std::cerr << "Status interval argument must be one or greater." << std::endl;
return EXIT_FAILURE;
}
cpu_usage_delay = status_interval * 1000000 - 100000;
++arg_index;
}
if( argc > arg_index )
{
iss.str( argv[arg_index] );
iss.clear();
iss >> graph_lines;
if( graph_lines < 1 )
{
std::cerr << "Graph lines argument must be one or greater." << std::endl;
return EXIT_FAILURE;
}
}
}
catch(const std::exception &e)
{
std::cerr << "Usage: " << argv[0] << " [--colors] [tmux_status-interval(seconds)] [graph lines]" << std::endl;
return EXIT_FAILURE;
}
std::cout << mem_string( use_colors ) << ' ' << cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' ' << load_string( use_colors ); static struct option long_options[] =
{
// Struct is a s follows:
// const char * name, int has_arg, int *flag, int val
// if *flag is null, val is option identifier to use in switch()
// otherwise it's a value to set the variable *flag points to
{ "help", no_argument, NULL, 'h' },
{ "colors", no_argument, NULL, 'c' },
{ "interval", required_argument, NULL, 'i' },
{ "graph-lines", required_argument, NULL, 'g' },
{ 0, 0, 0, 0 } // used to handle unknown long options
};
int c;
// while c != -1
while( (c = getopt_long( argc, argv, "hi:g:", long_options, NULL) ) != -1 )
{
switch( c )
{
case 'h': // --help, -h
print_help();
return EXIT_FAILURE;
break;
case 'c': // --colors
use_colors = true;
break;
case 'i': // --interval, -i
if( atoi( optarg ) < 1 )
{
std::cerr << "Status interval argument must be one or greater.\n";
return EXIT_FAILURE;
}
cpu_usage_delay = atoi( optarg ) * 1000000 - 10000;
break;
case 'g': // --graph-lines, -g
if( atoi( optarg ) < 0 )
{
std::cerr << "Graph lines argument must be zero or greater.\n";
return EXIT_FAILURE;
}
graph_lines = atoi( optarg );
break;
case '?':
// getopt_long prints error message automatically
return EXIT_FAILURE;
break;
default:
std::cout << "?? getopt returned character code 0 " << c << std::endl;
return EXIT_FAILURE;
}
}
std::cout << mem_string( use_colors ) << ' '
<< cpu_string( cpu_usage_delay, graph_lines, use_colors ) << ' '
<< load_string( use_colors );
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

24
version.h.in Normal file

@ -0,0 +1,24 @@
/* 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.
*/
// the configured options and settings for sysstat
#define tmux_mem_cpu_load_VERSION_MAJOR @tmux-mem-cpu-load_VERSION_MAJOR@
#define tmux_mem_cpu_load_VERSION_MINOR @tmux-mem-cpu-load_VERSION_MINOR@
#define tmux_mem_cpu_load_VERSION_PATCH @tmux-mem-cpu-load_VERSION_PATCH@
#define tmux_mem_cpu_load_VERSION "@tmux-mem-cpu-load_VERSION@"