summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am44
-rw-r--r--src/Makefile.in536
-rw-r--r--src/dataframe.h88
-rw-r--r--src/device.cpp226
-rw-r--r--src/device.h62
-rw-r--r--src/devreader-bsd.cpp175
-rw-r--r--src/devreader-bsd.h39
-rw-r--r--src/devreader-hpux.cpp294
-rw-r--r--src/devreader-hpux.h39
-rw-r--r--src/devreader-linux-proc.cpp156
-rw-r--r--src/devreader-linux-proc.h41
-rw-r--r--src/devreader-linux-sys.cpp110
-rw-r--r--src/devreader-linux-sys.h43
-rw-r--r--src/devreader-linux.cpp33
-rw-r--r--src/devreader-linux.h32
-rw-r--r--src/devreader-solaris.cpp101
-rw-r--r--src/devreader-solaris.h39
-rw-r--r--src/devreader.cpp106
-rw-r--r--src/devreader.h42
-rw-r--r--src/devreaderfactory.cpp128
-rw-r--r--src/devreaderfactory.h45
-rw-r--r--src/form_field.cpp237
-rw-r--r--src/form_field.h110
-rw-r--r--src/graph.cpp110
-rw-r--r--src/graph.h45
-rw-r--r--src/main.cpp583
-rw-r--r--src/main.h34
-rw-r--r--src/opt_window.cpp193
-rw-r--r--src/opt_window.h50
-rw-r--r--src/screen.cpp56
-rw-r--r--src/screen.h32
-rw-r--r--src/setting.cpp144
-rw-r--r--src/setting.h88
-rw-r--r--src/settingfilter.cpp222
-rw-r--r--src/settingfilter.h128
-rw-r--r--src/settingstore.cpp98
-rw-r--r--src/settingstore.h44
-rw-r--r--src/statistics.cpp216
-rw-r--r--src/statistics.h114
-rw-r--r--src/stringutils.cpp97
-rw-r--r--src/stringutils.h49
-rw-r--r--src/templates/cpp_template16
-rw-r--r--src/templates/header_template16
-rw-r--r--src/traffic_window.cpp85
-rw-r--r--src/traffic_window.h43
-rw-r--r--src/window.cpp289
-rw-r--r--src/window.h142
47 files changed, 5620 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..c5f77fa
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,44 @@
+## Helder Correia <helder.correia@netcabo.pt>
+
+bin_PROGRAMS = nload
+
+nload_SOURCES = \
+ dataframe.h \
+ device.cpp device.h \
+ devreader.cpp devreader.h \
+ devreaderfactory.cpp devreaderfactory.h \
+ form_field.cpp form_field.h \
+ graph.cpp graph.h \
+ main.cpp main.h \
+ opt_window.cpp opt_window.h \
+ screen.cpp screen.h \
+ setting.cpp setting.h \
+ settingfilter.cpp settingfilter.h \
+ settingstore.cpp settingstore.h \
+ statistics.cpp statistics.h \
+ stringutils.cpp stringutils.h \
+ traffic_window.cpp traffic_window.h \
+ window.cpp window.h
+
+if HAVE_BSD
+nload_SOURCES += \
+ devreader-bsd.cpp devreader-bsd.h
+endif
+
+if HAVE_HPUX
+nload_SOURCES += \
+ devreader-hpux.cpp devreader-hpux.h
+endif
+
+if HAVE_LINUX
+nload_SOURCES += \
+ devreader-linux.cpp devreader-linux.h \
+ devreader-linux-proc.cpp devreader-linux-proc.h \
+ devreader-linux-sys.cpp devreader-linux-sys.h
+endif
+
+if HAVE_SOLARIS
+nload_SOURCES += \
+ devreader-solaris.cpp devreader-solaris.h
+endif
+
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..52a5278
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,536 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = nload$(EXEEXT)
+@HAVE_BSD_TRUE@am__append_1 = \
+@HAVE_BSD_TRUE@ devreader-bsd.cpp devreader-bsd.h
+
+@HAVE_HPUX_TRUE@am__append_2 = \
+@HAVE_HPUX_TRUE@ devreader-hpux.cpp devreader-hpux.h
+
+@HAVE_LINUX_TRUE@am__append_3 = \
+@HAVE_LINUX_TRUE@ devreader-linux.cpp devreader-linux.h \
+@HAVE_LINUX_TRUE@ devreader-linux-proc.cpp devreader-linux-proc.h \
+@HAVE_LINUX_TRUE@ devreader-linux-sys.cpp devreader-linux-sys.h
+
+@HAVE_SOLARIS_TRUE@am__append_4 = \
+@HAVE_SOLARIS_TRUE@ devreader-solaris.cpp devreader-solaris.h
+
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am__nload_SOURCES_DIST = dataframe.h device.cpp device.h devreader.cpp \
+ devreader.h devreaderfactory.cpp devreaderfactory.h \
+ form_field.cpp form_field.h graph.cpp graph.h main.cpp main.h \
+ opt_window.cpp opt_window.h screen.cpp screen.h setting.cpp \
+ setting.h settingfilter.cpp settingfilter.h settingstore.cpp \
+ settingstore.h statistics.cpp statistics.h stringutils.cpp \
+ stringutils.h traffic_window.cpp traffic_window.h window.cpp \
+ window.h devreader-bsd.cpp devreader-bsd.h devreader-hpux.cpp \
+ devreader-hpux.h devreader-linux.cpp devreader-linux.h \
+ devreader-linux-proc.cpp devreader-linux-proc.h \
+ devreader-linux-sys.cpp devreader-linux-sys.h \
+ devreader-solaris.cpp devreader-solaris.h
+@HAVE_BSD_TRUE@am__objects_1 = devreader-bsd.$(OBJEXT)
+@HAVE_HPUX_TRUE@am__objects_2 = devreader-hpux.$(OBJEXT)
+@HAVE_LINUX_TRUE@am__objects_3 = devreader-linux.$(OBJEXT) \
+@HAVE_LINUX_TRUE@ devreader-linux-proc.$(OBJEXT) \
+@HAVE_LINUX_TRUE@ devreader-linux-sys.$(OBJEXT)
+@HAVE_SOLARIS_TRUE@am__objects_4 = devreader-solaris.$(OBJEXT)
+am_nload_OBJECTS = device.$(OBJEXT) devreader.$(OBJEXT) \
+ devreaderfactory.$(OBJEXT) form_field.$(OBJEXT) \
+ graph.$(OBJEXT) main.$(OBJEXT) opt_window.$(OBJEXT) \
+ screen.$(OBJEXT) setting.$(OBJEXT) settingfilter.$(OBJEXT) \
+ settingstore.$(OBJEXT) statistics.$(OBJEXT) \
+ stringutils.$(OBJEXT) traffic_window.$(OBJEXT) \
+ window.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
+ $(am__objects_3) $(am__objects_4)
+nload_OBJECTS = $(am_nload_OBJECTS)
+nload_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(nload_SOURCES)
+DIST_SOURCES = $(am__nload_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INCLUDES = @INCLUDES@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+nload_SOURCES = dataframe.h device.cpp device.h devreader.cpp \
+ devreader.h devreaderfactory.cpp devreaderfactory.h \
+ form_field.cpp form_field.h graph.cpp graph.h main.cpp main.h \
+ opt_window.cpp opt_window.h screen.cpp screen.h setting.cpp \
+ setting.h settingfilter.cpp settingfilter.h settingstore.cpp \
+ settingstore.h statistics.cpp statistics.h stringutils.cpp \
+ stringutils.h traffic_window.cpp traffic_window.h window.cpp \
+ window.h $(am__append_1) $(am__append_2) $(am__append_3) \
+ $(am__append_4)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+nload$(EXEEXT): $(nload_OBJECTS) $(nload_DEPENDENCIES)
+ @rm -f nload$(EXEEXT)
+ $(CXXLINK) $(nload_OBJECTS) $(nload_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/device.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devreader-bsd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devreader-hpux.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devreader-linux-proc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devreader-linux-sys.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devreader-linux.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devreader-solaris.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devreader.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devreaderfactory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/form_field.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/graph.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt_window.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/screen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setting.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingfilter.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/settingstore.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/statistics.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stringutils.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/traffic_window.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/window.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic ctags distclean distclean-compile \
+ distclean-generic distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-binPROGRAMS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/dataframe.h b/src/dataframe.h
new file mode 100644
index 0000000..3311292
--- /dev/null
+++ b/src/dataframe.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ dataframe.h
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DATAFRAME_H
+#define DATAFRAME_H
+
+#include <string>
+
+class DataFrame
+{
+ public:
+ DataFrame()
+ : m_totalDataIn(0), m_totalDataOut(0), m_totalPacketsIn(0), m_totalPacketsOut(0),
+ m_totalErrorsIn(0), m_totalErrorsOut(0), m_totalDropsIn(0), m_totalDropsOut(0),
+ m_timeStampSeconds(0), m_timeStampMicroseconds(0), m_valid(false) {}
+ ~DataFrame() {}
+
+ bool isValid() const { return m_valid; }
+ void setValid(bool valid) { m_valid = valid; }
+
+ const std::string& getDeviceName() const { return m_deviceName; }
+ void setDeviceName(const std::string& deviceName) { m_deviceName = deviceName; }
+
+ const std::string& getIpV4() const { return m_ipv4; }
+ void setIpV4(const std::string& ipv4) { m_ipv4 = ipv4; }
+
+ unsigned long long getTotalDataIn() const { return m_totalDataIn; }
+ void setTotalDataIn(unsigned long long totalDataIn) { m_totalDataIn = totalDataIn; }
+
+ unsigned long long getTotalDataOut() const { return m_totalDataOut; }
+ void setTotalDataOut(unsigned long long totalDataOut) { m_totalDataOut = totalDataOut; }
+
+ unsigned long long getTotalPacketsIn() const { return m_totalPacketsIn; }
+ void setTotalPacketsIn(unsigned long long totalPacketsIn) { m_totalPacketsIn = totalPacketsIn; }
+
+ unsigned long long getTotalPacketsOut() const { return m_totalPacketsOut; }
+ void setTotalPacketsOut(unsigned long long totalPacketsOut) { m_totalPacketsOut = totalPacketsOut; }
+
+ unsigned long long getTotalErrorsIn() const { return m_totalErrorsIn; }
+ void setTotalErrorsIn(unsigned long long totalErrorsIn) { m_totalErrorsIn = totalErrorsIn; }
+
+ unsigned long long getTotalErrorsOut() const { return m_totalErrorsOut; }
+ void setTotalErrorsOut(unsigned long long totalErrorsOut) { m_totalErrorsOut = totalErrorsOut; }
+
+ unsigned long long getTotalDropsIn() const { return m_totalDropsIn; }
+ void setTotalDropsIn(unsigned long long totalDropsIn) { m_totalDropsIn = totalDropsIn; }
+
+ unsigned long long getTotalDropsOut() const { return m_totalDropsOut; }
+ void setTotalDropsOut(unsigned long long totalDropsOut) { m_totalDropsOut = totalDropsOut; }
+
+ unsigned long getTimeStampSeconds() const { return m_timeStampSeconds; }
+ void setTimeStampSeconds(unsigned long seconds) { m_timeStampSeconds = seconds; }
+
+ unsigned long getTimeStampMicroseconds() const { return m_timeStampMicroseconds; }
+ void setTimeStampMicroseconds(unsigned long microseconds) { m_timeStampMicroseconds = microseconds; }
+
+ private:
+ std::string m_deviceName;
+ std::string m_ipv4;
+ unsigned long long m_totalDataIn;
+ unsigned long long m_totalDataOut;
+ unsigned long long m_totalPacketsIn;
+ unsigned long long m_totalPacketsOut;
+ unsigned long long m_totalErrorsIn;
+ unsigned long long m_totalErrorsOut;
+ unsigned long long m_totalDropsIn;
+ unsigned long long m_totalDropsOut;
+ unsigned long m_timeStampSeconds;
+ unsigned long m_timeStampMicroseconds;
+ bool m_valid;
+};
+
+#endif
+
diff --git a/src/device.cpp b/src/device.cpp
new file mode 100644
index 0000000..e3d6372
--- /dev/null
+++ b/src/device.cpp
@@ -0,0 +1,226 @@
+/***************************************************************************
+ dev.cpp
+ -------------------
+ begin : Wed Aug 1 2001
+ copyright : (C) 2001 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "device.h"
+#include "devreader.h"
+#include "graph.h"
+#include "setting.h"
+#include "settingstore.h"
+#include "window.h"
+
+#include <iomanip>
+
+using namespace std;
+
+Device::Device(DevReader& devReader)
+ : m_deviceNumber(0), m_totalNumberOfDevices(0), m_devReader(devReader)
+{
+}
+
+Device::~Device()
+{
+}
+
+// update the device's data
+void Device::update()
+{
+ // read current traffic
+ DataFrame dataFrame = m_devReader.getNewDataFrame();
+
+ if(dataFrame.isValid())
+ {
+ /* Depending on the CPU architecture and the OS interface
+ * used for reading the device statistics, the counts can
+ * overflow. We monitor the overflows and fix them.
+ */
+ fixOverflows(dataFrame, m_dataFrameOld);
+
+ m_deviceStatistics.insertDataFrame(dataFrame);
+
+ m_deviceGraphIn.update(m_deviceStatistics.getDataInPerSecond());
+ m_deviceGraphOut.update(m_deviceStatistics.getDataOutPerSecond());
+
+ m_dataFrameOld = dataFrame;
+ }
+ else
+ {
+ m_deviceStatistics.reset();
+ m_deviceGraphIn.resetTrafficData();
+ m_deviceGraphOut.resetTrafficData();
+ }
+}
+
+// print the device's data
+void Device::print(Window& window)
+{
+ // if device does not exist
+ if(!m_deviceStatistics.isValid())
+ {
+ // ... print warning message ...
+ window.print() << "Device " << m_devReader.getDeviceName() << " (" << (m_deviceNumber + 1) << "/" << m_totalNumberOfDevices << "): does not exist" << endl;
+ window.print() << string(window.getWidth(), '=') << endl;
+
+ // ... and exit
+ return;
+ }
+
+ // print header
+ string ip4 = m_dataFrameOld.getIpV4();
+ if(!ip4.empty())
+ window.print() << "Device " << m_devReader.getDeviceName() << " [" << ip4 << "] (" << (m_deviceNumber + 1) << "/" << m_totalNumberOfDevices << "):" << endl;
+ else
+ window.print() << "Device " << m_devReader.getDeviceName() << " (" << (m_deviceNumber + 1) << "/" << m_totalNumberOfDevices << "):" << endl;
+ window.print() << string(window.getWidth(), '=');
+
+ // if graphs should be hidden ...
+ if(SettingStore::get("MultipleDevices"))
+ {
+ window.print() << "Incoming:";
+ window.print(window.getWidth() / 2) << "Outgoing:" << endl;
+
+ int statusY = window.getY();
+
+ printStatisticsIn(window, 0, statusY);
+ printStatisticsOut(window, window.getWidth() / 2, statusY);
+
+ window.print() << endl;
+ }
+ // ... or not
+ else
+ {
+ // incoming traffic
+ window.print() << "Incoming:" << endl;
+
+ m_deviceGraphIn.setNumOfBars(window.getWidth() * 2 / 3);
+ m_deviceGraphIn.setHeightOfBars((window.getHeight() - window.getY() - 1) / 2);
+ m_deviceGraphIn.setMaxDeflection((unsigned long long) SettingStore::get("BarMaxIn") * 1024 / 8);
+ m_deviceGraphIn.print(window, 0, window.getY());
+
+ printStatisticsIn(window, window.getWidth() * 2 / 3 + 2, window.getY() - 5);
+
+ // outgoing traffic
+ window.print() << "Outgoing:" << endl;
+
+ m_deviceGraphOut.setNumOfBars(window.getWidth() * 2 / 3);
+ m_deviceGraphOut.setHeightOfBars(window.getHeight() - window.getY());
+ m_deviceGraphOut.setMaxDeflection((unsigned long long) SettingStore::get("BarMaxOut") * 1024 / 8);
+ m_deviceGraphOut.print(window, 0, window.getY());
+
+ printStatisticsOut(window, window.getWidth() * 2 / 3 + 2, window.getY() - 4);
+ }
+}
+
+// set the number identifying the device (for display only)
+void Device::setDeviceNumber(int deviceNumber)
+{
+ m_deviceNumber = deviceNumber;
+}
+
+// set the total number of shown devices (for display only)
+void Device::setTotalNumberOfDevices(int totalNumberOfDevices)
+{
+ m_totalNumberOfDevices = totalNumberOfDevices;
+}
+
+void Device::fixOverflows(DataFrame& dataFrame, const DataFrame& dataFrameOld)
+{
+ if(!dataFrame.isValid() || !dataFrameOld.isValid())
+ return;
+
+ dataFrame.setTotalDataIn(fixOverflow(dataFrame.getTotalDataIn(), dataFrameOld.getTotalDataIn()));
+ dataFrame.setTotalDataOut(fixOverflow(dataFrame.getTotalDataOut(), dataFrameOld.getTotalDataOut()));
+ dataFrame.setTotalPacketsIn(fixOverflow(dataFrame.getTotalPacketsIn(), dataFrameOld.getTotalPacketsIn()));
+ dataFrame.setTotalPacketsOut(fixOverflow(dataFrame.getTotalPacketsOut(), dataFrameOld.getTotalPacketsOut()));
+ dataFrame.setTotalErrorsIn(fixOverflow(dataFrame.getTotalErrorsIn(), dataFrameOld.getTotalErrorsIn()));
+ dataFrame.setTotalErrorsOut(fixOverflow(dataFrame.getTotalErrorsOut(), dataFrameOld.getTotalErrorsOut()));
+ dataFrame.setTotalDropsIn(fixOverflow(dataFrame.getTotalDropsIn(), dataFrameOld.getTotalDropsIn()));
+ dataFrame.setTotalDropsOut(fixOverflow(dataFrame.getTotalDropsOut(), dataFrameOld.getTotalDropsOut()));
+}
+
+unsigned long long Device::fixOverflow(unsigned long long value, unsigned long long valueOld)
+{
+ if(value > 0xffffffffULL)
+ return value;
+
+ if(value < (valueOld & 0xffffffffULL))
+ {
+ // overflow happend (again)
+ valueOld += 0x100000000ULL;
+ }
+
+ // no overflow happend, keep previous ones
+ valueOld &= 0xffffffff00000000ULL;
+ value |= valueOld;
+ return value;
+}
+
+void Device::printTrafficValue(Window& window, int x, int y, const std::string& description, unsigned long long value)
+{
+ Statistics::dataUnit trafficFormat = (Statistics::dataUnit) ((int) SettingStore::get("TrafficFormat"));
+
+ string unitString = Statistics::getUnitString(trafficFormat, value);
+ float unitFactor = Statistics::getUnitFactor(trafficFormat, value);
+
+ window.print(x, y) << fixed << setprecision(2) << description << ": " << ((float) value / unitFactor) << " " << unitString << "/s" << endl;
+}
+
+void Device::printDataValue(Window& window, int x, int y, const std::string& description, unsigned long long value)
+{
+ Statistics::dataUnit dataFormat = (Statistics::dataUnit) ((int) SettingStore::get("DataFormat"));
+
+ string unitString = Statistics::getUnitString(dataFormat, value);
+ float unitFactor = Statistics::getUnitFactor(dataFormat, value);
+
+ window.print(x, y) << fixed << setprecision(2) << description << ": " << ((float) value / unitFactor) << " " << unitString << endl;
+}
+
+void Device::printStatisticsIn(Window& window, int x, int y)
+{
+ // print current traffic
+ printTrafficValue(window, x, y, "Curr", m_deviceStatistics.getDataInPerSecond());
+
+ // print average traffic
+ printTrafficValue(window, x, y + 1, "Avg", m_deviceStatistics.getDataInAverage());
+
+ // print min traffic since nload start
+ printTrafficValue(window, x, y + 2, "Min", m_deviceStatistics.getDataInMin());
+
+ // print max traffic since nload start
+ printTrafficValue(window, x, y + 3, "Max", m_deviceStatistics.getDataInMax());
+
+ // print total traffic since last system reboot
+ printDataValue(window, x, y + 4, "Ttl", m_deviceStatistics.getDataInTotal());
+}
+
+void Device::printStatisticsOut(Window& window, int x, int y)
+{
+ // print current traffic
+ printTrafficValue(window, x, y, "Curr", m_deviceStatistics.getDataOutPerSecond());
+
+ // print average traffic
+ printTrafficValue(window, x, y + 1, "Avg", m_deviceStatistics.getDataOutAverage());
+
+ // print min traffic since nload start
+ printTrafficValue(window, x, y + 2, "Min", m_deviceStatistics.getDataOutMin());
+
+ // print max traffic since nload start
+ printTrafficValue(window, x, y + 3, "Max", m_deviceStatistics.getDataOutMax());
+
+ // print total traffic since last system reboot
+ printDataValue(window, x, y + 4, "Ttl", m_deviceStatistics.getDataOutTotal());
+}
+
diff --git a/src/device.h b/src/device.h
new file mode 100644
index 0000000..25d8211
--- /dev/null
+++ b/src/device.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ device.h
+ -------------------
+ begin : Wed Aug 1 2001
+ copyright : (C) 2001 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVICE_H
+#define DEVICE_H
+
+#include "dataframe.h"
+#include "graph.h"
+#include "statistics.h"
+
+#include <string>
+
+class DevReader;
+class Window;
+
+class Device
+{
+ public:
+ explicit Device(DevReader& devReader);
+ ~Device();
+
+ void update();
+ void print(Window&);
+ void setDeviceNumber(int deviceNumber);
+ void setTotalNumberOfDevices(int totalNumberOfDevices);
+
+ private:
+ void fixOverflows(DataFrame& dataFrame, const DataFrame& dataFrameOld);
+ unsigned long long fixOverflow(unsigned long long value, unsigned long long valueOld);
+
+ void printTrafficValue(Window& window, int x, int y, const std::string& description, unsigned long long value);
+ void printDataValue(Window& window, int x, int y, const std::string& description, unsigned long long value);
+ void printStatisticsIn(Window& window, int x, int y);
+ void printStatisticsOut(Window& window, int x, int y);
+
+ int m_deviceNumber;
+ int m_totalNumberOfDevices;
+
+ Statistics m_deviceStatistics;
+ Graph m_deviceGraphIn;
+ Graph m_deviceGraphOut;
+
+ DataFrame m_dataFrameOld;
+ DevReader& m_devReader;
+};
+
+#endif
+
diff --git a/src/devreader-bsd.cpp b/src/devreader-bsd.cpp
new file mode 100644
index 0000000..b542704
--- /dev/null
+++ b/src/devreader-bsd.cpp
@@ -0,0 +1,175 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * Free/Net/OpenBSD specific network code taken out of gkrellm: *
+ * Copyright by Bill Wilson <bill@gkrellm.net> *
+ * FreeBSD code by Hajimu Umemoto <ume@mahoroba.org> *
+ * NetBSD code by Anthony Mallet <anthony.mallet@useless-ficus.net> *
+ * Hajimu Umemoto merged Free/Net/OpenBSD code *
+ * adapted for nload by Roland Riegel <feedback@roland-riegel.de> *
+ ***************************************************************************/
+
+#include "devreader-bsd.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <string>
+#include <list>
+
+using namespace std;
+
+DevReaderBsd::DevReaderBsd(const string& deviceName)
+ : DevReader(deviceName)
+{
+}
+
+DevReaderBsd::~DevReaderBsd()
+{
+}
+
+list<string> DevReaderBsd::findAllDevices()
+{
+ list<string> interfaceNames;
+
+ struct if_msghdr *ifm, *nextifm;
+ struct sockaddr_dl *sdl;
+ char *lim, *next;
+ size_t needed;
+ int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
+ char *buf = 0;
+
+ if(sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ return interfaceNames;
+
+ buf = (char *) malloc(needed);
+ if(buf == NULL)
+ return interfaceNames;
+
+ if(sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+ return interfaceNames;
+
+ lim = buf + needed;
+
+ next = buf;
+ while(next < lim)
+ {
+ ifm = (struct if_msghdr *) next;
+ if(ifm->ifm_type != RTM_IFINFO)
+ break;
+
+ next += ifm->ifm_msglen;
+
+ while(next < lim)
+ {
+ nextifm = (struct if_msghdr *) next;
+ if(nextifm->ifm_type != RTM_NEWADDR)
+ break;
+ next += nextifm->ifm_msglen;
+ }
+
+ sdl = (struct sockaddr_dl *) (ifm + 1);
+ if(sdl->sdl_family != AF_LINK)
+ continue;
+
+ interfaceNames.push_back(string(sdl->sdl_data));
+ }
+
+ free(buf);
+
+ return interfaceNames;
+}
+
+void DevReaderBsd::readFromDevice(DataFrame& dataFrame)
+{
+ struct if_msghdr *ifm, *nextifm;
+ struct sockaddr_dl *sdl;
+ char *lim, *next;
+ size_t needed;
+ int mib[] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
+ char *buf = 0;
+
+ if(m_deviceName.empty())
+ return;
+
+ do
+ {
+ if(sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ break;
+
+ buf = (char *) malloc(needed);
+ if(buf == NULL)
+ break;
+
+ if(sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
+ break;
+
+ lim = buf + needed;
+
+ next = buf;
+ while(next < lim)
+ {
+ ifm = (struct if_msghdr *) next;
+ if(ifm->ifm_type != RTM_IFINFO)
+ break;
+
+ next += ifm->ifm_msglen;
+
+ while(next < lim)
+ {
+ nextifm = (struct if_msghdr *) next;
+ if(nextifm->ifm_type != RTM_NEWADDR)
+ break;
+ next += nextifm->ifm_msglen;
+ }
+
+ if(ifm->ifm_flags & IFF_UP)
+ {
+ sdl = (struct sockaddr_dl *) (ifm + 1);
+ if(sdl->sdl_family != AF_LINK)
+ continue;
+
+ if(strncmp(m_deviceName.c_str(), sdl->sdl_data, sdl->sdl_nlen) == 0)
+ {
+ dataFrame.setTotalDataIn(ifm->ifm_data.ifi_ibytes);
+ dataFrame.setTotalDataOut(ifm->ifm_data.ifi_obytes);
+
+ dataFrame.setTotalPacketsIn(ifm->ifm_data.ifi_ipackets);
+ dataFrame.setTotalPacketsOut(ifm->ifm_data.ifi_opackets);
+
+ dataFrame.setTotalErrorsIn(ifm->ifm_data.ifi_ierrors);
+ dataFrame.setTotalErrorsOut(ifm->ifm_data.ifi_oerrors);
+
+ dataFrame.setTotalDropsIn(0); // ifi_iqdrops ?
+ dataFrame.setTotalDropsOut(0);
+
+ dataFrame.setValid(true);
+
+ break;
+ }
+ }
+ }
+ } while(0);
+
+ free(buf);
+}
+
diff --git a/src/devreader-bsd.h b/src/devreader-bsd.h
new file mode 100644
index 0000000..0907b19
--- /dev/null
+++ b/src/devreader-bsd.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ devreader-bsd.h
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVREADER_BSD_H
+#define DEVREADER_BSD_H
+
+#include "devreader.h"
+
+#include <string>
+#include <list>
+
+class DevReaderBsd : public DevReader
+{
+ public:
+ DevReaderBsd(const std::string& deviceName);
+ virtual ~DevReaderBsd();
+
+ static std::list<std::string> findAllDevices();
+
+ protected:
+ void readFromDevice(DataFrame& dataFrame);
+};
+
+#endif
+
diff --git a/src/devreader-hpux.cpp b/src/devreader-hpux.cpp
new file mode 100644
index 0000000..c1f5403
--- /dev/null
+++ b/src/devreader-hpux.cpp
@@ -0,0 +1,294 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * HP-UX specific network code *
+ * *
+ * Copyright 1998 by Hewlett-Packard Company *
+ * *
+ * Permission to use, copy, modify, and distribute this *
+ * software and its documentation for any purpose and without *
+ * fee is hereby granted, provided that the above copyright *
+ * notice appear in all copies and that both that copyright *
+ * notice and this permission notice appear in supporting *
+ * documentation, and that the name of Hewlett-Packard Company not *
+ * be used in advertising or publicity pertaining to distribution *
+ * of the software without specific, written prior permission. *
+ * Hewlett-Packard makes no representations about the *
+ * suitability of this software for any purpose. It is provided *
+ * "as is" without express or implied warranty. *
+ * *
+ * *
+ * Modification History: *
+ * *
+ * int_stats.c : Get network statistics from the dlpi device *
+ * On 10.20 only get a mib_ifEntry, on 11.0 this is followed *
+ * by an mib_Dot3StatsEntry. Accessing the latter structure *
+ * is left as an exercise for the reader, the struct is defined *
+ * in /usr/include/sys/mib.h along with mib_ifEntry. *
+ * *
+ * Author: Jon Dewis, SPP 3/26/98 *
+ * (With ackn to 'lanadmin' source code and streams class notes) *
+ * *
+ * 24-June-1998 Add mib3 stats (AJD) when compiling *
+ * for 11.0 ensure HP_UX11 macro defined *
+ * e.g. cc -o int_stats -DHP_UX11 int_stats.c *
+ * 16-Dec-1999 Change to obviate need for lanscan to get *
+ * nmid - thus assumes any old nmid will do *
+ * and just iterates thru the 1st 100 possibilities *
+ * (MAX_NMID). Works on 10.20 and 11.0 *
+ * Dec 2003 Modified by Roshan Sequeira roshan.sequeira@hp.com, *
+ * to get network statistics for the nload port to HP-UX. *
+ * Original code available at *
+ * http://h21007.www2.hp.com/dspp/tech/tech_TechDocumentDetailPage_IDX/1,1701,2599,00.html
+ * *
+ ***************************************************************************/
+
+#include "devreader-hpux.h"
+#include "stringutils.h"
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stropts.h>
+#include <sys/dlpi.h>
+#include <sys/dlpi_ext.h>
+#include <sys/mib.h>
+
+#include <string>
+#include <list>
+
+using namespace std;
+
+#define AREA_SIZE 40000
+#define LONG_AREA_SIZE (AREA_SIZE / sizeof(u_long))
+
+static u_long ctrl_area[LONG_AREA_SIZE]; /* for control messages */
+static u_long data_area[LONG_AREA_SIZE]; /* for data messages */
+static u_long ppa_area[LONG_AREA_SIZE]; /* for saving ppa area */
+static struct strbuf ctrl_buf = {AREA_SIZE, 0, (char*) ctrl_area};
+static struct strbuf data_buf = {AREA_SIZE, 0, (char*) data_area};
+
+DevReaderHpux::DevReaderHpux(const string& deviceName)
+ : DevReader(deviceName)
+{
+}
+
+DevReaderHpux::~DevReaderHpux()
+{
+}
+
+list<string> DevReaderHpux::findAllDevices()
+{
+ list<string> devicesFound;
+
+ dl_hp_ppa_info_t* ppa_info_temp;
+ dl_hp_ppa_req_t* ppa_req;
+ dl_hp_ppa_ack_t* ppa_ack;
+ dl_attach_req_t* attach_req;
+
+ int fd = -1;
+ if((fd = open("/dev/dlpi", O_RDWR)) < 0)
+ {
+ perror("open /dev/dlpi");
+ return devicesFound;
+ }
+
+ do
+ {
+ ppa_req = (dl_hp_ppa_req_t*) ctrl_area;
+ ppa_ack = (dl_hp_ppa_ack_t*) ctrl_area;
+
+ ppa_req->dl_primitive = DL_HP_PPA_REQ;
+
+ ctrl_buf.len = sizeof(dl_hp_ppa_req_t);
+ if(putmsg(fd, &ctrl_buf, 0, 0) < 0)
+ {
+ perror("putmsg DL_HP_PPA_REQ");
+ break;
+ }
+
+ int flags = 0;
+ ctrl_area[0] = 0;
+
+ if(getmsg(fd, &ctrl_buf, &data_buf, &flags) < 0)
+ {
+ perror("getmsg DL_HP_PPA_REQ");
+ break;
+ }
+
+ if(ppa_ack->dl_length == 0)
+ {
+ fprintf(stderr, "error: no PPAs available\n");
+ break;
+ }
+
+ // save all the PPA information
+ memcpy((u_char*) ppa_area, (u_char*) ctrl_area + ppa_ack->dl_offset, ppa_ack->dl_length);
+ int ppa_count = ppa_ack->dl_count;
+
+ int count;
+ for(count = 0, ppa_info_temp = (dl_hp_ppa_info_t*) ppa_area; count < ppa_count; count++, ppa_info_temp++)
+ devicesFound.push_back(string("lan") + toString(ppa_info_temp->dl_ppa));
+
+ } while(0);
+
+ close(fd);
+
+ return devicesFound;
+}
+
+void DevReaderHpux::readFromDevice(DataFrame& dataFrame)
+{
+ dl_get_statistics_req_t* get_statistics_req = (dl_get_statistics_req_t*) ctrl_area;
+ dl_get_statistics_ack_t* get_statistics_ack = (dl_get_statistics_ack_t*) ctrl_area;
+
+ dl_hp_ppa_info_t ppa_info;
+ dl_hp_ppa_info_t* ppa_info_temp;
+ dl_hp_ppa_req_t* ppa_req;
+ dl_hp_ppa_ack_t* ppa_ack;
+ dl_attach_req_t* attach_req;
+ mib_ifEntry* mib_ptr;
+
+ unsigned int ppa = 0;
+ int flags = 0, ppa_count = 0, count = 0;
+
+ // make sure interface name begins with lan
+ if(m_deviceName.length() < 3 || m_deviceName.substr(0, 3) != "lan")
+ return;
+
+ // get the PPA from the interface name
+ ppa = fromString<int>(m_deviceName.substr(3));
+ if(ppa == 0 && m_deviceName != "lan0")
+ return;
+
+ int fd = -1;
+ if((fd = open("/dev/dlpi", O_RDWR)) < 0)
+ {
+ perror("open /dev/dlpi");
+ return;
+ }
+
+ do
+ {
+ ppa_req = (dl_hp_ppa_req_t*) ctrl_area;
+ ppa_ack = (dl_hp_ppa_ack_t*) ctrl_area;
+
+ ppa_req->dl_primitive = DL_HP_PPA_REQ;
+
+ ctrl_buf.len = sizeof(dl_hp_ppa_req_t);
+ if(putmsg(fd, &ctrl_buf, 0, 0) < 0)
+ {
+ perror("putmsg DL_HP_PPA_REQ");
+ break;
+ }
+
+ flags = 0;
+ ctrl_area[0] = 0;
+
+ if(getmsg(fd, &ctrl_buf, &data_buf, &flags) < 0)
+ {
+ perror("getmsg DL_HP_PPA_REQ");
+ break;
+ }
+
+ if(ppa_ack->dl_length == 0)
+ {
+ fprintf(stderr, "Error: No PPAs available\n");
+ break;
+ }
+
+ // save all the PPA information
+ memcpy((u_char*) ppa_area, (u_char*) ctrl_area + ppa_ack->dl_offset, ppa_ack->dl_length);
+ ppa_count = ppa_ack->dl_count;
+
+ bool found = false;
+ for(count = 0, ppa_info_temp = (dl_hp_ppa_info_t*) ppa_area; count < ppa_count; count++, ppa_info_temp++)
+ {
+ if(ppa_info_temp->dl_ppa == ppa)
+ {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ {
+ fprintf(stderr, "error: PPA %d not found\n", ppa);
+ break;
+ }
+
+ attach_req = (dl_attach_req_t*) ctrl_area;
+ attach_req->dl_primitive = DL_ATTACH_REQ;
+ attach_req->dl_ppa = ppa;
+ ctrl_buf.len = sizeof(dl_attach_req_t);
+ if(putmsg(fd, &ctrl_buf, 0, 0) < 0)
+ {
+ perror("putmsg DL_ATTACH_REQ");
+ break;
+ }
+
+ ctrl_area[0] = 0;
+ if(getmsg(fd, &ctrl_buf, &data_buf, &flags) < 0)
+ {
+ perror("getmsg DL_ATTACH_REQ");
+ break;
+ }
+ memcpy(&ppa_info, ppa_info_temp, sizeof(ppa_info));
+
+ get_statistics_req->dl_primitive = DL_GET_STATISTICS_REQ;
+ ctrl_buf.len = sizeof(dl_get_statistics_req_t);
+ flags = 0;
+
+ if(putmsg(fd, &ctrl_buf, NULL, 0) < 0)
+ {
+ perror("putmsg DL_GET_STATISTICS_REQ");
+ break;
+ }
+
+ if(getmsg(fd, &ctrl_buf, NULL, &flags) < 0)
+ {
+ perror("getmsg DL_GET_STATISTICS_REQ");
+ break;
+ }
+ if(get_statistics_ack->dl_primitive != DL_GET_STATISTICS_ACK)
+ fprintf(stderr, "error: wrong primitive\n");
+
+ mib_ptr = (mib_ifEntry*) ((u_char*) ctrl_area + get_statistics_ack->dl_stat_offset);
+
+ dataFrame.setTotalDataIn(mib_ptr->ifInOctets);
+ dataFrame.setTotalDataOut(mib_ptr->ifOutOctets);
+
+ dataFrame.setTotalPacketsIn(mib_ptr->ifInUcastPkts + mib_ptr->ifInNUcastPkts);
+ dataFrame.setTotalPacketsOut(mib_ptr->ifOutUcastPkts + mib_ptr->ifOutNUcastPkts);
+
+ dataFrame.setTotalErrorsIn(mib_ptr->ifInErrors);
+ dataFrame.setTotalErrorsOut(mib_ptr->ifOutErrors);
+
+ dataFrame.setTotalDropsIn(mib_ptr->ifInDiscards);
+ dataFrame.setTotalDropsOut(mib_ptr->ifOutDiscards);
+
+ dataFrame.setValid(true);
+
+ } while(0);
+
+ close(fd);
+}
+
diff --git a/src/devreader-hpux.h b/src/devreader-hpux.h
new file mode 100644
index 0000000..ad57105
--- /dev/null
+++ b/src/devreader-hpux.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ devreader-hpux.h
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVREADER_HPUX_H
+#define DEVREADER_HPUX_H
+
+#include "devreader.h"
+
+#include <string>
+#include <list>
+
+class DevReaderHpux : public DevReader
+{
+ public:
+ DevReaderHpux(const std::string& deviceName);
+ virtual ~DevReaderHpux();
+
+ static std::list<std::string> findAllDevices();
+
+ protected:
+ void readFromDevice(DataFrame& dataFrame);
+};
+
+#endif
+
diff --git a/src/devreader-linux-proc.cpp b/src/devreader-linux-proc.cpp
new file mode 100644
index 0000000..2d698b7
--- /dev/null
+++ b/src/devreader-linux-proc.cpp
@@ -0,0 +1,156 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "devreader-linux-proc.h"
+#include "stringutils.h"
+
+#include <fstream>
+#include <list>
+#include <string>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+using namespace std;
+
+DevReaderLinuxProc::DevReaderLinuxProc(const string& deviceName)
+ : DevReader(deviceName)
+{
+}
+
+DevReaderLinuxProc::~DevReaderLinuxProc()
+{
+}
+
+bool DevReaderLinuxProc::isAvailable()
+{
+ struct stat procStat;
+ if(stat("/proc/net/dev", &procStat) < 0 || ! S_ISREG(procStat.st_mode))
+ return false;
+
+ return true;
+}
+
+list<string> DevReaderLinuxProc::findAllDevices()
+{
+ list<string> interfaceNames;
+
+ ifstream fin("/proc/net/dev");
+ if(!fin.is_open())
+ return interfaceNames;
+
+ // skip the two header lines
+ string line;
+ getline(fin, line);
+ getline(fin, line);
+
+ if(!fin.good())
+ return interfaceNames;
+
+ // read all remaining lines and extract the device name
+ while(fin.good())
+ {
+ getline(fin, line);
+ if(line.empty())
+ continue;
+
+ string::size_type posEnd = line.find(':');
+ if(posEnd == string::npos)
+ continue;
+
+ interfaceNames.push_back(trim(line.substr(0, posEnd)));
+ }
+
+ return interfaceNames;
+}
+
+void DevReaderLinuxProc::readFromDevice(DataFrame& dataFrame)
+{
+ if(m_deviceName.empty())
+ return;
+
+ ifstream fin("/proc/net/dev");
+ if(!fin.is_open())
+ return;
+
+ // skip the two header lines
+ string line;
+ getline(fin, line);
+ getline(fin, line);
+
+ if(!fin.good())
+ return;
+
+ // search for device
+ while(fin.good())
+ {
+ getline(fin, line);
+ if(line.empty())
+ continue;
+
+ string::size_type posEnd = line.find(':');
+ if(posEnd == string::npos)
+ continue;
+
+ string interfaceName = trim(line.substr(0, posEnd));
+ if(interfaceName.empty())
+ continue;
+
+ // check if it is the device we want
+ if(m_deviceName != interfaceName)
+ continue;
+
+ // read device data
+ unsigned long long bytesIn = 0;
+ unsigned long long packetsIn = 0;
+ unsigned long long errorsIn = 0;
+ unsigned long long dropsIn = 0;
+ unsigned long long bytesOut = 0;
+ unsigned long long packetsOut = 0;
+ unsigned long long errorsOut = 0;
+ unsigned long long dropsOut = 0;
+ unsigned long long dummy = 0;
+
+ istringstream sin(trim(line.substr(posEnd + 1)));
+
+ sin >> bytesIn
+ >> packetsIn
+ >> errorsIn
+ >> dropsIn
+ >> dummy
+ >> dummy
+ >> dummy
+ >> dummy
+ >> bytesOut
+ >> packetsOut
+ >> errorsOut
+ >> dropsOut;
+
+ if(sin.fail())
+ break;
+
+ dataFrame.setTotalDataIn(bytesIn);
+ dataFrame.setTotalDataOut(bytesOut);
+
+ dataFrame.setTotalPacketsIn(packetsIn);
+ dataFrame.setTotalPacketsOut(packetsOut);
+
+ dataFrame.setTotalErrorsIn(errorsIn);
+ dataFrame.setTotalErrorsOut(errorsOut);
+
+ dataFrame.setTotalDropsIn(dropsIn);
+ dataFrame.setTotalDropsOut(dropsOut);
+
+ dataFrame.setValid(true);
+
+ break;
+ }
+}
+
diff --git a/src/devreader-linux-proc.h b/src/devreader-linux-proc.h
new file mode 100644
index 0000000..8e8def6
--- /dev/null
+++ b/src/devreader-linux-proc.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+ devreader-linux-proc.h
+ ----------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVREADER_LINUX_PROC_H
+#define DEVREADER_LINUX_PROC_H
+
+#include "devreader.h"
+
+#include <string>
+#include <list>
+
+class DevReaderLinuxProc : public DevReader
+{
+ public:
+ DevReaderLinuxProc(const std::string& deviceName);
+ virtual ~DevReaderLinuxProc();
+
+ static bool isAvailable();
+ static std::list<std::string> findAllDevices();
+
+ protected:
+ void readFromDevice(DataFrame& dataFrame);
+};
+
+#endif
+
+
diff --git a/src/devreader-linux-sys.cpp b/src/devreader-linux-sys.cpp
new file mode 100644
index 0000000..2fc81fe
--- /dev/null
+++ b/src/devreader-linux-sys.cpp
@@ -0,0 +1,110 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "devreader-linux-sys.h"
+
+#include <fstream>
+#include <string>
+#include <list>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace std;
+
+DevReaderLinuxSys::DevReaderLinuxSys(const string& deviceName)
+ : DevReader(deviceName)
+{
+}
+
+DevReaderLinuxSys::~DevReaderLinuxSys()
+{
+}
+
+bool DevReaderLinuxSys::isAvailable()
+{
+ struct stat sysStat;
+ if(stat("/sys/class/net", &sysStat) < 0 || ! S_ISDIR(sysStat.st_mode))
+ return false;
+
+ return true;
+}
+
+list<string> DevReaderLinuxSys::findAllDevices()
+{
+ list<string> interfaceNames;
+ DIR* sysDir = opendir("/sys/class/net");
+ struct dirent* sysDirEntry = 0;
+
+ if(!sysDir)
+ return interfaceNames;
+
+ while((sysDirEntry = readdir(sysDir)))
+ {
+ string interfaceName(sysDirEntry->d_name);
+
+ if(interfaceName[0] == '.')
+ continue;
+
+ interfaceNames.push_back(interfaceName);
+ }
+
+ closedir(sysDir);
+
+ return interfaceNames;
+}
+
+void DevReaderLinuxSys::readFromDevice(DataFrame& dataFrame)
+{
+ string devPath = "/sys/class/net/";
+ devPath += m_deviceName;
+
+ struct stat sysStat;
+ if(stat(devPath.c_str(), &sysStat) < 0 || ! S_ISDIR(sysStat.st_mode))
+ return;
+
+ dataFrame.setTotalDataIn(readULongSysEntry("statistics/rx_bytes"));
+ dataFrame.setTotalDataOut(readULongSysEntry("statistics/tx_bytes"));
+
+ dataFrame.setTotalPacketsIn(readULongSysEntry("statistics/rx_packets"));
+ dataFrame.setTotalPacketsOut(readULongSysEntry("statistics/tx_packets"));
+
+ dataFrame.setTotalErrorsIn(readULongSysEntry("statistics/rx_errors"));
+ dataFrame.setTotalErrorsOut(readULongSysEntry("statistics/tx_errors"));
+
+ dataFrame.setTotalDropsIn(readULongSysEntry("statistics/rx_dropped"));
+ dataFrame.setTotalDropsOut(readULongSysEntry("statistics/tx_dropped"));
+
+ dataFrame.setValid(true);
+}
+
+unsigned long long DevReaderLinuxSys::readULongSysEntry(const string& entry)
+{
+ string sysEntryPath = "/sys/class/net/";
+ sysEntryPath += m_deviceName;
+ sysEntryPath += '/';
+ sysEntryPath += entry;
+
+ ifstream sysEntry(sysEntryPath.c_str());
+ if(!sysEntry.is_open())
+ return 0;
+
+ unsigned long long num = 0;
+ sysEntry >> num;
+ if(sysEntry.fail())
+ return 0;
+
+ return num;
+}
+
+
diff --git a/src/devreader-linux-sys.h b/src/devreader-linux-sys.h
new file mode 100644
index 0000000..c945516
--- /dev/null
+++ b/src/devreader-linux-sys.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ devreader-linux-sys.h
+ ---------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVREADER_LINUX_SYS_H
+#define DEVREADER_LINUX_SYS_H
+
+#include "devreader.h"
+
+#include <string>
+#include <list>
+
+class DevReaderLinuxSys : public DevReader
+{
+ public:
+ DevReaderLinuxSys(const std::string& deviceName);
+ virtual ~DevReaderLinuxSys();
+
+ static bool isAvailable();
+ static std::list<std::string> findAllDevices();
+
+ protected:
+ void readFromDevice(DataFrame& dataFrame);
+
+ private:
+ unsigned long long readULongSysEntry(const std::string& entry);
+};
+
+#endif
+
diff --git a/src/devreader-linux.cpp b/src/devreader-linux.cpp
new file mode 100644
index 0000000..5b6e9eb
--- /dev/null
+++ b/src/devreader-linux.cpp
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "devreader-linux.h"
+#include "devreader-linux-proc.h"
+#include "devreader-linux-sys.h"
+
+#include <string>
+#include <list>
+
+using namespace std;
+
+bool DevReaderLinux::isAvailable()
+{
+ return DevReaderLinuxSys::isAvailable() || DevReaderLinuxProc::isAvailable();
+}
+
+list<string> DevReaderLinux::findAllDevices()
+{
+ if(DevReaderLinuxSys::isAvailable())
+ return DevReaderLinuxSys::findAllDevices();
+ else if(DevReaderLinuxProc::isAvailable())
+ return DevReaderLinuxProc::findAllDevices();
+ else
+ return list<string>();
+}
+
diff --git a/src/devreader-linux.h b/src/devreader-linux.h
new file mode 100644
index 0000000..4fea735
--- /dev/null
+++ b/src/devreader-linux.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ devreader-linux.h
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVREADER_LINUX_H
+#define DEVREADER_LINUX_H
+
+#include <string>
+#include <list>
+
+class DevReaderLinux
+{
+ public:
+ static bool isAvailable();
+ static std::list<std::string> findAllDevices();
+};
+
+#endif
+
diff --git a/src/devreader-solaris.cpp b/src/devreader-solaris.cpp
new file mode 100644
index 0000000..478b3ca
--- /dev/null
+++ b/src/devreader-solaris.cpp
@@ -0,0 +1,101 @@
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+/***************************************************************************
+ * Solaris specific network code taken out of gkrellm *
+ * Copyright by Bill Wilson <bill@gkrellm.net> *
+ * Solaris code by Daisuke Yabuki <dxy@acm.org> *
+ * adapted for nload by Roland Riegel <feedback@roland-riegel.de> *
+ ***************************************************************************/
+
+#include "devreader-solaris.h"
+
+#include <string.h>
+#include <kstat.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <string>
+#include <list>
+
+using namespace std;
+
+DevReaderSolaris::DevReaderSolaris(const string& deviceName)
+ : DevReader(deviceName)
+{
+}
+
+DevReaderSolaris::~DevReaderSolaris()
+{
+}
+
+list<string> DevReaderSolaris::findAllDevices()
+{
+ list<string> interfaceNames;
+ struct if_nameindex* interfaces = if_nameindex();
+
+ if(!interfaces)
+ return interfaceNames;
+
+ int i = 0;
+ while(interfaces[i].if_name)
+ {
+ interfaceNames.push_back(string(interfaces[i].if_name));
+ ++i;
+ }
+
+ if_freenameindex(interfaces);
+
+ return interfaceNames;
+}
+
+void DevReaderSolaris::readFromDevice(DataFrame& dataFrame)
+{
+ kstat_ctl_t *kc;
+ kstat_t *ksp;
+ kstat_named_t *knp;
+ char* devName = 0;
+
+ if(m_deviceName.empty())
+ return;
+
+ devName = (char*) malloc(m_deviceName.length() + 1);
+ strncpy(devName, m_deviceName.c_str(), m_deviceName.length());
+ devName[m_deviceName.length()] = '\0';
+
+ kc = kstat_open();
+ ksp = kstat_lookup(kc, NULL, -1, devName);
+ if(ksp && kstat_read(kc, ksp, NULL) >= 0)
+ {
+ knp = (kstat_named_t *) kstat_data_lookup(ksp, "rbytes");
+ dataFrame.setTotalDataIn(knp ? knp->value.ui32 : 0);
+
+ knp = (kstat_named_t *) kstat_data_lookup(ksp, "obytes");
+ dataFrame.setTotalDataOut(knp ? knp->value.ui32 : 0);
+
+ knp = (kstat_named_t *) kstat_data_lookup(ksp, "ipackets");
+ dataFrame.setTotalPacketsIn(knp ? knp->value.ui32 : 0);
+
+ knp = (kstat_named_t *) kstat_data_lookup(ksp, "opackets");
+ dataFrame.setTotalPacketsOut(knp ? knp->value.ui32 : 0);
+
+ knp = (kstat_named_t *) kstat_data_lookup(ksp, "ierrors");
+ dataFrame.setTotalErrorsIn(knp ? knp->value.ui32 : 0);
+
+ knp = (kstat_named_t *) kstat_data_lookup(ksp, "oerrors");
+ dataFrame.setTotalErrorsOut(knp ? knp->value.ui32 : 0);
+
+ dataFrame.setValid(true);
+ }
+
+ kstat_close(kc);
+ free(devName);
+ devName = 0;
+}
+
diff --git a/src/devreader-solaris.h b/src/devreader-solaris.h
new file mode 100644
index 0000000..027c7fa
--- /dev/null
+++ b/src/devreader-solaris.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ devreader-solaris.h
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVREADER_SOLARIS_H
+#define DEVREADER_SOLARIS_H
+
+#include "devreader.h"
+
+#include <string>
+#include <list>
+
+class DevReaderSolaris : public DevReader
+{
+ public:
+ DevReaderSolaris(const std::string& deviceName);
+ virtual ~DevReaderSolaris();
+
+ static std::list<std::string> findAllDevices();
+
+ protected:
+ void readFromDevice(DataFrame& dataFrame);
+};
+
+#endif
+
diff --git a/src/devreader.cpp b/src/devreader.cpp
new file mode 100644
index 0000000..5006309
--- /dev/null
+++ b/src/devreader.cpp
@@ -0,0 +1,106 @@
+/***************************************************************************
+ devreader.cpp
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "devreader.h"
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <time.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_SOLARIS
+ #include <sys/sockio.h>
+#endif
+
+using namespace std;
+
+DevReader::DevReader(const string& deviceName)
+ : m_deviceName(deviceName)
+{
+}
+
+DevReader::~DevReader()
+{
+}
+
+const string& DevReader::getDeviceName() const
+{
+ return m_deviceName;
+}
+
+DataFrame DevReader::getNewDataFrame()
+{
+ DataFrame deviceData;
+
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+
+ readFromDevice(deviceData);
+
+ deviceData.setDeviceName(m_deviceName);
+
+ deviceData.setTimeStampSeconds((unsigned long) tv.tv_sec);
+ deviceData.setTimeStampMicroseconds((unsigned long) tv.tv_usec);
+
+ deviceData.setIpV4(getDeviceIp4Address());
+
+ return deviceData;
+}
+
+string DevReader::getDeviceIp4Address()
+{
+ struct ifreq ifr;
+ int sk;
+
+ string deviceIp = "";
+
+ if(m_deviceName.empty())
+ return deviceIp;
+
+ /* create a temporary socket: ioctl needs one */
+ if((sk = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ return deviceIp;
+
+ /* copy the device name into the ifreq structure */
+ strncpy(ifr.ifr_name, m_deviceName.c_str(), IFNAMSIZ - 1);
+ ifr.ifr_name[IFNAMSIZ - 1] = 0;
+
+ /* make the request */
+ if(!ioctl(sk, SIOCGIFADDR, &ifr))
+ {
+ struct sockaddr_in sin;
+ memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
+
+ /* only use the IP number if the address family is really IPv4 */
+ if(sin.sin_family == AF_INET)
+ deviceIp = inet_ntoa(sin.sin_addr);
+ }
+
+ /* close the temporary socket */
+ close(sk);
+
+ return deviceIp;
+}
+
diff --git a/src/devreader.h b/src/devreader.h
new file mode 100644
index 0000000..c4631ce
--- /dev/null
+++ b/src/devreader.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ devreader.h
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVREADER_H
+#define DEVREADER_H
+
+#include <string>
+
+#include "dataframe.h"
+
+class DevReader
+{
+ public:
+ DevReader(const std::string& deviceName);
+ virtual ~DevReader();
+
+ const std::string& getDeviceName() const;
+ DataFrame getNewDataFrame();
+
+ protected:
+ virtual void readFromDevice(DataFrame& dataFrame) = 0;
+ std::string getDeviceIp4Address();
+
+ std::string m_deviceName;
+};
+
+#endif
+
diff --git a/src/devreaderfactory.cpp b/src/devreaderfactory.cpp
new file mode 100644
index 0000000..c2fc656
--- /dev/null
+++ b/src/devreaderfactory.cpp
@@ -0,0 +1,128 @@
+/***************************************************************************
+ devreaderfactory.cpp
+ --------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "devreaderfactory.h"
+
+#include "config.h"
+
+#include "devreader.h"
+#include "devreader-bsd.h"
+#include "devreader-hpux.h"
+#include "devreader-linux-proc.h"
+#include "devreader-linux-sys.h"
+#include "devreader-linux.h"
+#include "devreader-solaris.h"
+
+#include <string>
+#include <list>
+#include <map>
+
+using namespace std;
+
+map<string, DevReader*> DevReaderFactory::m_devReaders;
+DevReaderFactory DevReaderFactory::m_instance;
+
+DevReaderFactory::DevReaderFactory()
+{
+}
+
+DevReaderFactory::~DevReaderFactory()
+{
+ for(map<string, DevReader*>::const_iterator it = m_devReaders.begin(); it != m_devReaders.end(); ++it)
+ delete it->second;
+
+ m_devReaders.clear();
+}
+
+int DevReaderFactory::findAllDevices()
+{
+#if defined HAVE_BSD
+ list<string> interfaceNames = DevReaderBsd::findAllDevices();
+#elif defined HAVE_HPUX
+ list<string> interfaceNames = DevReaderHpux::findAllDevices();
+#elif defined HAVE_LINUX
+ list<string> interfaceNames = DevReaderLinux::findAllDevices();
+#elif defined HAVE_SOLARIS
+ list<string> interfaceNames = DevReaderSolaris::findAllDevices();
+#endif
+
+ map<string, DevReader*>::iterator devReaderIt = m_devReaders.begin();
+ while(devReaderIt != m_devReaders.end())
+ {
+ list<string>::iterator interfaceIt = interfaceNames.begin();
+ list<string>::iterator interfaceItEnd = interfaceNames.end();
+
+ while(*interfaceIt != devReaderIt->first && interfaceIt != interfaceItEnd)
+ ++interfaceIt;
+
+ // delete all devices which disappeared
+ if(interfaceIt == interfaceItEnd)
+ {
+ delete devReaderIt->second;
+ m_devReaders.erase(devReaderIt++);
+ }
+ // delete all entries in the interface name list which we know of already
+ else
+ {
+ interfaceNames.erase(interfaceIt);
+ devReaderIt++;
+ }
+ }
+
+ // the interface name list now contains only devices which just appeared in the system
+ for(list<string>::const_iterator it = interfaceNames.begin(); it != interfaceNames.end(); ++it)
+ {
+ DevReader* newReader = createDevReader(*it);
+ if(newReader)
+ m_devReaders[*it] = newReader;
+ }
+
+ return m_devReaders.size();
+}
+
+int DevReaderFactory::getDeviceCount()
+{
+ return m_devReaders.size();
+}
+
+const map<string, DevReader*>& DevReaderFactory::getAllDevReaders()
+{
+ return m_devReaders;
+}
+
+DevReader* DevReaderFactory::createDevReader(const string& deviceName)
+{
+ DevReader* reader = 0;
+
+#if defined HAVE_BSD
+ reader = new DevReaderBsd(deviceName);
+#elif defined HAVE_HPUX
+ reader = new DevReaderHpux(deviceName);
+#elif defined HAVE_LINUX
+ if(DevReaderLinuxSys::isAvailable())
+ reader = new DevReaderLinuxSys(deviceName);
+ else if(DevReaderLinuxProc::isAvailable())
+ reader = new DevReaderLinuxProc(deviceName);
+ else
+ reader = 0;
+#elif defined HAVE_SOLARIS
+ reader = new DevReaderSolaris(deviceName);
+#endif
+
+ return reader;
+}
+
diff --git a/src/devreaderfactory.h b/src/devreaderfactory.h
new file mode 100644
index 0000000..d9d2e5c
--- /dev/null
+++ b/src/devreaderfactory.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ devreaderfactory.h
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef DEVREADERFACTORY_H
+#define DEVREADERFACTORY_H
+
+#include <string>
+#include <map>
+
+class DevReader;
+
+class DevReaderFactory
+{
+ public:
+ DevReaderFactory();
+ ~DevReaderFactory();
+
+ static int findAllDevices();
+ static int getDeviceCount();
+
+ static const std::map<std::string, DevReader*>& getAllDevReaders();
+
+ private:
+ static DevReader* createDevReader(const std::string& deviceName);
+
+ static std::map<std::string, DevReader*> m_devReaders;
+ static DevReaderFactory m_instance;
+};
+
+#endif
+
diff --git a/src/form_field.cpp b/src/form_field.cpp
new file mode 100644
index 0000000..03b70f7
--- /dev/null
+++ b/src/form_field.cpp
@@ -0,0 +1,237 @@
+/***************************************************************************
+ form_field.cpp
+ -------------------
+ begin : Tue Jul 30 2002
+ copyright : (C) 2002 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "form_field.h"
+#include "window.h"
+
+using namespace std;
+
+Field::Field(int x, int y, int width, int height) : m_field(0)
+{
+ m_field = new_field(height, width, y, x, 0, 0);
+ set_field_opts(m_field, field_opts(m_field) | O_BLANK | O_PASSOK);
+
+ m_enumElementsArray = 0;
+}
+
+Field::~Field()
+{
+ setEnumField(vector<string>());
+ free_field(m_field);
+}
+
+void Field::setText(const string& text)
+{
+ set_field_buffer(m_field, 0, text.c_str());
+}
+
+string Field::getText()
+{
+ return field_buffer(m_field, 0);
+}
+
+void Field::move(int x, int y)
+{
+ move_field(m_field, y, x);
+}
+
+void Field::setVisible(bool new_visible)
+{
+ set_field_opts(m_field, new_visible ? field_opts(m_field) | O_VISIBLE : field_opts(m_field) & ~O_VISIBLE);
+}
+
+bool Field::isVisible()
+{
+ return (field_opts(m_field) & O_VISIBLE) == O_VISIBLE;
+}
+
+void Field::setEnabled(bool new_enabled)
+{
+ set_field_opts(m_field, new_enabled ? field_opts(m_field) | O_ACTIVE : field_opts(m_field) & ~O_ACTIVE);
+}
+
+bool Field::isEnabled()
+{
+ return (field_opts(m_field) & O_ACTIVE) == O_ACTIVE;
+}
+
+void Field::setIntegerField(int min, int max)
+{
+ set_field_type(m_field, TYPE_INTEGER, 0, min, max);
+}
+
+void Field::setEnumField(const vector<string>& elements)
+{
+ if(elements.empty())
+ {
+ set_field_type(m_field, TYPE_ALNUM, 0);
+
+ if(m_enumElementsArray)
+ delete[] m_enumElementsArray;
+ m_enumElementsArray = 0;
+
+ m_enumElements.clear();
+
+ return;
+ }
+
+ m_enumElements = elements;
+
+ if(m_enumElementsArray)
+ delete[] m_enumElementsArray;
+ m_enumElementsArray = new const char*[m_enumElements.size() + 1];
+
+ for(vector<string>::const_iterator itElement = m_enumElements.begin(); itElement != m_enumElements.end(); ++itElement)
+ m_enumElementsArray[itElement - m_enumElements.begin()] = itElement->c_str();
+ m_enumElementsArray[elements.size()] = 0;
+
+ set_field_type(m_field, TYPE_ENUM, m_enumElementsArray, 0, 0);
+}
+
+void Field::setFixed(bool new_fixed)
+{
+ set_field_opts(m_field, new_fixed ? field_opts(m_field) & ~O_EDIT : field_opts(m_field) | O_EDIT);
+}
+
+bool Field::isFixed()
+{
+ return (field_opts(m_field) & O_EDIT) != O_EDIT;
+}
+
+void Field::setFirstOnPage(bool new_newpage)
+{
+ set_new_page(m_field, new_newpage);
+}
+
+bool Field::isFirstOnPage()
+{
+ return new_page(m_field);
+}
+
+bool operator==(const Field& field1, const Field& field2)
+{
+ return field1.m_field == field2.m_field;
+}
+
+bool operator==(const Field& field1, const FIELD* field2)
+{
+ return field1.m_field == field2;
+}
+
+
+Form::Form(Slots* slots)
+ : m_slots(slots), m_form(0), m_visible(false)
+{
+}
+
+Form::~Form()
+{
+}
+
+vector<Field*>& Form::fields()
+{
+ return m_fields;
+}
+
+void Form::show(Window* main_window, SubWindow* sub_window)
+{
+ if(m_form)
+ return;
+
+ m_curses_fields = new FIELD* [ m_fields.size() ];
+ vector<Field*>::const_iterator r = m_fields.begin();
+ int i = 0;
+ while(r != m_fields.end())
+ {
+ m_curses_fields[i] = (*r)->m_field;
+ r++; i++;
+ }
+
+ m_curses_fields[m_fields.size()] = 0;
+ m_form = new_form(m_curses_fields);
+
+ if(!m_form)
+ return;
+
+ set_form_userptr(m_form, this);
+ set_form_win(m_form, main_window->m_window);
+ set_form_sub(m_form, sub_window->m_window);
+ set_field_term(m_form, fieldChanged);
+
+ post_form(m_form);
+
+ m_visible = true;
+}
+
+void Form::hide()
+{
+ if(!m_form)
+ return;
+
+ unpost_form(m_form);
+ free_form(m_form);
+ m_form = 0;
+
+ delete[] m_curses_fields;
+ m_curses_fields = 0;
+
+ m_visible = false;
+}
+
+bool Form::isVisible()
+{
+ return m_visible;
+}
+
+void Form::processKey(int key)
+{
+ if(m_form)
+ form_driver(m_form, key);
+}
+
+int Form::getPage()
+{
+ if(!m_form)
+ return 0;
+ return form_page(m_form);
+}
+
+int Form::getPageCount()
+{
+ int pages = 0;
+ for(vector<Field*>::const_iterator i = m_fields.begin(); i != m_fields.end(); i++)
+ {
+ if((*i)->isFirstOnPage())
+ pages++;
+ }
+ return pages;
+}
+
+void Form::fieldChanged(FORM* form)
+{
+ Form* f = (Form*) form_userptr(form);
+ if(!f)
+ return;
+
+ if(f->m_slots)
+ {
+ for(vector<Field*>::const_iterator i = f->m_fields.begin(); i != f->m_fields.end(); ++i)
+ if((*i)->m_field == current_field(form))
+ f->m_slots->slot_fieldChanged(*i);
+ }
+}
+
diff --git a/src/form_field.h b/src/form_field.h
new file mode 100644
index 0000000..7ce2734
--- /dev/null
+++ b/src/form_field.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+ form_field.h
+ -------------------
+ begin : Sat Jul 27 2002
+ copyright : (C) 2002 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef FORM_FIELD_H
+#define FORM_FIELD_H
+
+#include <curses.h>
+#include <form.h>
+#undef clear
+#undef erase
+#undef refresh
+
+#include <string>
+#include <vector>
+
+class Window;
+class SubWindow;
+class Form;
+
+class Field
+{
+ public:
+ Field(int x, int y, int width, int height);
+ ~Field();
+
+ void setText(const std::string& text);
+ std::string getText();
+
+ void move(int x, int y);
+
+ void setVisible(bool new_visible);
+ bool isVisible();
+
+ void setEnabled(bool new_enabled);
+ bool isEnabled();
+
+ void setIntegerField(int min, int max);
+ void setEnumField(const std::vector<std::string>& elements);
+
+ void setFixed(bool new_fixed);
+ bool isFixed();
+
+ void setFirstOnPage(bool new_newpage);
+ bool isFirstOnPage();
+
+ friend bool operator==(const Field& field1, const Field& field2);
+ friend bool operator==(const Field& field1, const FIELD* field2);
+
+ private:
+ friend class Form;
+
+ FIELD* m_field;
+ std::vector<std::string> m_enumElements;
+ const char** m_enumElementsArray;
+};
+
+class Form
+{
+ public:
+ class Slots
+ {
+ public:
+ Slots() {}
+ virtual ~Slots() {}
+ virtual void slot_fieldChanged(Field* field) {}
+ };
+
+ Form(Slots* slots = 0);
+ ~Form();
+
+ std::vector<Field *>& fields();
+
+ void show(Window* main_window, SubWindow* sub_window);
+ void hide();
+
+ void processKey(int key);
+
+ bool isVisible();
+
+ int getPage();
+ int getPageCount();
+
+ private:
+ Slots* m_slots;
+
+ FORM* m_form;
+ FIELD** m_curses_fields;
+ std::vector<Field *> m_fields;
+
+ bool m_visible;
+
+ static void fieldChanged(FORM* form);
+};
+
+#endif
+
diff --git a/src/graph.cpp b/src/graph.cpp
new file mode 100644
index 0000000..f0b4e8b
--- /dev/null
+++ b/src/graph.cpp
@@ -0,0 +1,110 @@
+/***************************************************************************
+ graph.cpp
+ -------------------
+ begin : Sat Sep 29 2001
+ copyright : (C) 2001 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "graph.h"
+#include "setting.h"
+#include "settingstore.h"
+#include "window.h"
+
+using namespace std;
+
+Graph::Graph()
+ : m_heightOfBars(5), m_maxDeflection(10 * 1024 * 1024 / 8)
+{
+}
+
+Graph::~Graph()
+{
+}
+
+// sets the number of the graph's vertical #-bars
+void Graph::setNumOfBars(unsigned int numOfBars)
+{
+ // vertically resize the graph's value list
+ m_values.resize(numOfBars);
+}
+
+// sets the height of the graph's vertical #-bars
+void Graph::setHeightOfBars(unsigned int heightOfBars)
+{
+ m_heightOfBars = heightOfBars;
+}
+
+void Graph::setMaxDeflection(unsigned long long maxDeflection)
+{
+ m_maxDeflection = maxDeflection;
+}
+
+// new traffic measurement has been made => update the graph's value list
+void Graph::update(unsigned long long value)
+{
+ // [new_value] = Bytes/s
+
+ // put new value to the beginning of the list, it becomes the first #-bar
+ m_values.push_front(value);
+
+ // delete the last #-bar of the list, but keep at least one
+ if(m_values.size() > 1)
+ m_values.pop_back();
+}
+
+// print the graph with the upper left corner at the coordinates (x, y)
+void Graph::print(Window& window, int x, int y)
+{
+ window.setXY(x, y);
+
+ // cycle through through the lines
+ for(unsigned int l = 0; l < m_heightOfBars; l++)
+ {
+ // for each line cycle through the rows
+ for(list<unsigned long long>::reverse_iterator r = m_values.rbegin(); r != m_values.rend() ; r++)
+ {
+ unsigned long long trafficPerLine = m_maxDeflection / m_heightOfBars;
+ unsigned long long lowerLimit = m_maxDeflection * (m_heightOfBars - l - 1) / m_heightOfBars;
+
+ if(*r < lowerLimit)
+ {
+ window.print(' ');
+ }
+ else
+ {
+ unsigned long long restOfTraffic = *r - lowerLimit;
+
+ if(restOfTraffic >= trafficPerLine)
+ window.print('#');
+ else if(restOfTraffic >= trafficPerLine * 7 / 10)
+ window.print('|');
+ else if(restOfTraffic >= trafficPerLine * 3 / 10)
+ window.print('.');
+ else
+ window.print(' ');
+ }
+ }
+ window.print('\n');
+ window.setX(x);
+ }
+
+}
+
+// reset all traffic values in the graph to zero
+void Graph::resetTrafficData()
+{
+ int size = m_values.size();
+ m_values.clear();
+ m_values.resize(size);
+}
+
diff --git a/src/graph.h b/src/graph.h
new file mode 100644
index 0000000..1e493b3
--- /dev/null
+++ b/src/graph.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ graph.h
+ -------------------
+ begin : Sat Sep 29 2001
+ copyright : (C) 2001 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef GRAPH_H
+#define GRAPH_H
+
+#include <list>
+
+class Window;
+
+class Graph
+{
+ public:
+ Graph();
+ ~Graph();
+
+ void setNumOfBars(unsigned int numOfBars);
+ void setHeightOfBars(unsigned int heightOfBars);
+ void setMaxDeflection(unsigned long long maxDeflection);
+
+ void update(unsigned long long value);
+ void print(Window& window, int x, int y);
+ void resetTrafficData();
+
+ private:
+ unsigned int m_heightOfBars;
+ unsigned long long m_maxDeflection;
+ std::list<unsigned long long> m_values;
+};
+
+#endif
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..c53e142
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,583 @@
+/***************************************************************************
+ main.cpp
+ -------------------
+ begin : Wed Jul 25 2001
+ copyright : (C) 2001 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+/*
+ * nload
+ * real time monitor for network traffic
+ * Copyright (C) 2001 - 2012 Roland Riegel <feedback@roland-riegel.de>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include <config.h>
+#endif
+
+#include "device.h"
+#include "devreader.h"
+#include "devreaderfactory.h"
+#include "graph.h"
+#include "main.h"
+#include "screen.h"
+#include "setting.h"
+#include "settingfilter.h"
+#include "settingstore.h"
+
+#include <cstdlib>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <ctype.h>
+#include <time.h>
+#include <curses.h>
+#include <signal.h>
+#include <string.h>
+#undef clear
+#undef erase
+#undef refresh
+
+#define STANDARD_AVERAGE_WINDOW 300
+#define STANDARD_DATA_FORMAT Statistics::humanReadableByte
+#define STANDARD_HIDE_GRAPHS false
+#define STANDARD_MAX_DEFLECTION 10240
+#define STANDARD_REFRESH_INTERVAL 500
+#define STANDARD_TRAFFIC_FORMAT Statistics::humanReadableBit
+
+using namespace std;
+
+static OptWindow m_optWindow;
+static TrafficWindow m_mainWindow;
+
+static bool quit = false;
+
+int main(int argc, char *argv[])
+{
+ SettingStore::add(Setting("AverageWindow", "Window length for average (s)", STANDARD_AVERAGE_WINDOW));
+ SettingStore::add(Setting("BarMaxIn", "Max Incoming deflection (kBit/s)", STANDARD_MAX_DEFLECTION));
+ SettingStore::add(Setting("BarMaxOut", "Max Outgoing deflection (kBit/s)", STANDARD_MAX_DEFLECTION));
+ SettingStore::add(Setting("DataFormat", "Unit for data numbers", STANDARD_DATA_FORMAT));
+ SettingStore::add(Setting("Devices", "Devices to show", "all"));
+ SettingStore::add(Setting("MultipleDevices", "Show multiple devices", STANDARD_HIDE_GRAPHS));
+ SettingStore::add(Setting("RefreshInterval", "Refresh interval (ms)", STANDARD_REFRESH_INTERVAL));
+ SettingStore::add(Setting("TrafficFormat", "Unit for traffic numbers", STANDARD_TRAFFIC_FORMAT));
+
+ SettingStore::get("AverageWindow").pushFilter(new SettingFilterMin(5));
+ SettingStore::get("BarMaxIn").pushFilter(new SettingFilterMin(10));
+ SettingStore::get("BarMaxOut").pushFilter(new SettingFilterMin(10));
+ SettingStore::get("RefreshInterval").pushFilter(new SettingFilterMin(50));
+
+ SettingStore::get("Devices").pushFilter(new SettingFilterDefault("all"));
+ SettingStore::get("Devices").pushFilter(new SettingFilterExclusive("all"));
+
+ map<string, string> valueMapping;
+
+ valueMapping[toString(false)] = "[ ]";
+ valueMapping[toString(true)] = "[x]";
+ SettingStore::get("MultipleDevices").pushFilter(new SettingFilterMap(valueMapping));
+ valueMapping.clear();
+
+ valueMapping[toString(Statistics::humanReadableBit)] = "Human Readable (Bit)";
+ valueMapping[toString(Statistics::humanReadableByte)] = "Human Readable (Byte)";
+ valueMapping[toString(Statistics::bit)] = "Bit";
+ valueMapping[toString(Statistics::byte)] = "Byte";
+ valueMapping[toString(Statistics::kiloBit)] = "kBit";
+ valueMapping[toString(Statistics::kiloByte)] = "kByte";
+ valueMapping[toString(Statistics::megaBit)] = "MBit";
+ valueMapping[toString(Statistics::megaByte)] = "MByte";
+ valueMapping[toString(Statistics::gigaBit)] = "GBit";
+ valueMapping[toString(Statistics::gigaByte)] = "GByte";
+ SettingStore::get("TrafficFormat").pushFilter(new SettingFilterMap(valueMapping));
+ SettingStore::get("DataFormat").pushFilter(new SettingFilterMap(valueMapping));
+ valueMapping.clear();
+
+ // retrieve home directory
+ const char* homeDirArray = getenv("HOME");
+ if(!homeDirArray)
+ {
+ cerr << "Could not retrieve home directory." << endl;
+ exit(1);
+ }
+
+ string homeDir = homeDirArray;
+ SettingStore::readFromFile(SYSCONFDIR "/nload.conf");
+ SettingStore::readFromFile(homeDir + "/.nload");
+
+ // parse the command line
+ bool deleteDevicesRequested = true;
+ for(int i = 1; i < argc; i++)
+ {
+ // does the user want help?
+ if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
+ {
+ printHelp(false);
+ exit(0);
+ }
+ // has the user set a non-default average time window?
+ else if(strcmp(argv[i], "-a") == 0)
+ {
+ Setting& setting = SettingStore::get("AverageWindow");
+
+ if(i < argc - 1 && isdigit(argv[ i + 1 ][0]) != 0)
+ {
+ setting = atoi(argv[ i + 1 ]);
+ if(setting < 1)
+ setting = STANDARD_AVERAGE_WINDOW;
+
+ i++;
+ }
+ else
+ {
+ cerr << "Wrong argument for the -a parameter." << endl;
+ printHelp(true);
+ exit(1);
+ }
+ }
+ // has the user set a non-default 100% mark for
+ // the incoming bandwidth bar?
+ else if(strcmp(argv[i], "-i") == 0)
+ {
+ Setting& setting = SettingStore::get("BarMaxIn");
+
+ if(i < argc - 1 && isdigit(argv[ i + 1 ][0]) != 0)
+ {
+ setting = atol(argv[ i + 1 ]);
+ if(setting == 0)
+ setting = STANDARD_MAX_DEFLECTION;
+
+ i++;
+ }
+ else
+ {
+ cerr << "Wrong argument for the -i parameter." << endl;
+ printHelp(true);
+ exit(1);
+ }
+ }
+ // has the user set a non-default 100% mark for
+ // the outgoing bandwidth bar?
+ else if(strcmp(argv[i], "-o") == 0)
+ {
+ Setting& setting = SettingStore::get("BarMaxOut");
+
+ if(i < argc - 1 && isdigit(argv[ i + 1 ][0]) != 0)
+ {
+ setting = atol(argv[ i + 1 ]);
+ if(setting == 0)
+ setting = STANDARD_MAX_DEFLECTION;
+
+ i++;
+ }
+ else
+ {
+ cerr << "Wrong argument for the -o parameter." << endl;
+ printHelp(true);
+ exit(1);
+ }
+ }
+ // has the user set a non-default refresh interval?
+ else if(strcmp(argv[i], "-t") == 0)
+ {
+ Setting& setting = SettingStore::get("RefreshInterval");
+
+ if(i < argc - 1 && isdigit(argv[ i + 1 ][0]) != 0)
+ {
+ setting = atoi(argv[ i + 1 ]);
+ if(setting == 0)
+ setting = STANDARD_REFRESH_INTERVAL;
+
+ i++;
+ }
+ else
+ {
+ cerr << "Wrong argument for the -t parameter." << endl;
+ printHelp(true);
+ exit(1);
+ }
+ }
+ // has the user set a non-default unit for traffic numbers?
+ else if(strcmp(argv[i], "-u") == 0)
+ {
+ Setting& setting = SettingStore::get("TrafficFormat");
+
+ if(i < argc - 1 && isalpha(argv[ i + 1 ][0]) != 0)
+ {
+ switch(argv[ i + 1 ][0])
+ {
+ case 'H':
+ setting = Statistics::humanReadableByte;
+ break;
+ case 'h':
+ setting = Statistics::humanReadableBit;
+ break;
+ case 'B':
+ setting = Statistics::byte;
+ break;
+ case 'b':
+ setting = Statistics::bit;
+ break;
+ case 'K':
+ setting = Statistics::kiloByte;
+ break;
+ case 'k':
+ setting = Statistics::kiloBit;
+ break;
+ case 'M':
+ setting = Statistics::megaByte;
+ break;
+ case 'm':
+ setting = Statistics::megaBit;
+ break;
+ case 'G':
+ setting = Statistics::gigaByte;
+ break;
+ case 'g':
+ setting = Statistics::gigaBit;
+ break;
+ default:
+ cerr << "Wrong argument for the -u parameter." << endl;
+ printHelp(true);
+ exit(1);
+ }
+
+ i++;
+ }
+ else
+ {
+ cerr << "Wrong argument for the -u parameter." << endl;
+ printHelp(true);
+ exit(1);
+ }
+ }
+ // has the user set a non-default unit for numbers of amount of data?
+ else if(strcmp(argv[i], "-U") == 0)
+ {
+ Setting& setting = SettingStore::get("DataFormat");
+
+ if(i < argc - 1 && isalpha(argv[ i + 1 ][0]) != 0)
+ {
+ switch(argv[ i + 1 ][0])
+ {
+ case 'H':
+ setting = Statistics::humanReadableByte;
+ break;
+ case 'h':
+ setting = Statistics::humanReadableBit;
+ break;
+ case 'B':
+ setting = Statistics::byte;
+ break;
+ case 'b':
+ setting = Statistics::bit;
+ break;
+ case 'K':
+ setting = Statistics::kiloByte;
+ break;
+ case 'k':
+ setting = Statistics::kiloBit;
+ break;
+ case 'M':
+ setting = Statistics::megaByte;
+ break;
+ case 'm':
+ setting = Statistics::megaBit;
+ break;
+ case 'G':
+ setting = Statistics::gigaByte;
+ break;
+ case 'g':
+ setting = Statistics::gigaBit;
+ break;
+ default:
+ cerr << "Wrong argument for the -U parameter." << endl;
+ printHelp(true);
+ exit(1);
+ }
+
+ i++;
+ }
+ else
+ {
+ cerr << "Wrong argument for the -U parameter." << endl;
+ printHelp(true);
+ exit(1);
+ }
+
+ }
+ // has the user chosen to display multiple devices and thus not to display graphs?
+ else if(strcmp(argv[i], "-m") == 0)
+ {
+ SettingStore::get("MultipleDevices") = true;
+ }
+ // obsolete -b option
+ else if(strcmp(argv[i], "-b") == 0)
+ {
+ }
+ // obsolete -s option
+ else if(strcmp(argv[i], "-s") == 0)
+ {
+ }
+ // assume unknown parameter to be the network device
+ else
+ {
+ Setting& devices = SettingStore::get("Devices");
+
+ if(deleteDevicesRequested)
+ {
+ devices = "";
+ deleteDevicesRequested = false;
+ }
+
+ devices.setThroughFilter(trim(devices.getThroughFilter() + " " + argv[i]));
+ }
+ }
+
+ // auto-detect network devices
+ DevReaderFactory::findAllDevices();
+ const map<string, DevReader*>& deviceReaders = DevReaderFactory::getAllDevReaders();
+
+ // create one instance of the Device class per device
+ map<string, Device*> deviceHandlers;
+ for(map<string, DevReader*>::const_iterator itDevice = deviceReaders.begin(); itDevice != deviceReaders.end(); ++itDevice)
+ {
+ Device* device = new Device(*itDevice->second);
+ device->update();
+
+ deviceHandlers[itDevice->first] = device;
+ }
+
+ init();
+
+ while(!quit)
+ {
+ // wait RefreshInterval milliseconds (in steps of 100 ms)
+ struct timespec wantedTime;
+ wantedTime.tv_sec = 0;
+
+ int restOfRefreshInterval = SettingStore::get("RefreshInterval");
+
+ while(restOfRefreshInterval > 0 && !quit)
+ {
+ restOfRefreshInterval -= 100;
+ wantedTime.tv_nsec = (restOfRefreshInterval >= 0 ? 100 : 100 + restOfRefreshInterval) * 1000000L;
+
+ nanosleep(&wantedTime, 0);
+
+ // process keyboard
+ int key;
+ while((key = getch()) != ERR)
+ {
+ if(m_optWindow.isVisible())
+ {
+ if(key == KEY_F(2))
+ {
+ m_optWindow.hide();
+ m_mainWindow.resize(0, 0, Screen::width(), Screen::height());
+ restOfRefreshInterval = 0; // update the screen
+ }
+ else
+ {
+ m_optWindow.processKey(key);
+ }
+ }
+ else
+ {
+ switch(key)
+ {
+ case KEY_F(2):
+ m_mainWindow.resize(0, Screen::height() / 4, Screen::width(), Screen::height() - Screen::height() / 4);
+ m_optWindow.show(0, 0, Screen::width(), Screen::height() / 4);
+ restOfRefreshInterval = 0; // update the screen
+ break;
+ case KEY_F(5):
+ SettingStore::writeToFile(homeDir + "/.nload");
+ break;
+ case KEY_F(6):
+ SettingStore::readFromFile("/etc/nload.conf");
+ SettingStore::readFromFile(homeDir + "/.nload");
+ break;
+ case 'q':
+ case 'Q':
+ quit = true;
+ break;
+ default:
+ m_mainWindow.processKey(key);
+ }
+ }
+ }
+ }
+
+ if(quit)
+ break;
+
+ vector<string> devicesRequested = split(trim(SettingStore::get("Devices").getThroughFilter()), " ");
+ vector<Device*> devicesToShow;
+
+ if(!devicesRequested.empty() && devicesRequested.front() != "all")
+ {
+ // check if requested devices are available
+ for(vector<string>::const_iterator itRequested = devicesRequested.begin(); itRequested != devicesRequested.end(); ++itRequested)
+ {
+ map<string, Device*>::const_iterator itDetectedDevice = deviceHandlers.find(*itRequested);
+ if(itDetectedDevice != deviceHandlers.end())
+ devicesToShow.push_back(itDetectedDevice->second);
+ }
+ }
+
+ if(devicesToShow.empty())
+ {
+ // use all detected devices
+ for(map<string, Device*>::const_iterator itDevice = deviceHandlers.begin(); itDevice != deviceHandlers.end(); ++itDevice)
+ devicesToShow.push_back(itDevice->second);
+ }
+
+ // enumerate devices for display
+ unsigned int deviceIndex = 0;
+ for(vector<Device*>::const_iterator itDevice = devicesToShow.begin(); itDevice != devicesToShow.end(); ++itDevice)
+ {
+ (*itDevice)->setDeviceNumber(deviceIndex++);
+ (*itDevice)->setTotalNumberOfDevices(devicesToShow.size());
+ }
+
+ // update all devices
+ for(map<string, Device*>::const_iterator itDevice = deviceHandlers.begin(); itDevice != deviceHandlers.end(); ++itDevice)
+ itDevice->second->update();
+
+ // clear the screen
+ m_mainWindow.clear();
+
+ // print device data
+ m_mainWindow.printTraffic(devicesToShow);
+
+ // refresh the screen
+ m_mainWindow.refresh();
+
+ if(m_optWindow.isVisible())
+ m_optWindow.refresh(); // always show cursor in option dialog
+
+ }
+
+ finish();
+
+ for(map<string, Device*>::const_iterator itDevice = deviceHandlers.begin(); itDevice != deviceHandlers.end(); ++itDevice)
+ delete itDevice->second;
+ deviceHandlers.clear();
+
+ return 0;
+}
+
+void init()
+{
+ // handle interrrupt signal
+ signal(SIGINT, end);
+ signal(SIGTERM, end);
+ signal(SIGWINCH, terminalResized);
+
+ // initialize ncurses
+ initscr();
+ keypad(stdscr, true);
+ nodelay(stdscr, true);
+ noecho();
+ nonl();
+ cbreak();
+
+ // create main window
+ m_mainWindow.show(0, 0, Screen::width(), Screen::height());
+}
+
+void finish()
+{
+ // destroy main window
+ m_mainWindow.hide();
+
+ // stop ncurses
+ endwin();
+}
+
+void end(int signal)
+{
+ quit = true;
+}
+
+void terminalResized(int signal)
+{
+ bool optWindowWasVisible = m_optWindow.isVisible();
+
+ m_optWindow.hide();
+
+ finish();
+ init();
+
+ if(optWindowWasVisible)
+ {
+ m_mainWindow.resize(0, Screen::height() / 4, Screen::width(), Screen::height() - Screen::height() / 4);
+ m_optWindow.show(0, 0, Screen::width(), Screen::height() / 4);
+ }
+}
+
+void printHelp(bool error)
+{
+ // print disclaimer
+ (error ? cerr : cout)
+ << "\n"
+ << PACKAGE << " version " << VERSION << "\n"
+ << "Copyright (C) 2001 - 2012 by Roland Riegel <feedback@roland-riegel.de>\n"
+ << PACKAGE << " comes with ABSOLUTELY NO WARRANTY. This is free software, and you are\n"
+ << "welcome to redistribute it under certain conditions. For more details see the\n"
+ << "GNU General Public License Version 2 (http://www.gnu.org/copyleft/gpl.html).\n\n"
+
+ << "Command line syntax:\n"
+ << PACKAGE << " [options] [devices]\n"
+ << PACKAGE << " --help|-h\n\n"
+
+ << "Options:\n"
+ << "-a period Sets the length in seconds of the time window for average\n"
+ << " calculation.\n"
+ << " Default is " << STANDARD_AVERAGE_WINDOW << ".\n"
+ << "-i max_scaling Specifies the 100% mark in kBit/s of the graph indicating the\n"
+ << " incoming bandwidth usage. Ignored if max_scaling is 0 or the\n"
+ << " switch -m is given.\n"
+ << " Default is " << STANDARD_MAX_DEFLECTION << ".\n"
+ << "-m Show multiple devices at a time; no traffic graphs.\n"
+ << "-o max_scaling Same as -i but for the graph indicating the outgoing bandwidth\n"
+ << " usage.\n"
+ << " Default is " << STANDARD_MAX_DEFLECTION << ".\n"
+ << "-t interval Determines the refresh interval of the display in milliseconds.\n"
+ << " Default is " << STANDARD_REFRESH_INTERVAL << ".\n"
+ << "-u h|b|k|m|g Sets the type of unit used for the display of traffic numbers.\n"
+ << " H|B|K|M|G h: auto, b: Bit/s, k: kBit/s, m: MBit/s etc.\n"
+ << " H: auto, B: Byte/s, K: kByte/s, M: MByte/s etc.\n"
+ << " Default is h.\n"
+ << "-U h|b|k|m|g Same as -u, but for a total amount of data (without \"/s\").\n"
+ << " H|B|K|M|G Default is H.\n"
+ << "devices Network devices to use.\n"
+ << " Default is to use all auto-detected devices.\n"
+ << "--help\n"
+ << "-h Print this help.\n\n"
+
+ << "example: " << PACKAGE << " -t 200 -i 1024 -o 128 -U M\n\n"
+
+ << "The options above can also be changed at run time by pressing the 'F2' key.\n"
+ << endl;
+}
+
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..e92e878
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ main.h
+ -------------------
+ begin : Wed Jul 25 2001
+ copyright : (C) 2001 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#include "traffic_window.h"
+#include "opt_window.h"
+
+int main(int argc, char *argv[]);
+
+void init();
+void finish();
+void end(int signal = 0);
+void terminalResized(int signal);
+
+void printHelp(bool error);
+
+#endif
+
diff --git a/src/opt_window.cpp b/src/opt_window.cpp
new file mode 100644
index 0000000..b8e1a9a
--- /dev/null
+++ b/src/opt_window.cpp
@@ -0,0 +1,193 @@
+/***************************************************************************
+ opt_window.cpp
+ -------------------
+ begin : Thu Jan 17 2002
+ copyright : (C) 2002 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "opt_window.h"
+#include "setting.h"
+#include "settingfilter.h"
+#include "settingstore.h"
+#include "stringutils.h"
+
+#define BORDER_LEFT 1
+#define BORDER_RIGHT 1
+#define BORDER_TOP 2
+#define BORDER_BOTTOM 1
+
+using namespace std;
+
+OptWindow::OptWindow()
+ : Window(), Form::Slots(), m_subWindow(this), m_form(this)
+{
+}
+
+OptWindow::~OptWindow()
+{
+ hide();
+}
+
+// create option window and display the current settings
+void OptWindow::show(int x, int y, int width, int height)
+{
+ if(m_visible)
+ hide();
+
+ Window::show(x, y, width, height);
+ m_subWindow.show(BORDER_LEFT, BORDER_TOP, width - BORDER_LEFT - BORDER_RIGHT, height - BORDER_TOP - BORDER_BOTTOM);
+
+ const int field_width = m_subWindow.getWidth() / 2;
+ int line = 0;
+
+ map<string, Setting>& settings = SettingStore::getAll();
+
+ for(map<string, Setting>::const_iterator itSetting = settings.begin(); itSetting != settings.end(); ++itSetting)
+ {
+ Field* label = new Field(0, line, field_width, 1);
+ Field* field = new Field(field_width, line, field_width, 1);
+
+ m_labels[label] = itSetting->first;
+ m_fields[field] = itSetting->first;
+
+ m_form.fields().push_back(label);
+ m_form.fields().push_back(field);
+
+ label->setEnabled(false);
+ label->setText((itSetting->second.getDescription() + ":").c_str());
+ label->setFirstOnPage(line == 0);
+
+ field->setText(itSetting->second.getThroughFilter().c_str());
+
+ const SettingFilterMap* mappingFilter = (SettingFilterMap*) itSetting->second.findFilterWithId("map");
+ if(mappingFilter)
+ {
+ const map<string, string>& mapping = mappingFilter->getMap();
+
+ vector<string> elements;
+ for(map<string, string>::const_iterator itMapping = mapping.begin(); itMapping != mapping.end(); ++itMapping)
+ elements.push_back(itMapping->second);
+
+ field->setEnumField(elements);
+ field->setFixed(true);
+ }
+
+ ++line;
+ line %= m_subWindow.getHeight() < 1 ? 1 : m_subWindow.getHeight();
+ }
+
+ m_form.show(this, &m_subWindow);
+
+ m_visible = true;
+}
+
+// this function is called when a form field changes
+void OptWindow::slot_fieldChanged(Field* field)
+{
+ map<Field*, string>::const_iterator itField = m_fields.find(field);
+ if(itField == m_fields.end())
+ return;
+
+ map<string, Setting>& settings = SettingStore::getAll();
+ map<string, Setting>::iterator itSetting = settings.find(itField->second);
+ if(itSetting == settings.end())
+ return;
+
+ itSetting->second.setThroughFilter(trim(field->getText()));
+ field->setText(itSetting->second.getThroughFilter());
+}
+
+// hide window and destroy it
+void OptWindow::hide()
+{
+ m_form.hide();
+ m_form.fields().clear();
+ m_subWindow.hide();
+ Window::hide();
+
+ for(map<Field*, string>::const_iterator itLabel = m_labels.begin(); itLabel != m_labels.end(); ++itLabel)
+ delete itLabel->first;
+ for(map<Field*, string>::const_iterator itField = m_fields.begin(); itField != m_fields.end(); ++itField)
+ delete itField->first;
+
+ m_labels.clear();
+ m_fields.clear();
+
+ m_visible = false;
+}
+
+// process key presses
+void OptWindow::processKey(int request)
+{
+ if(m_visible)
+ {
+ switch(request)
+ {
+ case KEY_LEFT:
+ request = REQ_PREV_CHAR;
+ break;
+ case KEY_RIGHT:
+ request = REQ_NEXT_CHAR;
+ break;
+ case KEY_UP:
+ request = REQ_PREV_FIELD;
+ break;
+ case KEY_DOWN:
+ case KEY_ENTER:
+ case '\n':
+ case '\015':
+ request = REQ_NEXT_FIELD;
+ break;
+ case KEY_DC:
+ request = REQ_DEL_CHAR;
+ break;
+ case KEY_BACKSPACE:
+ request = REQ_DEL_PREV;
+ break;
+ case KEY_PPAGE:
+ request = REQ_PREV_CHOICE;
+ break;
+ case KEY_NPAGE:
+ case '\t':
+ request = REQ_NEXT_CHOICE;
+ break;
+ case KEY_HOME:
+ request = REQ_BEG_LINE;
+ break;
+ case KEY_END:
+ request = REQ_END_LINE;
+ break;
+ case '+':
+ request = REQ_NEXT_PAGE;
+ break;
+ case '-':
+ request = REQ_PREV_PAGE;
+ break;
+ }
+ m_form.processKey(request);
+ refresh();
+ }
+}
+
+void OptWindow::refresh()
+{
+ print(0, 0) << "Options:" << endl
+ << string(getWidth(), '=');
+
+ string navigator = " <-- (-) page " + toString(m_form.getPage() + 1) + "/" + toString(m_form.getPageCount()) + " (+) --> ";
+ print(navigator, getWidth() - navigator.length() - 1, 1);
+
+ wrefresh(m_window);
+ m_subWindow.refresh();
+}
+
diff --git a/src/opt_window.h b/src/opt_window.h
new file mode 100644
index 0000000..01a320a
--- /dev/null
+++ b/src/opt_window.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ opt_window.h
+ -------------------
+ begin : Thu Jan 17 2002
+ copyright : (C) 2002 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef OPT_WINDOW_H
+#define OPT_WINDOW_H
+
+#include "window.h"
+#include "form_field.h"
+
+#include <map>
+#include <string>
+
+class OptWindow : public Window, public Form::Slots
+{
+ public:
+ OptWindow();
+ ~OptWindow();
+
+ void show(int x, int y, int width, int height);
+ void hide();
+
+ void refresh();
+
+ void processKey(int request);
+ void slot_fieldChanged(Field* field);
+
+ private:
+ SubWindow m_subWindow;
+ Form m_form;
+
+ std::map<Field*, std::string> m_labels;
+ std::map<Field*, std::string> m_fields;
+};
+
+#endif
+
diff --git a/src/screen.cpp b/src/screen.cpp
new file mode 100644
index 0000000..05e8c00
--- /dev/null
+++ b/src/screen.cpp
@@ -0,0 +1,56 @@
+/***************************************************************************
+ screen.cpp
+ -------------------
+ begin : Thu Nov 25 2003
+ copyright : (C) 2003 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "screen.h"
+
+#include <curses.h>
+#undef clear
+#undef erase
+#undef refresh
+
+int Screen::width()
+{
+ int width;
+ int height;
+ getmaxyx(stdscr, height, width);
+ return width;
+}
+
+int Screen::height()
+{
+ int width;
+ int height;
+ getmaxyx(stdscr, height, width);
+ return height;
+}
+
+int Screen::x()
+{
+ int x;
+ int y;
+ getyx(stdscr, y, x);
+ return x;
+}
+
+int Screen::y()
+{
+ int x;
+ int y;
+ getyx(stdscr, y, x);
+ return y;
+}
+
diff --git a/src/screen.h b/src/screen.h
new file mode 100644
index 0000000..cf502ca
--- /dev/null
+++ b/src/screen.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ screen.h
+ -------------------
+ begin : Thu Jul 04 2002
+ copyright : (C) 2002 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef SCREEN_H
+#define SCREEN_H
+
+class Screen
+{
+ public:
+ static int width();
+ static int height();
+
+ static int x();
+ static int y();
+};
+
+#endif
+
diff --git a/src/setting.cpp b/src/setting.cpp
new file mode 100644
index 0000000..9e7ed70
--- /dev/null
+++ b/src/setting.cpp
@@ -0,0 +1,144 @@
+/***************************************************************************
+ setting.cpp
+ -------------------
+ begin : Tue Nov 06 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "setting.h"
+#include "settingfilter.h"
+#include "stringutils.h"
+
+#include <istream>
+#include <ostream>
+#include <sstream>
+
+using namespace std;
+
+Setting::~Setting()
+{
+ for(list<SettingFilter*>::const_iterator itFilter = m_filters.begin(); itFilter != m_filters.end(); ++itFilter)
+ delete *itFilter;
+ m_filters.clear();
+}
+
+void Setting::pushFilter(SettingFilter* filter)
+{
+ if(!filter)
+ return;
+
+ m_filters.push_back(filter);
+}
+
+void Setting::popFilter()
+{
+ if(m_filters.empty())
+ return;
+
+ delete m_filters.back();
+ m_filters.pop_back();
+}
+
+SettingFilter* Setting::findFilterWithId(const string& id)
+{
+ for(list<SettingFilter*>::const_iterator itFilter = m_filters.begin(); itFilter != m_filters.end(); ++itFilter)
+ {
+ if((*itFilter)->getId() == id)
+ return *itFilter;
+ }
+
+ return 0;
+}
+
+const SettingFilter* Setting::findFilterWithId(const string& id) const
+{
+ for(list<SettingFilter*>::const_iterator itFilter = m_filters.begin(); itFilter != m_filters.end(); ++itFilter)
+ {
+ if((*itFilter)->getId() == id)
+ return *itFilter;
+ }
+
+ return 0;
+}
+
+string Setting::getThroughFilter() const
+{
+ string valueCopy = m_value;
+
+ for(list<SettingFilter*>::const_reverse_iterator itFilter = m_filters.rbegin(); itFilter != m_filters.rend(); ++itFilter)
+ (*itFilter)->filterRead(valueCopy);
+
+ return valueCopy;
+}
+
+bool Setting::setThroughFilter(const string& value)
+{
+ string valueCopy = value;
+
+ for(list<SettingFilter*>::iterator itFilter = m_filters.begin(); itFilter != m_filters.end(); ++itFilter)
+ {
+ if(!(*itFilter)->filterWrite(valueCopy))
+ return false;
+ }
+
+ m_value = valueCopy;
+ return true;
+}
+
+istream& operator>>(istream& in, Setting& setting)
+{
+ while(!in.eof())
+ {
+ // extract line from stream
+ string line;
+ getline(in, line);
+
+ if(in.fail())
+ return in;
+
+ // strip whitespace
+ line = trim(line);
+
+ // skip empty lines
+ if(line.empty())
+ continue;
+
+ // skip comments
+ if(line[0] == '#')
+ continue;
+
+ // split line into id and value
+ vector<string> words = splitQuoted(line, "=");
+
+ if(words.size() < 2 || words[0].empty())
+ {
+ in.setstate(ios_base::failbit);
+ return in;
+ }
+
+ setting.setId(words[0]);
+ setting.setThroughFilter(words[1]);
+
+ break;
+ }
+
+ return in;
+}
+
+ostream& operator<<(ostream& out, const Setting& setting)
+{
+ out << setting.getId() << "=\"" << setting.getThroughFilter() << "\"" << endl;
+ return out;
+}
+
+
diff --git a/src/setting.h b/src/setting.h
new file mode 100644
index 0000000..eef52f5
--- /dev/null
+++ b/src/setting.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ setting.h
+ -------------------
+ begin : Tue Nov 06 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef SETTING_H
+#define SETTING_H
+
+#include "stringutils.h"
+
+#include <iosfwd>
+#include <list>
+#include <string>
+
+class SettingFilter;
+
+class Setting
+{
+ public:
+ Setting(const std::string& id = "", const std::string& description = "")
+ : m_id(id), m_description(description), m_value() {}
+ template<class T>
+ Setting(const std::string& id, const std::string& description, const T& value)
+ : m_id(id), m_description(description), m_value(toString(value)) {}
+ ~Setting();
+
+ const std::string& getId() const { return m_id; }
+ const std::string& getDescription() const { return m_description; }
+ const std::string& getValue() const { return m_value; }
+
+ void setId(const std::string& id) { m_id = id; }
+ void setDescription(const std::string& description) { m_description = description; }
+
+ void pushFilter(SettingFilter* filter);
+ void popFilter();
+ SettingFilter* findFilterWithId(const std::string& id);
+ const SettingFilter* findFilterWithId(const std::string& id) const;
+
+ std::string getThroughFilter() const;
+ bool setThroughFilter(const std::string& value);
+
+ template<class T>
+ operator T() { return fromString<T>(m_value); }
+
+ template<class T>
+ Setting& operator=(const T& t) { m_value = toString(t); return *this; }
+
+ template<class T>
+ bool operator==(const T& t) const { return toString(t) == m_value; }
+ template<class T>
+ bool operator!=(const T& t) const { return toString(t) != m_value; }
+ template<class T>
+ bool operator<(const T& t) const { return fromString<T>(m_value) < t; }
+ template<class T>
+ bool operator>(const T& t) const { return fromString<T>(m_value) > t; }
+ template<class T>
+ bool operator<=(const T& t) const { return fromString<T>(m_value) <= t; }
+ template<class T>
+ bool operator>=(const T& t) const { return fromString<T>(m_value) >= t; }
+
+ bool operator==(const Setting& s) const { return s.m_value == m_value; }
+ bool operator!=(const Setting& s) const { return s.m_value != m_value; }
+
+ private:
+ std::string m_id;
+ std::string m_description;
+ std::string m_value;
+
+ std::list<SettingFilter*> m_filters;
+};
+
+std::istream& operator>>(std::istream& in, Setting& setting);
+std::ostream& operator<<(std::ostream& out, const Setting& setting);
+
+#endif
+
diff --git a/src/settingfilter.cpp b/src/settingfilter.cpp
new file mode 100644
index 0000000..fb7df78
--- /dev/null
+++ b/src/settingfilter.cpp
@@ -0,0 +1,222 @@
+/***************************************************************************
+ settingfilter.cpp
+ -------------------
+ begin : Wed Nov 28 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "settingfilter.h"
+#include "stringutils.h"
+
+using namespace std;
+
+SettingFilterDefault::SettingFilterDefault(const string& def)
+ : m_default(def)
+{
+}
+
+SettingFilterDefault::~SettingFilterDefault()
+{
+}
+
+string SettingFilterDefault::getId() const
+{
+ return "default";
+}
+
+void SettingFilterDefault::setDefault(const string& def)
+{
+ m_default = def;
+}
+
+const string& SettingFilterDefault::getDefault() const
+{
+ return m_default;
+}
+
+bool SettingFilterDefault::filterWrite(string& valueNew)
+{
+ if(valueNew.empty())
+ valueNew = m_default;
+
+ return true;
+}
+
+void SettingFilterDefault::filterRead(string& value)
+{
+}
+
+SettingFilterExclusive::SettingFilterExclusive(const string& exclusive)
+ : m_exclusive(exclusive)
+{
+}
+
+SettingFilterExclusive::~SettingFilterExclusive()
+{
+}
+
+string SettingFilterExclusive::getId() const
+{
+ return "exclusive";
+}
+
+void SettingFilterExclusive::setExclusive(const string& exclusive)
+{
+ m_exclusive = exclusive;
+}
+
+const string& SettingFilterExclusive::getExclusive() const
+{
+ return m_exclusive;
+}
+
+bool SettingFilterExclusive::filterWrite(string& valueNew)
+{
+ substituteExclusive(valueNew);
+ return true;
+}
+
+void SettingFilterExclusive::filterRead(string& value)
+{
+ substituteExclusive(value);
+}
+
+void SettingFilterExclusive::substituteExclusive(string& value)
+{
+ if(value.find(m_exclusive + " ") == 0 ||
+ value.find(string(" ") + m_exclusive) == value.length() - (m_exclusive.length() + 1) ||
+ value.find(string(" ") + m_exclusive + " ") != string::npos
+ )
+ value = m_exclusive;
+}
+
+SettingFilterMap::SettingFilterMap(const map<string, string>& filterMap)
+ : m_filterMap(filterMap)
+{
+}
+
+SettingFilterMap::~SettingFilterMap()
+{
+}
+
+string SettingFilterMap::getId() const
+{
+ return "map";
+}
+
+void SettingFilterMap::setMap(const map<string, string>& filterMap)
+{
+ m_filterMap = filterMap;
+}
+
+const map<string, string>& SettingFilterMap::getMap() const
+{
+ return m_filterMap;
+}
+
+bool SettingFilterMap::filterWrite(string& valueNew)
+{
+ for(map<string, string>::const_iterator itMapping = m_filterMap.begin(); itMapping != m_filterMap.end(); ++itMapping)
+ {
+ if(itMapping->second == valueNew)
+ {
+ valueNew = itMapping->first;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void SettingFilterMap::filterRead(string& value)
+{
+ if(m_filterMap.empty())
+ return;
+
+ map<string, string>::const_iterator itMapping = m_filterMap.find(value);
+ if(itMapping != m_filterMap.end())
+ value = itMapping->second;
+}
+
+SettingFilterMin::SettingFilterMin(int min)
+ : m_min(min)
+{
+}
+
+SettingFilterMin::~SettingFilterMin()
+{
+}
+
+string SettingFilterMin::getId() const
+{
+ return "min";
+}
+
+void SettingFilterMin::setMin(int min)
+{
+ m_min = min;
+}
+
+int SettingFilterMin::getMin() const
+{
+ return m_min;
+}
+
+bool SettingFilterMin::filterWrite(string& valueNew)
+{
+ if(fromString<int>(valueNew) < m_min)
+ valueNew = toString(m_min);
+
+ return true;
+}
+
+void SettingFilterMin::filterRead(string& value)
+{
+}
+
+SettingFilterMax::SettingFilterMax(int max)
+ : m_max(max)
+{
+}
+
+SettingFilterMax::~SettingFilterMax()
+{
+}
+
+string SettingFilterMax::getId() const
+{
+ return "max";
+}
+
+void SettingFilterMax::setMax(int max)
+{
+ m_max = max;
+}
+
+int SettingFilterMax::getMax() const
+{
+ return m_max;
+}
+
+bool SettingFilterMax::filterWrite(string& valueNew)
+{
+ if(fromString<int>(valueNew) > m_max)
+ valueNew = toString(m_max);
+
+ return true;
+}
+
+void SettingFilterMax::filterRead(string& value)
+{
+}
+
diff --git a/src/settingfilter.h b/src/settingfilter.h
new file mode 100644
index 0000000..c306667
--- /dev/null
+++ b/src/settingfilter.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+ settingfilter.h
+ -------------------
+ begin : Wed Nov 28 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef SETTINGFILTER_H
+#define SETTINGFILTER_H
+
+#include <map>
+#include <string>
+
+class SettingFilter
+{
+ public:
+ virtual ~SettingFilter() {}
+
+ virtual std::string getId() const = 0;
+
+ virtual bool filterWrite(std::string& valueNew) = 0;
+ virtual void filterRead(std::string& value) = 0;
+};
+
+class SettingFilterDefault : public SettingFilter
+{
+ public:
+ SettingFilterDefault(const std::string& def);
+ ~SettingFilterDefault();
+
+ std::string getId() const;
+
+ void setDefault(const std::string& def);
+ const std::string& getDefault() const;
+
+ bool filterWrite(std::string& valueNew);
+ void filterRead(std::string& value);
+
+ private:
+ std::string m_default;
+};
+
+class SettingFilterExclusive : public SettingFilter
+{
+ public:
+ SettingFilterExclusive(const std::string& exclusive);
+ ~SettingFilterExclusive();
+
+ std::string getId() const;
+
+ void setExclusive(const std::string& exclusive);
+ const std::string& getExclusive() const;
+
+ bool filterWrite(std::string& valueNew);
+ void filterRead(std::string& value);
+
+ private:
+ void substituteExclusive(std::string& value);
+
+ std::string m_exclusive;
+};
+
+class SettingFilterMap : public SettingFilter
+{
+ public:
+ SettingFilterMap(const std::map<std::string, std::string>& filterMap);
+ ~SettingFilterMap();
+
+ std::string getId() const;
+
+ void setMap(const std::map<std::string, std::string>& filterMap);
+ const std::map<std::string, std::string>& getMap() const;
+
+ bool filterWrite(std::string& valueNew);
+ void filterRead(std::string& value);
+
+ private:
+ std::map<std::string, std::string> m_filterMap;
+};
+
+class SettingFilterMin : public SettingFilter
+{
+ public:
+ SettingFilterMin(int min);
+ ~SettingFilterMin();
+
+ std::string getId() const;
+
+ void setMin(int min);
+ int getMin() const;
+
+ bool filterWrite(std::string& valueNew);
+ void filterRead(std::string& value);
+
+ private:
+ int m_min;
+};
+
+class SettingFilterMax : public SettingFilter
+{
+ public:
+ SettingFilterMax(int max);
+ ~SettingFilterMax();
+
+ std::string getId() const;
+
+ void setMax(int max);
+ int getMax() const;
+
+ bool filterWrite(std::string& valueNew);
+ void filterRead(std::string& value);
+
+ private:
+ int m_max;
+};
+
+#endif
+
diff --git a/src/settingstore.cpp b/src/settingstore.cpp
new file mode 100644
index 0000000..1dcb626
--- /dev/null
+++ b/src/settingstore.cpp
@@ -0,0 +1,98 @@
+/***************************************************************************
+ settingstore.cpp
+ -------------------
+ begin : Tue Nov 06 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "setting.h"
+#include "settingstore.h"
+
+#include <fstream>
+
+using namespace std;
+
+map<string, Setting> SettingStore::m_settings;
+
+Setting& SettingStore::get(const string& key)
+{
+ return m_settings[key];
+}
+
+void SettingStore::add(const Setting& setting)
+{
+ m_settings[setting.getId()] = setting;
+}
+
+void SettingStore::remove(const string& key)
+{
+ m_settings.erase(key);
+}
+
+bool SettingStore::exists(const string& key)
+{
+ return m_settings.find(key) != m_settings.end();
+}
+
+map<std::string, Setting>& SettingStore::getAll()
+{
+ return m_settings;
+}
+
+bool SettingStore::readFromFile(const std::string& file)
+{
+ if(file.empty())
+ return false;
+
+ // open file
+ ifstream fin(file.c_str());
+ if(!fin.is_open())
+ return false;
+
+ // parse file
+ while(fin.good())
+ {
+ Setting setting;
+
+ fin >> setting;
+ if(setting.getId().empty())
+ break;
+
+ if(exists(setting.getId()))
+ get(setting.getId()).setThroughFilter(setting.getValue());
+ else
+ add(setting);
+ }
+
+ return !fin.fail();
+}
+
+bool SettingStore::writeToFile(const std::string& file)
+{
+ if(file.empty())
+ return false;
+
+ // open file
+ ofstream fout(file.c_str());
+ if(!fout.is_open())
+ return false;
+
+ fout << "Version=\"1\"\n";
+
+ // output settings
+ for(map<string, Setting>::const_iterator itSetting = m_settings.begin(); itSetting != m_settings.end(); ++itSetting)
+ fout << itSetting->second;
+
+ return fout.good();
+}
+
diff --git a/src/settingstore.h b/src/settingstore.h
new file mode 100644
index 0000000..4fc1ebb
--- /dev/null
+++ b/src/settingstore.h
@@ -0,0 +1,44 @@
+/***************************************************************************
+ settingstore.h
+ -------------------
+ begin : Tue Nov 06 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef SETTINGSTORE_H
+#define SETTINGSTORE_H
+
+#include <map>
+#include <string>
+
+class Setting;
+
+class SettingStore
+{
+ public:
+ static Setting& get(const std::string& key);
+ static void add(const Setting& setting);
+ static void remove(const std::string& key);
+ static bool exists(const std::string& key);
+
+ static std::map<std::string, Setting>& getAll();
+
+ static bool readFromFile(const std::string& file);
+ static bool writeToFile(const std::string& file);
+
+ private:
+ static std::map<std::string, Setting> m_settings;
+};
+
+#endif
+
diff --git a/src/statistics.cpp b/src/statistics.cpp
new file mode 100644
index 0000000..a983c9c
--- /dev/null
+++ b/src/statistics.cpp
@@ -0,0 +1,216 @@
+/***************************************************************************
+ statistics.cpp
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "setting.h"
+#include "settingstore.h"
+#include "statistics.h"
+
+using namespace std;
+
+void Statistics::insertDataFrame(const DataFrame& dataFrame)
+{
+ if(!dataFrame.isValid())
+ return;
+
+ m_dataFrames.push_back(dataFrame);
+
+ unsigned int frameCount = m_dataFrames.size();
+ if(frameCount < 2)
+ return;
+
+ unsigned int averageCount = getAverageWindow();
+ unsigned int secondCount = getSecondWindow();
+
+ if(frameCount > averageCount)
+ {
+ m_dataFrames.erase(m_dataFrames.begin(), m_dataFrames.begin() + (frameCount - averageCount));
+ frameCount = averageCount;
+ }
+
+ vector<DataFrame>::const_reverse_iterator itFrameSecond = m_dataFrames.rbegin();
+ vector<DataFrame>::const_reverse_iterator itFrameAverage = m_dataFrames.rbegin();
+
+ if(frameCount > secondCount)
+ itFrameSecond += secondCount;
+ else
+ itFrameSecond += frameCount - 1;
+
+ if(frameCount > averageCount)
+ itFrameAverage += averageCount;
+ else
+ itFrameAverage += frameCount - 1;
+
+ calculateAverage(*itFrameSecond, m_dataFrames.back(), m_second);
+ calculateAverage(*itFrameAverage, m_dataFrames.back(), m_average);
+
+ if(frameCount > 2)
+ calculateMinMax(m_second, m_min, m_max);
+ else
+ m_min = m_max = m_second;
+}
+
+void Statistics::reset()
+{
+ m_second = DataFrame();
+ m_average = DataFrame();
+ m_min = DataFrame();
+ m_max = DataFrame();
+
+ m_dataFrames.clear();
+}
+
+float Statistics::getUnitFactor(dataUnit unit, unsigned long long value)
+{
+ float factor = 1.0 / (unit % 2 == 0 ? 8 : 1);
+
+ switch(unit)
+ {
+ case humanReadableBit:
+ case humanReadableByte:
+ for(int i = 0; i < 3; ++i)
+ {
+ if(value / factor < 1024)
+ return factor;
+
+ factor *= 1024;
+ }
+ return factor;
+ case bit:
+ case byte:
+ return factor;
+ case kiloBit:
+ case kiloByte:
+ return factor * 1024;
+ case megaBit:
+ case megaByte:
+ return factor * 1024 * 1024;
+ case gigaBit:
+ case gigaByte:
+ return factor * 1024 * 1024 * 1024;
+ default: // should never be executed
+ return factor;
+ }
+}
+
+string Statistics::getUnitString(dataUnit unit, unsigned long long value)
+{
+ const string description = (unit % 2 == 0 ? "Bit" : "Byte");
+ const string units[] = { "", "k", "M", "G" };
+
+ switch(unit)
+ {
+ case humanReadableBit:
+ case humanReadableByte:
+ value *= (unit % 2 == 0 ? 8 : 1);
+ for(int i = 0; i < 3; ++i)
+ {
+ if(value < 1024)
+ return units[i] + description;
+
+ value /= 1024;
+ }
+ return units[3] + description;
+ case bit:
+ case byte:
+ return description;
+ case kiloBit:
+ case kiloByte:
+ return 'k' + description;
+ case megaBit:
+ case megaByte:
+ return 'M' + description;
+ case gigaBit:
+ case gigaByte:
+ return 'G' + description;
+ default: // should never be executed
+ return description;
+ }
+}
+
+void Statistics::calculateAverage(const DataFrame& dataFrameFrom, const DataFrame& dataFrameTo, DataFrame& result)
+{
+ float timeSpan = (dataFrameTo.getTimeStampSeconds() + dataFrameTo.getTimeStampMicroseconds() / 1000000.0) -
+ (dataFrameFrom.getTimeStampSeconds() + dataFrameFrom.getTimeStampMicroseconds() / 1000000.0);
+
+ if(timeSpan <= 0)
+ return;
+
+ result.setTotalDataIn((unsigned long long)((dataFrameTo.getTotalDataIn() - dataFrameFrom.getTotalDataIn()) / timeSpan));
+ result.setTotalDataOut((unsigned long long)((dataFrameTo.getTotalDataOut() - dataFrameFrom.getTotalDataOut()) / timeSpan));
+ result.setTotalPacketsIn((unsigned long long)((dataFrameTo.getTotalPacketsIn() - dataFrameFrom.getTotalPacketsIn()) / timeSpan));
+ result.setTotalPacketsOut((unsigned long long)((dataFrameTo.getTotalPacketsOut() - dataFrameFrom.getTotalPacketsOut()) / timeSpan));
+ result.setTotalErrorsIn((unsigned long long)((dataFrameTo.getTotalErrorsIn() - dataFrameFrom.getTotalErrorsIn()) / timeSpan));
+ result.setTotalErrorsOut((unsigned long long)((dataFrameTo.getTotalErrorsOut() - dataFrameFrom.getTotalErrorsOut()) / timeSpan));
+ result.setTotalDropsIn((unsigned long long)((dataFrameTo.getTotalDropsIn() - dataFrameFrom.getTotalDropsIn()) / timeSpan));
+ result.setTotalDropsOut((unsigned long long)((dataFrameTo.getTotalDropsOut() - dataFrameFrom.getTotalDropsOut()) / timeSpan));
+}
+
+void Statistics::calculateMinMax(const DataFrame& dataFrame, DataFrame& min, DataFrame& max)
+{
+ if(dataFrame.getTotalDataIn() < min.getTotalDataIn())
+ min.setTotalDataIn(dataFrame.getTotalDataIn());
+ if(dataFrame.getTotalDataIn() > max.getTotalDataIn())
+ max.setTotalDataIn(dataFrame.getTotalDataIn());
+ if(dataFrame.getTotalDataOut() < min.getTotalDataOut())
+ min.setTotalDataOut(dataFrame.getTotalDataOut());
+ if(dataFrame.getTotalDataOut() > max.getTotalDataOut())
+ max.setTotalDataOut(dataFrame.getTotalDataOut());
+
+ if(dataFrame.getTotalPacketsIn() < min.getTotalPacketsIn())
+ min.setTotalPacketsIn(dataFrame.getTotalPacketsIn());
+ if(dataFrame.getTotalPacketsIn() > max.getTotalPacketsIn())
+ max.setTotalPacketsIn(dataFrame.getTotalPacketsIn());
+ if(dataFrame.getTotalPacketsOut() < min.getTotalPacketsOut())
+ min.setTotalPacketsOut(dataFrame.getTotalPacketsOut());
+ if(dataFrame.getTotalPacketsOut() > max.getTotalPacketsOut())
+ max.setTotalPacketsOut(dataFrame.getTotalPacketsOut());
+
+ if(dataFrame.getTotalErrorsIn() < min.getTotalErrorsIn())
+ min.setTotalErrorsIn(dataFrame.getTotalErrorsIn());
+ if(dataFrame.getTotalErrorsIn() > max.getTotalErrorsIn())
+ max.setTotalErrorsIn(dataFrame.getTotalErrorsIn());
+ if(dataFrame.getTotalErrorsOut() < min.getTotalErrorsOut())
+ min.setTotalErrorsOut(dataFrame.getTotalErrorsOut());
+ if(dataFrame.getTotalErrorsOut() > max.getTotalErrorsOut())
+ max.setTotalErrorsOut(dataFrame.getTotalErrorsOut());
+
+ if(dataFrame.getTotalDropsIn() < min.getTotalDropsIn())
+ min.setTotalDropsIn(dataFrame.getTotalDropsIn());
+ if(dataFrame.getTotalDropsIn() > max.getTotalDropsIn())
+ max.setTotalDropsIn(dataFrame.getTotalDropsIn());
+ if(dataFrame.getTotalDropsOut() < min.getTotalDropsOut())
+ min.setTotalDropsOut(dataFrame.getTotalDropsOut());
+ if(dataFrame.getTotalDropsOut() > max.getTotalDropsOut())
+ max.setTotalDropsOut(dataFrame.getTotalDropsOut());
+}
+
+unsigned int Statistics::getAverageWindow()
+{
+ unsigned int refreshInterval = SettingStore::get("RefreshInterval");
+ unsigned int averageWindow = SettingStore::get("AverageWindow");
+
+ return (unsigned int) (1000.0 / refreshInterval * averageWindow);
+}
+
+unsigned int Statistics::getSecondWindow()
+{
+ unsigned int refreshInterval = SettingStore::get("RefreshInterval");
+ unsigned int secondWindow = (unsigned int) (1000.0 / refreshInterval);
+
+ return secondWindow > 0 ? secondWindow : 1;
+}
+
diff --git a/src/statistics.h b/src/statistics.h
new file mode 100644
index 0000000..961b7e9
--- /dev/null
+++ b/src/statistics.h
@@ -0,0 +1,114 @@
+/***************************************************************************
+ statistics.h
+ -------------------
+ begin : Fri Nov 16 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef STATISTICS_H
+#define STATISTICS_H
+
+#include "dataframe.h"
+
+#include <string>
+#include <vector>
+
+class Statistics
+{
+ public:
+ enum dataUnit
+ {
+ humanReadableBit = -2,
+ humanReadableByte = -1,
+ bit = 0,
+ byte = 1,
+ kiloBit = 2,
+ kiloByte = 3,
+ megaBit = 4,
+ megaByte = 5,
+ gigaBit = 6,
+ gigaByte = 7
+ };
+
+ Statistics() {}
+ ~Statistics() {}
+
+ static float getUnitFactor(dataUnit unit, unsigned long long value);
+ static std::string getUnitString(dataUnit unit, unsigned long long value);
+
+ void insertDataFrame(const DataFrame& dataFrame);
+ void reset();
+
+ bool isValid() const { return !m_dataFrames.empty(); }
+
+ unsigned long long getDataInTotal() const { return m_dataFrames.empty() ? 0 : m_dataFrames.back().getTotalDataIn(); }
+ unsigned long long getDataOutTotal() const { return m_dataFrames.empty() ? 0 : m_dataFrames.back().getTotalDataOut(); }
+ unsigned long long getPacketsInTotal() const { return m_dataFrames.empty() ? 0 : m_dataFrames.back().getTotalPacketsIn(); }
+ unsigned long long getPacketsOutTotal() const { return m_dataFrames.empty() ? 0 : m_dataFrames.back().getTotalPacketsOut(); }
+ unsigned long long getErrorsInTotal() const { return m_dataFrames.empty() ? 0 : m_dataFrames.back().getTotalErrorsIn(); }
+ unsigned long long getErrorsOutTotal() const { return m_dataFrames.empty() ? 0 : m_dataFrames.back().getTotalErrorsOut(); }
+ unsigned long long getDropsInTotal() const { return m_dataFrames.empty() ? 0 : m_dataFrames.back().getTotalDropsIn(); }
+ unsigned long long getDropsOutTotal() const { return m_dataFrames.empty() ? 0 : m_dataFrames.back().getTotalDropsOut(); }
+
+ unsigned long long getDataInPerSecond() const { return m_second.getTotalDataIn(); }
+ unsigned long long getDataOutPerSecond() const { return m_second.getTotalDataOut(); }
+ unsigned long long getPacketsInPerSecond() const { return m_second.getTotalPacketsIn(); }
+ unsigned long long getPacketsOutPerSecond() const { return m_second.getTotalPacketsOut(); }
+ unsigned long long getErrorsInPerSecond() const { return m_second.getTotalErrorsIn(); }
+ unsigned long long getErrorsOutPerSecond() const { return m_second.getTotalErrorsOut(); }
+ unsigned long long getDropsInPerSecond() const { return m_second.getTotalDropsIn(); }
+ unsigned long long getDropsOutPerSecond() const { return m_second.getTotalDropsOut(); }
+
+ unsigned long long getDataInAverage() const { return m_average.getTotalDataIn(); }
+ unsigned long long getDataOutAverage() const { return m_average.getTotalDataOut(); }
+ unsigned long long getPacketsInAverage() const { return m_average.getTotalPacketsIn(); }
+ unsigned long long getPacketsOutAverage() const { return m_average.getTotalPacketsOut(); }
+ unsigned long long getErrorsInAverage() const { return m_average.getTotalErrorsIn(); }
+ unsigned long long getErrorsOutAverage() const { return m_average.getTotalErrorsOut(); }
+ unsigned long long getDropsInAverage() const { return m_average.getTotalDropsIn(); }
+ unsigned long long getDropsOutAverage() const { return m_average.getTotalDropsOut(); }
+
+ unsigned long long getDataInMin() const { return m_min.getTotalDataIn(); }
+ unsigned long long getDataOutMin() const { return m_min.getTotalDataOut(); }
+ unsigned long long getPacketsInMin() const { return m_min.getTotalPacketsIn(); }
+ unsigned long long getPacketsOutMin() const { return m_min.getTotalPacketsOut(); }
+ unsigned long long getErrorsInMin() const { return m_min.getTotalErrorsIn(); }
+ unsigned long long getErrorsOutMin() const { return m_min.getTotalErrorsOut(); }
+ unsigned long long getDropsInMin() const { return m_min.getTotalDropsIn(); }
+ unsigned long long getDropsOutMin() const { return m_min.getTotalDropsOut(); }
+
+ unsigned long long getDataInMax() const { return m_max.getTotalDataIn(); }
+ unsigned long long getDataOutMax() const { return m_max.getTotalDataOut(); }
+ unsigned long long getPacketsInMax() const { return m_max.getTotalPacketsIn(); }
+ unsigned long long getPacketsOutMax() const { return m_max.getTotalPacketsOut(); }
+ unsigned long long getErrorsInMax() const { return m_max.getTotalErrorsIn(); }
+ unsigned long long getErrorsOutMax() const { return m_max.getTotalErrorsOut(); }
+ unsigned long long getDropsInMax() const { return m_max.getTotalDropsIn(); }
+ unsigned long long getDropsOutMax() const { return m_max.getTotalDropsOut(); }
+
+ private:
+ void calculateAverage(const DataFrame& dataFrameFrom, const DataFrame& dataFrameTo, DataFrame& result);
+ void calculateMinMax(const DataFrame& dataFrame, DataFrame& min, DataFrame& max);
+ unsigned int getAverageWindow();
+ unsigned int getSecondWindow();
+
+ DataFrame m_second;
+ DataFrame m_average;
+ DataFrame m_min;
+ DataFrame m_max;
+
+ std::vector<DataFrame> m_dataFrames;
+};
+
+#endif
+
diff --git a/src/stringutils.cpp b/src/stringutils.cpp
new file mode 100644
index 0000000..3d30943
--- /dev/null
+++ b/src/stringutils.cpp
@@ -0,0 +1,97 @@
+/***************************************************************************
+ stringutils.cpp
+ -------------------
+ begin : Tue Nov 06 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "stringutils.h"
+
+using namespace std;
+
+string trim(const string& s)
+{
+ // find end of whitespace at the beginning
+ string::size_type posBegin = s.find_first_not_of(" \011\012\015");
+ if(posBegin == string::npos)
+ return string();
+
+ // find beginning of whitespace at the end
+ string::size_type posEnd = s.find_last_not_of(" \011\012\015");
+
+ return s.substr(posBegin, posEnd - posBegin + 1);
+}
+
+vector<string> split(const string& s, const string& separators)
+{
+ vector<string> words;
+ if(s.empty())
+ return words;
+
+ string::size_type pos = s.find_first_of(separators);
+ string::size_type posOld = 0;
+ while(pos != string::npos)
+ {
+ words.push_back(s.substr(posOld, pos - posOld));
+ posOld = pos + 1;
+
+ pos = s.find_first_of(separators, posOld);
+ }
+
+ words.push_back(s.substr(posOld));
+
+ return words;
+}
+
+vector<string> splitQuoted(const string& s, const string& separators, const string& quotes)
+{
+ if(s.empty())
+ return vector<string>();
+
+ vector<string> words(1);
+ string::size_type pos = s.find_first_of(separators + quotes);
+ string::size_type posOld = 0;
+ bool quoted = false;
+
+ while(true)
+ {
+ words.back() += s.substr(posOld, pos - posOld);
+ posOld = pos + 1;
+
+ if(pos == string::npos)
+ return words;
+
+ if(separators.find(s[pos]) != string::npos)
+ {
+ // separator found
+
+ words.push_back(string());
+
+ pos = s.find_first_of(separators + quotes, posOld);
+ }
+ else
+ {
+ // quote found
+
+ posOld = pos + 1;
+
+ quoted = !quoted;
+
+ if(quoted)
+ pos = s.find_first_of(quotes, posOld);
+ else
+ pos = s.find_first_of(separators + quotes, posOld);
+ }
+ }
+}
+
diff --git a/src/stringutils.h b/src/stringutils.h
new file mode 100644
index 0000000..b181b5e
--- /dev/null
+++ b/src/stringutils.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ stringutils.h
+ -------------------
+ begin : Tue Nov 06 2007
+ copyright : (C) 2007 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef STRINGUTILS_H
+#define STRINGUTILS_H
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+std::string trim(const std::string& s);
+std::vector<std::string> split(const std::string& s, const std::string& separators);
+std::vector<std::string> splitQuoted(const std::string& s, const std::string& separators, const std::string& quotes = "\"");
+
+template<class T>
+std::string toString(const T& t)
+{
+ std::ostringstream stream;
+ stream << t;
+
+ return stream.str();
+}
+
+template<class T>
+T fromString(const std::string& s)
+{
+ std::istringstream stream(s);
+ T t = T();
+ stream >> t;
+
+ return t;
+}
+
+#endif
+
diff --git a/src/templates/cpp_template b/src/templates/cpp_template
new file mode 100644
index 0000000..6afef5d
--- /dev/null
+++ b/src/templates/cpp_template
@@ -0,0 +1,16 @@
+/***************************************************************************
+ |FILENAME| - description
+ -------------------
+ begin : |DATE|
+ copyright : (C) |YEAR| by |AUTHOR|
+ email : |EMAIL|
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
diff --git a/src/templates/header_template b/src/templates/header_template
new file mode 100644
index 0000000..6afef5d
--- /dev/null
+++ b/src/templates/header_template
@@ -0,0 +1,16 @@
+/***************************************************************************
+ |FILENAME| - description
+ -------------------
+ begin : |DATE|
+ copyright : (C) |YEAR| by |AUTHOR|
+ email : |EMAIL|
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
diff --git a/src/traffic_window.cpp b/src/traffic_window.cpp
new file mode 100644
index 0000000..7296db5
--- /dev/null
+++ b/src/traffic_window.cpp
@@ -0,0 +1,85 @@
+/***************************************************************************
+ traffic_window.cpp
+ -------------------
+ begin : Thu Jul 04 2002
+ copyright : (C) 2002 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "device.h"
+#include "setting.h"
+#include "settingstore.h"
+#include "traffic_window.h"
+
+using namespace std;
+
+TrafficWindow::TrafficWindow()
+ : Window(), m_curDev(0)
+{
+}
+
+TrafficWindow::~TrafficWindow()
+{
+}
+
+void TrafficWindow::processKey(int key)
+{
+ switch(key)
+ {
+ case KEY_RIGHT:
+ case KEY_DOWN:
+ case KEY_NPAGE:
+ case KEY_ENTER:
+ case '\n':
+ case '\t':
+ case '\015':
+ m_curDev += showMultipleDevices() ? getHeight() / 9 : 1;
+ break;
+ case KEY_LEFT:
+ case KEY_UP:
+ case KEY_PPAGE:
+ m_curDev -= showMultipleDevices() ? getHeight() / 9 : 1;
+ break;
+ }
+}
+
+void TrafficWindow::printTraffic(const vector<Device*>& devices)
+{
+ if((unsigned int) m_curDev >= devices.size() || m_curDev < 0)
+ m_curDev = 0;
+
+ // print data of the current device(s)
+ if(!showMultipleDevices())
+ {
+ devices[m_curDev]->print(*this);
+ }
+ else
+ {
+ if((unsigned int) getHeight() / 9 >= devices.size())
+ m_curDev = 0;
+
+ int i = m_curDev;
+ while(getHeight() - getY() >= 9)
+ {
+ devices[i++]->print(*this);
+
+ if((unsigned int) i >= devices.size())
+ break;
+ }
+ }
+}
+
+bool TrafficWindow::showMultipleDevices()
+{
+ return SettingStore::get("MultipleDevices");
+}
+
diff --git a/src/traffic_window.h b/src/traffic_window.h
new file mode 100644
index 0000000..1baa246
--- /dev/null
+++ b/src/traffic_window.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ traffic_window.h
+ -------------------
+ begin : Thu Jul 04 2002
+ copyright : (C) 2002 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef TRAFFIC_WINDOW_H
+#define TRAFFIC_WINDOW_H
+
+#include "window.h"
+
+#include <vector>
+
+class Device;
+
+class TrafficWindow : public Window
+{
+ public:
+ TrafficWindow();
+ ~TrafficWindow();
+
+ void processKey(int key);
+ void printTraffic(const std::vector<Device*>& devices);
+
+ private:
+ bool showMultipleDevices();
+
+ int m_curDev;
+};
+
+#endif
+
diff --git a/src/window.cpp b/src/window.cpp
new file mode 100644
index 0000000..bfa7701
--- /dev/null
+++ b/src/window.cpp
@@ -0,0 +1,289 @@
+/***************************************************************************
+ window.cpp
+ -------------------
+ begin : Thu Nov 25 2003
+ copyright : (C) 2003 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "window.h"
+
+using namespace std;
+
+Window::WindowStreamBuf::WindowStreamBuf(Window& window)
+ : m_window(window)
+{
+}
+
+Window::WindowStreamBuf::~WindowStreamBuf()
+{
+}
+
+streamsize Window::WindowStreamBuf::xsputn(const char_type* str, streamsize n)
+{
+ m_window.print(string(str, n));
+ return n;
+}
+
+Window::WindowStreamBuf::int_type Window::WindowStreamBuf::overflow(int_type c)
+{
+ if(c == traits_type::eof())
+ return c;
+
+ m_window.print((char) c);
+ return c;
+}
+
+Window::WindowStream::WindowStream(Window& window)
+ : basic_ostream<char>(new WindowStreamBuf(window))
+{
+}
+
+Window::WindowStream::~WindowStream()
+{
+ delete rdbuf();
+}
+
+Window::Window()
+ : m_visible(false), m_window(0), m_stream(*this)
+{
+}
+
+Window::~Window()
+{
+ hide();
+}
+
+// create window and display it
+void Window::show(int x, int y, int width, int height)
+{
+ if(m_window)
+ return;
+
+ m_window = newwin(height, width, y, x);
+ clear();
+ refresh();
+
+ m_visible = true;
+}
+
+// hide window and destroy it
+void Window::hide()
+{
+ if(!m_window)
+ return;
+
+ clear();
+ refresh();
+ delwin(m_window);
+
+ m_window = 0;
+
+ m_visible = false;
+}
+
+// is the window currently visible?
+bool Window::isVisible()
+{
+ return m_visible;
+}
+
+// refresh window
+void Window::refresh()
+{
+ if(m_window)
+ wrefresh(m_window);
+}
+
+// clear the content of the window
+void Window::clear()
+{
+ if(m_window)
+ wclear(m_window);
+}
+
+// move and resize window
+void Window::resize(int x, int y, int width, int height)
+{
+ if(!m_window)
+ return;
+
+ wresize(m_window, height, width);
+ mvwin(m_window, y, x);
+}
+
+// return current window width
+int Window::getWidth()
+{
+ if(!m_window)
+ return 0;
+
+ int width, height;
+ getmaxyx(m_window, height, width);
+
+ return width;
+}
+
+// return current window height
+int Window::getHeight()
+{
+ if(!m_window)
+ return 0;
+
+ int width, height;
+ getmaxyx(m_window, height, width);
+
+ return height;
+}
+
+// return current distance to left screen edge
+int Window::getLeft()
+{
+ if(!m_window)
+ return 0;
+
+ int x, y;
+ getbegyx(m_window, y, x);
+
+ return x;
+}
+
+// return current distance to top screen edge
+int Window::getTop()
+{
+ if(!m_window)
+ return 0;
+
+ int x, y;
+ getbegyx(m_window, y, x);
+
+ return y;
+}
+
+// return current cursor position on the x-axis
+int Window::getX()
+{
+ if(!m_window)
+ return 0;
+
+ int x, y;
+ getyx(m_window, y, x);
+
+ return x;
+}
+
+// return current cursor position on the y-axis
+int Window::getY()
+{
+ if(!m_window)
+ return 0;
+
+ int x, y;
+ getyx(m_window, y, x);
+
+ return y;
+}
+
+// set current cursor x position
+void Window::setX(int new_x)
+{
+ if(!m_window)
+ return;
+
+ wmove(m_window, getY(), new_x);
+}
+
+// set current cursor y position
+void Window::setY(int new_y)
+{
+ if(!m_window)
+ return;
+
+ wmove(m_window, new_y, getX());
+}
+
+// set current cursor position
+void Window::setXY(int new_x, int new_y)
+{
+ if(!m_window)
+ return;
+
+ wmove(m_window, new_y, new_x);
+}
+
+// print some text to the window
+void Window::print(const string& text, int new_x, int new_y)
+{
+ if(!m_window)
+ return;
+ if(new_x <= -1)
+ new_x = getX();
+ if(new_y <= -1)
+ new_y = getY();
+
+ mvwaddstr(m_window, new_y, new_x, text.c_str());
+}
+
+// print a char to the window
+void Window::print(char text, int new_x, int new_y)
+{
+ if(!m_window)
+ return;
+ if(new_x <= -1)
+ new_x = getX();
+ if(new_y <= -1)
+ new_y = getY();
+
+ mvwaddch(m_window, new_y, new_x, text);
+}
+
+// print via stream to window
+Window::WindowStream& Window::print(int x, int y)
+{
+ if(x <= -1)
+ x = getX();
+ if(y <= -1)
+ y = getY();
+ setXY(x, y);
+
+ return m_stream;
+}
+
+SubWindow::SubWindow(Window* parent)
+ : Window(), m_parent(parent)
+{
+}
+
+SubWindow::~SubWindow()
+{
+ hide();
+}
+
+// return parent window
+Window* SubWindow::getParent()
+{
+ return m_parent;
+}
+
+// create window and display it
+void SubWindow::show(int x, int y, int width, int height)
+{
+ if(m_window)
+ return;
+
+ m_window = derwin(m_parent->m_window, height, width, y, x);
+ clear();
+ refresh();
+
+ m_visible = true;
+}
+
diff --git a/src/window.h b/src/window.h
new file mode 100644
index 0000000..fb36b08
--- /dev/null
+++ b/src/window.h
@@ -0,0 +1,142 @@
+/***************************************************************************
+ window.h
+ -------------------
+ begin : Thu Jul 04 2002
+ copyright : (C) 2002 - 2012 by Roland Riegel
+ email : feedback@roland-riegel.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <ostream>
+#include <streambuf>
+#include <string>
+
+#include <curses.h>
+#undef clear
+#undef erase
+#undef refresh
+
+class Form;
+
+class Window
+{
+ public:
+ class WindowStreamBuf : public std::basic_streambuf<char>
+ {
+ public:
+ WindowStreamBuf(Window& window);
+ ~WindowStreamBuf();
+
+ protected:
+ std::streamsize xsputn(const char_type* str, std::streamsize n);
+ int_type overflow(int_type c = traits_type::eof());
+
+ private:
+ Window& m_window;
+ };
+
+ class WindowStream : public std::basic_ostream<char>
+ {
+ public:
+ WindowStream(Window& window);
+ ~WindowStream();
+ };
+
+ Window();
+ virtual ~Window();
+
+ // create window and display it
+ virtual void show(int x, int y, int width, int height);
+
+ // hide window and destroy it
+ virtual void hide();
+
+ // is the window currently visible?
+ virtual bool isVisible();
+
+ // refresh window
+ virtual void refresh();
+
+ // clear the content of the window
+ virtual void clear();
+
+ // move and resize window
+ virtual void resize(int x, int y, int width, int height);
+
+ // return current window width
+ virtual int getWidth();
+
+ // return current window height
+ virtual int getHeight();
+
+ // return current distance to left screen edge
+ virtual int getLeft();
+
+ // return current distance to top screen edge
+ virtual int getTop();
+
+ // return current cursor position on the x-axis
+ virtual int getX();
+
+ // return current cursor position on the y-axis
+ virtual int getY();
+
+ // set current cursor x position
+ virtual void setX(int new_x);
+
+ // set current cursor y position
+ virtual void setY(int new_y);
+
+ // set current cursor position
+ virtual void setXY(int new_x, int new_y);
+
+ // print some text to the window
+ virtual void print(const std::string& text, int new_x = -1, int new_y = -1);
+
+ // print a char to the window
+ virtual void print(char text, int new_x = -1, int new_y = -1);
+
+ // print via stream to the window
+ virtual WindowStream& print(int x = -1, int y = -1);
+
+ protected:
+ friend class SubWindow;
+ friend class Form;
+
+ bool m_visible;
+ WINDOW* m_window;
+
+ WindowStream m_stream;
+};
+
+class SubWindow : public Window
+{
+ public:
+ SubWindow( Window* parent );
+ ~SubWindow();
+
+ // return parent window
+ Window* getParent();
+
+ // create window and display it
+ virtual void show(int x, int y, int width, int height);
+
+ private:
+ friend class Form;
+
+ Window* m_parent;
+};
+
+#endif
+