Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
d133cb0916 | |||
05c682ad94 | |||
05c199f20a |
28
.gitignore
vendored
28
.gitignore
vendored
@ -2,6 +2,30 @@
|
||||
*.so
|
||||
*.d
|
||||
sammler
|
||||
sammler_norrd
|
||||
sammler.log
|
||||
rrd
|
||||
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autoconfig.h.in
|
||||
autom4te.cache
|
||||
config.guess
|
||||
config.sub
|
||||
configure
|
||||
install-sh
|
||||
ltmain.sh
|
||||
missing
|
||||
|
||||
Makefile
|
||||
autoconfig.h
|
||||
config.log
|
||||
config.status
|
||||
libtool
|
||||
stamp-h1
|
||||
|
||||
.libs
|
||||
autoconfig.h.in~
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
sammler-*.tar.bz2
|
||||
sammler-*.tar.gz
|
||||
|
236
INSTALL
Normal file
236
INSTALL
Normal file
@ -0,0 +1,236 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script). Here is a another example:
|
||||
|
||||
/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
|
||||
configuration-related scripts to be executed by `/bin/bash'.
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
110
Makefile
110
Makefile
@ -1,110 +0,0 @@
|
||||
# Toplevel Makefile
|
||||
WITH_RRD?=yes
|
||||
|
||||
PLUGINS := ctstat diskstat hwmon load memory mount netdev random rtstat stat uptime vmstat
|
||||
#PLUGINS += apache mysql conntrack alixusv ts2 diskstandby hddtemp
|
||||
|
||||
DESTDIR =
|
||||
BINARY_DIR = /usr/local/bin
|
||||
CONFIG_DIR = /usr/local/etc
|
||||
PLUGIN_DIR = /usr/local/lib/sammler
|
||||
DATA_DIR = /var/lib/sammler
|
||||
LOG_DIR = /var/log
|
||||
PID_DIR = /var/run
|
||||
WWW_DIR = /var/www
|
||||
WWW_CONFIG = $(WWW_DIR)/sammler_graph.conf
|
||||
WWW_OWNER = www-data
|
||||
|
||||
# ############################
|
||||
|
||||
SRC := $(wildcard *.c)
|
||||
BUILD_DIR = build
|
||||
CFLAGS = -O2 -g -pipe -Wall -Wno-unused-result -I.
|
||||
CFLAGS += -MMD -MF $(BUILD_DIR)/$(*D)/$(*F).d
|
||||
LDFLAGS = -rdynamic -ldl
|
||||
|
||||
# ############################
|
||||
|
||||
ifeq ("$(WITH_RRD)", "yes")
|
||||
CFLAGS += -DWITH_RRD
|
||||
LDFLAGS_TARGET = -lrrd
|
||||
TARGET = sammler
|
||||
else
|
||||
LDFLAGS_TARGET =
|
||||
TARGET = sammler_norrd
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(wildcard $(DESTDIR)$(CONFIG_DIR)/sammler.conf)),)
|
||||
NEWCONF=sammler.conf
|
||||
else
|
||||
NEWCONF=sammler.conf.dist
|
||||
endif
|
||||
|
||||
# ############################
|
||||
|
||||
all: $(TARGET) plugins
|
||||
|
||||
$(TARGET): $(patsubst %,$(BUILD_DIR)/%, $(SRC:.c=.o))
|
||||
@echo " Linking file: $@"
|
||||
@$(CC) $^ $(LDFLAGS) $(LDFLAGS_TARGET) -o $@
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c $(MAKEFILE_LIST)
|
||||
@echo " Building file: $<"
|
||||
@$(shell test -d $(BUILD_DIR)/$(*D) || mkdir -p $(BUILD_DIR)/$(*D))
|
||||
@$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
.PHONY: plugins
|
||||
plugins: $(PLUGINS:%=plugins/%.so)
|
||||
|
||||
.SECONDARY: $(patsubst %,$(BUILD_DIR)/%, $(PLUGINS:%=plugins/%.o))
|
||||
plugins/%.so: $(BUILD_DIR)/plugins/%.o
|
||||
@echo " Linking file: $@"
|
||||
@$(CC) $(LDFLAGS) -shared -o $@ $<
|
||||
|
||||
plugins/apache.so: $(BUILD_DIR)/plugins/apache.o
|
||||
@echo " Linking file: $@"
|
||||
@$(CC) $(LDFLAGS) -shared -lcurl -o $@ $<
|
||||
|
||||
plugins/conntrack.so: $(BUILD_DIR)/plugins/conntrack.o
|
||||
@echo " Linking file: $@"
|
||||
@$(CC) $(LDFLAGS) -shared -lnfnetlink -lnetfilter_conntrack -o $@ $<
|
||||
|
||||
plugins/mysql.so: $(BUILD_DIR)/plugins/mysql.o $(BUILD_DIR)/plugins/mysql_helper.o
|
||||
@echo " Linking file: $@"
|
||||
@$(CC) $(LDFLAGS) -shared -lmysqlclient -o $@ $^
|
||||
|
||||
plugins/diskstandby.so: $(BUILD_DIR)/plugins/diskstandby.o $(BUILD_DIR)/plugins/sgio.o
|
||||
@echo " Linking file: $@"
|
||||
@$(CC) $(LDFLAGS) -shared -o $@ $^
|
||||
|
||||
install: all
|
||||
install -D -m 755 -s $(TARGET) $(DESTDIR)$(BINARY_DIR)/$(TARGET)
|
||||
install -D -m 644 sammler.conf $(DESTDIR)$(CONFIG_DIR)/$(NEWCONF)
|
||||
sed -i -e "s:^logfile .*$$:logfile $(LOG_DIR)/sammler.log:" \
|
||||
-e "s:^pidfile .*$$:pidfile $(PID_DIR)/sammler.pid:" \
|
||||
-e "s:^rrd_dir .*$$:rrd_dir $(DATA_DIR):" \
|
||||
-e "s:^plugin_dir .*$$:plugin_dir $(PLUGIN_DIR):" \
|
||||
$(DESTDIR)$(CONFIG_DIR)/$(NEWCONF)
|
||||
install -d -m 755 $(DESTDIR)$(PLUGIN_DIR)
|
||||
install -m 755 -s plugins/*.so $(DESTDIR)$(PLUGIN_DIR)
|
||||
install -d -m 755 $(DESTDIR)$(LOG_DIR)
|
||||
|
||||
|
||||
ifeq ("$(WITH_RRD)", "yes")
|
||||
install -d -m 755 $(DESTDIR)$(DATA_DIR)
|
||||
install -D -m 644 sammler.php $(DESTDIR)$(WWW_DIR)/sammler.php
|
||||
sed -i -e "s:%%WWW_CONFIG%%:$(WWW_CONFIG):" \
|
||||
-e "s:%%DATA_DIR%%:$(DATA_DIR)/:" \
|
||||
$(DESTDIR)$(WWW_DIR)/sammler.php
|
||||
ifeq ($(strip $(wildcard $(DESTDIR)$(WWW_CONFIG))),)
|
||||
-install -D -m 644 -o $(WWW_OWNER) /dev/null $(DESTDIR)$(WWW_CONFIG)
|
||||
endif
|
||||
else
|
||||
sed -i -e "s:^forward_only .*$$:forward_only true:" \
|
||||
$(DESTDIR)$(CONFIG_DIR)/$(NEWCONF)
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -rf build plugins/*.so $(TARGET)
|
||||
|
||||
include $(shell find $(BUILD_DIR) -name \*.d 2> /dev/null)
|
59
Makefile.am
Normal file
59
Makefile.am
Normal file
@ -0,0 +1,59 @@
|
||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||
|
||||
EXTRA_DIST = sammler.conf
|
||||
|
||||
AM_CFLAGS = -Wall -Werror
|
||||
|
||||
bin_PROGRAMS = sammler
|
||||
|
||||
sammler_SOURCES = config.c config.h \
|
||||
list.h \
|
||||
logging.c logging.h \
|
||||
plugins.c plugins.h \
|
||||
rrdtool.c rrdtool.h \
|
||||
sammler.c
|
||||
|
||||
sammler_LDADD = -ldl -lrrd
|
||||
sammler_LDFLAGS = -rdynamic
|
||||
|
||||
pkglib_LTLIBRARIES =
|
||||
|
||||
pkglib_LTLIBRARIES += p_ctstat.la
|
||||
p_ctstat_la_SOURCES = p_ctstat.c
|
||||
p_ctstat_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_load.la
|
||||
p_load_la_SOURCES = p_load.c
|
||||
p_load_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_memory.la
|
||||
p_memory_la_SOURCES = p_memory.c
|
||||
p_memory_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_mount.la
|
||||
p_mount_la_SOURCES = p_mount.c
|
||||
p_mount_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_netdev.la
|
||||
p_netdev_la_SOURCES = p_netdev.c
|
||||
p_netdev_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_random.la
|
||||
p_random_la_SOURCES = p_random.c
|
||||
p_random_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_rtstat.la
|
||||
p_rtstat_la_SOURCES = p_rtstat.c
|
||||
p_rtstat_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_stat.la
|
||||
p_stat_la_SOURCES = p_stat.c
|
||||
p_stat_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_uptime.la
|
||||
p_uptime_la_SOURCES = p_uptime.c
|
||||
p_uptime_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
pkglib_LTLIBRARIES += p_vmstat.la
|
||||
p_vmstat_la_SOURCES = p_vmstat.c
|
||||
p_vmstat_la_LDFLAGS = -module -avoid-version
|
7
autobuild.sh
Executable file
7
autobuild.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#! /bin/sh
|
||||
|
||||
autoheader \
|
||||
&& aclocal \
|
||||
&& libtoolize --copy --force \
|
||||
&& automake --add-missing --copy \
|
||||
&& autoconf
|
182
config.c
Normal file
182
config.c
Normal file
@ -0,0 +1,182 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 06/2006 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "logging.h"
|
||||
|
||||
static LIST_HEAD(config_list);
|
||||
|
||||
static struct conf_section * config_add_section(char *name)
|
||||
{
|
||||
struct conf_section *section;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
section = malloc(sizeof(struct conf_section));
|
||||
if (section) {
|
||||
INIT_LIST_HEAD(§ion->list);
|
||||
INIT_LIST_HEAD(§ion->tupel);
|
||||
|
||||
strncpy(section->name, name, sizeof(section->name));
|
||||
list_add_tail(§ion->list, &config_list);
|
||||
}
|
||||
return section;
|
||||
}
|
||||
|
||||
static int config_add_tupel(struct conf_section *section, char *option, char *parameter)
|
||||
{
|
||||
struct conf_tupel *tupel;
|
||||
|
||||
if (!section || !option || !parameter)
|
||||
return 0;
|
||||
|
||||
if (!(tupel = malloc(sizeof(struct conf_tupel))))
|
||||
return 0;
|
||||
|
||||
INIT_LIST_HEAD(&tupel->list);
|
||||
|
||||
tupel->option = strdup(option);
|
||||
tupel->parameter = strdup(parameter);
|
||||
|
||||
list_add_tail(&tupel->list, §ion->tupel);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void config_free(void)
|
||||
{
|
||||
struct conf_section *section, *section_tmp;
|
||||
struct conf_tupel *tupel, *tupel_tmp;
|
||||
|
||||
list_for_each_entry_safe(section, section_tmp, &config_list, list) {
|
||||
list_for_each_entry_safe(tupel, tupel_tmp, §ion->tupel, list) {
|
||||
list_del(&tupel->list);
|
||||
free(tupel->option);
|
||||
free(tupel->parameter);
|
||||
free(tupel);
|
||||
}
|
||||
list_del(§ion->list);
|
||||
free(section);
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse(char *config)
|
||||
{
|
||||
struct conf_section *section = NULL;
|
||||
FILE *fz;
|
||||
int i = 0, ret = 1;
|
||||
char *row, *tok, *tok2;
|
||||
|
||||
if (!config)
|
||||
return 0;
|
||||
|
||||
if (!(row = malloc(1024)))
|
||||
return 0;
|
||||
|
||||
if (!(fz = fopen(config, "r"))) {
|
||||
log_print(LOG_ERROR, "config_parse(): %s", config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (fgets(row, 1024, fz)) {
|
||||
i++;
|
||||
|
||||
if (row[0] == '#' || row[0] <= ' ') {
|
||||
continue;
|
||||
|
||||
} else if (row[0] == '[') {
|
||||
tok = strtok(row +1, " ]\n");
|
||||
section = config_add_section(tok);
|
||||
if (!section) {
|
||||
log_print(LOG_WARN, "config_parse(): invalid section in row %d", i);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
|
||||
} else if (!section) {
|
||||
log_print(LOG_WARN, "config_parse(): missing section in row %d", i);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((tok = strtok(row, " \n")) && (tok2 = strtok(NULL, " \n")))
|
||||
if (!config_add_tupel(section, tok, tok2))
|
||||
log_print(LOG_WARN, "config_parse(): invalid row %d", i);
|
||||
}
|
||||
|
||||
fclose(fz);
|
||||
free(row);
|
||||
|
||||
if (atexit(config_free) != 0) {
|
||||
log_print(LOG_ERROR, "config_parse(): atexit()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct conf_section * config_get_section(char *name)
|
||||
{
|
||||
struct conf_section *section;
|
||||
|
||||
list_for_each_entry(section, &config_list, list) {
|
||||
if (!strcmp(section->name, name))
|
||||
return section;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * config_get_parameter(struct conf_section *section, char *option)
|
||||
{
|
||||
struct conf_tupel *tupel;
|
||||
|
||||
list_for_each_entry(tupel, §ion->tupel, list) {
|
||||
if (!strcmp(tupel->option, option))
|
||||
return tupel->parameter;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * config_get_string(char *section, char *option, char *def)
|
||||
{
|
||||
struct conf_section *tmp;
|
||||
char *ret;
|
||||
|
||||
tmp = config_get_section(section);
|
||||
if (tmp && (ret = config_get_parameter(tmp, option)))
|
||||
return ret;
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
int config_get_int(char *section, char *option, int def)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
ret = config_get_string(section, option, NULL);
|
||||
return ret ? atoi(ret) : def;
|
||||
}
|
24
config.h
Normal file
24
config.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
#include "list.h"
|
||||
|
||||
struct conf_section {
|
||||
struct list_head list;
|
||||
char name[32];
|
||||
struct list_head tupel;
|
||||
};
|
||||
|
||||
struct conf_tupel {
|
||||
struct list_head list;
|
||||
char *option;
|
||||
char *parameter;
|
||||
};
|
||||
|
||||
int config_parse(char *config);
|
||||
struct conf_section * config_get_section(char *name);
|
||||
char * config_get_parameter(struct conf_section *section, char *option);
|
||||
char * config_get_string(char *section, char *option, char *def);
|
||||
int config_get_int(char *section, char *option, int def);
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
292
configfile.c
292
configfile.c
@ -1,292 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 03/2010 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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; version 2 of the License *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
struct conf_section {
|
||||
struct list_head list;
|
||||
struct list_head tupel_list;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct conf_tupel {
|
||||
struct list_head list;
|
||||
const char *option;
|
||||
const char *parameter;
|
||||
};
|
||||
|
||||
static LIST_HEAD(config_list);
|
||||
|
||||
static struct conf_section * config_add_section(const char *name)
|
||||
{
|
||||
struct conf_section *section;
|
||||
section = malloc(sizeof(struct conf_section) + strlen(name));
|
||||
if (section == NULL)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(§ion->list);
|
||||
INIT_LIST_HEAD(§ion->tupel_list);
|
||||
|
||||
section->name = strdup(name);
|
||||
if (section->name == NULL) {
|
||||
free(section);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_add_tail(§ion->list, &config_list);
|
||||
return section;
|
||||
}
|
||||
|
||||
static int config_add_tupel(struct conf_section *section, const char *option, const char *parameter)
|
||||
{
|
||||
struct conf_tupel *tupel = malloc(sizeof(struct conf_tupel));
|
||||
if (tupel == NULL)
|
||||
return -1;
|
||||
|
||||
INIT_LIST_HEAD(&tupel->list);
|
||||
tupel->option = strdup(option);
|
||||
tupel->parameter = strdup(parameter);
|
||||
|
||||
if (tupel->option == NULL || tupel->parameter == NULL) {
|
||||
free(tupel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_add_tail(&tupel->list, §ion->tupel_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse(const char *config)
|
||||
{
|
||||
FILE *fz = fopen(config, "r");
|
||||
if (fz == NULL) {
|
||||
log_print(LOG_ERROR, "%s(): failed to open config '%s'", __FUNCTION__, config);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *line = malloc(BUFSIZE);
|
||||
if (line == NULL) {
|
||||
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
|
||||
fclose(fz);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int linenum = 0;
|
||||
struct conf_section *section = NULL;
|
||||
while (fgets(line, BUFSIZE, fz) != NULL) {
|
||||
linenum++;
|
||||
|
||||
if (line[0] == '#' || line[0] <= ' ') {
|
||||
continue;
|
||||
|
||||
} else if (line[0] == '[') {
|
||||
char *tok = strtok(line +1, " ]\n");
|
||||
|
||||
if (tok == NULL || (section = config_add_section(tok)) == NULL) {
|
||||
log_print(LOG_WARN, "%s(): invalid section in row %d", __FUNCTION__, linenum);
|
||||
free(line);
|
||||
fclose(fz);
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
|
||||
} else if (section == NULL) {
|
||||
log_print(LOG_WARN, "%s(): missing section in row %d", __FUNCTION__, linenum);
|
||||
free(line);
|
||||
fclose(fz);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *tmp, *tok = strtok_r(line, " \t\n", &tmp);
|
||||
if (tok != NULL) {
|
||||
char *tok2;
|
||||
while ((tok2 = strtok_r(NULL, " \n", &tmp))) {
|
||||
if (config_add_tupel(section, tok, tok2) != 0)
|
||||
log_print(LOG_WARN, "%s(): invalid row %d", __FUNCTION__, linenum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fz);
|
||||
free(line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void config_free(void)
|
||||
{
|
||||
struct conf_section *section, *section_tmp;
|
||||
struct conf_tupel *tupel, *tupel_tmp;
|
||||
|
||||
list_for_each_entry_safe(section, section_tmp, &config_list, list) {
|
||||
list_for_each_entry_safe(tupel, tupel_tmp, §ion->tupel_list, list) {
|
||||
list_del(&tupel->list);
|
||||
free((char *)tupel->option);
|
||||
free((char *)tupel->parameter);
|
||||
free(tupel);
|
||||
}
|
||||
list_del(§ion->list);
|
||||
free(section);
|
||||
}
|
||||
}
|
||||
|
||||
static struct conf_section * config_get_section(const char *name)
|
||||
{
|
||||
struct conf_section *section;
|
||||
|
||||
list_for_each_entry(section, &config_list, list) {
|
||||
if (!strcmp(section->name, name))
|
||||
return section;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * config_get_string(const char *section_str, const char *option, const char *def)
|
||||
{
|
||||
struct conf_section *section = config_get_section(section_str);
|
||||
if (section != NULL) {
|
||||
struct conf_tupel *tupel;
|
||||
list_for_each_entry(tupel, §ion->tupel_list, list) {
|
||||
if (!strcmp(tupel->option, option))
|
||||
return tupel->parameter;
|
||||
}
|
||||
}
|
||||
|
||||
if (def != NULL)
|
||||
log_print(LOG_WARN, "config [%s:%s] not found, using default: '%s'",
|
||||
section_str, option, def);
|
||||
return def;
|
||||
}
|
||||
|
||||
int config_get_int(const char *section, const char *option, int *value, int def)
|
||||
{
|
||||
const char *ret = config_get_string(section, option, NULL);
|
||||
if (ret == NULL) {
|
||||
log_print(LOG_WARN, "config [%s:%s] not found, using default: '%d'",
|
||||
section, option, def);
|
||||
|
||||
*value = def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *tmp;
|
||||
*value = strtol(ret, &tmp, 0);
|
||||
|
||||
if (*tmp != '\0' && !isspace(*tmp)) {
|
||||
log_print(LOG_WARN, "config [%s:%s] not an integer: '%s', using default '%d'",
|
||||
section, option, ret, def);
|
||||
|
||||
*value = def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_get_strings(const char *section_str, const char *option,
|
||||
int (*callback)(const char *value, void *privdata),
|
||||
void *privdata)
|
||||
{
|
||||
struct conf_section *section = config_get_section(section_str);
|
||||
if (section == NULL)
|
||||
return -1;
|
||||
|
||||
int cnt = 0;
|
||||
struct conf_tupel *tupel;
|
||||
list_for_each_entry(tupel, §ion->tupel_list, list) {
|
||||
if (!strcmp(tupel->option, option))
|
||||
if (callback(tupel->parameter, privdata) == 0)
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
struct strtoken * strtokenize(const char *input, const char *delim, int maxfields)
|
||||
{
|
||||
struct strtoken *tokens = malloc(sizeof(struct strtoken) +
|
||||
(maxfields +1) * sizeof(char *) +
|
||||
strlen(input));
|
||||
if (tokens == NULL)
|
||||
return NULL;
|
||||
|
||||
char *ptr = (char *)&tokens->field[maxfields];
|
||||
strcpy(ptr, input);
|
||||
|
||||
tokens->input = input;
|
||||
tokens->delim = delim;
|
||||
tokens->maxfields = maxfields;
|
||||
|
||||
int i;
|
||||
char *tmp;
|
||||
|
||||
tokens->count = 0;
|
||||
for (i = 0; i < maxfields; i++) {
|
||||
tokens->field[i] = strtok_r(ptr, delim, &tmp);
|
||||
ptr = NULL;
|
||||
|
||||
if (tokens->field[i] != NULL)
|
||||
tokens->count++;
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
struct strtoken * config_get_strtoken(const char *section, const char *option, const char *delim, int maxfields)
|
||||
{
|
||||
const char *ret = config_get_string(section, option, NULL);
|
||||
if (ret == NULL) {
|
||||
log_print(LOG_WARN, "config [%s:%s] not found", section, option);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return strtokenize(ret, delim, maxfields);
|
||||
}
|
||||
|
||||
int config_get_strtokens(const char *section_str, const char *option, const char *delim, int maxfields,
|
||||
int (*callback)(struct strtoken *data, void *privdata),
|
||||
void *privdata)
|
||||
{
|
||||
struct conf_section *section = config_get_section(section_str);
|
||||
if (section == NULL)
|
||||
return -1;
|
||||
|
||||
int cnt = 0;
|
||||
struct conf_tupel *tupel;
|
||||
list_for_each_entry(tupel, §ion->tupel_list, list) {
|
||||
if (!strcmp(tupel->option, option)) {
|
||||
struct strtoken *tokens = strtokenize(tupel->parameter, delim, maxfields);
|
||||
if (tokens != NULL) {
|
||||
if (callback(tokens, privdata) == 0)
|
||||
cnt++;
|
||||
|
||||
free(tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
31
configfile.h
31
configfile.h
@ -1,31 +0,0 @@
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
int config_parse(const char *config);
|
||||
void config_free(void);
|
||||
|
||||
const char * config_get_string(const char *section_str, const char *option, const char *def);
|
||||
|
||||
int config_get_int(const char *section, const char *option, int *value, int def);
|
||||
|
||||
int config_get_strings(const char *section_str, const char *option,
|
||||
int (*callback)(const char *value, void *privdata),
|
||||
void *privdata);
|
||||
|
||||
struct strtoken {
|
||||
const char *input;
|
||||
const char *delim;
|
||||
int maxfields;
|
||||
int count;
|
||||
char *field[0];
|
||||
};
|
||||
|
||||
struct strtoken * strtokenize(const char *input, const char *delim, int maxfields);
|
||||
|
||||
struct strtoken * config_get_strtoken(const char *section_str, const char *option, const char *delim, int maxfields);
|
||||
|
||||
int config_get_strtokens(const char *section_str, const char *option, const char *delim, int maxfields,
|
||||
int (*callback)(struct strtoken *tokens, void *privdata),
|
||||
void *privdata);
|
||||
|
||||
#endif /* _CONFIG_H_ */
|
21
configure.in
Normal file
21
configure.in
Normal file
@ -0,0 +1,21 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(sammler, 0.00)
|
||||
AC_CONFIG_SRCDIR(sammler.c)
|
||||
AC_CONFIG_HEADER(autoconfig.h)
|
||||
AM_INIT_AUTOMAKE(dist-bzip2)
|
||||
AC_LANG(C)
|
||||
|
||||
AC_PREFIX_DEFAULT("/usr/local")
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
AM_CONDITIONAL(COMPILER_IS_GCC, test "x$GCC" = "xyes")
|
||||
|
||||
dnl configure libtool
|
||||
AC_DISABLE_STATIC
|
||||
AC_LIBTOOL_DLOPEN
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_OUTPUT(Makefile)
|
331
event.c
331
event.c
@ -1,331 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 03/2010 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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; version 2 of the License *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
|
||||
#include "event.h"
|
||||
|
||||
static LIST_HEAD(event_fd_list);
|
||||
static LIST_HEAD(event_timeout_list);
|
||||
|
||||
struct event_fd {
|
||||
struct list_head list;
|
||||
unsigned int flags;
|
||||
int fd;
|
||||
int (*read_cb)(int fd, void *privdata);
|
||||
int (*write_cb)(int fd, void *privdata);
|
||||
void *read_priv;
|
||||
void *write_priv;
|
||||
};
|
||||
|
||||
struct event_timeout {
|
||||
struct list_head list;
|
||||
unsigned int flags;
|
||||
struct timeval intervall;
|
||||
struct timeval nextrun;
|
||||
int (*callback)(int timerid, void *privdata);
|
||||
int timerid;
|
||||
void *privdata;
|
||||
};
|
||||
|
||||
struct event_fd * event_add_fd(
|
||||
struct event_fd *entry,
|
||||
int fd,
|
||||
int type,
|
||||
int (*callback)(int fd, void *privdata),
|
||||
void *privdata)
|
||||
{
|
||||
/* check valid filediskriptor */
|
||||
if (fd < 0 || fd > FD_SETSIZE) {
|
||||
log_print(LOG_ERROR, "%s(): invalid fd", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* check valid type (read/write) */
|
||||
if (!(type & FD_TYPES)) {
|
||||
log_print(LOG_ERROR, "%s(): invalid type", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create new entry */
|
||||
if (entry == NULL) {
|
||||
entry = malloc(sizeof(struct event_fd));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(entry, 0, sizeof(struct event_fd));
|
||||
entry->flags |= EVENT_NEW;
|
||||
entry->fd = fd;
|
||||
|
||||
/* put it on the list */
|
||||
list_add_tail(&entry->list, &event_fd_list);
|
||||
}
|
||||
|
||||
if (type & FD_READ) {
|
||||
entry->flags = (callback != NULL) ? (entry->flags | FD_READ | EVENT_NEW) : (entry->flags & ~FD_READ);
|
||||
entry->read_cb = callback;
|
||||
entry->read_priv = privdata;
|
||||
|
||||
} else if (type & FD_WRITE) {
|
||||
entry->flags = (callback != NULL) ? (entry->flags | FD_WRITE | EVENT_NEW) : (entry->flags & ~FD_WRITE);
|
||||
entry->write_cb = callback;
|
||||
entry->write_priv = privdata;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
int event_get_fd(struct event_fd *entry)
|
||||
{
|
||||
return (entry != NULL) ? entry->fd: -1;
|
||||
}
|
||||
|
||||
void event_remove_fd(struct event_fd *entry)
|
||||
{
|
||||
/* mark the event as deleted -> remove in select() loop */
|
||||
entry->flags |= EVENT_DELETE;
|
||||
}
|
||||
|
||||
static void add_timeval(struct timeval *ret, struct timeval *a, struct timeval *b)
|
||||
{
|
||||
ret->tv_usec = a->tv_usec + b->tv_usec;
|
||||
ret->tv_sec = a->tv_sec + b->tv_sec;
|
||||
|
||||
if (ret->tv_usec >= 1000000) {
|
||||
ret->tv_usec -= 1000000;
|
||||
ret->tv_sec++;
|
||||
}
|
||||
}
|
||||
|
||||
static void sub_timeval(struct timeval *ret, struct timeval *a, struct timeval *b)
|
||||
{
|
||||
ret->tv_usec = a->tv_usec - b->tv_usec;
|
||||
ret->tv_sec = a->tv_sec - b->tv_sec;
|
||||
|
||||
if (ret->tv_usec < 0) {
|
||||
ret->tv_usec += 1000000;
|
||||
ret->tv_sec--;
|
||||
}
|
||||
}
|
||||
|
||||
static int cmp_timeval(struct timeval *a, struct timeval *b)
|
||||
{
|
||||
if (a->tv_sec > b->tv_sec)
|
||||
return -1;
|
||||
|
||||
if (a->tv_sec < b->tv_sec)
|
||||
return 1;
|
||||
|
||||
if (a->tv_usec > b->tv_usec)
|
||||
return -1;
|
||||
|
||||
if (a->tv_usec < b->tv_usec)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void schedule_nextrun(struct event_timeout *entry, struct timeval *now)
|
||||
{
|
||||
add_timeval(&entry->nextrun, now, &entry->intervall);
|
||||
|
||||
struct event_timeout *search;
|
||||
list_for_each_entry(search, &event_timeout_list, list) {
|
||||
if (search->nextrun.tv_sec > entry->nextrun.tv_sec) {
|
||||
list_add_tail(&entry->list, &search->list);
|
||||
return;
|
||||
|
||||
} else if (search->nextrun.tv_sec == entry->nextrun.tv_sec &&
|
||||
search->nextrun.tv_usec > entry->nextrun.tv_usec) {
|
||||
list_add_tail(&entry->list, &search->list);
|
||||
return;
|
||||
}
|
||||
}
|
||||
list_add_tail(&entry->list, &event_timeout_list);
|
||||
}
|
||||
|
||||
struct event_timeout * event_add_timeout(
|
||||
struct timeval *timeout,
|
||||
int (*callback)(int timerid, void *privdata),
|
||||
int timerid,
|
||||
void *privdata)
|
||||
{
|
||||
struct event_timeout *entry;
|
||||
entry = malloc(sizeof(struct event_timeout));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry->flags = 0;
|
||||
memcpy(&entry->intervall, timeout, sizeof(entry->intervall));
|
||||
entry->callback = callback;
|
||||
entry->timerid = timerid;
|
||||
entry->privdata = privdata;
|
||||
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
schedule_nextrun(entry, &now);
|
||||
return entry;
|
||||
}
|
||||
|
||||
struct event_timeout * event_add_timeout_ms(
|
||||
int timeout_ms,
|
||||
int (*callback)(int timerid, void *privdata),
|
||||
int timerid,
|
||||
void *privdata)
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeout_ms / 1000;
|
||||
tv.tv_usec = (timeout_ms % 1000) * 1000;
|
||||
|
||||
return event_add_timeout(&tv, callback, timerid, privdata);
|
||||
}
|
||||
|
||||
void event_remove_timeout(struct event_timeout *entry)
|
||||
{
|
||||
/* mark the event as deleted -> remove in select() loop */
|
||||
entry->flags |= EVENT_DELETE;
|
||||
}
|
||||
|
||||
int event_loop(int (*pre_select_cb)(int *maxfd, void *readfds, void *writefds, struct timeval *timeout, void *privdata),
|
||||
int (*post_select_cb)(int retval, void *readfds, void *writefds, void *privdata),
|
||||
void *privdata)
|
||||
{
|
||||
while (1) {
|
||||
/* default value if no application timeout is present */
|
||||
struct timeval timeout = {
|
||||
.tv_sec = -1,
|
||||
.tv_usec = -1,
|
||||
};
|
||||
|
||||
if (!list_empty(&event_timeout_list)) {
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
struct event_timeout *entry, *tmp;
|
||||
list_for_each_entry_safe(entry, tmp, &event_timeout_list, list) {
|
||||
if (entry->flags & EVENT_DELETE) {
|
||||
list_del(&entry->list);
|
||||
free(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* first timeout not elapsed, exit search (since list is sorted) */
|
||||
if (cmp_timeval(&entry->nextrun, &now) == -1)
|
||||
break;
|
||||
|
||||
/* remove event from list */
|
||||
list_del(&entry->list);
|
||||
|
||||
/* execute callback, when callback returns 0 -> schedule event again */
|
||||
if (entry->callback(entry->timerid, entry->privdata)) {
|
||||
free(entry);
|
||||
|
||||
} else {
|
||||
schedule_nextrun(entry, &now);
|
||||
}
|
||||
}
|
||||
|
||||
if (!list_empty(&event_timeout_list)) {
|
||||
entry = list_entry(event_timeout_list.next, typeof(*entry), list);
|
||||
|
||||
/* calc select() timeout */
|
||||
sub_timeval(&timeout, &entry->nextrun, &now);
|
||||
}
|
||||
}
|
||||
|
||||
struct event_fd *entry, *tmp;
|
||||
int maxfd = -1;
|
||||
|
||||
fd_set readfds, writefds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_ZERO(&writefds);
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &event_fd_list, list) {
|
||||
entry->flags &= ~EVENT_NEW;
|
||||
|
||||
if (entry->flags & EVENT_DELETE) {
|
||||
list_del(&entry->list);
|
||||
free(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry->flags & FD_READ)
|
||||
FD_SET(entry->fd, &readfds);
|
||||
|
||||
if (entry->flags & FD_WRITE)
|
||||
FD_SET(entry->fd, &writefds);
|
||||
|
||||
maxfd = (entry->fd > maxfd) ? entry->fd : maxfd;
|
||||
}
|
||||
|
||||
maxfd++;
|
||||
|
||||
/* exit loop if callback returns true */
|
||||
if (pre_select_cb != NULL && pre_select_cb(&maxfd, (void *)&readfds, (void *)&writefds, &timeout, privdata) != 0)
|
||||
break;
|
||||
|
||||
int retval;
|
||||
if (timeout.tv_sec == -1 && timeout.tv_usec == -1)
|
||||
retval = select(maxfd, &readfds, &writefds, NULL, NULL);
|
||||
else
|
||||
retval = select(maxfd, &readfds, &writefds, NULL, &timeout);
|
||||
|
||||
/* exit loop if callback returns true */
|
||||
if (post_select_cb != NULL && post_select_cb(retval, (void *)&readfds, (void *)&writefds, privdata) != 0)
|
||||
break;
|
||||
|
||||
if (retval < 0 && errno == EINTR) {
|
||||
errno = 0;
|
||||
continue;
|
||||
|
||||
} else if (retval < 0) {
|
||||
log_print(LOG_ERROR, "%s(): select():", __FUNCTION__);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* timeout */
|
||||
if (retval == 0)
|
||||
continue;
|
||||
|
||||
list_for_each_entry(entry, &event_fd_list, list) {
|
||||
if (((entry->flags & (FD_READ | EVENT_NEW)) == FD_READ) && FD_ISSET(entry->fd, &readfds))
|
||||
if (entry->read_cb(entry->fd, entry->read_priv) != 0)
|
||||
entry->flags |= EVENT_DELETE;
|
||||
|
||||
if (((entry->flags & (FD_WRITE | EVENT_NEW)) == FD_WRITE) && FD_ISSET(entry->fd, &writefds))
|
||||
if (entry->write_cb(entry->fd, entry->write_priv) != 0)
|
||||
entry->flags |= EVENT_DELETE;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
51
event.h
51
event.h
@ -1,51 +0,0 @@
|
||||
#ifndef _EVENT_H_
|
||||
#define _EVENT_H_
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#define EVENT_NEW 0x1000
|
||||
#define EVENT_DELETE 0x2000
|
||||
|
||||
#define FD_READ 0x0001
|
||||
#define FD_WRITE 0x0002
|
||||
#define FD_TYPES (FD_READ | FD_WRITE)
|
||||
|
||||
#define event_add_readfd(entry, fd, callback, privdata) \
|
||||
event_add_fd(entry, fd, FD_READ, callback, privdata)
|
||||
|
||||
#define event_add_writefd(entry, fd, callback, privdata) \
|
||||
event_add_fd(entry, fd, FD_WRITE, callback, privdata)
|
||||
|
||||
/* inner details are not visible to external users (TODO: size unknown) */
|
||||
struct event_fd;
|
||||
struct event_timeout;
|
||||
|
||||
struct event_fd * event_add_fd(
|
||||
struct event_fd *entry,
|
||||
int fd,
|
||||
int type,
|
||||
int (*callback)(int fd, void *privdata),
|
||||
void *privdata);
|
||||
|
||||
int event_get_fd(struct event_fd *entry);
|
||||
void event_remove_fd(struct event_fd *entry);
|
||||
|
||||
struct event_timeout * event_add_timeout(
|
||||
struct timeval *timeout,
|
||||
int (*callback)(int timerid, void *privdata),
|
||||
int timerid,
|
||||
void *privdata);
|
||||
|
||||
struct event_timeout * event_add_timeout_ms(
|
||||
int timeout_ms,
|
||||
int (*callback)(int timerid, void *privdata),
|
||||
int timerid,
|
||||
void *privdata);
|
||||
|
||||
void event_remove_timeout(struct event_timeout *entry);
|
||||
|
||||
int event_loop(int (*pre_select_cb)(int *maxfd, void *readfds, void *writefds, struct timeval *timeout, void *privdata),
|
||||
int (*post_select_cb)(int retval, void *readfds, void *writefds, void *privdata),
|
||||
void *privdata);
|
||||
|
||||
#endif /* _EVENT_H_ */
|
37
helper.c
37
helper.c
@ -1,37 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 10/2006 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int strsplit(char *string, char *delim, char **fields, int size)
|
||||
{
|
||||
int i = 0;
|
||||
char *tmp, *ptr = string;
|
||||
|
||||
while ((fields[i] = strtok_r(ptr, delim, &tmp)) != NULL) {
|
||||
ptr = NULL;
|
||||
i++;
|
||||
|
||||
if (i >= size)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
8
helper.h
8
helper.h
@ -1,8 +0,0 @@
|
||||
#ifndef _HELPER_H_
|
||||
#define _HELPER_H_
|
||||
|
||||
#define DFLT_DELIM " \n\t"
|
||||
|
||||
int strsplit(char *string, char *delim, char **fields, int size);
|
||||
|
||||
#endif /* _HELPER_H_ */
|
239
linebuffer.c
239
linebuffer.c
@ -1,239 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 03/2010 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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; version 2 of the License *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "linebuffer.h"
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
struct lbuf {
|
||||
size_t size;
|
||||
size_t pos;
|
||||
|
||||
char *token;
|
||||
char data[0];
|
||||
};
|
||||
|
||||
/*
|
||||
* creates linebuffer with given size
|
||||
*/
|
||||
struct lbuf * lbuf_create(size_t size)
|
||||
{
|
||||
struct lbuf *buf = malloc(sizeof(struct lbuf) + size);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
buf->size = size;
|
||||
buf->pos = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* frees the linebuffer and all data in it
|
||||
*/
|
||||
void lbuf_free(struct lbuf *buf)
|
||||
{
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* clears the linebuffer
|
||||
* - returns the datasize it was holding
|
||||
*/
|
||||
int lbuf_clear(struct lbuf *buf)
|
||||
{
|
||||
int oldpos = buf->pos;
|
||||
buf->pos = 0;
|
||||
return oldpos;
|
||||
}
|
||||
|
||||
/*
|
||||
* get pointer to internal data
|
||||
* - returns pointer to datasize
|
||||
*/
|
||||
char * lbuf_getdata(struct lbuf *buf, size_t *len)
|
||||
{
|
||||
if (len != NULL)
|
||||
*len = buf->pos;
|
||||
|
||||
return buf->data;
|
||||
}
|
||||
|
||||
/*
|
||||
* appends data to the buffer
|
||||
* - returns the number of bytes copied
|
||||
*/
|
||||
int lbuf_append(struct lbuf *buf, const char *src, size_t size)
|
||||
{
|
||||
int len = MIN(buf->size - buf->pos, size);
|
||||
memcpy(buf->data + buf->pos, src, len);
|
||||
buf->pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* reads as much data as it can get from a FD
|
||||
* - returns the number of bytes read, or -1 on error
|
||||
*/
|
||||
int lbuf_readfd(struct lbuf *buf, int fd)
|
||||
{
|
||||
int len = read(fd, buf->data + buf->pos, buf->size - buf->pos);
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
|
||||
buf->pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* parses as much data as it can get from a FD
|
||||
* parses means: backspaces remove one byte from the end of the buffer
|
||||
* - returns 0 on success, or -1 on error
|
||||
*/
|
||||
int lbuf_parsefd(struct lbuf *buf, int fd)
|
||||
{
|
||||
char tmp[32];
|
||||
int len = read(fd, tmp, sizeof(tmp));
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
/* "understand" backspace */
|
||||
if (tmp[i] == 0x08 && buf->pos > 0) {
|
||||
buf->pos--;
|
||||
|
||||
/* copy */
|
||||
} else if (tmp[i] >= ' ' || tmp[i] == '\n') {
|
||||
*(buf->data + buf->pos++) = tmp[i];
|
||||
}
|
||||
|
||||
if (buf->pos > buf->size)
|
||||
return -1;
|
||||
}
|
||||
/* TODO: return bytes appended to buffer? */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* writes as much data as it can to a FD
|
||||
* - returns the number of bytes written, or -1 on error
|
||||
*/
|
||||
int lbuf_writefd(struct lbuf *buf, int fd)
|
||||
{
|
||||
int len = write(fd, buf->data, buf->pos);
|
||||
if (len <= 0)
|
||||
return -1;
|
||||
|
||||
/* handle partial writes */
|
||||
if (len != buf->pos)
|
||||
memmove(buf->data, buf->data + len, buf->pos - len);
|
||||
|
||||
buf->pos -= len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* append va_list to buffer
|
||||
* - returns number ob bytes appended, or -1 on error
|
||||
*/
|
||||
int lbuf_vprintf(struct lbuf *buf, const char *fmt, va_list az)
|
||||
{
|
||||
int len = vsnprintf(buf->data + buf->pos, buf->size - buf->pos, fmt, az);
|
||||
if (len < 0 || len >= (buf->size - buf->pos))
|
||||
return -1;
|
||||
|
||||
buf->pos += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* printf into buffer
|
||||
* - returns number of bytes appended, or -1 on error
|
||||
*/
|
||||
int lbuf_printf(struct lbuf *buf, const char *fmt, ...)
|
||||
{
|
||||
va_list az;
|
||||
|
||||
va_start(az, fmt);
|
||||
int ret = lbuf_vprintf(buf, fmt, az);
|
||||
va_end(az);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* get next non-empty token
|
||||
* - returns pointer to next token
|
||||
* - returns NULL if no delimter is found in buffer
|
||||
*/
|
||||
char * lbuf_gettok(struct lbuf *buf, const char *delim)
|
||||
{
|
||||
char *start = buf->data;
|
||||
char *end = buf->data + buf->pos;
|
||||
int dlen = strlen(delim);
|
||||
|
||||
while (1) {
|
||||
buf->token = NULL;
|
||||
|
||||
/* find first delimiter in buffer */
|
||||
int i;
|
||||
for (i = 0; i < dlen; i++) {
|
||||
char *tok = memchr(start, delim[i], end - start);
|
||||
if (tok != NULL && (tok < buf->token || buf->token == NULL))
|
||||
buf->token = tok;
|
||||
}
|
||||
|
||||
/* nothing found */
|
||||
if (buf->token == NULL)
|
||||
return NULL;
|
||||
|
||||
/* delimter found on start pos -> skip empty token */
|
||||
if (buf->token == start) {
|
||||
start++;
|
||||
if (start >= end)
|
||||
return NULL;
|
||||
} else {
|
||||
/* non-empty token found, exit */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* overwrite token, return start ptr */
|
||||
*(buf->token) = '\0';
|
||||
return start;
|
||||
}
|
||||
|
||||
/*
|
||||
* release previous fetched line
|
||||
* - returns number of remaining bytes in buffer
|
||||
*/
|
||||
int lbuf_freetok(struct lbuf *buf)
|
||||
{
|
||||
if (buf->token != NULL) {
|
||||
buf->pos -= (buf->token - buf->data) +1;
|
||||
memmove(buf->data, buf->token +1, buf->pos);
|
||||
buf->token = NULL;
|
||||
}
|
||||
return buf->pos;
|
||||
}
|
27
linebuffer.h
27
linebuffer.h
@ -1,27 +0,0 @@
|
||||
#ifndef _LINEBUFFER_H_
|
||||
#define _LINEBUFFER_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/* hide details */
|
||||
struct lbuf;
|
||||
|
||||
struct lbuf * lbuf_create(size_t size);
|
||||
void lbuf_free(struct lbuf *buf);
|
||||
|
||||
int lbuf_clear(struct lbuf *buf);
|
||||
|
||||
int lbuf_readfd(struct lbuf *buf, int fd);
|
||||
int lbuf_parsefd(struct lbuf *buf, int fd);
|
||||
int lbuf_writefd(struct lbuf *buf, int fd);
|
||||
|
||||
char * lbuf_getdata(struct lbuf *buf, size_t *len);
|
||||
|
||||
int lbuf_append(struct lbuf *buf, const char *src, size_t size);
|
||||
int lbuf_vprintf(struct lbuf *buf, const char *fmt, va_list ap);
|
||||
int lbuf_printf(struct lbuf *buf, const char *fmt, ...);
|
||||
|
||||
char * lbuf_gettok(struct lbuf *buf, const char *delim);
|
||||
int lbuf_freetok(struct lbuf *buf);
|
||||
|
||||
#endif /* _LINEBUFFER_H_ */
|
98
logging.c
98
logging.c
@ -1,10 +1,11 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 07/2007 by Olaf Rempel *
|
||||
* Copyright (C) 06/2006 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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; version 2 of the License *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
@ -18,98 +19,85 @@
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
#define BUFSIZE 8192
|
||||
|
||||
static FILE *log_file = NULL;
|
||||
static int log_prio = LOG_EVERYTIME;
|
||||
static FILE *log_fd = NULL;
|
||||
static char *buffer = NULL;
|
||||
|
||||
int log_print(int prio, const char *fmt, ...)
|
||||
void log_print(int prio, const char *fmt, ...)
|
||||
{
|
||||
va_list az;
|
||||
int len = 0, retval;
|
||||
|
||||
if (prio < log_prio)
|
||||
return 0;
|
||||
int len;
|
||||
|
||||
if (buffer == NULL) {
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
fprintf(stderr, "%s(): out of memory\n", __FUNCTION__);
|
||||
return -1;
|
||||
fprintf(stderr, "log_print: out of memory\nBailing out!\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (log_file != NULL) {
|
||||
time_t tzgr;
|
||||
time(&tzgr);
|
||||
|
||||
len += strftime(buffer, BUFSIZE, "%b %d %H:%M:%S :", localtime(&tzgr));
|
||||
}
|
||||
|
||||
va_start(az, fmt);
|
||||
len += vsnprintf(buffer + len, BUFSIZE - len, fmt, az);
|
||||
len = vsnprintf(buffer, BUFSIZE, fmt, az);
|
||||
va_end(az);
|
||||
|
||||
if (len < 0 || len >= BUFSIZE) {
|
||||
log_print(LOG_ERROR, "log_print: arguments too long");
|
||||
errno = 0;
|
||||
return log_print(LOG_ERROR, "%s: arguments too long", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (errno) {
|
||||
len += snprintf(buffer + len, BUFSIZE - len, ": %s", strerror(errno));
|
||||
errno = 0;
|
||||
strncpy(buffer + len, ": ", BUFSIZE - len);
|
||||
len += 2;
|
||||
strncpy(buffer + len, strerror(errno), BUFSIZE - len);
|
||||
}
|
||||
|
||||
retval = fprintf((log_file ? log_file : stderr), "%s\n", buffer);
|
||||
fflush(log_file);
|
||||
return retval;
|
||||
if (log_fd) {
|
||||
char tbuf[64];
|
||||
time_t tzgr;
|
||||
|
||||
time(&tzgr);
|
||||
strftime(tbuf, sizeof(tbuf), "%b %d %H:%M:%S :", localtime(&tzgr));
|
||||
|
||||
fprintf(log_fd, "%s %s\n", tbuf, buffer);
|
||||
fflush(log_fd);
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s\n", buffer);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
void log_close(void)
|
||||
static void log_close(void)
|
||||
{
|
||||
if (buffer) {
|
||||
if (buffer)
|
||||
free(buffer);
|
||||
buffer = NULL;
|
||||
}
|
||||
|
||||
if (log_file) {
|
||||
fclose(log_file);
|
||||
log_file = NULL;
|
||||
}
|
||||
fclose(log_fd);
|
||||
}
|
||||
|
||||
int log_init(const char *logfile)
|
||||
int log_init(char *logfile)
|
||||
{
|
||||
if (log_file != NULL)
|
||||
log_close();
|
||||
|
||||
log_file = fopen(logfile, "a");
|
||||
if (log_file == NULL) {
|
||||
fprintf(stderr, "%s(): can not open logfile", __FUNCTION__);
|
||||
return -1;
|
||||
log_fd = fopen(logfile, "a");
|
||||
if (log_fd == NULL) {
|
||||
log_print(LOG_ERROR, "log_open('%s'): %s", logfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fcntl(fileno(log_file), F_SETFD, FD_CLOEXEC) < 0) {
|
||||
fprintf(stderr, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
|
||||
fclose(log_file);
|
||||
return -1;
|
||||
if (atexit(log_close) != 0) {
|
||||
log_print(LOG_ERROR, "log_open(): atexit()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_prio = LOG_EVERYTIME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void log_setprio(int prio)
|
||||
{
|
||||
log_prio = prio;
|
||||
log_print(LOG_EVERYTIME, "==========================");
|
||||
return 1;
|
||||
}
|
||||
|
25
logging.h
25
logging.h
@ -1,23 +1,16 @@
|
||||
#ifndef _LOGGING_H_
|
||||
#define _LOGGING_H_
|
||||
|
||||
#define LOG_EMERG 0 /* system is unusable */
|
||||
#define LOG_ALERT 1 /* action must be taken immediately */
|
||||
#define LOG_CRIT 2 /* critical conditions */
|
||||
#define LOG_ERR 3 /* error conditions */
|
||||
#define LOG_WARNING 4 /* warning conditions */
|
||||
#define LOG_NOTICE 5 /* normal but significant condition */
|
||||
#define LOG_INFO 6 /* informational */
|
||||
#define LOG_DEBUG 7 /* debug-level messages */
|
||||
#define LOG_DEBUG 5
|
||||
#define LOG_INFO 4
|
||||
#define LOG_NOTICE 3
|
||||
#define LOG_WARN 2
|
||||
#define LOG_ERROR 1
|
||||
#define LOG_CRIT 0
|
||||
|
||||
#define LOG_EVERYTIME LOG_EMERG
|
||||
#define LOG_ERROR LOG_ERR
|
||||
#define LOG_WARN LOG_WARNING
|
||||
#define LOG_EVERYTIME 0
|
||||
|
||||
int log_init(const char *logfile);
|
||||
void log_close(void);
|
||||
void log_setprio(int prio);
|
||||
|
||||
int log_print(int prio, const char *fmt, ... );
|
||||
int log_init(char *logfile);
|
||||
void log_print(int prio, const char *fmt, ... );
|
||||
|
||||
#endif /* _LOGGING_H_ */
|
||||
|
206
network.c
206
network.c
@ -1,206 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "event.h"
|
||||
#include "helper.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
#include "network.h"
|
||||
#include "plugins.h"
|
||||
#include "rrdtool.h"
|
||||
#include "sockaddr.h"
|
||||
|
||||
#define PKTSIZE 1400
|
||||
|
||||
struct net_entry {
|
||||
struct list_head list;
|
||||
struct event_fd *event;
|
||||
struct sockaddr_in addr;
|
||||
int socket;
|
||||
};
|
||||
|
||||
static LIST_HEAD(srv_list);
|
||||
static LIST_HEAD(cli_list);
|
||||
|
||||
static char *fwd_buf;
|
||||
static int fwd_buf_len;
|
||||
|
||||
void net_submit_flush(void)
|
||||
{
|
||||
if (fwd_buf_len == 0)
|
||||
return;
|
||||
|
||||
struct net_entry *entry;
|
||||
list_for_each_entry(entry, &cli_list, list)
|
||||
sendto(entry->socket, fwd_buf, fwd_buf_len, 0, (struct sockaddr *)&entry->addr, sizeof(entry->addr));
|
||||
|
||||
fwd_buf_len = 0;
|
||||
}
|
||||
|
||||
int net_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data)
|
||||
{
|
||||
if (list_empty(&cli_list))
|
||||
return 0;
|
||||
|
||||
int size = snprintf(fwd_buf + fwd_buf_len, PKTSIZE - fwd_buf_len, "%s:%s:%s:%d %s\n",
|
||||
hostname, pluginname, filename, ds_id, data);
|
||||
|
||||
if (size < 0 || size >= PKTSIZE - fwd_buf_len) {
|
||||
/* the complete buffer is already full */
|
||||
if (fwd_buf_len == 0) {
|
||||
log_print(LOG_ERROR, "net_submit(): arguments too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* flush & retry */
|
||||
net_submit_flush();
|
||||
return net_submit(hostname, pluginname, filename, ds_id, data);
|
||||
}
|
||||
|
||||
fwd_buf_len += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_receive(int socket, void *privdata)
|
||||
{
|
||||
int recvsize;
|
||||
if (ioctl(socket, FIONREAD, &recvsize) == -1) {
|
||||
log_print(LOG_WARN, "net_receive(): ioctl(FIONREAD)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *buf = malloc(recvsize);
|
||||
if (buf == NULL) {
|
||||
log_print(LOG_WARN, "net_receive(): out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int size = recv(socket, buf, recvsize, 0);
|
||||
if (size <= 0) {
|
||||
log_print(LOG_WARN, "net_receive(): recv()");
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *delim;
|
||||
int pos = 0;
|
||||
while ((delim = memchr(buf + pos, '\n', size - pos)) != NULL) {
|
||||
*delim = '\0';
|
||||
|
||||
char *data[2];
|
||||
int ret = strsplit(buf + pos, " ", data, 2);
|
||||
pos = (delim - buf) +1;
|
||||
if (ret != 2) {
|
||||
log_print(LOG_ERROR, "net_receive(): abort data-split");
|
||||
continue;
|
||||
}
|
||||
|
||||
char *part[4];
|
||||
ret = strsplit(data[0], ":", part, 4);
|
||||
if (ret != 4) {
|
||||
log_print(LOG_ERROR, "net_receive(): abort header-split");
|
||||
continue;
|
||||
}
|
||||
|
||||
rrd_submit(part[0], part[1], part[2], atoi(part[3]), data[1]);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct net_entry * create_net_entry(const char *value)
|
||||
{
|
||||
struct net_entry *entry = malloc(sizeof(struct net_entry));
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
|
||||
if (parse_sockaddr(value, &entry->addr) < 0) {
|
||||
free(entry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
entry->socket = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (entry->socket < 0) {
|
||||
free(entry);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
static int net_init_srv_cb(const char *value, void *privdata)
|
||||
{
|
||||
struct net_entry *entry = create_net_entry(value);
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "net_init_srv_cb(): can not create net_entry");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (bind(entry->socket, (struct sockaddr *)&entry->addr, sizeof(entry->addr)) < 0) {
|
||||
log_print(LOG_ERROR, "net_init_srv_cb(): bind()");
|
||||
close(entry->socket);
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->event = event_add_readfd(NULL, entry->socket, net_receive, NULL);
|
||||
list_add(&entry->list, &srv_list);
|
||||
log_print(LOG_INFO, "listen on %s", get_sockaddr_buf(&entry->addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_init_cli_cb(const char *value, void *privdata)
|
||||
{
|
||||
struct net_entry *entry = create_net_entry(value);
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "net_init_cli_cb(): can not create net_entry");
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_add(&entry->list, &cli_list);
|
||||
log_print(LOG_INFO, "forwarding to %s", get_sockaddr_buf(&entry->addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int net_init(void)
|
||||
{
|
||||
config_get_strings("global", "listen", net_init_srv_cb, NULL);
|
||||
config_get_strings("global", "forward", net_init_cli_cb, NULL);
|
||||
|
||||
fwd_buf = malloc(PKTSIZE);
|
||||
if (fwd_buf == NULL) {
|
||||
log_print(LOG_ERROR, "net_submit(): out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void net_close(void) {
|
||||
struct net_entry *entry, *tmp;
|
||||
list_for_each_entry_safe(entry, tmp, &cli_list, list) {
|
||||
list_del(&entry->list);
|
||||
close(entry->socket);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &srv_list, list) {
|
||||
list_del(&entry->list);
|
||||
event_remove_fd(entry->event);
|
||||
close(entry->socket);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
fwd_buf_len = 0;
|
||||
if (fwd_buf != NULL)
|
||||
free(fwd_buf);
|
||||
}
|
12
network.h
12
network.h
@ -1,12 +0,0 @@
|
||||
#ifndef _NETWORK_H_
|
||||
#define _NETWORK_H_
|
||||
|
||||
#include "plugins.h"
|
||||
|
||||
int net_init(void);
|
||||
void net_close(void);
|
||||
|
||||
int net_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data);
|
||||
void net_submit_flush(void);
|
||||
|
||||
#endif /* _NETWORK_H_ */
|
@ -21,58 +21,62 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "helper.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
static char *buffer;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:entries:GAUGE:15:0:U "
|
||||
"DS:searched:DERIVE:15:0:U "
|
||||
"DS:found:DERIVE:15:0:U "
|
||||
"DS:new:DERIVE:15:0:U "
|
||||
"DS:invalid:DERIVE:15:0:U "
|
||||
"DS:ignore:DERIVE:15:0:U "
|
||||
"DS:delete:DERIVE:15:0:U "
|
||||
"DS:delete_list:DERIVE:15:0:U "
|
||||
"DS:insert:DERIVE:15:0:U "
|
||||
"DS:insert_failed:DERIVE:15:0:U "
|
||||
"DS:drop:DERIVE:15:0:U "
|
||||
"DS:early_drop:DERIVE:15:0:U "
|
||||
"DS:icmp_error:DERIVE:15:0:U "
|
||||
"DS:expect_new:DERIVE:15:0:U "
|
||||
"DS:expect_create:DERIVE:15:0:U "
|
||||
"DS:expect_delete:DERIVE:15:0:U "
|
||||
static char *ds_def[] = {
|
||||
"DS:entries:GAUGE:%d:0:U",
|
||||
"DS:searched:DERIVE:%d:0:U",
|
||||
"DS:found:DERIVE:%d:0:U",
|
||||
"DS:new:DERIVE:%d:0:U",
|
||||
"DS:invalid:DERIVE:%d:0:U",
|
||||
"DS:ignore:DERIVE:%d:0:U",
|
||||
"DS:delete:DERIVE:%d:0:U",
|
||||
"DS:delete_list:DERIVE:%d:0:U",
|
||||
"DS:insert:DERIVE:%d:0:U",
|
||||
"DS:insert_failed:DERIVE:%d:0:U",
|
||||
"DS:drop:DERIVE:%d:0:U",
|
||||
"DS:early_drop:DERIVE:%d:0:U",
|
||||
"DS:icmp_error:DERIVE:%d:0:U",
|
||||
"DS:expect_new:DERIVE:%d:0:U",
|
||||
"DS:expect_create:DERIVE:%d:0:U",
|
||||
"DS:expect_delete:DERIVE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *val[16], filename[16];
|
||||
char *buffer, *val[16], filename[16];
|
||||
unsigned long long arr[16];
|
||||
int i, len, cpu = 0;
|
||||
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_WARN, "plugin ctstat: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
fp = fopen("/proc/net/stat/ip_conntrack", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin ctstat");
|
||||
return -1;
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFSIZE, fp) != NULL) {
|
||||
if (!strncmp(buffer, "entries", 7))
|
||||
continue;
|
||||
|
||||
if (strsplit(buffer, " \t\n", val, 16) != 16)
|
||||
if (strsplit(buffer, val, 16) != 16)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
@ -92,26 +96,12 @@ static int probe(void)
|
||||
cpu++;
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
buffer = malloc(BUFSIZE);
|
||||
return (buffer == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "ctstat",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -20,46 +20,51 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:1min:GAUGE:15:0:U "
|
||||
"DS:5min:GAUGE:15:0:U "
|
||||
"DS:15min:GAUGE:15:0:U "
|
||||
static char *ds_def[] = {
|
||||
"DS:1min:GAUGE:%d:0:U",
|
||||
"DS:5min:GAUGE:%d:0:U",
|
||||
"DS:15min:GAUGE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp = fopen("/proc/loadavg", "r");
|
||||
FILE *fp;
|
||||
char buffer[32];
|
||||
char *val[3];
|
||||
|
||||
fp = fopen("/proc/loadavg", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin load: fopen()");
|
||||
return -1;
|
||||
log_print(LOG_WARN, "plugin load");
|
||||
return;
|
||||
}
|
||||
|
||||
double load1, load5, load15;
|
||||
if (fscanf(fp, "%lf %lf %lf", &load1, &load5, &load15) != 3) {
|
||||
log_print(LOG_WARN, "plugin load: fscanf()");
|
||||
if (fgets(buffer, sizeof(buffer), fp) == NULL) {
|
||||
log_print(LOG_WARN, "plugin load");
|
||||
fclose(fp);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
probe_submit(&plugin, "load.rrd", 0, "%.02lf:%.02lf:%.02lf", load1, load5, load15);
|
||||
return 0;
|
||||
if (strsplit(buffer, val, 3) != 3)
|
||||
return;
|
||||
|
||||
probe_submit(&plugin, "load.rrd", 0, "%s:%s:%s", val[0], val[1], val[2]);
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "load",
|
||||
.interval = 10,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -21,31 +21,30 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
#define DS_MEMORY 1
|
||||
#define DS_SWAP 2
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
static char *buffer;
|
||||
|
||||
static const char *mem_ds_def = {
|
||||
"DS:total:GAUGE:15:0:U "
|
||||
"DS:free:GAUGE:15:0:U "
|
||||
"DS:buffers:GAUGE:15:0:U "
|
||||
"DS:cached:GAUGE:15:0:U "
|
||||
static char *mem_ds_def[] = {
|
||||
"DS:total:GAUGE:%d:0:U",
|
||||
"DS:free:GAUGE:%d:0:U",
|
||||
"DS:buffers:GAUGE:%d:0:U",
|
||||
"DS:cached:GAUGE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *swap_ds_def = {
|
||||
"DS:total:GAUGE:15:0:U "
|
||||
"DS:free:GAUGE:15:0:U "
|
||||
static char *swap_ds_def[] = {
|
||||
"DS:total:GAUGE:%d:0:U",
|
||||
"DS:free:GAUGE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
switch (ds_id) {
|
||||
case DS_MEMORY:
|
||||
@ -68,17 +67,23 @@ struct meminfo_ {
|
||||
unsigned long long swapfree;
|
||||
};
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buffer;
|
||||
struct meminfo_ meminfo;
|
||||
|
||||
memset(&meminfo, 0, sizeof(meminfo));
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_WARN, "plugin memory: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
fp = fopen("/proc/meminfo", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin memory");
|
||||
return -1;
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFSIZE, fp) != NULL) {
|
||||
@ -109,26 +114,12 @@ static int probe(void)
|
||||
meminfo.swaptotal, meminfo.swapfree);
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
buffer = malloc(BUFSIZE);
|
||||
return (buffer == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "memory",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -19,92 +19,58 @@
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mntent.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define MAXFSNAME 16
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:block_total:GAUGE:15:0:U "
|
||||
"DS:block_free:GAUGE:15:0:U "
|
||||
static char *ds_def[] = {
|
||||
"DS:block_total:GAUGE:%d:0:U",
|
||||
"DS:block_free:GAUGE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static char * get_valid_fs(int *xcnt)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp = fopen("/proc/filesystems", "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
FILE *fp;
|
||||
struct mntent *mnt;
|
||||
struct statfs fs;
|
||||
char *slash, filename[64];
|
||||
int len;
|
||||
|
||||
int cnt = 0;
|
||||
char buffer[64];
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
if (!strncmp(buffer, "nodev", 5))
|
||||
continue;
|
||||
|
||||
cnt++;
|
||||
}
|
||||
|
||||
char *valid_arr = malloc(cnt * MAXFSNAME);
|
||||
if (valid_arr == NULL)
|
||||
return NULL;
|
||||
|
||||
rewind(fp);
|
||||
|
||||
int i = 0;
|
||||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||||
if (!strncmp(buffer, "nodev", 5))
|
||||
continue;
|
||||
|
||||
char *end = memccpy(valid_arr + (i++ * MAXFSNAME), buffer +1, '\n', MAXFSNAME);
|
||||
*(end -1) = '\0';
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
*xcnt = cnt;
|
||||
return valid_arr;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
FILE *fp = setmntent("/etc/mtab", "r");
|
||||
fp = setmntent("/etc/mtab", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin mount");
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
int cnt;
|
||||
char *valid_arr = get_valid_fs(&cnt);
|
||||
if (valid_arr == NULL) {
|
||||
log_print(LOG_WARN, "plugin mount");
|
||||
endmntent(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct mntent *mnt;
|
||||
while ((mnt = getmntent(fp)) != NULL) {
|
||||
|
||||
int i, valid = 0;
|
||||
for (i = 0; i < cnt; i++)
|
||||
if (strncmp(mnt->mnt_type, valid_arr + (i * MAXFSNAME), MAXFSNAME) == 0)
|
||||
valid = 1;
|
||||
|
||||
if (valid == 0)
|
||||
if (!strcmp(mnt->mnt_fsname, "none"))
|
||||
continue;
|
||||
|
||||
if (!strcmp(mnt->mnt_fsname, "proc"))
|
||||
continue;
|
||||
|
||||
if (!strcmp(mnt->mnt_fsname, "sysfs"))
|
||||
continue;
|
||||
|
||||
if (!strcmp(mnt->mnt_fsname, "udev"))
|
||||
continue;
|
||||
|
||||
if (!strcmp(mnt->mnt_fsname, "devpts"))
|
||||
continue;
|
||||
|
||||
if (!strcmp(mnt->mnt_type, "nfs"))
|
||||
continue;
|
||||
|
||||
struct statfs fs;
|
||||
if (statfs(mnt->mnt_dir, &fs) == -1) {
|
||||
log_print(LOG_WARN, "plugin mount: statfs(%s)", mnt->mnt_dir);
|
||||
continue;
|
||||
@ -113,14 +79,13 @@ static int probe(void)
|
||||
if (fs.f_blocks == 0)
|
||||
continue;
|
||||
|
||||
char *slash = mnt->mnt_fsname;
|
||||
slash = mnt->mnt_fsname;
|
||||
while (slash && (slash = strchr(slash, '/'))) {
|
||||
slash = strchr(slash, '/');
|
||||
*slash++ = '_';
|
||||
}
|
||||
|
||||
char filename[64];
|
||||
int len = snprintf(filename, sizeof(filename), "mount%s.rrd", mnt->mnt_fsname);
|
||||
len = snprintf(filename, sizeof(filename), "mount%s.rrd", mnt->mnt_fsname);
|
||||
if (len < 0 || len >= sizeof(filename)) {
|
||||
log_print(LOG_WARN, "plugin mount: file name too long", mnt->mnt_fsname);
|
||||
continue;
|
||||
@ -130,15 +95,12 @@ static int probe(void)
|
||||
fs.f_blocks * (fs.f_bsize /1024),
|
||||
fs.f_bfree * (fs.f_bsize /1024));
|
||||
}
|
||||
|
||||
free(valid_arr);
|
||||
endmntent(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "mount",
|
||||
.interval = 10,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -21,39 +21,43 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "helper.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
static char *buffer;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:byte_in:COUNTER:15:0:U "
|
||||
"DS:byte_out:COUNTER:15:0:U "
|
||||
"DS:pkt_in:COUNTER:15:0:U "
|
||||
"DS:pkt_out:COUNTER:15:0:U "
|
||||
static char *ds_def[] = {
|
||||
"DS:byte_in:COUNTER:%d:0:U",
|
||||
"DS:byte_out:COUNTER:%d:0:U",
|
||||
"DS:pkt_in:COUNTER:%d:0:U",
|
||||
"DS:pkt_out:COUNTER:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *stats, *device;
|
||||
char *buffer, *stats, *device;
|
||||
char *val[16], filename[32];
|
||||
int len;
|
||||
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_WARN, "plugin netdev: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
fp = fopen("/proc/net/dev", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin netdev");
|
||||
return -1;
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFSIZE, fp) != NULL) {
|
||||
@ -70,7 +74,7 @@ static int probe(void)
|
||||
if (*device == '\0')
|
||||
continue;
|
||||
|
||||
if (strsplit(stats, " \t\n", val, 16) != 16)
|
||||
if (strsplit(stats, val, 16) != 16)
|
||||
continue;
|
||||
|
||||
len = snprintf(filename, sizeof(filename), "net-%s.rrd", device);
|
||||
@ -81,26 +85,12 @@ static int probe(void)
|
||||
val[0], val[8], val[1], val[9]);
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
buffer = malloc(BUFSIZE);
|
||||
return (buffer == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "netdev",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -20,44 +20,49 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:entropy:GAUGE:15:0:U "
|
||||
static char *ds_def[] = {
|
||||
"DS:entropy:GAUGE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp = fopen("/proc/sys/kernel/random/entropy_avail", "r");
|
||||
FILE *fp;
|
||||
char buffer[32];
|
||||
char *val[1];
|
||||
|
||||
fp = fopen("/proc/sys/kernel/random/entropy_avail", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin random: fopen()");
|
||||
return -1;
|
||||
log_print(LOG_WARN, "plugin random");
|
||||
return;
|
||||
}
|
||||
|
||||
int entropy;
|
||||
if (fscanf(fp, "%d", &entropy) != 1) {
|
||||
log_print(LOG_WARN, "plugin random: fopen()");
|
||||
if (fgets(buffer, sizeof(buffer), fp) == NULL) {
|
||||
log_print(LOG_WARN, "plugin random");
|
||||
fclose(fp);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
probe_submit(&plugin, "random.rrd", 0, "%d", entropy);
|
||||
return 0;
|
||||
if (strsplit(buffer, val, 1) != 1)
|
||||
return;
|
||||
|
||||
probe_submit(&plugin, "random.rrd", 0, "%s", val[0]);
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "random",
|
||||
.interval = 10,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -21,74 +21,63 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "helper.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define DS_STAT 1
|
||||
#define DS_GC 2
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
static char *buffer;
|
||||
|
||||
static const char *ds_def_stat = {
|
||||
"DS:in_hit:DERIVE:15:0:U "
|
||||
"DS:in_slow_tot:DERIVE:15:0:U "
|
||||
"DS:in_slow_mc:DERIVE:15:0:U "
|
||||
"DS:in_no_route:DERIVE:15:0:U "
|
||||
"DS:in_brd:DERIVE:15:0:U "
|
||||
"DS:in_martian_dst:DERIVE:15:0:U "
|
||||
"DS:in_martian_src:DERIVE:15:0:U "
|
||||
"DS:out_hit:DERIVE:15:0:U "
|
||||
"DS:out_slow_tot:DERIVE:15:0:U "
|
||||
"DS:out_slow_mc:DERIVE:15:0:U "
|
||||
"DS:in_hlist_search:DERIVE:15:0:U "
|
||||
"DS:out_hlist_search:DERIVE:15:0:U "
|
||||
static char *ds_def[] = {
|
||||
"DS:entries:GAUGE:%d:0:U",
|
||||
"DS:in_hit:DERIVE:%d:0:U",
|
||||
"DS:in_slow_tot:DERIVE:%d:0:U",
|
||||
"DS:in_slow_mc:DERIVE:%d:0:U",
|
||||
"DS:in_no_route:DERIVE:%d:0:U",
|
||||
"DS:in_brd:DERIVE:%d:0:U",
|
||||
"DS:in_martian_dst:DERIVE:%d:0:U",
|
||||
"DS:in_martian_src:DERIVE:%d:0:U",
|
||||
"DS:out_hit:DERIVE:%d:0:U",
|
||||
"DS:out_slow_tot:DERIVE:%d:0:U",
|
||||
"DS:out_slow_mc:DERIVE:%d:0:U",
|
||||
"DS:gc_total:DERIVE:%d:0:U",
|
||||
"DS:gc_ignored:DERIVE:%d:0:U",
|
||||
"DS:gc_goal_miss:DERIVE:%d:0:U",
|
||||
"DS:gc_dst_overflow:DERIVE:%d:0:U",
|
||||
"DS:in_hlist_search:DERIVE:%d:0:U",
|
||||
"DS:out_hlist_search:DERIVE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *ds_def_gc = {
|
||||
"DS:entries:GAUGE:15:0:U "
|
||||
"DS:gc_total:DERIVE:15:0:U "
|
||||
"DS:gc_ignored:DERIVE:15:0:U "
|
||||
"DS:gc_goal_miss:DERIVE:15:0:U "
|
||||
"DS:gc_dst_overflow:DERIVE:15:0:U "
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
switch (ds_id) {
|
||||
case DS_STAT:
|
||||
return ds_def_stat;
|
||||
|
||||
case DS_GC:
|
||||
return ds_def_gc;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *val[17], filename[16];
|
||||
char *buffer, *val[17], filename[16];
|
||||
unsigned long long arr[17];
|
||||
int i, len, cpu = 0;
|
||||
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_WARN, "plugin rtstat: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
fp = fopen("/proc/net/stat/rt_cache", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin rtstat");
|
||||
return -1;
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFSIZE, fp) != NULL) {
|
||||
if (!strncmp(buffer, "entries", 7))
|
||||
continue;
|
||||
|
||||
if (strsplit(buffer, " \t\n", val, 17) != 17)
|
||||
if (strsplit(buffer, val, 17) != 17)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < 17; i++)
|
||||
@ -98,43 +87,22 @@ static int probe(void)
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, DS_STAT,
|
||||
"%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
|
||||
arr[1], arr[2], arr[3], arr[4],
|
||||
arr[5], arr[6], arr[7], arr[8],
|
||||
arr[9], arr[10], arr[15], arr[16]);
|
||||
|
||||
len = snprintf(filename, sizeof(filename), "rtcache-%d.rrd", cpu);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, DS_GC,
|
||||
"%llu:%llu:%llu:%llu:%llu",
|
||||
arr[0], arr[11], arr[12], arr[13], arr[14]);
|
||||
|
||||
probe_submit(&plugin, filename, 0,
|
||||
"%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
|
||||
arr[0], arr[1], arr[2], arr[3],
|
||||
arr[4], arr[5], arr[6], arr[7],
|
||||
arr[8], arr[9], arr[10], arr[11],
|
||||
arr[12], arr[13], arr[14], arr[15],
|
||||
arr[16]);
|
||||
cpu++;
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
buffer = malloc(BUFSIZE);
|
||||
return (buffer == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "rtstat",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -21,37 +21,34 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "helper.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
#define DS_CPU 1
|
||||
#define DS_PROC 2
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
static char *buffer;
|
||||
|
||||
static const char *cpu_ds_def = {
|
||||
"DS:user:COUNTER:15:0:U "
|
||||
"DS:nice:COUNTER:15:0:U "
|
||||
"DS:system:COUNTER:15:0:U "
|
||||
"DS:idle:COUNTER:15:0:U "
|
||||
"DS:iowait:COUNTER:15:0:U "
|
||||
"DS:irq:COUNTER:15:0:U "
|
||||
"DS:softirq:COUNTER:15:0:U "
|
||||
"DS:steal:COUNTER:15:0:U "
|
||||
static char *cpu_ds_def[] = {
|
||||
"DS:user:COUNTER:%d:0:U",
|
||||
"DS:nice:COUNTER:%d:0:U",
|
||||
"DS:syst:COUNTER:%d:0:U",
|
||||
"DS:idle:COUNTER:%d:0:U",
|
||||
"DS:wait:COUNTER:%d:0:U",
|
||||
"DS:intr:COUNTER:%d:0:U",
|
||||
"DS:sitr:COUNTER:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *proc_ds_def = {
|
||||
"DS:intr:COUNTER:15:0:U "
|
||||
"DS:ctxt:COUNTER:15:0:U "
|
||||
"DS:fork:COUNTER:15:0:U "
|
||||
static char *proc_ds_def[] = {
|
||||
"DS:intr:COUNTER:%d:0:U",
|
||||
"DS:ctxt:COUNTER:%d:0:U",
|
||||
"DS:fork:COUNTER:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
switch (ds_id) {
|
||||
case DS_CPU:
|
||||
@ -71,17 +68,23 @@ struct proc_ {
|
||||
unsigned long long fork;
|
||||
};
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buffer;
|
||||
struct proc_ proc;
|
||||
|
||||
memset(&proc, 0, sizeof(proc));
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_WARN, "plugin stat: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
fp = fopen("/proc/stat", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin stat");
|
||||
return -1;
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFSIZE, fp) != NULL) {
|
||||
@ -99,20 +102,21 @@ static int probe(void)
|
||||
strncpy(filename, "cpu.rrd", sizeof(filename));
|
||||
}
|
||||
|
||||
numfields = strsplit(buffer, " \t\n", val, 9);
|
||||
numfields = strsplit(buffer, val, 9);
|
||||
if (numfields < 5)
|
||||
continue;
|
||||
|
||||
else if (numfields == 5)
|
||||
val[5] = val[6] = val[7] = val[8] = "0";
|
||||
if (numfields >= 8) {
|
||||
probe_submit(&plugin, filename, DS_CPU,
|
||||
"%s:%s:%s:%s:%s:%s:%s",
|
||||
val[1], val[2], val[3], val[4],
|
||||
val[5], val[6], val[7]);
|
||||
|
||||
else if (numfields == 8)
|
||||
val[8] = "0";
|
||||
|
||||
probe_submit(&plugin, filename, DS_CPU,
|
||||
"%s:%s:%s:%s:%s:%s:%s:%s",
|
||||
val[1], val[2], val[3], val[4],
|
||||
val[5], val[6], val[7], val[8]);
|
||||
} else {
|
||||
probe_submit(&plugin, filename, DS_CPU,
|
||||
"%s:%s:%s:%s:0:0:0",
|
||||
val[1], val[2], val[3], val[4]);
|
||||
}
|
||||
|
||||
} else if (!strncmp(buffer, "intr", 4)) {
|
||||
proc.intr = atoll(buffer + 5);
|
||||
@ -129,26 +133,12 @@ static int probe(void)
|
||||
proc.intr, proc.ctxt, proc.fork);
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
buffer = malloc(BUFSIZE);
|
||||
return (buffer == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "stat",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -20,45 +20,50 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:uptime:GAUGE:15:0:U "
|
||||
"DS:idletime:GAUGE:15:0:U "
|
||||
static char *ds_def[] = {
|
||||
"DS:uptime:GAUGE:%d:0:U",
|
||||
"DS:idletime:GAUGE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp = fopen("/proc/uptime", "r");
|
||||
FILE *fp;
|
||||
char buffer[32];
|
||||
char *val[2];
|
||||
|
||||
fp = fopen("/proc/uptime", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin uptime: fopen()");
|
||||
return -1;
|
||||
log_print(LOG_WARN, "plugin uptime");
|
||||
return;
|
||||
}
|
||||
|
||||
double uptime, idletime;
|
||||
if (fscanf(fp, "%lf %lf\n", &uptime, &idletime) != 2) {
|
||||
log_print(LOG_WARN, "plugin uptime: fscanf()");
|
||||
if (fgets(buffer, sizeof(buffer), fp) == NULL) {
|
||||
log_print(LOG_WARN, "plugin uptime");
|
||||
fclose(fp);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
probe_submit(&plugin, "uptime.rrd", 0, "%.02lf:%.02lf", uptime, idletime);
|
||||
return 0;
|
||||
if (strsplit(buffer, val, 2) != 2)
|
||||
return;
|
||||
|
||||
probe_submit(&plugin, "uptime.rrd", 0, "%s:%s", val[0], val[1]);
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "uptime",
|
||||
.interval = 10,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -21,24 +21,22 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
static char *buffer;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:pgalloc_high:DERIVE:15:0:U "
|
||||
"DS:pgalloc_normal:DERIVE:15:0:U "
|
||||
"DS:pgalloc_dma:DERIVE:15:0:U "
|
||||
"DS:pgfree:DERIVE:15:0:U "
|
||||
"DS:pgfault:DERIVE:15:0:U "
|
||||
static char *ds_def[] = {
|
||||
"DS:pgalloc_high:DERIVE:%d:0:U",
|
||||
"DS:pgalloc_normal:DERIVE:%d:0:U",
|
||||
"DS:pgalloc_dma:DERIVE:%d:0:U",
|
||||
"DS:pgfree:DERIVE:%d:0:U",
|
||||
"DS:pgfault:DERIVE:%d:0:U",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
static char ** get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
@ -51,17 +49,23 @@ struct vmstat_ {
|
||||
unsigned long long pgfault;
|
||||
};
|
||||
|
||||
static int probe(void)
|
||||
static void probe(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char *buffer;
|
||||
struct vmstat_ vmstat;
|
||||
|
||||
memset(&vmstat, 0, sizeof(vmstat));
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_WARN, "plugin vmstat: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
fp = fopen("/proc/vmstat", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin vmstat");
|
||||
return -1;
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFSIZE, fp) != NULL) {
|
||||
@ -86,26 +90,12 @@ static int probe(void)
|
||||
vmstat.pgalloc_dma, vmstat.pgfree, vmstat.pgfault);
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
buffer = malloc(BUFSIZE);
|
||||
return (buffer == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "vmstat",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.version = 1,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
73
pidfile.c
73
pidfile.c
@ -1,73 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
int pidfile_create(const char *filename)
|
||||
{
|
||||
int fd = open(filename, O_CREAT | O_EXCL | O_RDWR, 0644);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
char buf[8];
|
||||
int len = snprintf(buf, sizeof(buf), "%d", getpid());
|
||||
write(fd, buf, len);
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pidfile_remove(const char *filename)
|
||||
{
|
||||
return unlink(filename);
|
||||
}
|
||||
|
||||
pid_t pidfile_check(const char *filename, int remove_stale)
|
||||
{
|
||||
int fd = open(filename, O_RDWR);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOENT) {
|
||||
errno = 0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char buf[9];
|
||||
int len = read(fd, buf, sizeof(buf) -1);
|
||||
buf[len] = '\0';
|
||||
|
||||
close(fd);
|
||||
|
||||
char *tmp;
|
||||
pid_t pid = strtol(buf, &tmp, 10);
|
||||
if (len == 0 || tmp == buf)
|
||||
pid = -1;
|
||||
|
||||
/* just return the pid */
|
||||
if (!remove_stale)
|
||||
return pid;
|
||||
|
||||
/* invalid pid, remove stale file */
|
||||
if (pid == -1) {
|
||||
pidfile_remove(filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if pid is still running */
|
||||
if (kill(pid, 0) == 0 || errno != ESRCH) {
|
||||
errno = 0;
|
||||
return pid;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
pidfile_remove(filename);
|
||||
return 0;
|
||||
}
|
11
pidfile.h
11
pidfile.h
@ -1,11 +0,0 @@
|
||||
#ifndef _PIDFILE_H_
|
||||
#define _PIDFILE_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
int pidfile_create(const char *filename);
|
||||
int pidfile_remove(const char *filename);
|
||||
|
||||
pid_t pidfile_check(const char *filename, int remove_stale);
|
||||
|
||||
#endif // _PIDFILE_H_
|
203
plugins.c
203
plugins.c
@ -22,127 +22,146 @@
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
#include "configfile.h"
|
||||
#include "event.h"
|
||||
#include "logging.h"
|
||||
#include "network.h"
|
||||
#include "plugins.h"
|
||||
#include "config.h"
|
||||
#include "logging.h"
|
||||
#include "rrdtool.h"
|
||||
|
||||
#define FLAGS_ACTIVE 0x01
|
||||
#define BUFSIZE 1024
|
||||
|
||||
static LIST_HEAD(plugin_list);
|
||||
static struct event_timeout *probe_event;
|
||||
|
||||
static int plugin_init_cb(const char *filename, void *privdata)
|
||||
static void plugin_load(char *filename)
|
||||
{
|
||||
const char *plugin_dir = (const char *)privdata;
|
||||
struct sammler_plugin *plugin = NULL;
|
||||
static char *plugin_dir;
|
||||
|
||||
char *fullname = malloc(PATH_MAX);
|
||||
if (fullname == NULL) {
|
||||
log_print(LOG_ERROR, "plugin_init_cb(): out of memory");
|
||||
return -1;
|
||||
char *buffer;
|
||||
void *tmp;
|
||||
int len;
|
||||
|
||||
if (plugin_dir == NULL)
|
||||
plugin_dir = config_get_string("global", "plugin_dir", ".");
|
||||
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_ERROR, "plugin_load: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
int len = snprintf(fullname, PATH_MAX, "%s/%s", plugin_dir, filename);
|
||||
if (len < 0 || len >= PATH_MAX) {
|
||||
log_print(LOG_ERROR, "plugin_init_cb(): file name too long: %s/%s", plugin_dir, filename);
|
||||
free(fullname);
|
||||
return -1;
|
||||
len = snprintf(buffer, BUFSIZE, "%s/%s", plugin_dir, filename);
|
||||
if (len < 0 || len >= BUFSIZE) {
|
||||
log_print(LOG_ERROR, "plugin_load: file name too long: %s/%s", plugin_dir, filename);
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
dlerror();
|
||||
void *dlhandle = dlopen(fullname, RTLD_NOW);
|
||||
if (dlhandle == NULL) {
|
||||
log_print(LOG_ERROR, "plugin_init_cb(): dlopen: %s", dlerror());
|
||||
free(fullname);
|
||||
return -1;
|
||||
tmp = dlopen(buffer, RTLD_NOW);
|
||||
if (tmp == NULL) {
|
||||
log_print(LOG_ERROR, "plugin_load: dlopen: %s", dlerror());
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
free(fullname);
|
||||
|
||||
struct sammler_plugin *plugin = dlsym(dlhandle, "plugin");
|
||||
plugin = dlsym(tmp, "plugin");
|
||||
if (plugin == NULL) {
|
||||
log_print(LOG_ERROR, "plugin_init_cb(): failed to load '%s'", filename);
|
||||
dlclose(dlhandle);
|
||||
return -1;
|
||||
log_print(LOG_ERROR, "plugin_load: failed to load '%s'", filename);
|
||||
dlclose(tmp);
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin->init != NULL && (plugin->init() != 0)) {
|
||||
log_print(LOG_ERROR, "plugin_init_cb(): Plugin '%s': init() failed", plugin->name);
|
||||
dlclose(dlhandle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_print(LOG_INFO, "Plugin '%s' loaded", plugin->name);
|
||||
plugin->lastprobe = 0;
|
||||
plugin->flags = FLAGS_ACTIVE;
|
||||
plugin->dlhandle = dlhandle;
|
||||
log_print(LOG_INFO, "Plugin '%s' (v%d) loaded", plugin->name, plugin->version);
|
||||
|
||||
list_add_tail(&plugin->list, &plugin_list);
|
||||
return 0;
|
||||
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
static int plugins_probe(int timerid, void *privdata)
|
||||
void plugin_load_all()
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
struct conf_section *section;
|
||||
struct conf_tupel *tupel;
|
||||
|
||||
section = config_get_section("global");
|
||||
if (section == NULL)
|
||||
return;
|
||||
|
||||
list_for_each_entry(tupel, §ion->tupel, list)
|
||||
if (!strcmp(tupel->option, "plugin"))
|
||||
plugin_load(tupel->parameter);
|
||||
}
|
||||
|
||||
void plugins_probe(void)
|
||||
{
|
||||
struct sammler_plugin *plugin;
|
||||
|
||||
list_for_each_entry(plugin, &plugin_list, list)
|
||||
plugin->probe();
|
||||
}
|
||||
|
||||
char ** plugins_get_ds(char *name, int version, int ds_id)
|
||||
{
|
||||
struct sammler_plugin *plugin;
|
||||
list_for_each_entry(plugin, &plugin_list, list) {
|
||||
if (!(plugin->flags & FLAGS_ACTIVE))
|
||||
if (strcmp(plugin->name, name))
|
||||
continue;
|
||||
|
||||
if (plugin->lastprobe + plugin->interval <= now) {
|
||||
if (plugin->probe() != 0) {
|
||||
log_print(LOG_ERROR, "plugin_probe(): plugin '%s' disabled", plugin->name);
|
||||
plugin->flags &= ~FLAGS_ACTIVE;
|
||||
}
|
||||
plugin->lastprobe = now;
|
||||
}
|
||||
}
|
||||
if (plugin->version != version)
|
||||
continue;
|
||||
|
||||
net_submit_flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plugin_init(void)
|
||||
{
|
||||
const char *plugin_dir = config_get_string("global", "plugin_dir", "plugins");
|
||||
int cnt = config_get_strings("global", "plugin", plugin_init_cb, (void *)plugin_dir);
|
||||
if (cnt == 0) {
|
||||
log_print(LOG_ERROR, "plugin_init(): no working plugins");
|
||||
return -1;
|
||||
}
|
||||
|
||||
probe_event = event_add_timeout_ms(1000, plugins_probe, 0, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int plugin_close(void)
|
||||
{
|
||||
struct sammler_plugin *plugin, *tmp;
|
||||
list_for_each_entry_safe(plugin, tmp, &plugin_list, list) {
|
||||
list_del(&plugin->list);
|
||||
if (plugin->fini != NULL && plugin->fini() != 0)
|
||||
log_print(LOG_ERROR, "plugin_close(): Plugin '%s': fini() failed", plugin->name);
|
||||
|
||||
dlclose(plugin->dlhandle);
|
||||
}
|
||||
|
||||
event_remove_timeout(probe_event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin * plugin_lookup(const char *name)
|
||||
{
|
||||
struct sammler_plugin *plugin;
|
||||
list_for_each_entry(plugin, &plugin_list, list) {
|
||||
if (!strcmp(plugin->name, name))
|
||||
return plugin;
|
||||
return plugin->get_ds(ds_id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void probe_submit(struct sammler_plugin *plugin, char *filename, int ds_id, const char *fmt, ... )
|
||||
{
|
||||
va_list az;
|
||||
char *buffer;
|
||||
int len;
|
||||
|
||||
buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_ERROR, "probe_submit: out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(az, fmt);
|
||||
len = vsnprintf(buffer, BUFSIZE, fmt, az);
|
||||
va_end(az);
|
||||
|
||||
if (len < 0 || len >= BUFSIZE) {
|
||||
log_print(LOG_ERROR, "probe_submit: %s arguments too long", plugin->name);
|
||||
free(buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
rrd_submit(plugin->name, plugin->version, filename, ds_id, buffer);
|
||||
// net_submit(plugin->name, plugin->version, filename, ds_id, buffer);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int strsplit(char *string, char **fields, size_t size)
|
||||
{
|
||||
size_t i = 0;
|
||||
char *ptr = string;
|
||||
|
||||
while ((fields[i] = strtok(ptr, " \n\t")) != NULL) {
|
||||
ptr = NULL;
|
||||
i++;
|
||||
|
||||
if (i >= size)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
31
plugins.h
31
plugins.h
@ -1,30 +1,25 @@
|
||||
#ifndef _PLUGINS_H_
|
||||
#define _PLUGINS_H_
|
||||
|
||||
#include <time.h>
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
|
||||
struct sammler_plugin {
|
||||
struct list_head list;
|
||||
void *dlhandle;
|
||||
const char *name;
|
||||
|
||||
/* timing */
|
||||
unsigned int interval;
|
||||
time_t lastprobe;
|
||||
|
||||
/* flags */
|
||||
int flags;
|
||||
|
||||
int (*init) (void);
|
||||
int (*fini) (void);
|
||||
int (*probe) (void);
|
||||
const char * (*get_ds) (int ds_id);
|
||||
char *name;
|
||||
int version;
|
||||
void (*probe) (void);
|
||||
char ** (*get_ds) (int ds_id);
|
||||
};
|
||||
|
||||
int plugin_init(void);
|
||||
int plugin_close(void);
|
||||
void plugin_load_all(void);
|
||||
|
||||
struct sammler_plugin * plugin_lookup(const char *name);
|
||||
void plugins_probe(void);
|
||||
|
||||
char ** plugins_get_ds(char *plugin, int version, int ds_id);
|
||||
|
||||
void probe_submit(struct sammler_plugin *plugin, char *filename, int ds_id, const char *fmt, ... );
|
||||
|
||||
int strsplit(char *string, char **fields, size_t size);
|
||||
|
||||
#endif /* _PLUGINS_H_ */
|
||||
|
@ -1,106 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 04/2009 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "helper.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
static const char *socket_path;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:ibat:GAUGE:15:U:U "
|
||||
"DS:ubat:GAUGE:15:0:U "
|
||||
"DS:uin:GAUGE:15:0:U "
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sockfd == -1) {
|
||||
log_print(LOG_WARN, "plugin alixusv: socket()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
|
||||
int len = sizeof(addr.sun_family) + strlen(addr.sun_path);
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *)&addr, len) < 0) {
|
||||
log_print(LOG_ERROR, "plugin alixusv: connect(%s)", addr.sun_path);
|
||||
close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char buf[64] = "status";
|
||||
write(sockfd, buf, strlen(buf));
|
||||
|
||||
len = read(sockfd, buf, sizeof(buf));
|
||||
if (len <= 0) {
|
||||
log_print(LOG_ERROR, "plugin alixusv: read()");
|
||||
close(sockfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
|
||||
char *field[4];
|
||||
if (strsplit(buf, ": \t\n", field, 4) != 4)
|
||||
return -1;
|
||||
|
||||
int ibat = strtoll(field[1], NULL, 10);
|
||||
int ubat = strtoll(field[2], NULL, 10);
|
||||
int uin = strtoll(field[3], NULL, 10);
|
||||
|
||||
probe_submit(&plugin, "alixusv.rrd", 0, "%d:%d:%d", ibat, ubat, uin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
socket_path = config_get_string("p_alixusv", "socket", NULL);
|
||||
return (socket_path == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "alixusv",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
223
plugins/apache.c
223
plugins/apache.c
@ -1,223 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 10/2006 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "helper.h"
|
||||
#include "linebuffer.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define BUFSIZE 8192
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
struct server_entry {
|
||||
struct list_head list;
|
||||
CURL *handle;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static LIST_HEAD(server_list);
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:total_accesses:COUNTER:90:0:U "
|
||||
"DS:total_kbytes:COUNTER:90:0:U "
|
||||
"DS:busy_workers:GAUGE:90:0:U "
|
||||
"DS:idle_workers:GAUGE:90:0:U "
|
||||
};
|
||||
|
||||
struct stats {
|
||||
uint64_t total_accesses;
|
||||
uint64_t total_kbytes;
|
||||
uint64_t busy_workers;
|
||||
uint64_t idle_workers;
|
||||
};
|
||||
|
||||
static struct lbuf * rxbuf;
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static size_t curl_callback(void *buffer, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
size_t realsize = size * nmemb;
|
||||
|
||||
lbuf_append(rxbuf, buffer, realsize);
|
||||
|
||||
return realsize;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
struct server_entry *entry;
|
||||
list_for_each_entry(entry, &server_list, list) {
|
||||
lbuf_clear(rxbuf);
|
||||
|
||||
int ret = curl_easy_perform(entry->handle);
|
||||
if (ret != 0) {
|
||||
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
|
||||
continue;
|
||||
}
|
||||
|
||||
struct stats stats;
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
|
||||
char *line;
|
||||
while ((line = lbuf_gettok(rxbuf, "\r\n")) != NULL) {
|
||||
char *part[2];
|
||||
strsplit(line, ":", part, 2);
|
||||
|
||||
if (!strcmp(part[0], "Total Accesses"))
|
||||
stats.total_accesses = atoll(part[1]);
|
||||
|
||||
else if (!strcmp(part[0], "Total kBytes"))
|
||||
stats.total_kbytes = atoll(part[1]);
|
||||
|
||||
else if (!strcmp(part[0], "BusyWorkers") || !strcmp(part[0], "BusyServers"))
|
||||
stats.busy_workers = atoll(part[1]);
|
||||
|
||||
else if (!strcmp(part[0], "IdleWorkers") || !strcmp(part[0], "IdleServers"))
|
||||
stats.idle_workers = atoll(part[1]);
|
||||
|
||||
lbuf_freetok(rxbuf);
|
||||
}
|
||||
|
||||
char filename[32];
|
||||
int len = snprintf(filename, sizeof(filename), "apache-%s.rrd", entry->name);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, 0, "%llu:%llu:%llu:%llu",
|
||||
stats.total_accesses, stats.total_kbytes,
|
||||
stats.busy_workers, stats.idle_workers);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_cb(struct strtoken *tokens, void *privdata)
|
||||
{
|
||||
if (tokens->count < 2) {
|
||||
log_print(LOG_ERROR, "p_apache: parse error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct server_entry *entry = malloc(sizeof(struct server_entry));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "p_apache: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->name = strdup(tokens->field[0]);
|
||||
|
||||
entry->handle = curl_easy_init();
|
||||
if (entry->handle == NULL) {
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set URL */
|
||||
int ret = curl_easy_setopt(entry->handle, CURLOPT_URL, tokens->field[1]);
|
||||
if (ret != 0) {
|
||||
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
|
||||
curl_easy_cleanup(entry->handle);
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tokens->field[2] != NULL && tokens->field[3] != NULL) {
|
||||
*(tokens->field[3] -1) = ':';
|
||||
|
||||
log_print(LOG_INFO, "p_apache: auth: '%s'", tokens->field[2]);
|
||||
|
||||
/* set username:password */
|
||||
ret = curl_easy_setopt(entry->handle, CURLOPT_USERPWD, tokens->field[2]);
|
||||
if (ret != 0) {
|
||||
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
|
||||
curl_easy_cleanup(entry->handle);
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = curl_easy_setopt(entry->handle, CURLOPT_WRITEFUNCTION, &curl_callback);
|
||||
if (ret != 0) {
|
||||
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
|
||||
curl_easy_cleanup(entry->handle);
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = curl_easy_setopt(entry->handle, CURLOPT_WRITEDATA, entry);
|
||||
if (ret != 0) {
|
||||
log_print(LOG_ERROR, "p_apache: %s", curl_easy_strerror(ret));
|
||||
curl_easy_cleanup(entry->handle);
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_print(LOG_INFO, "p_apache: added server '%s'", entry->name);
|
||||
list_add_tail(&entry->list, &server_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
rxbuf = lbuf_create(BUFSIZE);
|
||||
if (rxbuf == NULL) {
|
||||
log_print(LOG_ERROR, "p_apache: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
config_get_strtokens("p_apache", "server", ",", 4, init_cb, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
struct server_entry *entry, *tmp;
|
||||
list_for_each_entry_safe(entry, tmp, &server_list, list) {
|
||||
curl_easy_cleanup(entry->handle);
|
||||
free(entry->name);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
lbuf_free(rxbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "apache",
|
||||
.interval = 60,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -1,176 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 04/2007 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libnfnetlink/libnfnetlink.h>
|
||||
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define DS_L3PROTO 1
|
||||
#define DS_L4PROTO 2
|
||||
#define DS_TCP 3
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
static struct nfct_handle *cth;
|
||||
struct ct_values {
|
||||
int total;
|
||||
int local;
|
||||
int nated;
|
||||
int unreplied;
|
||||
|
||||
int proto_tcp;
|
||||
int proto_udp;
|
||||
int proto_unknown;
|
||||
|
||||
int tcp_state[10];
|
||||
};
|
||||
|
||||
static const char *l3proto_ds_def = {
|
||||
"DS:total:GAUGE:15:0:U "
|
||||
"DS:local:GAUGE:15:0:U "
|
||||
"DS:nated:GAUGE:15:0:U "
|
||||
"DS:unreplied:GAUGE:15:0:U "
|
||||
};
|
||||
|
||||
static const char *l4proto_ds_def = {
|
||||
"DS:tcp:GAUGE:15:0:U "
|
||||
"DS:udp:GAUGE:15:0:U "
|
||||
"DS:unknown:GAUGE:15:0:U "
|
||||
};
|
||||
|
||||
static const char *tcp_ds_def = {
|
||||
"DS:none:GAUGE:15:0:U "
|
||||
"DS:syn_sent:GAUGE:15:0:U "
|
||||
"DS:syn_recv:GAUGE:15:0:U "
|
||||
"DS:established:GAUGE:15:0:U "
|
||||
"DS:fin_wait:GAUGE:15:0:U "
|
||||
"DS:close_wait:GAUGE:15:0:U "
|
||||
"DS:last_ack:GAUGE:15:0:U "
|
||||
"DS:time_wait:GAUGE:15:0:U "
|
||||
"DS:close:GAUGE:15:0:U "
|
||||
"DS:listen:GAUGE:15:0:U "
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
switch (ds_id) {
|
||||
case DS_L3PROTO:
|
||||
return l3proto_ds_def;
|
||||
|
||||
case DS_L4PROTO:
|
||||
return l4proto_ds_def;
|
||||
|
||||
case DS_TCP:
|
||||
return tcp_ds_def;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int probe_cb(void *arg, unsigned int flags, int type, void *privdata)
|
||||
{
|
||||
struct nfct_conntrack *ct = (struct nfct_conntrack *)arg;
|
||||
struct ct_values *data = (struct ct_values *)privdata;
|
||||
|
||||
data->total++;
|
||||
|
||||
if (ct->status & IPS_NAT_MASK)
|
||||
data->nated++;
|
||||
else
|
||||
data->local++;
|
||||
|
||||
if (!(ct->status & IPS_SEEN_REPLY))
|
||||
data->unreplied++;
|
||||
|
||||
switch (ct->tuple[NFCT_DIR_ORIGINAL].protonum) {
|
||||
case IPPROTO_TCP:
|
||||
data->proto_tcp++;
|
||||
data->tcp_state[ct->protoinfo.tcp.state]++;
|
||||
break;
|
||||
|
||||
case IPPROTO_UDP:
|
||||
data->proto_udp++;
|
||||
break;
|
||||
|
||||
default:
|
||||
data->proto_unknown++;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
struct ct_values data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
nfct_register_callback(cth, probe_cb, &data);
|
||||
|
||||
if (nfct_dump_conntrack_table(cth, AF_INET) < 0) {
|
||||
log_print(LOG_WARN, "plugin conntrack: nfct_dump_conntrack_table()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
probe_submit(&plugin, "conntrack.rrd", DS_L3PROTO, "%d:%d:%d:%d",
|
||||
data.total, data.local, data.nated, data.unreplied);
|
||||
|
||||
probe_submit(&plugin, "conntrack-proto.rrd", DS_L4PROTO, "%d:%d:%d",
|
||||
data.proto_tcp, data.proto_udp, data.proto_unknown);
|
||||
|
||||
probe_submit(&plugin, "conntrack-tcp.rrd", DS_TCP, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
|
||||
data.tcp_state[0], data.tcp_state[1], data.tcp_state[2], data.tcp_state[3],
|
||||
data.tcp_state[4], data.tcp_state[5], data.tcp_state[6], data.tcp_state[7],
|
||||
data.tcp_state[8], data.tcp_state[9]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
cth = nfct_open(CONNTRACK, 0);
|
||||
if (cth == NULL) {
|
||||
log_print(LOG_WARN, "plugin conntrack: nfct_open()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
nfct_close(cth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "conntrack",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -1,152 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 06/2010 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#include "sgio.h"
|
||||
int verbose = 0;
|
||||
int prefer_ata12 = 0;
|
||||
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
struct device_entry {
|
||||
struct list_head list;
|
||||
char *devpath;
|
||||
};
|
||||
|
||||
static LIST_HEAD(device_list);
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:active:GAUGE:90:0:1 "
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
struct device_entry *entry;
|
||||
list_for_each_entry(entry, &device_list, list) {
|
||||
|
||||
int fd = open(entry->devpath, O_RDONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
log_print(LOG_ERROR, "%s: failed to open %s", plugin.name, entry->devpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t args[4] = { ATA_OP_CHECKPOWERMODE1, 0, 0, 0 };
|
||||
|
||||
if (do_drive_cmd(fd, args)) {
|
||||
args[0] = ATA_OP_CHECKPOWERMODE2;
|
||||
if (do_drive_cmd(fd, args)) {
|
||||
log_print(LOG_ERROR, "%s: failed to query %s", plugin.name, entry->devpath);
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/*
|
||||
switch (args[2]) {
|
||||
case 0x00: state = "standby"; break;
|
||||
case 0x40: state = "NVcache_spindown"; break;
|
||||
case 0x41: state = "NVcache_spinup"; break;
|
||||
case 0x80: state = "idle"; break;
|
||||
case 0xff: state = "active/idle"; break;
|
||||
default: state = "unknown"; break;
|
||||
}
|
||||
*/
|
||||
char *dev = strrchr(entry->devpath, '/');
|
||||
if (dev == NULL) {
|
||||
dev = entry->devpath;
|
||||
} else {
|
||||
dev++;
|
||||
}
|
||||
|
||||
char filename[32];
|
||||
int len = snprintf(filename, sizeof(filename), "diskstandby-%s.rrd", dev);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, 0, "%u", (args[2] == 0xff) ? 1 : 0);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_cb(struct strtoken *tokens, void *privdata)
|
||||
{
|
||||
if (tokens->count != 1) {
|
||||
log_print(LOG_ERROR, "%s: parse error", plugin.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct device_entry *entry = malloc(sizeof(struct device_entry));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "%s: out of memory", plugin.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->devpath = strdup(tokens->field[0]);
|
||||
|
||||
log_print(LOG_INFO, "%s: added device '%s'", plugin.name, entry->devpath);
|
||||
list_add_tail(&entry->list, &device_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
config_get_strtokens("p_diskstandby", "device", ",", 1, init_cb, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
struct device_entry *entry, *tmp;
|
||||
list_for_each_entry_safe(entry, tmp, &device_list, list) {
|
||||
free(entry->devpath);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "diskstandby",
|
||||
.interval = 60,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -1,102 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 04/2007 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
static char *buffer;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:read_cnt:COUNTER:15:0:U "
|
||||
"DS:read_sec:COUNTER:15:0:U "
|
||||
"DS:read_ms:COUNTER:15:0:U "
|
||||
"DS:write_cnt:COUNTER:15:0:U "
|
||||
"DS:write_sec:COUNTER:15:0:U "
|
||||
"DS:write_ms:COUNTER:15:0:U "
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
FILE *fp = fopen("/proc/diskstats", "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin diskstats: fopen()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buffer, BUFSIZE, fp) != NULL) {
|
||||
int major, minor;
|
||||
char device[16];
|
||||
unsigned int val[11];
|
||||
int cnt = sscanf(buffer, "%d %d %s %u %u %u %u %u %u %u %u %u %u %u",
|
||||
&major, &minor, device, &val[0],
|
||||
&val[1], &val[2], &val[3], &val[4],
|
||||
&val[5], &val[6], &val[7], &val[8],
|
||||
&val[9], &val[10]);
|
||||
|
||||
if (cnt != 14 || val[0] == 0 || val[1] == 0)
|
||||
continue;
|
||||
|
||||
char filename[32];
|
||||
int len = snprintf(filename, sizeof(filename), "disk-%s.rrd", device);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, 0,
|
||||
"%u:%u:%u:%u:%u:%u",
|
||||
val[0], val[2], val[3],
|
||||
val[4], val[6], val[7]);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
buffer = malloc(BUFSIZE);
|
||||
return (buffer == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "diskstat",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -1,212 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 12/2012 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "helper.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
#include "sockaddr.h"
|
||||
|
||||
#define RESP_SIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
struct server_entry {
|
||||
struct list_head list;
|
||||
|
||||
char *name;
|
||||
int errors;
|
||||
struct sockaddr_in sa;
|
||||
};
|
||||
|
||||
static LIST_HEAD(server_list);
|
||||
static char *resp_buf;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:temperature:GAUGE:90:0:100"
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
struct server_entry *entry;
|
||||
list_for_each_entry(entry, &server_list, list) {
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == -1) {
|
||||
log_print(LOG_WARN, "%s: socket()", plugin.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
int ret = connect(sock, (struct sockaddr *)&entry->sa, sizeof(entry->sa));
|
||||
if (ret != 0) {
|
||||
if (entry->errors++ == 0)
|
||||
log_print(LOG_ERROR, "%s: connect(%s)", plugin.name, get_sockaddr_buf(&entry->sa));
|
||||
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
int pos = 0;
|
||||
int len;
|
||||
do {
|
||||
len = read(sock, resp_buf + pos, RESP_SIZE - pos);
|
||||
if ((pos == 0) && (len <= 0)) {
|
||||
if (entry->errors++ == 0)
|
||||
log_print(LOG_ERROR, "%s: read()", plugin.name);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
pos += len;
|
||||
} while (len > 0);
|
||||
|
||||
close(sock);
|
||||
|
||||
if (pos == 0)
|
||||
continue;
|
||||
|
||||
resp_buf[pos] = '\0';
|
||||
|
||||
/* '|/dev/sda|OCZ-VERTEX3|128|C||/dev/sdb|HDT722525DLA380|SLP|*||/dev/sdc|Generic STORAGE DEVICE|NA|*|' */
|
||||
|
||||
char *tok, *tmp = NULL, *resp = resp_buf;
|
||||
int i = 0;
|
||||
char *device = NULL;
|
||||
int temperature = 0;
|
||||
while ((tok = strtok_r(resp, "|", &tmp)) != NULL) {
|
||||
if ((i % 4) == 0) {
|
||||
device = strrchr(tok, '/');
|
||||
if (device != NULL && *(device +1) == '\0')
|
||||
device = NULL;
|
||||
else
|
||||
device++;
|
||||
|
||||
} else if ((i % 4) == 2) {
|
||||
char *tmp2;
|
||||
|
||||
temperature = strtol(tok, &tmp2, 10);
|
||||
if (*tmp2 != '\0')
|
||||
device = NULL;
|
||||
|
||||
} else if ((i % 4) == 3) {
|
||||
if ((tok[0] == 'C') && (device != NULL)) {
|
||||
char filename[32];
|
||||
len = snprintf(filename, sizeof(filename), "%s-%s.rrd", plugin.name, device);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, 0, "%d", temperature);
|
||||
}
|
||||
|
||||
device = NULL;
|
||||
temperature = 0;
|
||||
}
|
||||
i++;
|
||||
|
||||
resp = NULL;
|
||||
}
|
||||
|
||||
if (entry->errors > 0) {
|
||||
log_print(LOG_ERROR, "%s: success (%s) after %d errors",
|
||||
plugin.name, entry->name, entry->errors);
|
||||
|
||||
entry->errors = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_cb(struct strtoken *tokens, void *privdata)
|
||||
{
|
||||
if (tokens->count != 2) {
|
||||
log_print(LOG_ERROR, "%s: parse error", plugin.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct server_entry *entry = malloc(sizeof(struct server_entry));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "%s: out of memory", plugin.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->name = strdup(tokens->field[0]);
|
||||
entry->errors = 0;
|
||||
|
||||
if (parse_sockaddr(tokens->field[1], &entry->sa) < 0) {
|
||||
log_print(LOG_ERROR, "%s: invalid address: <%s>", plugin.name, tokens->field[1]);
|
||||
free(entry->name);
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_print(LOG_INFO, "%s: added server '%s'", plugin.name, entry->name);
|
||||
list_add_tail(&entry->list, &server_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
resp_buf = malloc(RESP_SIZE);
|
||||
if (resp_buf == NULL) {
|
||||
log_print(LOG_ERROR, "%s: out of memory", plugin.name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
config_get_strtokens("p_hddtemp", "server", ",", 2, init_cb, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
struct server_entry *entry, *tmp;
|
||||
list_for_each_entry_safe(entry, tmp, &server_list, list) {
|
||||
free(entry->name);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
free(resp_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "hddtemp",
|
||||
.interval = 60,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
125
plugins/hwmon.c
125
plugins/hwmon.c
@ -1,125 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 10/2006 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "helper.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
struct hwmon_entry {
|
||||
struct list_head list;
|
||||
char *name;
|
||||
char *path;
|
||||
};
|
||||
|
||||
static LIST_HEAD(hwmon_list);
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:temp:GAUGE:15:0:U "
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
struct hwmon_entry *entry;
|
||||
list_for_each_entry(entry, &hwmon_list, list) {
|
||||
FILE *fp = fopen(entry->path, "r");
|
||||
if (fp == NULL) {
|
||||
log_print(LOG_WARN, "plugin hwmon: fopen(%s)", entry->path);
|
||||
continue;
|
||||
}
|
||||
|
||||
int temp;
|
||||
if (fscanf(fp, "%d\n", &temp) != 1) {
|
||||
log_print(LOG_WARN, "plugin hwmon: fscanf()");
|
||||
fclose(fp);
|
||||
continue;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
char filename[32];
|
||||
int len = snprintf(filename, sizeof(filename), "hwmon-%s.rrd", entry->name);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, 0, "%d", temp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_cb(struct strtoken *tokens, void *privdata)
|
||||
{
|
||||
if (tokens->count != 2) {
|
||||
log_print(LOG_ERROR, "p_hwmon: parse error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct hwmon_entry *entry = malloc(sizeof(struct hwmon_entry));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "p_hwmon: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->name = strdup(tokens->field[0]);
|
||||
entry->path = strdup(tokens->field[1]);
|
||||
|
||||
log_print(LOG_DEBUG, "p_hwmon: added sensor '%s' (%s)", entry->name, entry->path);
|
||||
list_add_tail(&entry->list, &hwmon_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
config_get_strtokens("p_hwmon", "temp", ",", 2, init_cb, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
struct hwmon_entry *entry, *tmp;
|
||||
list_for_each_entry_safe(entry, tmp, &hwmon_list, list) {
|
||||
free(entry->name);
|
||||
free(entry->path);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "hwmon",
|
||||
.interval = 10,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
204
plugins/mysql.c
204
plugins/mysql.c
@ -1,204 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 10/2006 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "helper.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
|
||||
#include "mysql_helper.h"
|
||||
|
||||
#define DS_TRAFFIC 1
|
||||
#define DS_COMMANDS 2
|
||||
#define DS_QCACHE 3
|
||||
#define DS_THREADS 4
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
struct server_entry {
|
||||
struct list_head list;
|
||||
void *mysql;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static LIST_HEAD(server_list);
|
||||
|
||||
static const char *traffic_ds_def = {
|
||||
"DS:bytes_received:COUNTER:90:0:U "
|
||||
"DS:bytes_sent:COUNTER:90:0:U "
|
||||
};
|
||||
|
||||
static const char *commands_ds_def = {
|
||||
"DS:com_delete:COUNTER:90:0:U "
|
||||
"DS:com_insert:COUNTER:90:0:U "
|
||||
"DS:com_select:COUNTER:90:0:U "
|
||||
"DS:com_update:COUNTER:90:0:U "
|
||||
"DS:connections:COUNTER:90:0:U "
|
||||
"DS:questions:COUNTER:90:0:U "
|
||||
};
|
||||
|
||||
static const char *qcache_ds_def = {
|
||||
"DS:qc_free_blocks:GAUGE:90:0:U "
|
||||
"DS:qc_free_memory:GAUGE:90:0:U "
|
||||
"DS:qc_hits:COUNTER:90:0:U "
|
||||
"DS:qc_inserts:COUNTER:90:0:U "
|
||||
"DS:qc_lowmem_prunes:COUNTER:90:0:U "
|
||||
"DS:qc_not_cached:COUNTER:90:0:U "
|
||||
"DS:qc_queries_in_cache:GAUGE:90:0:U "
|
||||
"DS:qc_total_blocks:GAUGE:90:0:U "
|
||||
};
|
||||
|
||||
static const char *threads_ds_def = {
|
||||
"DS:threads_cached:GAUGE:90:0:U "
|
||||
"DS:threads_connected:GAUGE:90:0:U "
|
||||
"DS:threads_created:COUNTER:90:0:U "
|
||||
"DS:threads_running:GAUGE:90:0:U "
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
switch (ds_id) {
|
||||
case DS_TRAFFIC:
|
||||
return traffic_ds_def;
|
||||
|
||||
case DS_COMMANDS:
|
||||
return commands_ds_def;
|
||||
|
||||
case DS_QCACHE:
|
||||
return qcache_ds_def;
|
||||
|
||||
case DS_THREADS:
|
||||
return threads_ds_def;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
struct mysql_stats stats;
|
||||
char filename[32];
|
||||
int len;
|
||||
|
||||
memset(&stats, 0, sizeof(struct mysql_stats));
|
||||
|
||||
struct server_entry *entry;
|
||||
list_for_each_entry(entry, &server_list, list) {
|
||||
if (ping_connection(entry->mysql) != 0)
|
||||
continue;
|
||||
|
||||
if (get_stats(entry->mysql, &stats) != 0)
|
||||
continue;
|
||||
|
||||
len = snprintf(filename, sizeof(filename), "mysql-traffic-%s.rrd", entry->name);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, DS_TRAFFIC, "%llu:%llu",
|
||||
stats.bytes_received, stats.bytes_sent);
|
||||
|
||||
len = snprintf(filename, sizeof(filename), "mysql-commands-%s.rrd", entry->name);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, DS_COMMANDS, "%llu:%llu:%llu:%llu:%llu:%llu",
|
||||
stats.com_delete, stats.com_insert,
|
||||
stats.com_select, stats.com_update,
|
||||
stats.connections, stats.questions);
|
||||
|
||||
len = snprintf(filename, sizeof(filename), "mysql-qcache-%s.rrd", entry->name);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, DS_QCACHE, "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
|
||||
stats.qc_free_blocks, stats.qc_free_memory,
|
||||
stats.qc_hits, stats.qc_inserts,
|
||||
stats.qc_lowmem_prunes, stats.qc_not_cached,
|
||||
stats.qc_queries_in_cache, stats.qc_total_blocks);
|
||||
|
||||
len = snprintf(filename, sizeof(filename), "mysql-threads-%s.rrd", entry->name);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, DS_THREADS, "%llu:%llu:%llu:%llu",
|
||||
stats.threads_cached, stats.threads_connected,
|
||||
stats.threads_created, stats.threads_running);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_cb(struct strtoken *tokens, void *privdata)
|
||||
{
|
||||
if (tokens->count != 4) {
|
||||
log_print(LOG_ERROR, "p_mysql: parse error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *mysql = init_connection(tokens->field[1], tokens->field[2], tokens->field[3]);
|
||||
if (mysql == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct server_entry *entry = malloc(sizeof(struct server_entry));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "p_mysql: out of memory");
|
||||
close_connection(mysql);
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->name = strdup(tokens->field[0]);
|
||||
entry->mysql = mysql;
|
||||
|
||||
log_print(LOG_DEBUG, "p_mysql: added server '%s'", entry->name);
|
||||
list_add_tail(&entry->list, &server_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
config_get_strtokens("p_mysql", "server", ",", 4, init_cb, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
struct server_entry *entry, *tmp;
|
||||
list_for_each_entry_safe(entry, tmp, &server_list, list) {
|
||||
close_connection(entry->mysql);
|
||||
free(entry->name);
|
||||
free(entry);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "mysql",
|
||||
.interval = 60,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
@ -1,141 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
#include "logging.h"
|
||||
#include "mysql_helper.h"
|
||||
|
||||
void * init_connection(const char *host, const char *user, const char *pass)
|
||||
{
|
||||
MYSQL *con = NULL;
|
||||
|
||||
con = mysql_init(con);
|
||||
if (con == NULL)
|
||||
return NULL;
|
||||
|
||||
con = mysql_real_connect(con, host, user, pass, NULL, 0, NULL, 0);
|
||||
if (con == NULL) {
|
||||
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return con;
|
||||
}
|
||||
|
||||
int ping_connection(void *mysql)
|
||||
{
|
||||
MYSQL *con = mysql;
|
||||
|
||||
return mysql_ping(con);
|
||||
}
|
||||
|
||||
int close_connection(void *mysql)
|
||||
{
|
||||
MYSQL *con = mysql;
|
||||
|
||||
mysql_close(con);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_stats(void *mysql, struct mysql_stats *stats)
|
||||
{
|
||||
MYSQL *con = mysql;
|
||||
|
||||
char *query;
|
||||
if (mysql_get_server_version(con) >= 50002)
|
||||
query = "SHOW GLOBAL STATUS";
|
||||
else
|
||||
query = "SHOW STATUS";
|
||||
|
||||
if (mysql_real_query(con, query, strlen(query))) {
|
||||
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
|
||||
return -1;
|
||||
}
|
||||
|
||||
MYSQL_RES *res;
|
||||
res = mysql_store_result(con);
|
||||
if (res == NULL) {
|
||||
log_print(LOG_ERROR, "p_mysql: %s", mysql_error(con));
|
||||
return -1;
|
||||
}
|
||||
|
||||
MYSQL_ROW row;
|
||||
while ((row = mysql_fetch_row(res))) {
|
||||
char *key;
|
||||
unsigned long long val;
|
||||
|
||||
key = row[0];
|
||||
val = atoll(row[1]);
|
||||
|
||||
if (!strncmp(key, "Bytes_", 6)) {
|
||||
if (!strcmp(key +6, "received"))
|
||||
stats->bytes_received = val;
|
||||
|
||||
else if (!strcmp(key +6, "sent"))
|
||||
stats->bytes_sent = val;
|
||||
|
||||
} else if (!strncmp(key, "Com_", 4)) {
|
||||
if (!strcmp(key +4, "delete"))
|
||||
stats->com_delete = val;
|
||||
|
||||
else if (!strcmp(key +4, "insert"))
|
||||
stats->com_insert = val;
|
||||
|
||||
else if (!strcmp(key +4, "select"))
|
||||
stats->com_select = val;
|
||||
|
||||
else if (!strcmp(key +4, "update"))
|
||||
stats->com_update = val;
|
||||
|
||||
} else if (!strcmp(key, "Connections")) {
|
||||
stats->connections = val;
|
||||
|
||||
} else if (!strncmp(key, "Qcache_", 7)) {
|
||||
if (!strcmp(key +7, "free_blocks"))
|
||||
stats->qc_free_blocks = val;
|
||||
|
||||
else if (!strcmp(key +7, "free_memory"))
|
||||
stats->qc_free_memory = val;
|
||||
|
||||
else if (!strcmp(key +7, "hits"))
|
||||
stats->qc_hits = val;
|
||||
|
||||
else if (!strcmp(key +7, "inserts"))
|
||||
stats->qc_inserts = val;
|
||||
|
||||
else if (!strcmp(key +7, "lowmem_prunes"))
|
||||
stats->qc_lowmem_prunes = val;
|
||||
|
||||
else if (!strcmp(key +7, "not_cached"))
|
||||
stats->qc_not_cached = val;
|
||||
|
||||
else if (!strcmp(key +7, "queries_in_cache"))
|
||||
stats->qc_queries_in_cache = val;
|
||||
|
||||
else if (!strcmp(key +7, "total_blocks"))
|
||||
stats->qc_total_blocks = val;
|
||||
|
||||
} else if (!strcmp(key, "Questions")) {
|
||||
stats->questions = val;
|
||||
|
||||
} else if (!strncmp(key, "Threads_", 8)) {
|
||||
if (!strcmp(key, "Threads_cached"))
|
||||
stats->threads_cached = val;
|
||||
|
||||
else if (!strcmp(key, "Threads_connected"))
|
||||
stats->threads_connected = val;
|
||||
|
||||
else if (!strcmp(key, "Threads_created"))
|
||||
stats->threads_created = val;
|
||||
|
||||
else if (!strcmp(key, "Threads_running"))
|
||||
stats->threads_running = val;
|
||||
}
|
||||
}
|
||||
|
||||
mysql_free_result(res);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#ifndef _MYSQL_HELPER_H_
|
||||
#define _MYSQL_HELPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct mysql_stats {
|
||||
uint64_t bytes_received;
|
||||
uint64_t bytes_sent;
|
||||
uint64_t com_delete;
|
||||
uint64_t com_insert;
|
||||
uint64_t com_select;
|
||||
uint64_t com_update;
|
||||
uint64_t connections;
|
||||
uint64_t qc_free_blocks;
|
||||
uint64_t qc_free_memory;
|
||||
uint64_t qc_hits;
|
||||
uint64_t qc_inserts;
|
||||
uint64_t qc_lowmem_prunes;
|
||||
uint64_t qc_not_cached;
|
||||
uint64_t qc_queries_in_cache;
|
||||
uint64_t qc_total_blocks;
|
||||
uint64_t questions;
|
||||
uint64_t threads_cached;
|
||||
uint64_t threads_connected;
|
||||
uint64_t threads_created;
|
||||
uint64_t threads_running;
|
||||
};
|
||||
|
||||
void * init_connection(const char *host, const char *user, const char *pass);
|
||||
int ping_connection(void *mysql);
|
||||
int close_connection(void *mysql);
|
||||
|
||||
int get_stats(void *mysql, struct mysql_stats *stats);
|
||||
|
||||
#endif /* _MYSQL_HELPER_H_ */
|
492
plugins/sgio.c
492
plugins/sgio.c
@ -1,492 +0,0 @@
|
||||
/* sgio.c - by Mark Lord (C) 2007 -- freely distributable */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/sg.h>
|
||||
|
||||
#include "sgio.h"
|
||||
//#include "hdparm.h"
|
||||
|
||||
#include <linux/hdreg.h>
|
||||
|
||||
extern int verbose;
|
||||
extern int prefer_ata12;
|
||||
|
||||
/*
|
||||
* Taskfile layout for SG_ATA_16 cdb:
|
||||
*
|
||||
* LBA48:
|
||||
* cdb[ 3] = hob_feat
|
||||
* cdb[ 5] = hob_nsect
|
||||
* cdb[ 7] = hob_lbal
|
||||
* cdb[ 9] = hob_lbam
|
||||
* cdb[11] = hob_lbah
|
||||
*
|
||||
* LBA28/LBA48:
|
||||
* cdb[ 4] = feat
|
||||
* cdb[ 6] = nsect
|
||||
* cdb[ 8] = lbal
|
||||
* cdb[10] = lbam
|
||||
* cdb[12] = lbah
|
||||
* cdb[13] = device
|
||||
* cdb[14] = command
|
||||
*
|
||||
* Taskfile layout for SG_ATA_12 cdb:
|
||||
*
|
||||
* cdb[ 3] = feat
|
||||
* cdb[ 4] = nsect
|
||||
* cdb[ 5] = lbal
|
||||
* cdb[ 6] = lbam
|
||||
* cdb[ 7] = lbah
|
||||
* cdb[ 8] = device
|
||||
* cdb[ 9] = command
|
||||
*
|
||||
* dxfer_direction choices:
|
||||
* SG_DXFER_TO_DEV, SG_DXFER_FROM_DEV, SG_DXFER_NONE
|
||||
*/
|
||||
|
||||
static inline int needs_lba48 (__u8 ata_op, __u64 lba, unsigned int nsect)
|
||||
{
|
||||
const __u64 lba28_limit = (1<<28) - 1;
|
||||
|
||||
switch (ata_op) {
|
||||
case ATA_OP_READ_PIO_EXT:
|
||||
case ATA_OP_READ_DMA_EXT:
|
||||
case ATA_OP_WRITE_PIO_EXT:
|
||||
case ATA_OP_WRITE_DMA_EXT:
|
||||
case ATA_OP_READ_VERIFY_EXT:
|
||||
case ATA_OP_WRITE_UNC_EXT:
|
||||
case ATA_OP_READ_NATIVE_MAX_EXT:
|
||||
case ATA_OP_SET_MAX_EXT:
|
||||
case ATA_OP_FLUSHCACHE_EXT:
|
||||
return 1;
|
||||
}
|
||||
if (lba >= lba28_limit)
|
||||
return 1;
|
||||
if (nsect) {
|
||||
if (nsect > 0xff)
|
||||
return 1;
|
||||
if ((lba + nsect - 1) >= lba28_limit)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tf_init (struct ata_tf *tf, __u8 ata_op, __u64 lba, unsigned int nsect)
|
||||
{
|
||||
memset(tf, 0, sizeof(*tf));
|
||||
tf->command = ata_op;
|
||||
tf->dev = ATA_USING_LBA;
|
||||
tf->lob.lbal = lba;
|
||||
tf->lob.lbam = lba >> 8;
|
||||
tf->lob.lbah = lba >> 16;
|
||||
tf->lob.nsect = nsect;
|
||||
if (needs_lba48(ata_op, lba, nsect)) {
|
||||
tf->is_lba48 = 1;
|
||||
tf->hob.nsect = nsect >> 8;
|
||||
tf->hob.lbal = lba >> 24;
|
||||
tf->hob.lbam = lba >> 32;
|
||||
tf->hob.lbah = lba >> 40;
|
||||
} else {
|
||||
tf->dev |= (lba >> 24) & 0x0f;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SG_IO
|
||||
|
||||
__u64 tf_to_lba (struct ata_tf *tf)
|
||||
{
|
||||
__u32 lba24, lbah;
|
||||
__u64 lba64;
|
||||
|
||||
lba24 = (tf->lob.lbah << 16) | (tf->lob.lbam << 8) | (tf->lob.lbal);
|
||||
if (tf->is_lba48)
|
||||
lbah = (tf->hob.lbah << 16) | (tf->hob.lbam << 8) | (tf->hob.lbal);
|
||||
else
|
||||
lbah = (tf->dev & 0x0f);
|
||||
lba64 = (((__u64)lbah) << 24) | (__u64)lba24;
|
||||
return lba64;
|
||||
}
|
||||
|
||||
enum {
|
||||
SG_CDB2_TLEN_NODATA = 0 << 0,
|
||||
SG_CDB2_TLEN_FEAT = 1 << 0,
|
||||
SG_CDB2_TLEN_NSECT = 2 << 0,
|
||||
|
||||
SG_CDB2_TLEN_BYTES = 0 << 2,
|
||||
SG_CDB2_TLEN_SECTORS = 1 << 2,
|
||||
|
||||
SG_CDB2_TDIR_TO_DEV = 0 << 3,
|
||||
SG_CDB2_TDIR_FROM_DEV = 1 << 3,
|
||||
|
||||
SG_CDB2_CHECK_COND = 1 << 5,
|
||||
};
|
||||
|
||||
static void dump_bytes (const char *prefix, unsigned char *p, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (prefix)
|
||||
fprintf(stderr, "%s: ", prefix);
|
||||
for (i = 0; i < len; ++i)
|
||||
fprintf(stderr, " %02x", p[i]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
int sg16 (int fd, int rw, int dma, struct ata_tf *tf,
|
||||
void *data, unsigned int data_bytes, unsigned int timeout_secs)
|
||||
{
|
||||
unsigned char cdb[SG_ATA_16_LEN];
|
||||
unsigned char sb[32], *desc;
|
||||
struct scsi_sg_io_hdr io_hdr;
|
||||
|
||||
memset(&cdb, 0, sizeof(cdb));
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
memset(&io_hdr, 0, sizeof(struct scsi_sg_io_hdr));
|
||||
|
||||
if (dma) {
|
||||
//cdb[1] = data ? (rw ? SG_ATA_PROTO_UDMA_OUT : SG_ATA_PROTO_UDMA_IN) : SG_ATA_PROTO_NON_DATA;
|
||||
cdb[1] = data ? SG_ATA_PROTO_DMA : SG_ATA_PROTO_NON_DATA;
|
||||
} else {
|
||||
cdb[1] = data ? (rw ? SG_ATA_PROTO_PIO_OUT : SG_ATA_PROTO_PIO_IN) : SG_ATA_PROTO_NON_DATA;
|
||||
}
|
||||
cdb[ 2] = SG_CDB2_CHECK_COND;
|
||||
if (data) {
|
||||
cdb[2] |= SG_CDB2_TLEN_NSECT | SG_CDB2_TLEN_SECTORS;
|
||||
cdb[2] |= rw ? SG_CDB2_TDIR_TO_DEV : SG_CDB2_TDIR_FROM_DEV;
|
||||
}
|
||||
|
||||
if (!prefer_ata12 || tf->is_lba48) {
|
||||
cdb[ 0] = SG_ATA_16;
|
||||
cdb[ 4] = tf->lob.feat;
|
||||
cdb[ 6] = tf->lob.nsect;
|
||||
cdb[ 8] = tf->lob.lbal;
|
||||
cdb[10] = tf->lob.lbam;
|
||||
cdb[12] = tf->lob.lbah;
|
||||
cdb[13] = tf->dev;
|
||||
cdb[14] = tf->command;
|
||||
if (tf->is_lba48) {
|
||||
cdb[ 1] |= SG_ATA_LBA48;
|
||||
cdb[ 3] = tf->hob.feat;
|
||||
cdb[ 5] = tf->hob.nsect;
|
||||
cdb[ 7] = tf->hob.lbal;
|
||||
cdb[ 9] = tf->hob.lbam;
|
||||
cdb[11] = tf->hob.lbah;
|
||||
}
|
||||
io_hdr.cmd_len = SG_ATA_16_LEN;
|
||||
} else {
|
||||
cdb[ 0] = SG_ATA_12;
|
||||
cdb[ 3] = tf->lob.feat;
|
||||
cdb[ 4] = tf->lob.nsect;
|
||||
cdb[ 5] = tf->lob.lbal;
|
||||
cdb[ 6] = tf->lob.lbam;
|
||||
cdb[ 7] = tf->lob.lbah;
|
||||
cdb[ 8] = tf->dev;
|
||||
cdb[ 9] = tf->command;
|
||||
io_hdr.cmd_len = SG_ATA_12_LEN;
|
||||
}
|
||||
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.mx_sb_len = sizeof(sb);
|
||||
io_hdr.dxfer_direction = data ? (rw ? SG_DXFER_TO_DEV : SG_DXFER_FROM_DEV) : SG_DXFER_NONE;
|
||||
io_hdr.dxfer_len = data ? data_bytes : 0;
|
||||
io_hdr.dxferp = data;
|
||||
io_hdr.cmdp = cdb;
|
||||
io_hdr.sbp = sb;
|
||||
io_hdr.pack_id = tf_to_lba(tf);
|
||||
io_hdr.timeout = (timeout_secs ? timeout_secs : 5) * 1000; /* msecs */
|
||||
|
||||
if (verbose)
|
||||
dump_bytes("outgoing cdb", cdb, sizeof(cdb));
|
||||
if (ioctl(fd, SG_IO, &io_hdr) == -1) {
|
||||
if (verbose)
|
||||
perror("ioctl(fd,SG_IO)");
|
||||
return -1; /* SG_IO not supported */
|
||||
}
|
||||
if (verbose)
|
||||
fprintf(stderr, "SG_IO: ATA_%u status=0x%x, host_status=0x%x, driver_status=0x%x\n",
|
||||
io_hdr.cmd_len, io_hdr.status, io_hdr.host_status, io_hdr.driver_status);
|
||||
|
||||
if (io_hdr.host_status || io_hdr.driver_status != SG_DRIVER_SENSE
|
||||
|| (io_hdr.status && io_hdr.status != SG_CHECK_CONDITION))
|
||||
{
|
||||
if (verbose)
|
||||
fprintf(stderr, "SG_IO: bad response (not CHECK_CONDITION)\n");
|
||||
errno = EBADE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
desc = sb + 8;
|
||||
if (sb[0] != 0x72 || sb[7] < 14 || desc[0] != 0x09 || desc[1] < 0x0c) {
|
||||
if (verbose)
|
||||
dump_bytes("SG_IO: bad/missing sense data, sb[]", sb, sizeof(sb));
|
||||
errno = EBADE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
dump_bytes("SG_IO: sb[]", sb, sizeof(sb));
|
||||
|
||||
if (verbose) {
|
||||
int len = desc[1], maxlen = sizeof(sb) - 8 - 2;
|
||||
if (len > maxlen)
|
||||
len = maxlen;
|
||||
dump_bytes("SG_IO: desc[]", desc, len);
|
||||
}
|
||||
|
||||
tf->is_lba48 = desc[ 2] & 1;
|
||||
tf->error = desc[ 3];
|
||||
tf->lob.nsect = desc[ 5];
|
||||
tf->lob.lbal = desc[ 7];
|
||||
tf->lob.lbam = desc[ 9];
|
||||
tf->lob.lbah = desc[11];
|
||||
tf->dev = desc[12];
|
||||
tf->status = desc[13];
|
||||
tf->hob.feat = 0;
|
||||
if (tf->is_lba48) {
|
||||
tf->hob.nsect = desc[ 4];
|
||||
tf->hob.lbal = desc[ 6];
|
||||
tf->hob.lbam = desc[ 8];
|
||||
tf->hob.lbah = desc[10];
|
||||
} else {
|
||||
tf->hob.nsect = 0;
|
||||
tf->hob.lbal = 0;
|
||||
tf->hob.lbam = 0;
|
||||
tf->hob.lbah = 0;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr, " ATA_%u stat=%02x err=%02x nsect=%02x lbal=%02x lbam=%02x lbah=%02x dev=%02x\n",
|
||||
io_hdr.cmd_len, tf->status, tf->error, tf->lob.nsect, tf->lob.lbal, tf->lob.lbam, tf->lob.lbah, tf->dev);
|
||||
|
||||
if (tf->status & (ATA_STAT_ERR | ATA_STAT_DRQ)) {
|
||||
if (verbose) {
|
||||
fprintf(stderr, "I/O error, ata_op=0x%02x ata_status=0x%02x ata_error=0x%02x\n",
|
||||
tf->command, tf->status, tf->error);
|
||||
}
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SG_IO */
|
||||
|
||||
int do_drive_cmd (int fd, unsigned char *args)
|
||||
{
|
||||
#ifdef SG_IO
|
||||
|
||||
struct ata_tf tf;
|
||||
void *data = NULL;
|
||||
unsigned int data_bytes = 0;
|
||||
int rc;
|
||||
|
||||
if (args == NULL)
|
||||
goto use_legacy_ioctl;
|
||||
/*
|
||||
* Reformat and try to issue via SG_IO:
|
||||
*/
|
||||
if (args[3]) {
|
||||
data_bytes = args[3] * 512;
|
||||
data = args + 4;
|
||||
}
|
||||
tf_init(&tf, args[0], 0, args[1]);
|
||||
tf.lob.feat = args[2];
|
||||
if (tf.command == ATA_OP_SMART) {
|
||||
tf.lob.nsect = args[3];
|
||||
tf.lob.lbal = args[1];
|
||||
tf.lob.lbam = 0x4f;
|
||||
tf.lob.lbah = 0xc2;
|
||||
}
|
||||
|
||||
rc = sg16(fd, SG_READ, SG_PIO, &tf, data, data_bytes, 0);
|
||||
if (rc == -1) {
|
||||
if (errno == EINVAL || errno == ENODEV)
|
||||
goto use_legacy_ioctl;
|
||||
}
|
||||
|
||||
if (rc == 0 || errno == EIO) {
|
||||
args[0] = tf.status;
|
||||
args[1] = tf.error;
|
||||
args[2] = tf.lob.nsect;
|
||||
}
|
||||
return rc;
|
||||
|
||||
use_legacy_ioctl:
|
||||
#endif /* SG_IO */
|
||||
if (verbose)
|
||||
fprintf(stderr, "Trying legacy HDIO_DRIVE_CMD\n");
|
||||
return ioctl(fd, HDIO_DRIVE_CMD, args);
|
||||
}
|
||||
|
||||
int do_taskfile_cmd (int fd, struct hdio_taskfile *r, unsigned int timeout_secs)
|
||||
{
|
||||
int rc;
|
||||
#ifdef SG_IO
|
||||
struct ata_tf tf;
|
||||
void *data = NULL;
|
||||
unsigned int data_bytes = 0;
|
||||
int rw = SG_READ;
|
||||
/*
|
||||
* Reformat and try to issue via SG_IO:
|
||||
*/
|
||||
tf_init(&tf, 0, 0, 0);
|
||||
#if 1 /* debugging */
|
||||
if (verbose) {
|
||||
printf("oflags.lob_all=0x%02x, flags={", r->oflags.lob_all);
|
||||
if (r->oflags.lob.feat) printf(" feat");
|
||||
if (r->oflags.lob.lbal) printf(" lbal");
|
||||
if (r->oflags.lob.nsect)printf(" nsect");
|
||||
if (r->oflags.lob.lbam) printf(" lbam");
|
||||
if (r->oflags.lob.lbah) printf(" lbah");
|
||||
if (r->oflags.lob.dev) printf(" dev");
|
||||
if (r->oflags.lob.command) printf(" command");
|
||||
printf(" }\n");
|
||||
printf("oflags.hob_all=0x%02x, flags={", r->oflags.hob_all);
|
||||
if (r->oflags.hob.feat) printf(" feat");
|
||||
if (r->oflags.hob.lbal) printf(" lbal");
|
||||
if (r->oflags.hob.nsect)printf(" nsect");
|
||||
if (r->oflags.hob.lbam) printf(" lbam");
|
||||
if (r->oflags.hob.lbah) printf(" lbah");
|
||||
printf(" }\n");
|
||||
}
|
||||
#endif
|
||||
if (r->oflags.lob.feat) tf.lob.feat = r->lob.feat;
|
||||
if (r->oflags.lob.lbal) tf.lob.lbal = r->lob.lbal;
|
||||
if (r->oflags.lob.nsect) tf.lob.nsect = r->lob.nsect;
|
||||
if (r->oflags.lob.lbam) tf.lob.lbam = r->lob.lbam;
|
||||
if (r->oflags.lob.lbah) tf.lob.lbah = r->lob.lbah;
|
||||
if (r->oflags.lob.dev) tf.dev = r->lob.dev;
|
||||
if (r->oflags.lob.command) tf.command = r->lob.command;
|
||||
if (r->oflags.hob_all || r->iflags.hob_all) {
|
||||
tf.is_lba48 = 1;
|
||||
if (r->oflags.hob.feat) tf.hob.feat = r->hob.feat;
|
||||
if (r->oflags.hob.lbal) tf.hob.lbal = r->hob.lbal;
|
||||
if (r->oflags.hob.nsect)tf.hob.nsect = r->hob.nsect;
|
||||
if (r->oflags.hob.lbam) tf.hob.lbam = r->hob.lbam;
|
||||
if (r->oflags.hob.lbah) tf.hob.lbah = r->hob.lbah;
|
||||
if (verbose)
|
||||
fprintf(stderr, "using LBA48 taskfile\n");
|
||||
}
|
||||
switch (r->cmd_req) {
|
||||
case TASKFILE_CMD_REQ_OUT:
|
||||
case TASKFILE_CMD_REQ_RAW_OUT:
|
||||
data_bytes = r->obytes;
|
||||
data = r->data;
|
||||
rw = SG_WRITE;
|
||||
break;
|
||||
case TASKFILE_CMD_REQ_IN:
|
||||
data_bytes = r->ibytes;
|
||||
data = r->data;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = sg16(fd, rw, SG_PIO, &tf, data, data_bytes, timeout_secs);
|
||||
if (rc == -1) {
|
||||
if (errno == EINVAL || errno == ENODEV)
|
||||
goto use_legacy_ioctl;
|
||||
}
|
||||
|
||||
if (rc == 0 || errno == EIO) {
|
||||
if (r->iflags.lob.feat) r->lob.feat = tf.error;
|
||||
if (r->iflags.lob.lbal) r->lob.lbal = tf.lob.lbal;
|
||||
if (r->iflags.lob.nsect) r->lob.nsect = tf.lob.nsect;
|
||||
if (r->iflags.lob.lbam) r->lob.lbam = tf.lob.lbam;
|
||||
if (r->iflags.lob.lbah) r->lob.lbah = tf.lob.lbah;
|
||||
if (r->iflags.lob.dev) r->lob.dev = tf.dev;
|
||||
if (r->iflags.lob.command) r->lob.command = tf.status;
|
||||
if (r->iflags.hob.feat) r->hob.feat = tf.hob.feat;
|
||||
if (r->iflags.hob.lbal) r->hob.lbal = tf.hob.lbal;
|
||||
if (r->iflags.hob.nsect) r->hob.nsect = tf.hob.nsect;
|
||||
if (r->iflags.hob.lbam) r->hob.lbam = tf.hob.lbam;
|
||||
if (r->iflags.hob.lbah) r->hob.lbah = tf.hob.lbah;
|
||||
}
|
||||
return rc;
|
||||
|
||||
use_legacy_ioctl:
|
||||
#else
|
||||
timeout_secs = 0; /* keep compiler happy */
|
||||
#endif /* SG_IO */
|
||||
if (verbose)
|
||||
fprintf(stderr, "trying legacy HDIO_DRIVE_TASKFILE\n");
|
||||
errno = 0;
|
||||
rc = ioctl(fd, HDIO_DRIVE_TASKFILE, r);
|
||||
if (verbose) {
|
||||
int err = errno;
|
||||
fprintf(stderr, "rc=%d, errno=%d, returned ATA registers: ", rc, err);
|
||||
if (r->iflags.lob.feat) fprintf(stderr, " er=%02x", r->lob.feat);
|
||||
if (r->iflags.lob.nsect) fprintf(stderr, " ns=%02x", r->lob.nsect);
|
||||
if (r->iflags.lob.lbal) fprintf(stderr, " ll=%02x", r->lob.lbal);
|
||||
if (r->iflags.lob.lbam) fprintf(stderr, " lm=%02x", r->lob.lbam);
|
||||
if (r->iflags.lob.lbah) fprintf(stderr, " lh=%02x", r->lob.lbah);
|
||||
if (r->iflags.lob.dev) fprintf(stderr, " dh=%02x", r->lob.dev);
|
||||
if (r->iflags.lob.command) fprintf(stderr, " st=%02x", r->lob.command);
|
||||
if (r->iflags.hob.feat) fprintf(stderr, " err=%02x", r->hob.feat);
|
||||
if (r->iflags.hob.nsect) fprintf(stderr, " err=%02x", r->hob.nsect);
|
||||
if (r->iflags.hob.lbal) fprintf(stderr, " err=%02x", r->hob.lbal);
|
||||
if (r->iflags.hob.lbam) fprintf(stderr, " err=%02x", r->hob.lbam);
|
||||
if (r->iflags.hob.lbah) fprintf(stderr, " err=%02x", r->hob.lbah);
|
||||
fprintf(stderr, "\n");
|
||||
errno = err;
|
||||
}
|
||||
if (rc == -1 && errno == EINVAL) {
|
||||
fprintf(stderr, "The running kernel lacks CONFIG_IDE_TASK_IOCTL support for this device.\n");
|
||||
errno = EINVAL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void init_hdio_taskfile (struct hdio_taskfile *r, __u8 ata_op, int rw, int force_lba48,
|
||||
__u64 lba, unsigned int nsect, int data_bytes)
|
||||
{
|
||||
memset(r, 0, sizeof(struct hdio_taskfile) + data_bytes);
|
||||
if (!data_bytes) {
|
||||
r->dphase = TASKFILE_DPHASE_NONE;
|
||||
r->cmd_req = TASKFILE_CMD_REQ_NODATA;
|
||||
} else if (rw == RW_WRITE) {
|
||||
r->dphase = TASKFILE_DPHASE_PIO_OUT;
|
||||
r->cmd_req = TASKFILE_CMD_REQ_RAW_OUT;
|
||||
r->obytes = data_bytes;
|
||||
} else { /* rw == RW_READ */
|
||||
r->dphase = TASKFILE_DPHASE_PIO_IN;
|
||||
r->cmd_req = TASKFILE_CMD_REQ_IN;
|
||||
r->ibytes = data_bytes;
|
||||
}
|
||||
r->lob.command = ata_op;
|
||||
r->oflags.lob.command = 1;
|
||||
r->oflags.lob.dev = 1;
|
||||
r->oflags.lob.lbal = 1;
|
||||
r->oflags.lob.lbam = 1;
|
||||
r->oflags.lob.lbah = 1;
|
||||
r->oflags.lob.nsect = 1;
|
||||
|
||||
r->iflags.lob.command = 1;
|
||||
r->iflags.lob.feat = 1;
|
||||
|
||||
r->lob.nsect = nsect;
|
||||
r->lob.lbal = lba;
|
||||
r->lob.lbam = lba >> 8;
|
||||
r->lob.lbah = lba >> 16;
|
||||
r->lob.dev = 0xa0 | ATA_USING_LBA;
|
||||
|
||||
if (needs_lba48(ata_op, lba, nsect) || force_lba48) {
|
||||
r->hob.nsect = nsect >> 8;
|
||||
r->hob.lbal = lba >> 24;
|
||||
r->hob.lbam = lba >> 32;
|
||||
r->hob.lbah = lba >> 40;
|
||||
r->oflags.hob.nsect = 1;
|
||||
r->oflags.hob.lbal = 1;
|
||||
r->oflags.hob.lbam = 1;
|
||||
r->oflags.hob.lbah = 1;
|
||||
} else {
|
||||
r->lob.dev |= (lba >> 24) & 0x0f;
|
||||
}
|
||||
}
|
230
plugins/sgio.h
230
plugins/sgio.h
@ -1,230 +0,0 @@
|
||||
/* prototypes and stuff for ATA command ioctls */
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum {
|
||||
ATA_OP_READ_PIO = 0x20,
|
||||
ATA_OP_READ_PIO_ONCE = 0x21,
|
||||
ATA_OP_READ_LONG = 0x22,
|
||||
ATA_OP_READ_LONG_ONCE = 0x23,
|
||||
ATA_OP_READ_PIO_EXT = 0x24,
|
||||
ATA_OP_READ_DMA_EXT = 0x25,
|
||||
ATA_OP_READ_FPDMA = 0x60, // NCQ
|
||||
ATA_OP_WRITE_PIO = 0x30,
|
||||
ATA_OP_WRITE_LONG = 0x32,
|
||||
ATA_OP_WRITE_LONG_ONCE = 0x33,
|
||||
ATA_OP_WRITE_PIO_EXT = 0x34,
|
||||
ATA_OP_WRITE_DMA_EXT = 0x35,
|
||||
ATA_OP_WRITE_FPDMA = 0x61, // NCQ
|
||||
ATA_OP_READ_VERIFY = 0x40,
|
||||
ATA_OP_READ_VERIFY_ONCE = 0x41,
|
||||
ATA_OP_READ_VERIFY_EXT = 0x42,
|
||||
ATA_OP_WRITE_UNC_EXT = 0x45, // lba48, no data, uses feat reg
|
||||
ATA_OP_FORMAT_TRACK = 0x50,
|
||||
ATA_OP_DOWNLOAD_MICROCODE = 0x92,
|
||||
ATA_OP_STANDBYNOW2 = 0x94,
|
||||
ATA_OP_CHECKPOWERMODE2 = 0x98,
|
||||
ATA_OP_SLEEPNOW2 = 0x99,
|
||||
ATA_OP_PIDENTIFY = 0xa1,
|
||||
ATA_OP_READ_NATIVE_MAX = 0xf8,
|
||||
ATA_OP_READ_NATIVE_MAX_EXT = 0x27,
|
||||
ATA_OP_SMART = 0xb0,
|
||||
ATA_OP_DCO = 0xb1,
|
||||
ATA_OP_ERASE_SECTORS = 0xc0,
|
||||
ATA_OP_READ_DMA = 0xc8,
|
||||
ATA_OP_WRITE_DMA = 0xca,
|
||||
ATA_OP_DOORLOCK = 0xde,
|
||||
ATA_OP_DOORUNLOCK = 0xdf,
|
||||
ATA_OP_STANDBYNOW1 = 0xe0,
|
||||
ATA_OP_IDLEIMMEDIATE = 0xe1,
|
||||
ATA_OP_SETIDLE = 0xe3,
|
||||
ATA_OP_SET_MAX = 0xf9,
|
||||
ATA_OP_SET_MAX_EXT = 0x37,
|
||||
ATA_OP_SET_MULTIPLE = 0xc6,
|
||||
ATA_OP_CHECKPOWERMODE1 = 0xe5,
|
||||
ATA_OP_SLEEPNOW1 = 0xe6,
|
||||
ATA_OP_FLUSHCACHE = 0xe7,
|
||||
ATA_OP_FLUSHCACHE_EXT = 0xea,
|
||||
ATA_OP_IDENTIFY = 0xec,
|
||||
ATA_OP_SETFEATURES = 0xef,
|
||||
ATA_OP_SECURITY_SET_PASS = 0xf1,
|
||||
ATA_OP_SECURITY_UNLOCK = 0xf2,
|
||||
ATA_OP_SECURITY_ERASE_PREPARE = 0xf3,
|
||||
ATA_OP_SECURITY_ERASE_UNIT = 0xf4,
|
||||
ATA_OP_SECURITY_FREEZE_LOCK = 0xf5,
|
||||
ATA_OP_SECURITY_DISABLE = 0xf6,
|
||||
};
|
||||
|
||||
/*
|
||||
* Some useful ATA register bits
|
||||
*/
|
||||
enum {
|
||||
ATA_USING_LBA = (1 << 6),
|
||||
ATA_STAT_DRQ = (1 << 3),
|
||||
ATA_STAT_ERR = (1 << 0),
|
||||
};
|
||||
|
||||
/*
|
||||
* Useful parameters for init_hdio_taskfile():
|
||||
*/
|
||||
enum { RW_READ = 0,
|
||||
RW_WRITE = 1,
|
||||
LBA28_OK = 0,
|
||||
LBA48_FORCE = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* Definitions and structures for use with SG_IO + ATA_16:
|
||||
*/
|
||||
struct ata_lba_regs {
|
||||
__u8 feat;
|
||||
__u8 nsect;
|
||||
__u8 lbal;
|
||||
__u8 lbam;
|
||||
__u8 lbah;
|
||||
};
|
||||
struct ata_tf {
|
||||
__u8 dev;
|
||||
__u8 command;
|
||||
__u8 error;
|
||||
__u8 status;
|
||||
__u8 is_lba48;
|
||||
struct ata_lba_regs lob;
|
||||
struct ata_lba_regs hob;
|
||||
};
|
||||
|
||||
/*
|
||||
* Definitions and structures for use with HDIO_DRIVE_TASKFILE:
|
||||
*/
|
||||
|
||||
enum {
|
||||
/*
|
||||
* These (redundantly) specify the category of the request
|
||||
*/
|
||||
TASKFILE_CMD_REQ_NODATA = 0, /* ide: IDE_DRIVE_TASK_NO_DATA */
|
||||
TASKFILE_CMD_REQ_IN = 2, /* ide: IDE_DRIVE_TASK_IN */
|
||||
TASKFILE_CMD_REQ_OUT = 3, /* ide: IDE_DRIVE_TASK_OUT */
|
||||
TASKFILE_CMD_REQ_RAW_OUT= 4, /* ide: IDE_DRIVE_TASK_RAW_WRITE */
|
||||
/*
|
||||
* These specify the method of transfer (pio, dma, multi, ..)
|
||||
*/
|
||||
TASKFILE_DPHASE_NONE = 0, /* ide: TASKFILE_IN */
|
||||
TASKFILE_DPHASE_PIO_IN = 1, /* ide: TASKFILE_IN */
|
||||
TASKFILE_DPHASE_PIO_OUT = 4, /* ide: TASKFILE_OUT */
|
||||
};
|
||||
|
||||
struct reg_flags {
|
||||
union {
|
||||
unsigned lob_all : 8;
|
||||
struct {
|
||||
unsigned data : 1;
|
||||
unsigned feat : 1;
|
||||
unsigned lbal : 1;
|
||||
unsigned nsect : 1;
|
||||
unsigned lbam : 1;
|
||||
unsigned lbah : 1;
|
||||
unsigned dev : 1;
|
||||
unsigned command : 1;
|
||||
} lob;
|
||||
};
|
||||
union {
|
||||
unsigned hob_all : 8;
|
||||
struct {
|
||||
unsigned data : 1;
|
||||
unsigned feat : 1;
|
||||
unsigned lbal : 1;
|
||||
unsigned nsect : 1;
|
||||
unsigned lbam : 1;
|
||||
unsigned lbah : 1;
|
||||
unsigned dev : 1;
|
||||
unsigned command : 1;
|
||||
} hob;
|
||||
};
|
||||
};
|
||||
|
||||
struct taskfile_regs {
|
||||
__u8 data;
|
||||
__u8 feat;
|
||||
__u8 nsect;
|
||||
__u8 lbal;
|
||||
__u8 lbam;
|
||||
__u8 lbah;
|
||||
__u8 dev;
|
||||
__u8 command;
|
||||
};
|
||||
|
||||
struct hdio_taskfile {
|
||||
struct taskfile_regs lob;
|
||||
struct taskfile_regs hob;
|
||||
struct reg_flags oflags;
|
||||
struct reg_flags iflags;
|
||||
int dphase;
|
||||
int cmd_req; /* IDE command_type */
|
||||
unsigned long obytes;
|
||||
unsigned long ibytes;
|
||||
__u16 data[0];
|
||||
};
|
||||
|
||||
struct scsi_sg_io_hdr {
|
||||
int interface_id;
|
||||
int dxfer_direction;
|
||||
unsigned char cmd_len;
|
||||
unsigned char mx_sb_len;
|
||||
unsigned short iovec_count;
|
||||
unsigned int dxfer_len;
|
||||
void * dxferp;
|
||||
unsigned char * cmdp;
|
||||
void * sbp;
|
||||
unsigned int timeout;
|
||||
unsigned int flags;
|
||||
int pack_id;
|
||||
void * usr_ptr;
|
||||
unsigned char status;
|
||||
unsigned char masked_status;
|
||||
unsigned char msg_status;
|
||||
unsigned char sb_len_wr;
|
||||
unsigned short host_status;
|
||||
unsigned short driver_status;
|
||||
int resid;
|
||||
unsigned int duration;
|
||||
unsigned int info;
|
||||
};
|
||||
|
||||
#ifndef SG_DXFER_NONE
|
||||
#define SG_DXFER_NONE -1
|
||||
#define SG_DXFER_TO_DEV -2
|
||||
#define SG_DXFER_FROM_DEV -3
|
||||
#define SG_DXFER_TO_FROM_DEV -4
|
||||
#endif
|
||||
|
||||
#define SG_READ 0
|
||||
#define SG_WRITE 1
|
||||
|
||||
#define SG_PIO 0
|
||||
#define SG_DMA 1
|
||||
|
||||
#define SG_CHECK_CONDITION 0x02
|
||||
#define SG_DRIVER_SENSE 0x08
|
||||
|
||||
#define SG_ATA_16 0x85
|
||||
#define SG_ATA_16_LEN 16
|
||||
|
||||
#define SG_ATA_12 0xa1
|
||||
#define SG_ATA_12_LEN 12
|
||||
|
||||
#define SG_ATA_LBA48 1
|
||||
#define SG_ATA_PROTO_NON_DATA ( 3 << 1)
|
||||
#define SG_ATA_PROTO_PIO_IN ( 4 << 1)
|
||||
#define SG_ATA_PROTO_PIO_OUT ( 5 << 1)
|
||||
#define SG_ATA_PROTO_DMA ( 6 << 1)
|
||||
#define SG_ATA_PROTO_UDMA_IN (11 << 1) /* not yet supported in libata */
|
||||
#define SG_ATA_PROTO_UDMA_OUT (12 << 1) /* not yet supported in libata */
|
||||
|
||||
void tf_init (struct ata_tf *tf, __u8 ata_op, __u64 lba, unsigned int nsect);
|
||||
__u64 tf_to_lba (struct ata_tf *tf);
|
||||
int sg16 (int fd, int rw, int dma, struct ata_tf *tf, void *data, unsigned int data_bytes, unsigned int timeout_secs);
|
||||
int do_drive_cmd (int fd, unsigned char *args);
|
||||
int do_taskfile_cmd (int fd, struct hdio_taskfile *r, unsigned int timeout_secs);
|
||||
int dev_has_sgio (int fd);
|
||||
void init_hdio_taskfile (struct hdio_taskfile *r, __u8 ata_op, int rw, int force_lba48,
|
||||
__u64 lba, unsigned int nsect, int data_bytes);
|
213
plugins/ts2.c
213
plugins/ts2.c
@ -1,213 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 02/2010 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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. *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "helper.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
#include "sockaddr.h"
|
||||
|
||||
#define TS2_RESP_SIZE 1024
|
||||
|
||||
struct sammler_plugin plugin;
|
||||
|
||||
struct server_entry {
|
||||
struct list_head list;
|
||||
|
||||
char *name;
|
||||
int errors;
|
||||
struct sockaddr_in sa;
|
||||
};
|
||||
|
||||
static LIST_HEAD(server_list);
|
||||
static char *ts2_resp_buf;
|
||||
|
||||
static const char *ds_def = {
|
||||
"DS:users:GAUGE:90:0:U "
|
||||
"DS:channels:GAUGE:90:0:U "
|
||||
};
|
||||
|
||||
static const char * get_ds(int ds_id)
|
||||
{
|
||||
return ds_def;
|
||||
}
|
||||
|
||||
static int probe(void)
|
||||
{
|
||||
struct server_entry *entry;
|
||||
list_for_each_entry(entry, &server_list, list) {
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock == -1) {
|
||||
log_print(LOG_WARN, "plugin ts2: socket()");
|
||||
continue;
|
||||
}
|
||||
|
||||
int ret = connect(sock, (struct sockaddr *)&entry->sa, sizeof(entry->sa));
|
||||
if (ret != 0) {
|
||||
if (entry->errors++ == 0)
|
||||
log_print(LOG_ERROR, "plugin ts2: connect(%s)", get_sockaddr_buf(&entry->sa));
|
||||
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* read prompt "[TS]" */
|
||||
int len = read(sock, ts2_resp_buf, TS2_RESP_SIZE);
|
||||
if (len <= 0) {
|
||||
if (entry->errors++ == 0)
|
||||
log_print(LOG_ERROR, "ts2: read(1)");
|
||||
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(ts2_resp_buf, "[TS]", 4) != 0) {
|
||||
if (entry->errors++ == 0)
|
||||
log_print(LOG_ERROR, "ts2: invalid prompt from server");
|
||||
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* query "general informations" */
|
||||
char cmd1[] = "gi\n";
|
||||
write(sock, cmd1, sizeof(cmd1));
|
||||
|
||||
len = read(sock, ts2_resp_buf, TS2_RESP_SIZE);
|
||||
if (len <= 0) {
|
||||
if (entry->errors++ == 0)
|
||||
log_print(LOG_ERROR, "ts2: read(2)");
|
||||
|
||||
close(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* send quit (but we close the socket anyway..) */
|
||||
char cmd2[] = "quit";
|
||||
write(sock, cmd2, sizeof(cmd2));
|
||||
|
||||
close(sock);
|
||||
|
||||
/* terminate response */
|
||||
ts2_resp_buf[len] = '\0';
|
||||
|
||||
char *tok, *tmp, *resp = ts2_resp_buf;
|
||||
int users = 0, channels = 0;
|
||||
while ((tok = strtok_r(resp, "\r\n", &tmp)) != NULL) {
|
||||
/* total_users_online=14 */
|
||||
if (strncmp(tok, "total_users_online", 18) == 0) {
|
||||
users = atoi(tok +19);
|
||||
|
||||
/* total_channels=3 */
|
||||
} else if (strncmp(tok, "total_channels", 14) == 0) {
|
||||
channels = atoi(tok +15);
|
||||
}
|
||||
resp = NULL;
|
||||
}
|
||||
|
||||
char filename[32];
|
||||
len = snprintf(filename, sizeof(filename), "ts2-%s.rrd", entry->name);
|
||||
if (len < 0 || len >= sizeof(filename))
|
||||
continue;
|
||||
|
||||
probe_submit(&plugin, filename, 0, "%d:%d", users, channels);
|
||||
|
||||
if (entry->errors > 0) {
|
||||
log_print(LOG_ERROR, "plugin ts2: success (%s) after %d errors",
|
||||
entry->name, entry->errors);
|
||||
|
||||
entry->errors = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_cb(struct strtoken *tokens, void *privdata)
|
||||
{
|
||||
if (tokens->count != 2) {
|
||||
log_print(LOG_ERROR, "p_ts2: parse error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct server_entry *entry = malloc(sizeof(struct server_entry));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_ERROR, "p_ts2: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->name = strdup(tokens->field[0]);
|
||||
entry->errors = 0;
|
||||
|
||||
if (parse_sockaddr(tokens->field[1], &entry->sa) < 0) {
|
||||
log_print(LOG_ERROR, "p_ts2: invalid address: <%s>", tokens->field[1]);
|
||||
free(entry->name);
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_print(LOG_INFO, "p_ts2: added server '%s'", entry->name);
|
||||
list_add_tail(&entry->list, &server_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void)
|
||||
{
|
||||
ts2_resp_buf = malloc(TS2_RESP_SIZE);
|
||||
if (ts2_resp_buf == NULL) {
|
||||
log_print(LOG_ERROR, "p_ts2: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
config_get_strtokens("p_ts2", "server", ",", 2, init_cb, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void)
|
||||
{
|
||||
struct server_entry *entry, *tmp;
|
||||
list_for_each_entry_safe(entry, tmp, &server_list, list) {
|
||||
free(entry->name);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
free(ts2_resp_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct sammler_plugin plugin = {
|
||||
.name = "ts2",
|
||||
.interval = 60,
|
||||
.init = &init,
|
||||
.fini = &fini,
|
||||
.probe = &probe,
|
||||
.get_ds = &get_ds,
|
||||
};
|
61
probe.c
61
probe.c
@ -1,61 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "logging.h"
|
||||
#include "network.h"
|
||||
#include "rrdtool.h"
|
||||
|
||||
#define BUFSIZE 512
|
||||
|
||||
#define SUBMIT_NET_ONLY 0x01
|
||||
|
||||
static int submit_flags;
|
||||
static const char *hostname;
|
||||
|
||||
int probe_init(void)
|
||||
{
|
||||
const char *fwd_only = config_get_string("global", "forward_only", "false");
|
||||
submit_flags = 0;
|
||||
|
||||
if (!strncmp(fwd_only, "true", 4))
|
||||
submit_flags |= SUBMIT_NET_ONLY;
|
||||
|
||||
static char hostname_buf[32];
|
||||
if (gethostname(hostname_buf, sizeof(hostname_buf)) != 0)
|
||||
strcpy(hostname_buf, "localhost");
|
||||
|
||||
hostname = config_get_string("global", "hostname", hostname_buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probe_submit(struct sammler_plugin *plugin, const char *filename, int ds_id, const char *fmt, ... )
|
||||
{
|
||||
char *buffer = malloc(BUFSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_ERROR, "probe_submit: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
va_list az;
|
||||
va_start(az, fmt);
|
||||
int len = vsnprintf(buffer, BUFSIZE, fmt, az);
|
||||
va_end(az);
|
||||
|
||||
if (len < 0 || len >= BUFSIZE) {
|
||||
log_print(LOG_ERROR, "probe_submit: %s arguments too long", plugin->name);
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
net_submit(hostname, plugin->name, filename, ds_id, buffer);
|
||||
|
||||
if (!(submit_flags & SUBMIT_NET_ONLY))
|
||||
rrd_submit(hostname, plugin->name, filename, ds_id, buffer);
|
||||
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
9
probe.h
9
probe.h
@ -1,9 +0,0 @@
|
||||
#ifndef _PROBE_H_
|
||||
#define _PROBE_H_
|
||||
|
||||
#include "plugins.h"
|
||||
|
||||
int probe_init(void);
|
||||
int probe_submit(struct sammler_plugin *plugin, const char *filename, int ds_id, const char *fmt, ... );
|
||||
|
||||
#endif /* _PROBE_H_ */
|
260
rrdtool.c
260
rrdtool.c
@ -17,7 +17,6 @@
|
||||
* Free Software Foundation, Inc., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#if (WITH_RRD)
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -27,117 +26,178 @@
|
||||
|
||||
#include <rrd.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "helper.h"
|
||||
#include "linebuffer.h"
|
||||
#include "list.h"
|
||||
|
||||
#include "logging.h"
|
||||
#include "config.h"
|
||||
#include "plugins.h"
|
||||
|
||||
#define DEFAULT_STEP 10
|
||||
|
||||
#define ARGCMAX 64
|
||||
#define ARGVSIZE 1024
|
||||
|
||||
#define RRDTOOL_CREATE 1
|
||||
#define RRDTOOL_UPDATE 2
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
static const char *rrd_dir;
|
||||
|
||||
int sammler_rrd_init(void)
|
||||
static int append_rra_config(char *buffer, int size, int *pos)
|
||||
{
|
||||
rrd_dir = config_get_string("global", "rrd_dir", ".");
|
||||
return 0;
|
||||
struct conf_section *section;
|
||||
struct conf_tupel *tupel;
|
||||
|
||||
int len, rra_cnt = 0;
|
||||
|
||||
section = config_get_section("global");
|
||||
if (section == NULL) {
|
||||
log_print(LOG_ERROR, "append_ds_config: conf-section 'global' not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_for_each_entry(tupel, §ion->tupel, list) {
|
||||
if (strcmp(tupel->option, "rra"))
|
||||
continue;
|
||||
|
||||
len = snprintf(buffer + *pos, size - *pos, "%s ", tupel->parameter);
|
||||
if (len < 0 || len >= size - *pos) {
|
||||
log_print(LOG_ERROR, "append_ds_config: arguments too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pos += len;
|
||||
rra_cnt++;
|
||||
}
|
||||
return rra_cnt;
|
||||
}
|
||||
|
||||
static int append_rra_config(const char *parameter, void *privdata)
|
||||
static int append_ds_config(char *buffer, int size, int *pos, int heartbeat, char **ds_def)
|
||||
{
|
||||
struct lbuf *buffer = (struct lbuf *)privdata;
|
||||
int len, ds_cnt = 0;
|
||||
char *dsbuild;
|
||||
|
||||
lbuf_printf(buffer, "%s ", parameter);
|
||||
return 0;
|
||||
dsbuild = malloc(BUFSIZE);
|
||||
if (dsbuild == NULL) {
|
||||
log_print(LOG_ERROR, "append_ds_config: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (*ds_def != NULL) {
|
||||
len = snprintf(dsbuild, BUFSIZE, *ds_def, heartbeat);
|
||||
if (len < 0 || len >= BUFSIZE) {
|
||||
log_print(LOG_ERROR, "append_ds_config: arguments too long");
|
||||
free(dsbuild);
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = snprintf(buffer + *pos, size - *pos, "%s ", dsbuild);
|
||||
if (len < 0 || len >= size - *pos) {
|
||||
log_print(LOG_ERROR, "append_ds_config: arguments too long");
|
||||
free(dsbuild);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*pos += len;
|
||||
*ds_def++;
|
||||
ds_cnt++;
|
||||
}
|
||||
free(dsbuild);
|
||||
|
||||
return ds_cnt;
|
||||
}
|
||||
|
||||
static int do_rrd(int (*rrd_func)(int, char **), struct lbuf *buffer)
|
||||
static int do_rrd(int mode, char *cmd)
|
||||
{
|
||||
size_t len;
|
||||
char *cmd = lbuf_getdata(buffer, &len);
|
||||
if (len < ARGVSIZE -1)
|
||||
cmd[len] = '\0';
|
||||
|
||||
int argc;
|
||||
char *argv[ARGCMAX];
|
||||
int argc = strsplit(cmd, " \t\n", argv, ARGCMAX -1);
|
||||
|
||||
argc = strsplit(cmd, argv, ARGCMAX -1);
|
||||
argv[argc] = NULL;
|
||||
|
||||
optind = 0;
|
||||
rrd_clear_error();
|
||||
|
||||
int retval = rrd_func(argc, argv);
|
||||
if (retval == -1) {
|
||||
errno = 0;
|
||||
log_print(LOG_ERROR, "rrd_func failed: %s: %s", argv[1], rrd_get_error());
|
||||
}
|
||||
if (mode == RRDTOOL_CREATE) {
|
||||
if (rrd_create(argc, argv) == -1) {
|
||||
errno = 0;
|
||||
log_print(LOG_ERROR, "rrd_create failed: %s: %s",
|
||||
argv[2], rrd_get_error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return retval;
|
||||
} else if (mode == RRDTOOL_UPDATE) {
|
||||
if (rrd_update(argc, argv) == -1) {
|
||||
errno = 0;
|
||||
log_print(LOG_ERROR, "rrd_update failed: %s: %s",
|
||||
argv[2], rrd_get_error());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rrd_create_file(const char *filename, const char *pluginname, int ds_id)
|
||||
static int rrd_create_file(char *filename, char **ds_def)
|
||||
{
|
||||
struct sammler_plugin *plugin = plugin_lookup(pluginname);
|
||||
if (plugin == NULL) {
|
||||
log_print(LOG_ERROR, "rrd_create_file: plugin not found (%s)", pluginname);
|
||||
return -1;
|
||||
}
|
||||
int pos, step, heartbeat, retval;
|
||||
char *buffer;
|
||||
|
||||
const char *ds_def = plugin->get_ds(ds_id);
|
||||
if (ds_def == NULL) {
|
||||
log_print(LOG_ERROR, "No vaild DS found (%s:%d)", plugin->name, ds_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct lbuf *buffer = lbuf_create(ARGVSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_ERROR, "rrd_create_file: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = lbuf_printf(buffer, "create %s -s %d %s ", filename, plugin->interval, ds_def);
|
||||
if (ret == -1) {
|
||||
log_print(LOG_ERROR, "rrd_create_file: arguments too long");
|
||||
lbuf_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = config_get_strings("global", "rra", append_rra_config, buffer);
|
||||
if (ret <= 0) {
|
||||
lbuf_free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = do_rrd(&rrd_create, buffer);
|
||||
lbuf_free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rrd_update_file(const char *filename, const char *values)
|
||||
{
|
||||
struct lbuf *buffer = lbuf_create(ARGVSIZE);
|
||||
buffer = malloc(ARGVSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_ERROR, "append_ds_config: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = lbuf_printf(buffer, "update %s N:%s", filename, values);
|
||||
if (ret == -1) {
|
||||
log_print(LOG_ERROR, "rrd_update_file: arguments too long");
|
||||
lbuf_free(buffer);
|
||||
step = config_get_int("global", "step", DEFAULT_STEP);
|
||||
heartbeat = (step * 2) + (step / 2);
|
||||
|
||||
pos = snprintf(buffer, ARGVSIZE, "create %s -s %d ", filename, step);
|
||||
if (pos < 0 || pos >= ARGVSIZE) {
|
||||
log_print(LOG_ERROR, "rrd_create_file: arguments too long");
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = do_rrd(&rrd_update, buffer);
|
||||
lbuf_free(buffer);
|
||||
return ret;
|
||||
if (append_rra_config(buffer, ARGVSIZE, &pos) <= 0) {
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (append_ds_config(buffer, ARGVSIZE, &pos, heartbeat, ds_def) <= 0) {
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = do_rrd(RRDTOOL_CREATE, buffer);
|
||||
free(buffer);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int check_create_dir(const char *dir)
|
||||
static int rrd_update_file(char *filename, char *values)
|
||||
{
|
||||
int pos, retval;
|
||||
char *buffer;
|
||||
|
||||
buffer = malloc(ARGVSIZE);
|
||||
if (buffer == NULL) {
|
||||
log_print(LOG_ERROR, "append_ds_config: out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = snprintf(buffer, ARGVSIZE, "update %s %lu:%s", filename, time(NULL), values);
|
||||
if (pos < 0 || pos >= ARGVSIZE) {
|
||||
log_print(LOG_ERROR, "rrd_update_file: arguments too long");
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
retval = do_rrd(RRDTOOL_UPDATE, buffer);
|
||||
free(buffer);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int check_create_dir(char *dir)
|
||||
{
|
||||
struct stat statbuf;
|
||||
if (stat(dir, &statbuf) == -1) {
|
||||
@ -162,9 +222,9 @@ static int check_create_dir(const char *dir)
|
||||
|
||||
static int create_parent_dirs(char *filename)
|
||||
{
|
||||
char *nextslash = filename;
|
||||
char *lastslash, *nextslash = filename;
|
||||
|
||||
char *lastslash = strrchr(filename, '/');
|
||||
lastslash = strrchr(filename, '/');
|
||||
if (lastslash == NULL) {
|
||||
log_print(LOG_ERROR, "create_parent_dirs: invalid file name");
|
||||
return -1;
|
||||
@ -194,61 +254,63 @@ static int create_parent_dirs(char *filename)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rrd_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data)
|
||||
void rrd_submit(char *plugin, int version, char *filename, int ds_id, char *data)
|
||||
{
|
||||
char *fullfile = malloc(BUFSIZE);
|
||||
struct stat statbuf;
|
||||
static char *rrd_dir = NULL;
|
||||
|
||||
char *fullfile, **ds_def;
|
||||
int len;
|
||||
|
||||
if (rrd_dir == NULL)
|
||||
rrd_dir = config_get_string("global", "rrd_dir", ".");
|
||||
|
||||
fullfile = malloc(BUFSIZE);
|
||||
if (fullfile == NULL) {
|
||||
log_print(LOG_ERROR, "rrd_submit: out of memory");
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
int len = snprintf(fullfile, BUFSIZE, "%s/%s/%s", rrd_dir, hostname, filename);
|
||||
len = snprintf(fullfile, BUFSIZE, "%s/%s", rrd_dir, filename);
|
||||
if (len < 0 || len >= BUFSIZE) {
|
||||
log_print(LOG_ERROR, "rrd_submit: arguments too long");
|
||||
free(fullfile);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
struct stat statbuf;
|
||||
if (stat(fullfile, &statbuf) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
errno = 0;
|
||||
|
||||
if (create_parent_dirs(fullfile) == -1) {
|
||||
free(fullfile);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rrd_create_file(fullfile, pluginname, ds_id) == -1) {
|
||||
ds_def = plugins_get_ds(plugin, version, ds_id);
|
||||
if (ds_def == NULL) {
|
||||
log_print(LOG_ERROR, "No vaild DS found (%s v%d %d)", plugin, version, ds_id);
|
||||
free(fullfile);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rrd_create_file(fullfile, ds_def) == -1) {
|
||||
free(fullfile);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
log_print(LOG_ERROR, "rrd_submit: stat(%s):", fullfile);
|
||||
free(fullfile);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (!S_ISREG (statbuf.st_mode)) {
|
||||
log_print(LOG_ERROR, "rrd_submit: stat(%s): Not a regular file!", fullfile);
|
||||
free(fullfile);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
rrd_update_file(fullfile, data);
|
||||
free(fullfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* (WITH_RRD) */
|
||||
int sammler_rrd_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rrd_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* (WITH_RRD) */
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef _RRDTOOL_H_
|
||||
#define _RRDTOOL_H_
|
||||
|
||||
int sammler_rrd_init(void);
|
||||
int rrd_submit(const char *hostname, const char *pluginname, const char *filename, int ds_id, const char *data);
|
||||
void rrd_submit(char *plugin, int version, char *filename, int ds_id, char *data);
|
||||
|
||||
#endif /* _RRDTOOL_H_ */
|
||||
|
102
sammler.c
102
sammler.c
@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 03/2010 by Olaf Rempel *
|
||||
* Copyright (C) 06/2006 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.de *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
@ -23,23 +23,13 @@
|
||||
#include <string.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "configfile.h"
|
||||
#include "event.h"
|
||||
#include "config.h"
|
||||
#include "logging.h"
|
||||
#include "network.h"
|
||||
#include "rrdtool.h"
|
||||
#include "pidfile.h"
|
||||
#include "plugins.h"
|
||||
#include "probe.h"
|
||||
#include "signals.h"
|
||||
|
||||
#define DEFAULT_CONFIG "sammler.conf"
|
||||
#define DEFAULT_LOGFILE "sammler.log"
|
||||
#define DEFAULT_PIDFILE "sammler.pid"
|
||||
|
||||
static struct option opts[] = {
|
||||
{"config", 1, 0, 'c'},
|
||||
@ -48,23 +38,6 @@ static struct option opts[] = {
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static int restart_var;
|
||||
|
||||
static void trigger_restart(void *privdata)
|
||||
{
|
||||
restart_var = 1;
|
||||
}
|
||||
|
||||
static int check_restart(int *maxfd, void *readfds, void *writefds, struct timeval *timeout, void *privdata)
|
||||
{
|
||||
if (restart_var == 1) {
|
||||
restart_var = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *config = DEFAULT_CONFIG;
|
||||
@ -93,7 +66,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case '?': /* error */
|
||||
exit(1);
|
||||
exit(-1);
|
||||
break;
|
||||
|
||||
default: /* unknown / all options parsed */
|
||||
@ -102,72 +75,27 @@ int main(int argc, char *argv[])
|
||||
} while (code != -1);
|
||||
|
||||
/* parse config file */
|
||||
if (config_parse(config) < 0)
|
||||
exit(1);
|
||||
|
||||
if (!debug) {
|
||||
/* check pidfile */
|
||||
const char *pidfile = config_get_string("global", "pidfile", DEFAULT_PIDFILE);
|
||||
if (pidfile_check(pidfile, 1) != 0) {
|
||||
log_print(LOG_ERROR, "sammler already running");
|
||||
exit(1);
|
||||
}
|
||||
if (!config_parse(config))
|
||||
exit(-1);
|
||||
|
||||
/* check logfile */
|
||||
char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE);
|
||||
if (logfile != NULL && debug == 0) {
|
||||
/* start logging */
|
||||
const char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE);
|
||||
if (log_init(logfile) < 0)
|
||||
exit(1);
|
||||
if (!log_init(logfile))
|
||||
exit(-1);
|
||||
|
||||
/* zum daemon mutieren */
|
||||
if (daemon(-1, 0) < 0) {
|
||||
log_print(LOG_ERROR, "failed to daemonize");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* create pidfile */
|
||||
if (pidfile_create(pidfile) < 0) {
|
||||
log_print(LOG_ERROR, "failed to create pidfile %s", pidfile);
|
||||
exit(1);
|
||||
}
|
||||
daemon(-1, 0);
|
||||
}
|
||||
|
||||
signal_init();
|
||||
signal_add_callback(SIGHUP, trigger_restart, NULL);
|
||||
log_print(LOG_EVERYTIME, "sammler started");
|
||||
|
||||
log_print(LOG_EVERYTIME, "sammler started (pid:%d)", getpid());
|
||||
plugin_load_all();
|
||||
|
||||
while (1) {
|
||||
if (probe_init())
|
||||
break;
|
||||
|
||||
if (net_init())
|
||||
break;
|
||||
|
||||
if (sammler_rrd_init())
|
||||
break;
|
||||
|
||||
if (plugin_init())
|
||||
break;
|
||||
|
||||
/* exited on restart / SIGUSR1 */
|
||||
event_loop(check_restart, NULL, NULL);
|
||||
|
||||
plugin_close();
|
||||
|
||||
net_close();
|
||||
|
||||
log_close();
|
||||
|
||||
config_free();
|
||||
|
||||
if (config_parse(config) < 0)
|
||||
break;
|
||||
|
||||
const char *logfile = config_get_string("global", "logfile", DEFAULT_LOGFILE);
|
||||
if (!debug && log_init(logfile) < 0)
|
||||
break;
|
||||
|
||||
log_print(LOG_EVERYTIME, "sammler restarted (pid:%d) ", getpid());
|
||||
plugins_probe();
|
||||
sleep (10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
81
sammler.conf
81
sammler.conf
@ -1,62 +1,35 @@
|
||||
[global]
|
||||
#hostname localhost
|
||||
|
||||
#listen 127.0.0.1:5000
|
||||
#forward 127.0.0.1:5000
|
||||
forward_only false
|
||||
|
||||
logfile sammler.log
|
||||
pidfile sammler.pid
|
||||
|
||||
plugin_dir .
|
||||
|
||||
plugin p_stat.so
|
||||
plugin p_load.so
|
||||
plugin p_memory.so
|
||||
plugin p_vmstat.so
|
||||
plugin p_uptime.so
|
||||
plugin p_netdev.so
|
||||
plugin p_mount.so
|
||||
#plugin p_ctstat.so
|
||||
plugin p_rtstat.so
|
||||
plugin p_random.so
|
||||
|
||||
rrd_dir rrd
|
||||
|
||||
plugin_dir plugins
|
||||
plugin stat.so
|
||||
plugin load.so
|
||||
plugin memory.so
|
||||
plugin vmstat.so
|
||||
plugin uptime.so
|
||||
plugin netdev.so
|
||||
plugin mount.so
|
||||
plugin diskstat.so
|
||||
plugin ctstat.so
|
||||
plugin rtstat.so
|
||||
plugin random.so
|
||||
#plugin mysql.so
|
||||
#plugin apache.so
|
||||
#plugin conntrack.so
|
||||
#plugin hwmon.so
|
||||
#plugin alixusv.so
|
||||
#plugin ts2.so
|
||||
#plugin diskstandby.so
|
||||
#plugin hddtemp.so
|
||||
step 10
|
||||
|
||||
# 1h(10s), 12h(1min), 48h(2min), 14d(15min), 4w(60min), 2y(12h)
|
||||
rra RRA:MIN:0.5:1:360 RRA:AVERAGE:0.5:1:360 RRA:MAX:0.5:1:360
|
||||
rra RRA:MIN:0.5:6:720 RRA:AVERAGE:0.5:6:720 RRA:MAX:0.5:6:720
|
||||
rra RRA:MIN:0.5:12:1440 RRA:AVERAGE:0.5:12:1440 RRA:MAX:0.5:12:1440
|
||||
rra RRA:MIN:0.5:90:1344 RRA:AVERAGE:0.5:90:1344 RRA:MAX:0.5:90:1344
|
||||
rra RRA:MIN:0.5:360:1440 RRA:AVERAGE:0.5:360:1440 RRA:MAX:0.5:360:1440
|
||||
rra RRA:MIN:0.5:4320:1440 RRA:AVERAGE:0.5:4320:1440 RRA:MAX:0.5:4320:1440
|
||||
# 1h(10s), 48h(1min), 7d(5min), 4w(30min)
|
||||
rra RRA:MIN:0.1:1:360
|
||||
rra RRA:MIN:0.1:6:2880
|
||||
rra RRA:MIN:0.1:30:2016
|
||||
rra RRA:MIN:0.1:180:1344
|
||||
|
||||
[p_mysql]
|
||||
#server name,host,user,password
|
||||
rra RRA:AVERAGE:0.1:1:360
|
||||
rra RRA:AVERAGE:0.1:6:2880
|
||||
rra RRA:AVERAGE:0.1:30:2016
|
||||
rra RRA:AVERAGE:0.1:180:1344
|
||||
|
||||
[p_apache]
|
||||
#server name,url,user,password
|
||||
|
||||
[p_hwmon]
|
||||
#temp board,/sys/class/hwmon/hwmon0/device/temp1_input
|
||||
#temp cpu,/sys/class/hwmon/hwmon0/device/temp2_input
|
||||
|
||||
[p_alixusv]
|
||||
#socket /var/run/alix-usvd.sock
|
||||
|
||||
[p_ts2]
|
||||
#server localhost,127.0.0.1:51234
|
||||
|
||||
[p_diskstandby]
|
||||
#device /dev/sda
|
||||
|
||||
[p_hddtemp]
|
||||
#server test,127.0.0.1:7634
|
||||
rra RRA:MAX:0.1:1:360
|
||||
rra RRA:MAX:0.1:6:2880
|
||||
rra RRA:MAX:0.1:30:2016
|
||||
rra RRA:MAX:0.1:180:13446
|
||||
|
896
sammler.php
896
sammler.php
@ -1,896 +0,0 @@
|
||||
<?php
|
||||
|
||||
define('CONFIG', '%%WWW_CONFIG%%');
|
||||
define('BASE_DIR', '%%DATA_DIR%%');
|
||||
define('RRDTOOL', '/usr/bin/rrdtool');
|
||||
|
||||
function setup_html($conf) {
|
||||
echo "<html><head><title>sammler graph setup</title>\n";
|
||||
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-15\"/>\n";
|
||||
echo "</head><body>\n";
|
||||
echo "<form method=\"POST\" action=\"{$_SERVER['SCRIPT_NAME']}?action=setup\">\n";
|
||||
echo "<table>\n";
|
||||
|
||||
echo "<tr><td><b>Graph Height:</b></td>\n";
|
||||
echo "<td><input type=\"text\" name=\"height\" value=\"{$conf['height']}\"></td></tr>\n";
|
||||
echo "<tr><td><b>Graph Width:</b></td>\n";
|
||||
echo "<td><input type=\"text\" name=\"width\" value=\"{$conf['width']}\"></td></tr>\n";
|
||||
echo "<tr><td colspan=\"4\"><hr></td></tr>\n";
|
||||
|
||||
echo "<tr><td><b>Available Views:</b></td><td colspan=\"2\"></td><td><b>default</b></td></tr>\n";
|
||||
foreach ($conf['views'] as $name => $value) {
|
||||
echo "<tr><td>({$value}s)</td>\n";
|
||||
echo "<td><input type=\"text\" name=\"views[$value]\" value=\"{$name}\"></td><td></td>\n";
|
||||
if ($conf['default_view'] == $value)
|
||||
echo "<td><input type=\"radio\" name=\"default_view\" value=\"{$value}\" checked=\"checked\"></td>\n";
|
||||
else
|
||||
echo "<td><input type=\"radio\" name=\"default_view\" value=\"{$value}\"></td>\n";
|
||||
|
||||
echo "</tr>\n";
|
||||
}
|
||||
|
||||
echo "<tr><td><b>add view:</b></td><td><input type=\"text\" name=\"views[new]\"></td></tr>\n";
|
||||
|
||||
echo "<tr><td colspan=\"4\"><hr></td></tr>\n";
|
||||
foreach ($conf['hosts'] as $hostid => $host) {
|
||||
echo "<tr><td><b>Hostname:</b></td>\n";
|
||||
echo "<td><input type=\"text\" name=\"hosts[{$hostid}][hostname]\" value=\"{$host['hostname']}\"></td>\n";
|
||||
|
||||
echo "<td><a href=\"{$_SERVER['SCRIPT_NAME']}?action=setup&sub=move_host_up&host={$hostid}\">up</a> \n";
|
||||
echo "<a href=\"{$_SERVER['SCRIPT_NAME']}?action=setup&sub=move_host_down&host={$hostid}\">down</a></td>\n";
|
||||
|
||||
if ($host['show'])
|
||||
echo "<td><input type=\"checkbox\" name=\"hosts[{$hostid}][show]\" checked=\"checked\">show</td>";
|
||||
else
|
||||
echo "<td><input type=\"checkbox\" name=\"hosts[{$hostid}][show]\">show</td>";
|
||||
|
||||
echo "</tr>\n";
|
||||
|
||||
foreach ($host['rrds'] as $rrdid => $rrd) {
|
||||
echo "<tr><td> {$rrd['rrd']}</td>\n";
|
||||
echo "<td><input type=\"text\" name=\"hosts[{$hostid}][rrds][{$rrdid}][title]\" value=\"{$rrd['title']}\"></td>\n";
|
||||
|
||||
echo "<td><a href=\"{$_SERVER['SCRIPT_NAME']}?action=setup&sub=move_rrd_up&host={$hostid}&rrd={$rrdid}\">up</a> \n";
|
||||
echo "<a href=\"{$_SERVER['SCRIPT_NAME']}?action=setup&sub=move_rrd_down&host={$hostid}&rrd={$rrdid}\">down</a></td>\n";
|
||||
|
||||
if ($rrd['show'])
|
||||
echo "<td><input type=\"checkbox\" name=\"hosts[{$hostid}][rrds][{$rrdid}][show]\" checked=\"checked\">show</td>";
|
||||
else
|
||||
echo "<td><input type=\"checkbox\" name=\"hosts[{$hostid}][rrds][{$rrdid}][show]\">show</td>";
|
||||
|
||||
echo "</tr>\n";
|
||||
}
|
||||
|
||||
echo "<tr><td colspan=\"4\"><hr></td></tr>\n";
|
||||
}
|
||||
|
||||
echo "<tr><td colspan=\"4\" align=\"center\">\n";
|
||||
echo "<input type=\"button\" value=\"Show\" onClick=\"javascript:window.location.href='{$_SERVER['SCRIPT_NAME']}?action=show'\"> \n";
|
||||
echo "<input type=\"submit\" value=\"Save Config\"> \n";
|
||||
echo "<input type=\"button\" value=\"Rebuild Config\" onClick=\"javascript:window.location.href='{$_SERVER['SCRIPT_NAME']}?action=init'\">\n";
|
||||
echo "</td></tr>\n";
|
||||
echo "</table></form>\n";
|
||||
echo "</body></html>\n";
|
||||
}
|
||||
|
||||
function show_html($conf) {
|
||||
echo "<html><head><title>Stats</title>\n";
|
||||
echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-15\"/>\n";
|
||||
echo "</head><body>\n";
|
||||
|
||||
$hostid = isset($_GET['host']) ? $_GET['host'] : 0;
|
||||
$view = isset($_GET['view']) ? $_GET['view'] : $conf['default_view'];
|
||||
|
||||
echo "<b>Select Host:</b>\n";
|
||||
echo "<select name=\"host\" OnChange=\"document.location.href='{$_SERVER['SCRIPT_NAME']}?action=show&host='+this.value+'&view={$view}'\">\n";
|
||||
foreach ($conf['hosts'] as $id => $host) {
|
||||
if (!$host['show'])
|
||||
continue;
|
||||
|
||||
if ($hostid == $id)
|
||||
echo "<option value=\"{$id}\" selected=\"selected\">{$host['hostname']}</option>\n";
|
||||
else
|
||||
echo "<option value=\"{$id}\">{$host['hostname']}</option>\n";
|
||||
}
|
||||
echo "</select> \n";
|
||||
|
||||
echo "<td><select name=\"view\" OnChange=\"document.location.href='{$_SERVER['SCRIPT_NAME']}?action=show&host={$hostid}&view='+this.value\">\n";
|
||||
foreach ($conf['views'] as $name => $value) {
|
||||
if ($view == $value)
|
||||
echo "<option value=\"{$value}\" selected=\"selected\">{$name}</option>\n";
|
||||
else
|
||||
echo "<option value=\"{$value}\">{$name}</option>\n";
|
||||
}
|
||||
echo "</select><br><br>\n";
|
||||
|
||||
|
||||
foreach ($conf['hosts'][$hostid]['rrds'] as $rrdid => $rrd) {
|
||||
if (!$rrd['show'])
|
||||
continue;
|
||||
|
||||
echo "<img src=\"{$_SERVER['SCRIPT_NAME']}?action=rrd&host={$hostid}&rrd={$rrdid}&view={$view}\" border=\"0\"><br><br>\n";
|
||||
}
|
||||
|
||||
echo "</body></html>\n";
|
||||
}
|
||||
|
||||
|
||||
function read_config($filename) {
|
||||
$handle = @fopen($filename, "r");
|
||||
if ($handle !== false && filesize($filename) > 0) {
|
||||
$contents = fread($handle, filesize($filename));
|
||||
fclose($handle);
|
||||
|
||||
return unserialize($contents);
|
||||
}
|
||||
}
|
||||
|
||||
function write_config($filename, $config) {
|
||||
$handle = fopen($filename, "w+");
|
||||
if ($handle !== false) {
|
||||
$contents = serialize($config);
|
||||
fwrite($handle, $contents);
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
|
||||
function get_hostdirs() {
|
||||
$retval = array();
|
||||
$dh = opendir(BASE_DIR);
|
||||
while (($file = readdir($dh)) !== false)
|
||||
if (is_dir(BASE_DIR.$file) && $file != "." && $file != "..")
|
||||
$retval[] = $file;
|
||||
|
||||
closedir($dh);
|
||||
natsort($retval);
|
||||
return $retval;
|
||||
}
|
||||
|
||||
function get_rrdfiles($directory) {
|
||||
$retval = array();
|
||||
$dh = opendir(BASE_DIR.$directory);
|
||||
while (($file = readdir($dh)) !== false) {
|
||||
if (is_dir(BASE_DIR.$file))
|
||||
continue;
|
||||
|
||||
if (strstr($file, "rrd") !== false)
|
||||
$retval[] = $file;
|
||||
}
|
||||
closedir($dh);
|
||||
natsort($retval);
|
||||
return $retval;
|
||||
}
|
||||
|
||||
function get_rrd_type($filename) {
|
||||
$types = array_flip(array(
|
||||
"cpu",
|
||||
"load",
|
||||
"memory",
|
||||
"swap",
|
||||
"proc",
|
||||
"vmstat",
|
||||
"random",
|
||||
"uptime",
|
||||
"hwmon",
|
||||
"alixusv",
|
||||
"net",
|
||||
"rtstat",
|
||||
"rtcache",
|
||||
"ctstat",
|
||||
"conntrack",
|
||||
"disk",
|
||||
"mount",
|
||||
"apache",
|
||||
"mysql",
|
||||
"ts2"
|
||||
));
|
||||
|
||||
$tmp1 = explode('-', $filename);
|
||||
$tmp2 = explode('_', $tmp1[0]);
|
||||
$type = $tmp2[0];
|
||||
|
||||
if (isset($types[$type]))
|
||||
return $types[$type];
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
function rrd_sort($a, $b) {
|
||||
if (!is_numeric($a['type']) && !is_numeric($b['type']))
|
||||
return strcmp($a['type'], $b['type']);
|
||||
|
||||
if (is_numeric($a['type']) && !is_numeric($b['type']))
|
||||
return -1;
|
||||
|
||||
if (!is_numeric($a['type']) && is_numeric($b['type']))
|
||||
return +1;
|
||||
|
||||
if ($a['type'] > $b['type'])
|
||||
return +1;
|
||||
|
||||
if ($a['type'] < $b['type'])
|
||||
return -1;
|
||||
|
||||
return strcmp($a['title'], $b['title']);
|
||||
}
|
||||
|
||||
function create_config() {
|
||||
$conf = array();
|
||||
$conf['default_view'] = 86400;
|
||||
$conf['views'] = array("1 hour" => 3600,
|
||||
"6 hours" => 21600,
|
||||
"1 day" => 86400,
|
||||
"1 week" => 604800,
|
||||
"1 month" => 2678400);
|
||||
$conf['height'] = 120;
|
||||
$conf['width'] = 800;
|
||||
$conf['hosts'] = array();
|
||||
|
||||
$hosts = get_hostdirs();
|
||||
foreach ($hosts as $host) {
|
||||
$rrds = array();
|
||||
$tmp = get_rrdfiles($host);
|
||||
foreach ($tmp as $file) {
|
||||
$basename = str_replace(".rrd", "", basename($file));
|
||||
$rrds[] = array(
|
||||
'show' => true,
|
||||
'title' => $basename,
|
||||
'rrd' => "$host/$file",
|
||||
'type' => get_rrd_type($basename),
|
||||
);
|
||||
}
|
||||
|
||||
uasort($rrds, rrd_sort);
|
||||
|
||||
$conf['hosts'][] = array(
|
||||
'hostname' => $host,
|
||||
'show' => true,
|
||||
'rrds' => $rrds,
|
||||
);
|
||||
}
|
||||
|
||||
return $conf;
|
||||
}
|
||||
|
||||
function setup($conf) {
|
||||
if (isset($_GET['sub']) && $_GET['sub'] == "move_host_up") {
|
||||
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
|
||||
if (isset($conf['hosts'][$hostid]) && isset($conf['hosts'][$hostid -1])) {
|
||||
$a = $conf['hosts'][$hostid];
|
||||
$b = $conf['hosts'][$hostid -1];
|
||||
|
||||
$conf['hosts'][$hostid] = $b;
|
||||
$conf['hosts'][$hostid -1] = $a;
|
||||
}
|
||||
return $conf;
|
||||
|
||||
} else if (isset($_GET['sub']) && $_GET['sub'] == "move_host_down") {
|
||||
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
|
||||
if (isset($conf['hosts'][$hostid]) && isset($conf['hosts'][$hostid +1])) {
|
||||
$a = $conf['hosts'][$hostid];
|
||||
$b = $conf['hosts'][$hostid +1];
|
||||
|
||||
$conf['hosts'][$hostid] = $b;
|
||||
$conf['hosts'][$hostid +1] = $a;
|
||||
}
|
||||
return $conf;
|
||||
|
||||
} else if (isset($_GET['sub']) && $_GET['sub'] == "move_rrd_up") {
|
||||
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
|
||||
$rrdid = isset($_GET['rrd']) ? $_GET['rrd'] : -1;
|
||||
if (isset($conf['hosts'][$hostid]['rrds'][$rrdid]) && isset($conf['hosts'][$hostid]['rrds'][$rrdid -1])) {
|
||||
$a = $conf['hosts'][$hostid]['rrds'][$rrdid];
|
||||
$b = $conf['hosts'][$hostid]['rrds'][$rrdid -1];
|
||||
|
||||
$conf['hosts'][$hostid]['rrds'][$rrdid] = $b;
|
||||
$conf['hosts'][$hostid]['rrds'][$rrdid -1] = $a;
|
||||
}
|
||||
return $conf;
|
||||
|
||||
} else if (isset($_GET['sub']) && $_GET['sub'] == "move_rrd_down") {
|
||||
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
|
||||
$rrdid = isset($_GET['rrd']) ? $_GET['rrd'] : -1;
|
||||
if (isset($conf['hosts'][$hostid]['rrds'][$rrdid]) && isset($conf['hosts'][$hostid]['rrds'][$rrdid +1])) {
|
||||
$a = $conf['hosts'][$hostid]['rrds'][$rrdid];
|
||||
$b = $conf['hosts'][$hostid]['rrds'][$rrdid +1];
|
||||
|
||||
$conf['hosts'][$hostid]['rrds'][$rrdid] = $b;
|
||||
$conf['hosts'][$hostid]['rrds'][$rrdid +1] = $a;
|
||||
}
|
||||
return $conf;
|
||||
|
||||
} else if (!empty($_POST)) {
|
||||
$conf['default_view'] = $_POST['default_view'];
|
||||
$conf['height'] = $_POST['height'];
|
||||
$conf['width'] = $_POST['width'];
|
||||
|
||||
$conf['views'] = array();
|
||||
foreach ($_POST['views'] as $name) {
|
||||
if (empty($name))
|
||||
continue;
|
||||
|
||||
$tmp = strtotime($name);
|
||||
if ($tmp != -1)
|
||||
$conf['views'][$name] = $tmp - time();
|
||||
}
|
||||
natsort($conf['views']);
|
||||
|
||||
foreach ($_POST['hosts'] as $hostid => $host) {
|
||||
$conf['hosts'][$hostid]['hostname'] = $host['hostname'];
|
||||
$conf['hosts'][$hostid]['show'] = ($host['show'] == "on");
|
||||
|
||||
foreach ($host['rrds'] as $rrdid => $rrd) {
|
||||
$conf['hosts'][$hostid]['rrds'][$rrdid]['title'] = $_POST['hosts'][$hostid]['rrds'][$rrdid]['title'];
|
||||
$conf['hosts'][$hostid]['rrds'][$rrdid]['show'] = ($_POST['hosts'][$hostid]['rrds'][$rrdid]['show'] == "on");
|
||||
}
|
||||
}
|
||||
return $conf;
|
||||
|
||||
} else {
|
||||
setup_html($conf);
|
||||
}
|
||||
}
|
||||
|
||||
function show_rrd($conf) {
|
||||
$hostid = isset($_GET['host']) ? $_GET['host'] : -1;
|
||||
$rrdid = isset($_GET['rrd']) ? $_GET['rrd'] : -1;
|
||||
|
||||
if (!isset($conf['hosts'][$hostid]['rrds'][$rrdid]['rrd']))
|
||||
return;
|
||||
|
||||
$view = isset($_GET['view']) ? -$_GET['view'] : -$conf['default_view'];
|
||||
$rrdfile = BASE_DIR.$conf['hosts'][$hostid]['rrds'][$rrdid]['rrd'];
|
||||
$title = $conf['hosts'][$hostid]['rrds'][$rrdid]['title'];
|
||||
$height = $conf['height'];
|
||||
$width = $conf['width'];
|
||||
|
||||
$cmd = RRDTOOL." graph - --imgformat PNG --start {$view} --end -10 --title \"{$title}\" --rigid ";
|
||||
|
||||
$tmp1 = explode('-', basename($rrdfile));
|
||||
$tmp2 = explode('_', $tmp1[0]);
|
||||
$tmp3 = explode('.', $tmp2[0]);
|
||||
switch ($tmp3[0]) {
|
||||
case 'alixusv':
|
||||
$height *= 2;
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale --vertical-label=\"Voltage\" ".
|
||||
"DEF:a={$rrdfile}:ibat:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:ubat:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:uin:AVERAGE ".
|
||||
'CDEF:aa=a,50,/ '.
|
||||
'CDEF:bb=b,1000,/ '.
|
||||
'CDEF:cc=c,1000,/ '.
|
||||
'CDEF:perr=aa,UN,INF,UNKN,IF CDEF:nerr=aa,UN,-INF,UNKN,IF '.
|
||||
'HRULE:0#808080 AREA:perr#FFD0D0 AREA:nerr#FFD0D0 '.
|
||||
'LINE2:aa#FF0000:"Ibat " GPRINT:a:LAST:"Current\:%7.0lf%smA" GPRINT:a:MIN:"Minimum\:%7.0lf%smA" GPRINT:a:MAX:"Maximum\:%7.0lf%smA\n" '.
|
||||
'LINE2:bb#00CF00:"Ubat " GPRINT:bb:LAST:"Current\:%7.3lf%s V" GPRINT:bb:MIN:"Minimum\:%7.3lf%s V" GPRINT:bb:MAX:"Maximum\:%7.3lf%s V\n" '.
|
||||
'LINE2:cc#0000FF:"Uin " GPRINT:cc:LAST:"Current\:%7.3lf%s V" GPRINT:cc:MIN:"Minimum\:%7.3lf%s V" GPRINT:cc:MAX:"Maximum\:%7.3lf%s V\n" '.
|
||||
'';
|
||||
break;
|
||||
|
||||
case 'apache':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"Workers\" ".
|
||||
"DEF:aa={$rrdfile}:total_accesses:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:total_kbytes:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:busy_workers:AVERAGE ".
|
||||
"DEF:d={$rrdfile}:idle_workers:AVERAGE ".
|
||||
'CDEF:a=aa,60,* '.
|
||||
'CDEF:err=aa,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:c#FF0000:"Busy Workers" GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:d#00CF00:"Idle Workers" GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE2:a#0000FF:"Accesses " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'';
|
||||
break;
|
||||
|
||||
case 'cpu':
|
||||
$height *= 2;
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"percent\" ".
|
||||
"DEF:a={$rrdfile}:user:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:nice:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:system:AVERAGE ".
|
||||
"DEF:e={$rrdfile}:iowait:AVERAGE ".
|
||||
"DEF:f={$rrdfile}:irq:AVERAGE ".
|
||||
"DEF:g={$rrdfile}:softirq:AVERAGE ".
|
||||
"DEF:h={$rrdfile}:steal:AVERAGE ".
|
||||
"DEF:amax={$rrdfile}:user:MAX ".
|
||||
"DEF:bmax={$rrdfile}:nice:MAX ".
|
||||
"DEF:cmax={$rrdfile}:system:MAX ".
|
||||
"DEF:emax={$rrdfile}:iowait:MAX ".
|
||||
"DEF:fmax={$rrdfile}:irq:MAX ".
|
||||
"DEF:gmax={$rrdfile}:softirq:MAX ".
|
||||
"DEF:hmax={$rrdfile}:steal:MAX ".
|
||||
"CDEF:allmax=amax,bmax,cmax,emax,fmax,gmax,hmax,+,+,+,+,+,+ ".
|
||||
'CDEF:err=allmax,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:allmax#C0C0C0 LINE1:allmax#808080 '.
|
||||
'AREA:c#FF0000:"System " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:f#EA8F00:"IRQ " GPRINT:f:LAST:"Current\:%8.2lf %s" GPRINT:f:AVERAGE:"Average\:%8.2lf %s" GPRINT:f:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:g#FFFF00:"Soft-IRQ" GPRINT:g:LAST:"Current\:%8.2lf %s" GPRINT:g:AVERAGE:"Average\:%8.2lf %s" GPRINT:g:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:h#0040FF:"IO-Wait " GPRINT:e:LAST:"Current\:%8.2lf %s" GPRINT:e:AVERAGE:"Average\:%8.2lf %s" GPRINT:e:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:a#00CFCF:"User " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:b#00CF00:"Nice " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:h#FF00FF:"Stolen " GPRINT:h:LAST:"Current\:%8.2lf %s" GPRINT:h:AVERAGE:"Average\:%8.2lf %s" GPRINT:h:MAX:"Maximum\:%8.2lf %s\n" ';
|
||||
break;
|
||||
|
||||
case 'conntrack':
|
||||
$tmp3 = explode('.', $tmp1[1]);
|
||||
switch ($tmp3[0]) {
|
||||
case 'proto':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"Connections\" ".
|
||||
"DEF:a={$rrdfile}:tcp:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:udp:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:unknown:AVERAGE ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:a#00CF00:"tcp " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:b#0000FF:"udp " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:c#FF0000:"unknown" GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" ';
|
||||
break;
|
||||
|
||||
case 'tcp':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"TCP Connections\" ".
|
||||
"DEF:a={$rrdfile}:none:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:syn_sent:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:syn_recv:AVERAGE ".
|
||||
"DEF:d={$rrdfile}:established:AVERAGE ".
|
||||
"DEF:e={$rrdfile}:fin_wait:AVERAGE ".
|
||||
"DEF:f={$rrdfile}:close_wait:AVERAGE ".
|
||||
"DEF:g={$rrdfile}:last_ack:AVERAGE ".
|
||||
"DEF:h={$rrdfile}:time_wait:AVERAGE ".
|
||||
"DEF:i={$rrdfile}:close:AVERAGE ".
|
||||
"DEF:j={$rrdfile}:listen:AVERAGE ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:b#FF0000:"SYN_SEND " GPRINT:b:LAST:"Current\:%8.2lf" GPRINT:b:AVERAGE:"Average\:%8.2lf" GPRINT:b:MAX:"Maximum\:%8.2lf\n" '.
|
||||
'STACK:f#FF00FF:"CLOSE_WAIT " GPRINT:f:LAST:"Current\:%8.2lf" GPRINT:f:AVERAGE:"Average\:%8.2lf" GPRINT:f:MAX:"Maximum\:%8.2lf\n" '.
|
||||
'STACK:g#0000FF:"LAST_ACK " GPRINT:g:LAST:"Current\:%8.2lf" GPRINT:g:AVERAGE:"Average\:%8.2lf" GPRINT:g:MAX:"Maximum\:%8.2lf\n" '.
|
||||
'STACK:h#007FFF:"TIME_WAIT " GPRINT:h:LAST:"Current\:%8.2lf" GPRINT:h:AVERAGE:"Average\:%8.2lf" GPRINT:h:MAX:"Maximum\:%8.2lf\n" '.
|
||||
'STACK:c#00FFFF:"SYN_RECV " GPRINT:c:LAST:"Current\:%8.2lf" GPRINT:c:AVERAGE:"Average\:%8.2lf" GPRINT:c:MAX:"Maximum\:%8.2lf\n" '.
|
||||
'STACK:d#00FF00:"ESTABLISHED" GPRINT:d:LAST:"Current\:%8.2lf" GPRINT:d:AVERAGE:"Average\:%8.2lf" GPRINT:d:MAX:"Maximum\:%8.2lf\n" '.
|
||||
'STACK:e#FFFF00:"FIN_WAIT " GPRINT:e:LAST:"Current\:%8.2lf" GPRINT:e:AVERAGE:"Average\:%8.2lf" GPRINT:e:MAX:"Maximum\:%8.2lf\n" '.
|
||||
'STACK:i#FF7F00:"CLOSE " GPRINT:i:LAST:"Current\:%8.2lf" GPRINT:i:AVERAGE:"Average\:%8.2lf" GPRINT:i:MAX:"Maximum\:%8.2lf\n" ';
|
||||
break;
|
||||
|
||||
default:
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"Connections\" ".
|
||||
"DEF:a={$rrdfile}:total:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:local:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:nated:AVERAGE ".
|
||||
"DEF:d={$rrdfile}:unreplied:AVERAGE ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'LINE1:a#000000:"Total " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'AREA:b#00CF00:"Local " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:c#0000FF:"NATed " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:d#FF0000:"Unreplied" GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" ';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ctstat':
|
||||
$height *= 2;
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"calls\" ".
|
||||
"DEF:a={$rrdfile}:searched:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:found:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:new:AVERAGE ".
|
||||
"DEF:d={$rrdfile}:invalid:AVERAGE ".
|
||||
"DEF:e={$rrdfile}:ignore:AVERAGE ".
|
||||
"DEF:f={$rrdfile}:delete:AVERAGE ".
|
||||
"DEF:g={$rrdfile}:delete_list:AVERAGE ".
|
||||
"DEF:h={$rrdfile}:insert:AVERAGE ".
|
||||
"DEF:i={$rrdfile}:insert_failed:AVERAGE ".
|
||||
"DEF:j={$rrdfile}:drop:AVERAGE ".
|
||||
"DEF:k={$rrdfile}:early_drop:AVERAGE ".
|
||||
"DEF:l={$rrdfile}:icmp_error:AVERAGE ".
|
||||
"DEF:m={$rrdfile}:expect_new:AVERAGE ".
|
||||
"DEF:n={$rrdfile}:expect_create:AVERAGE ".
|
||||
"DEF:o={$rrdfile}:expect_delete:AVERAGE ".
|
||||
'CDEF:ii=i,-1,* '.
|
||||
'CDEF:jj=j,-1,* '.
|
||||
'CDEF:kk=k,-1,* '.
|
||||
'CDEF:ll=l,-1,* '.
|
||||
'CDEF:mm=m,-1,* '.
|
||||
'CDEF:nn=n,-1,* '.
|
||||
'CDEF:oo=o,-1,* '.
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'LINE1:a#FF0000:"searched " GPRINT:a:LAST:"Current\:%8.0lf" GPRINT:a:AVERAGE:"Average\:%8.0lf" GPRINT:a:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:b#FF00FF:"found " GPRINT:b:LAST:"Current\:%8.0lf" GPRINT:b:AVERAGE:"Average\:%8.0lf" GPRINT:b:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:c#0000FF:"new " GPRINT:c:LAST:"Current\:%8.0lf" GPRINT:c:AVERAGE:"Average\:%8.0lf" GPRINT:c:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:d#007FFF:"invalid " GPRINT:d:LAST:"Current\:%8.0lf" GPRINT:d:AVERAGE:"Average\:%8.0lf" GPRINT:d:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:e#00FFFF:"ignore " GPRINT:e:LAST:"Current\:%8.0lf" GPRINT:e:AVERAGE:"Average\:%8.0lf" GPRINT:e:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:f#00FF00:"delete " GPRINT:f:LAST:"Current\:%8.0lf" GPRINT:f:AVERAGE:"Average\:%8.0lf" GPRINT:f:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:g#FFFF00:"delete_list " GPRINT:g:LAST:"Current\:%8.0lf" GPRINT:g:AVERAGE:"Average\:%8.0lf" GPRINT:g:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:h#FF7F00:"insert " GPRINT:h:LAST:"Current\:%8.0lf" GPRINT:h:AVERAGE:"Average\:%8.0lf" GPRINT:h:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'HRULE:0#000000:"-\n" '.
|
||||
'LINE1:ii#FF0000:"insert_failed " GPRINT:i:LAST:"Current\:%8.0lf" GPRINT:i:AVERAGE:"Average\:%8.0lf" GPRINT:i:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:jj#FF00FF:"drop " GPRINT:j:LAST:"Current\:%8.0lf" GPRINT:j:AVERAGE:"Average\:%8.0lf" GPRINT:j:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:kk#0000FF:"early_drop " GPRINT:k:LAST:"Current\:%8.0lf" GPRINT:k:AVERAGE:"Average\:%8.0lf" GPRINT:k:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:ll#007FFF:"icmp_errore " GPRINT:l:LAST:"Current\:%8.0lf" GPRINT:l:AVERAGE:"Average\:%8.0lf" GPRINT:l:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:mm#00FFFF:"expect_new " GPRINT:m:LAST:"Current\:%8.0lf" GPRINT:m:AVERAGE:"Average\:%8.0lf" GPRINT:m:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:nn#00FF00:"expect_create " GPRINT:n:LAST:"Current\:%8.0lf" GPRINT:n:AVERAGE:"Average\:%8.0lf" GPRINT:n:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:oo#FFFF00:"expect_delete " GPRINT:o:LAST:"Current\:%8.0lf" GPRINT:o:AVERAGE:"Average\:%8.0lf" GPRINT:o:MAX:"Maximum\:%8.0lf\n" ';
|
||||
break;
|
||||
|
||||
case 'disk':
|
||||
$height *= 2;
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"sectors\" ".
|
||||
"DEF:a={$rrdfile}:read_cnt:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:read_sec:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:read_ms:AVERAGE ".
|
||||
"DEF:dd={$rrdfile}:write_cnt:AVERAGE ".
|
||||
"DEF:ee={$rrdfile}:write_cnt:AVERAGE ".
|
||||
"DEF:ff={$rrdfile}:write_ms:AVERAGE ".
|
||||
'CDEF:d=dd,-1,* '.
|
||||
'CDEF:e=ee,-1,* '.
|
||||
'CDEF:f=ff,-1,* '.
|
||||
'CDEF:oerr=a,UN,INF,UNKN,IF CDEF:ierr=dd,UN,-INF,UNKN,IF '.
|
||||
'HRULE:0#FF0000 AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
|
||||
'LINE1:a#FF0000:"read_count " GPRINT:a:LAST:"Current\:%8.0lf" GPRINT:a:AVERAGE:"Average\:%8.0lf" GPRINT:a:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:b#FF00FF:"read_sectors " GPRINT:b:LAST:"Current\:%8.0lf" GPRINT:b:AVERAGE:"Average\:%8.0lf" GPRINT:b:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:c#0000FF:"sectors / ms " GPRINT:c:LAST:"Current\:%8.0lf" GPRINT:c:AVERAGE:"Average\:%8.0lf" GPRINT:c:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:d#FF0000:"write_count " GPRINT:dd:LAST:"Current\:%8.0lf" GPRINT:dd:AVERAGE:"Average\:%8.0lf" GPRINT:dd:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:e#FF00FF:"write_sectors " GPRINT:ee:LAST:"Current\:%8.0lf" GPRINT:ee:AVERAGE:"Average\:%8.0lf" GPRINT:ee:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:f#0000FF:"writes / ms " GPRINT:ff:LAST:"Current\:%8.0lf" GPRINT:ff:AVERAGE:"Average\:%8.0lf" GPRINT:ff:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'';
|
||||
break;
|
||||
|
||||
case 'diskstandby':
|
||||
$height /= 2;
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"Active\" ".
|
||||
"DEF:a={$rrdfile}:active:AVERAGE ".
|
||||
"CDEF:b=1,a,- ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:a#FF0000:"Active\n" '.
|
||||
'STACK:b#00CF00:"Standby" ';
|
||||
break;
|
||||
|
||||
case 'hddtemp':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"Temperature\" ".
|
||||
"DEF:a={$rrdfile}:temperature:AVERAGE ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:a#00CF00:"Temperature" GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:a#404040 ';
|
||||
break;
|
||||
|
||||
case 'hwmon':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"Temperature\" ".
|
||||
"DEF:a={$rrdfile}:temp:AVERAGE ".
|
||||
"CDEF:aa=a,1000,/ ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:aa#00CF00:"Temperature" GPRINT:aa:LAST:"Current\:%8.2lf %s" GPRINT:aa:AVERAGE:"Average\:%8.2lf %s" GPRINT:aa:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:aa#404040 ';
|
||||
break;
|
||||
|
||||
case 'load':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"load\" ".
|
||||
"DEF:a={$rrdfile}:1min:MAX ".
|
||||
"DEF:b={$rrdfile}:5min:MAX ".
|
||||
"DEF:c={$rrdfile}:15min:MAX ".
|
||||
'CDEF:x=a,b,c,MAX,MAX '.
|
||||
'CDEF:err=x,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:a#EACC00:" 1 Minute Maximum " GPRINT:a:LAST:"Current\:%8.2lf %s\n" '.
|
||||
'AREA:b#EA8F00:" 5 Minute Maximum " GPRINT:b:LAST:"Current\:%8.2lf %s\n" '.
|
||||
'AREA:c#FF0000:"15 Minute Maximum " GPRINT:c:LAST:"Current\:%8.2lf %s\n" '.
|
||||
'LINE1:x#404040:"Total"';
|
||||
break;
|
||||
|
||||
case 'memory':
|
||||
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"kB\" ".
|
||||
"DEF:aa={$rrdfile}:total:AVERAGE ".
|
||||
"DEF:bb={$rrdfile}:free:AVERAGE ".
|
||||
"DEF:cc={$rrdfile}:buffers:AVERAGE ".
|
||||
"DEF:dd={$rrdfile}:cached:AVERAGE ".
|
||||
'CDEF:a=aa,1024,* '.
|
||||
'CDEF:b=bb,1024,* '.
|
||||
'CDEF:c=cc,1024,* '.
|
||||
'CDEF:d=dd,1024,* '.
|
||||
'CDEF:x=aa,bb,cc,dd,+,+,-,1024,* '.
|
||||
'CDEF:xc=x,c,+ '.
|
||||
'CDEF:xcd=x,c,d,+,+ '.
|
||||
'CDEF:err=xcd,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'LINE1:a#000000:"Total Memory " GPRINT:a:LAST:"Current\:%8.2lf %s\n" '.
|
||||
'AREA:x#FF0000:"Used Memory " GPRINT:x:LAST:"Current\:%8.2lf %s" GPRINT:x:AVERAGE:"Average\:%8.2lf %s" GPRINT:x:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:c#FF7D00:"Buffer Memory " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:d#FFC73B:"Cache Memory " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:b#00CF00:"Free Memory " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:x#404040 LINE1:xc#404040 LINE1:xcd#404040';
|
||||
break;
|
||||
|
||||
case 'mount':
|
||||
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"kB\" ".
|
||||
"DEF:aa={$rrdfile}:block_total:AVERAGE ".
|
||||
"DEF:cc={$rrdfile}:block_free:AVERAGE ".
|
||||
'CDEF:a=aa,1024,* '.
|
||||
'CDEF:b=aa,cc,-,1024,* '.
|
||||
'CDEF:c=cc,1024,* '.
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'LINE1:a#000000:"Total " GPRINT:a:LAST:"Current\:%8.2lf %s\n" '.
|
||||
'AREA:b#FF0000:"Used " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:c#00CF00:"Free " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:b#404040 ';
|
||||
break;
|
||||
|
||||
case 'mysql':
|
||||
switch ($tmp1[1]) {
|
||||
case 'commands':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"commands\" ".
|
||||
"DEF:aa={$rrdfile}:com_delete:AVERAGE ".
|
||||
"DEF:bb={$rrdfile}:com_insert:AVERAGE ".
|
||||
"DEF:cc={$rrdfile}:com_select:AVERAGE ".
|
||||
"DEF:dd={$rrdfile}:com_update:AVERAGE ".
|
||||
"DEF:ee={$rrdfile}:questions:AVERAGE ".
|
||||
'CDEF:a=aa,60,* '.
|
||||
'CDEF:b=bb,60,* '.
|
||||
'CDEF:c=cc,60,* '.
|
||||
'CDEF:d=dd,60,* '.
|
||||
'CDEF:e=ee,60,* '.
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:e#0000FF:"All Commands " GPRINT:e:LAST:"Current\:%8.2lf %s" GPRINT:e:AVERAGE:"Average\:%8.2lf %s" GPRINT:e:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'AREA:a#FF0000:"DELETE ... " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:b#FF7D00:"INSERT ... " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:d#FFC73B:"UPDATE ... " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:c#00CF00:"SELECT ... " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'';
|
||||
break;
|
||||
|
||||
case 'qcache':
|
||||
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"???\" ".
|
||||
"DEF:a={$rrdfile}:qc_free_blocks:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:qc_free_memory:AVERAGE ".
|
||||
"DEF:cc={$rrdfile}:qc_hits:AVERAGE ".
|
||||
"DEF:dd={$rrdfile}:qc_inserts:AVERAGE ".
|
||||
"DEF:ee={$rrdfile}:qc_lowmem_prunes:AVERAGE ".
|
||||
"DEF:ff={$rrdfile}:qc_not_cached:AVERAGE ".
|
||||
"DEF:g={$rrdfile}:qc_queries_in_cache:AVERAGE ".
|
||||
"DEF:h={$rrdfile}:qc_total_blocks:AVERAGE ".
|
||||
'CDEF:c=cc,60,* '.
|
||||
'CDEF:d=dd,60,* '.
|
||||
'CDEF:e=ee,60,* '.
|
||||
'CDEF:f=ff,60,* '.
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'LINE1:a#FF0000:"qc_free_blocks " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:b#FFFF00:"qc_free_memory " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:c#00FF00:"qc_hits " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:d#00FFFF:"qc_inserts " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:e#0000FF:"qc_lowmemprunes " GPRINT:e:LAST:"Current\:%8.2lf %s" GPRINT:e:AVERAGE:"Average\:%8.2lf %s" GPRINT:e:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:f#FF00FF:"qc_not_cached " GPRINT:f:LAST:"Current\:%8.2lf %s" GPRINT:f:AVERAGE:"Average\:%8.2lf %s" GPRINT:f:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:g#FF00FF:"qc_queries_in_cache" GPRINT:g:LAST:"Current\:%8.2lf %s" GPRINT:g:AVERAGE:"Average\:%8.2lf %s" GPRINT:g:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:h#000000:"qc_total_blocks " GPRINT:h:LAST:"Current\:%8.2lf %s" GPRINT:h:AVERAGE:"Average\:%8.2lf %s" GPRINT:h:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'';
|
||||
break;
|
||||
|
||||
case 'threads':
|
||||
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"threads\" ".
|
||||
"DEF:a={$rrdfile}:threads_cached:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:threads_connected:AVERAGE ".
|
||||
"DEF:cc={$rrdfile}:threads_created:AVERAGE ".
|
||||
"DEF:d={$rrdfile}:threads_running:AVERAGE ".
|
||||
'CDEF:c=cc,60,* '.
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'LINE1:c#00CF00:"threads created " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:d#FF0000:"threads running " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:b#00FFFF:"threads connected" GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:a#0000FF:"threads cached " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'';
|
||||
break;
|
||||
|
||||
case 'traffic':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"bytes per second\" ".
|
||||
"DEF:imax={$rrdfile}:bytes_received:MAX ".
|
||||
"DEF:iavg={$rrdfile}:bytes_received:AVERAGE ".
|
||||
"DEF:imin={$rrdfile}:bytes_received:MIN ".
|
||||
"DEF:omax={$rrdfile}:bytes_sent:MAX ".
|
||||
"DEF:oavg={$rrdfile}:bytes_sent:AVERAGE ".
|
||||
"DEF:omin={$rrdfile}:bytes_sent:MIN ".
|
||||
'CDEF:omaxn=omax,-1,* CDEF:oavgn=oavg,-1,* CDEF:ominn=omin,-1,* '.
|
||||
'CDEF:imid=imax,imin,- CDEF:omid=omaxn,ominn,- '.
|
||||
'CDEF:oerr=oavg,UN,INF,UNKN,IF CDEF:ierr=iavg,UN,-INF,UNKN,IF '.
|
||||
'HRULE:0#FF0000 AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
|
||||
'AREA:imin STACK:imid#A0FFA0:"min/max Inbound " GPRINT:imin:MIN:"%6.2lf%s" GPRINT:imax:MAX:"%6.2lf%s" '.
|
||||
'LINE1:imin#a0a0a0 LINE1:imax#a0a0a0 LINE1:iavg#008000:"avg Inbound " '.
|
||||
'GPRINT:iavg:MIN:"min\: %6.2lf%s" GPRINT:iavg:AVERAGE:"avg\: %6.2lf%s" GPRINT:iavg:MAX:"max\: %6.2lf%s\n" '.
|
||||
'AREA:ominn STACK:omid#C0C0FF:"min/max Outbound" GPRINT:omin:MIN:"%6.2lf%s" GPRINT:omax:MAX:"%6.2lf%s" '.
|
||||
'LINE1:ominn#a0a0a0 LINE1:omaxn#a0a0a0 LINE1:oavgn#000080:"avg Outbound" '.
|
||||
'GPRINT:oavg:MIN:"min\: %6.2lf%s" GPRINT:oavg:AVERAGE:"avg\: %6.2lf%s" GPRINT:oavg:MAX:"max\: %6.2lf%s\n" ';
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'net':
|
||||
$height *= 2;
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"bytes per second\" ".
|
||||
"DEF:imax={$rrdfile}:byte_in:MAX ".
|
||||
"DEF:iavg={$rrdfile}:byte_in:AVERAGE ".
|
||||
"DEF:imin={$rrdfile}:byte_in:MIN ".
|
||||
"DEF:omax={$rrdfile}:byte_out:MAX ".
|
||||
"DEF:oavg={$rrdfile}:byte_out:AVERAGE ".
|
||||
"DEF:omin={$rrdfile}:byte_out:MIN ".
|
||||
'CDEF:omaxn=omax,-1,* CDEF:oavgn=oavg,-1,* CDEF:ominn=omin,-1,* '.
|
||||
'CDEF:imid=imax,imin,- CDEF:omid=omaxn,ominn,- '.
|
||||
'CDEF:oerr=oavg,UN,INF,UNKN,IF CDEF:ierr=iavg,UN,-INF,UNKN,IF '.
|
||||
'HRULE:0#FF0000 AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
|
||||
'AREA:imin#E0FFE0 STACK:imid#A0FFA0:"min/max Inbound " GPRINT:imin:MIN:"%6.2lf%s" GPRINT:imax:MAX:"%6.2lf%s" '.
|
||||
'LINE1:imin#a0a0a0 LINE1:imax#a0a0a0 LINE1:iavg#008000:"avg Inbound " '.
|
||||
'GPRINT:iavg:MIN:"min\: %6.2lf%s" GPRINT:iavg:AVERAGE:"avg\: %6.2lf%s" GPRINT:iavg:MAX:"max\: %6.2lf%s\n" '.
|
||||
'AREA:ominn#E0E0FF STACK:omid#C0C0FF:"min/max Outbound" GPRINT:omin:MIN:"%6.2lf%s" GPRINT:omax:MAX:"%6.2lf%s" '.
|
||||
'LINE1:ominn#a0a0a0 LINE1:omaxn#a0a0a0 LINE1:oavgn#000080:"avg Outbound" '.
|
||||
'GPRINT:oavg:MIN:"min\: %6.2lf%s" GPRINT:oavg:AVERAGE:"avg\: %6.2lf%s" GPRINT:oavg:MAX:"max\: %6.2lf%s\n" ';
|
||||
break;
|
||||
|
||||
case 'proc':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"per second\" ".
|
||||
"DEF:a={$rrdfile}:intr:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:ctxt:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:fork:AVERAGE ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:b#00AF00:"Context " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:a#FF0000:"Interrupts" GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:c#0000FF:"Forks " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" ';
|
||||
break;
|
||||
|
||||
case 'random':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit 0 --vertical-label=\"bytes\" ".
|
||||
"DEF:a={$rrdfile}:entropy:AVERAGE ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:a#00CF00:"Available Entropy" GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:a#404040 ';
|
||||
break;
|
||||
|
||||
case 'rtcache':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"calls\" ".
|
||||
"DEF:a={$rrdfile}:entries:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:gc_total:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:gc_ignored:AVERAGE ".
|
||||
"DEF:d={$rrdfile}:gc_goal_miss:AVERAGE ".
|
||||
"DEF:e={$rrdfile}:gc_dst_overflow:AVERAGE ".
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'LINE1:a#FF0000:"entries " GPRINT:a:LAST:"Current\:%8.0lf" GPRINT:a:AVERAGE:"Average\:%8.0lf" GPRINT:a:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:b#FF00FF:"gc_total " GPRINT:b:LAST:"Current\:%8.0lf" GPRINT:b:AVERAGE:"Average\:%8.0lf" GPRINT:b:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:c#0000FF:"gc_ignored " GPRINT:c:LAST:"Current\:%8.0lf" GPRINT:c:AVERAGE:"Average\:%8.0lf" GPRINT:c:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:d#007FFF:"gc_goal_miss " GPRINT:d:LAST:"Current\:%8.0lf" GPRINT:d:AVERAGE:"Average\:%8.0lf" GPRINT:d:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:e#00FFFF:"gc_dst_overflow " GPRINT:e:LAST:"Current\:%8.0lf" GPRINT:e:AVERAGE:"Average\:%8.0lf" GPRINT:e:MAX:"Maximum\:%8.0lf\n" ';
|
||||
break;
|
||||
|
||||
case 'rtstat':
|
||||
$height *= 2;
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"calls\" ".
|
||||
"DEF:a={$rrdfile}:in_hit:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:in_slow_tot:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:in_slow_mc:AVERAGE ".
|
||||
"DEF:d={$rrdfile}:in_no_route:AVERAGE ".
|
||||
"DEF:e={$rrdfile}:in_brd:AVERAGE ".
|
||||
"DEF:f={$rrdfile}:in_martian_dst:AVERAGE ".
|
||||
"DEF:g={$rrdfile}:in_martian_src:AVERAGE ".
|
||||
"DEF:h={$rrdfile}:in_hlist_search:AVERAGE ".
|
||||
"DEF:i={$rrdfile}:out_hit:AVERAGE ".
|
||||
"DEF:j={$rrdfile}:out_slow_tot:AVERAGE ".
|
||||
"DEF:k={$rrdfile}:out_slow_mc:AVERAGE ".
|
||||
"DEF:l={$rrdfile}:out_hlist_search:AVERAGE ".
|
||||
'CDEF:ii=i,-1,* '.
|
||||
'CDEF:jj=j,-1,* '.
|
||||
'CDEF:kk=k,-1,* '.
|
||||
'CDEF:ll=l,-1,* '.
|
||||
'CDEF:oerr=a,UN,INF,UNKN,IF CDEF:ierr=i,UN,-INF,UNKN,IF '.
|
||||
'AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
|
||||
'LINE1:a#FF0000:"in_hit " GPRINT:a:LAST:"Current\:%8.0lf" GPRINT:a:AVERAGE:"Average\:%8.0lf" GPRINT:a:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:b#FF00FF:"in_slow_tot " GPRINT:b:LAST:"Current\:%8.0lf" GPRINT:b:AVERAGE:"Average\:%8.0lf" GPRINT:b:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:c#0000FF:"in_slow_mc " GPRINT:c:LAST:"Current\:%8.0lf" GPRINT:c:AVERAGE:"Average\:%8.0lf" GPRINT:c:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:d#007FFF:"in_no_route " GPRINT:d:LAST:"Current\:%8.0lf" GPRINT:d:AVERAGE:"Average\:%8.0lf" GPRINT:d:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:e#00FFFF:"in_brd " GPRINT:e:LAST:"Current\:%8.0lf" GPRINT:e:AVERAGE:"Average\:%8.0lf" GPRINT:e:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:f#00FF00:"in_martian_dst " GPRINT:f:LAST:"Current\:%8.0lf" GPRINT:f:AVERAGE:"Average\:%8.0lf" GPRINT:f:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:g#FFFF00:"in_martian_src " GPRINT:g:LAST:"Current\:%8.0lf" GPRINT:g:AVERAGE:"Average\:%8.0lf" GPRINT:g:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:h#FF7F00:"in_hlist_search " GPRINT:h:LAST:"Current\:%8.0lf" GPRINT:h:AVERAGE:"Average\:%8.0lf" GPRINT:h:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'HRULE:0#FF0000:"-\n" '.
|
||||
'LINE1:ii#FF0000:"out_hit " GPRINT:i:LAST:"Current\:%8.0lf" GPRINT:i:AVERAGE:"Average\:%8.0lf" GPRINT:i:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:jj#FF00FF:"out_slow_tot " GPRINT:j:LAST:"Current\:%8.0lf" GPRINT:j:AVERAGE:"Average\:%8.0lf" GPRINT:j:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:kk#0000FF:"out_slow_mc " GPRINT:k:LAST:"Current\:%8.0lf" GPRINT:k:AVERAGE:"Average\:%8.0lf" GPRINT:k:MAX:"Maximum\:%8.0lf\n" '.
|
||||
'LINE1:ll#FF7F00:"out_hlist_search " GPRINT:l:LAST:"Current\:%8.0lf" GPRINT:l:AVERAGE:"Average\:%8.0lf" GPRINT:l:MAX:"Maximum\:%8.0lf\n" ';
|
||||
break;
|
||||
|
||||
case 'swap':
|
||||
$cmd .= "--base=1024 --height={$height} --width={$width} --alt-autoscale-max --lower-limit=0 --vertical-label=\"kB\" ".
|
||||
"DEF:aa={$rrdfile}:total:AVERAGE ".
|
||||
"DEF:bb={$rrdfile}:free:AVERAGE ".
|
||||
'CDEF:a=aa,1024,* '.
|
||||
'CDEF:b=bb,1024,* '.
|
||||
'CDEF:x=aa,bb,-,1024,* '.
|
||||
'CDEF:err=a,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'LINE1:a#000000:"Total Swap " GPRINT:a:LAST:"Current\:%8.2lf %s\n" '.
|
||||
'AREA:x#FF0000:"Used Swap " GPRINT:x:LAST:"Current\:%8.2lf %s" GPRINT:x:AVERAGE:"Average\:%8.2lf %s" GPRINT:x:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:b#00CF00:"Free Swap " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" ';
|
||||
break;
|
||||
|
||||
case 'ts2':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit 0 --vertical-label=\"users/chans\" ".
|
||||
"DEF:users={$rrdfile}:users:AVERAGE ".
|
||||
"DEF:chans={$rrdfile}:channels:AVERAGE ".
|
||||
'CDEF:err=users,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:chans#00CF00:"Channels \n" '.
|
||||
'LINE1:users#002A97:"Users "';
|
||||
break;
|
||||
|
||||
case 'uptime':
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --lower-limit 0 --vertical-label=\"days\" ".
|
||||
"DEF:ups={$rrdfile}:uptime:AVERAGE ".
|
||||
"DEF:idles={$rrdfile}:idletime:AVERAGE ".
|
||||
'CDEF:up=ups,86400,/ '.
|
||||
'CDEF:idle=idles,86400,/ '.
|
||||
'CDEF:err=ups,UN,INF,UNKN,IF '.
|
||||
'AREA:err#FFD0D0 '.
|
||||
'AREA:up#00CF00:"Uptime \n" '.
|
||||
'LINE1:idle#002A97:"Idletime "';
|
||||
break;
|
||||
|
||||
case 'vmstat':
|
||||
$height *= 2;
|
||||
$cmd .= "--base=1000 --height={$height} --width={$width} --alt-autoscale-max --vertical-label=\"allocs\" ".
|
||||
"DEF:a={$rrdfile}:pgalloc_high:AVERAGE ".
|
||||
"DEF:b={$rrdfile}:pgalloc_normal:AVERAGE ".
|
||||
"DEF:c={$rrdfile}:pgalloc_dma:AVERAGE ".
|
||||
"DEF:d={$rrdfile}:pgfree:AVERAGE ".
|
||||
"DEF:e={$rrdfile}:pgfault:AVERAGE ".
|
||||
"CDEF:ee=e,-1,* ".
|
||||
'CDEF:oerr=a,UN,INF,UNKN,IF CDEF:ierr=e,UN,-INF,UNKN,IF '.
|
||||
'AREA:ierr#FFD0D0 AREA:oerr#FFD0D0 '.
|
||||
'HRULE:0#FF0000: '.
|
||||
'AREA:c#FF0000:"pgalloc_dma " GPRINT:c:LAST:"Current\:%8.2lf %s" GPRINT:c:AVERAGE:"Average\:%8.2lf %s" GPRINT:c:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:b#00CF00:"pgalloc_normal " GPRINT:b:LAST:"Current\:%8.2lf %s" GPRINT:b:AVERAGE:"Average\:%8.2lf %s" GPRINT:b:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'STACK:a#00CFCF:"pgalloc_high " GPRINT:a:LAST:"Current\:%8.2lf %s" GPRINT:a:AVERAGE:"Average\:%8.2lf %s" GPRINT:a:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:d#FF7D00:"pgfree " GPRINT:d:LAST:"Current\:%8.2lf %s" GPRINT:d:AVERAGE:"Average\:%8.2lf %s" GPRINT:d:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'AREA:ee#0040FF:"pgfault " GPRINT:e:LAST:"Current\:%8.2lf %s" GPRINT:e:AVERAGE:"Average\:%8.2lf %s" GPRINT:e:MAX:"Maximum\:%8.2lf %s\n" '.
|
||||
'LINE1:ee#002A97 ';
|
||||
break;
|
||||
}
|
||||
|
||||
header('Content-type: image/x-png');
|
||||
passthru($cmd);
|
||||
die();
|
||||
}
|
||||
|
||||
$action = $_GET['action'];
|
||||
switch ($action) {
|
||||
case 'init':
|
||||
$conf = create_config();
|
||||
write_config(CONFIG, $conf);
|
||||
header("Location: {$_SERVER['SCRIPT_NAME']}?action=setup");
|
||||
break;
|
||||
|
||||
|
||||
case 'setup':
|
||||
$conf = read_config(CONFIG);
|
||||
$conf = setup($conf);
|
||||
if (isset($conf)) {
|
||||
write_config(CONFIG, $conf);
|
||||
header("Location: {$_SERVER['SCRIPT_NAME']}?action=setup");
|
||||
}
|
||||
break;
|
||||
|
||||
case 'rrd':
|
||||
$conf = read_config(CONFIG);
|
||||
show_rrd($conf);
|
||||
break;
|
||||
|
||||
default:
|
||||
case 'show':
|
||||
$conf = read_config(CONFIG);
|
||||
show_html($conf);
|
||||
break;
|
||||
}
|
||||
|
||||
?>
|
151
signals.c
151
signals.c
@ -1,151 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 05/2009 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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; version 2 of the License *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
#include "signals.h"
|
||||
|
||||
struct signal_entry {
|
||||
struct list_head list;
|
||||
int signum;
|
||||
int deleted;
|
||||
|
||||
void (*callback)(void *privdata);
|
||||
void *privdata;
|
||||
};
|
||||
|
||||
static LIST_HEAD(callback_list);
|
||||
static int sig_pipe[2];
|
||||
|
||||
static void sig_handler(int signal)
|
||||
{
|
||||
unsigned char signum = (signal & 0xFF);
|
||||
write(sig_pipe[1], &signum, 1);
|
||||
}
|
||||
|
||||
int signal_remove_callback(int signum, int type)
|
||||
{
|
||||
/* mark all old handler for deletion */
|
||||
struct signal_entry *search;
|
||||
list_for_each_entry(search, &callback_list, list) {
|
||||
if (search->signum == signum)
|
||||
search->deleted = 1;
|
||||
}
|
||||
|
||||
struct sigaction sig_action;
|
||||
|
||||
switch (type) {
|
||||
case SIG_IGNORE:
|
||||
sig_action.sa_handler = SIG_IGN;
|
||||
break;
|
||||
|
||||
default:
|
||||
case SIG_DEFAULT:
|
||||
sig_action.sa_handler = SIG_DFL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sigaction(signum, &sig_action, NULL) < 0) {
|
||||
log_print(LOG_WARN, "%s(): sigaction(%d)", __FUNCTION__, signum);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* trigger remove */
|
||||
sig_handler(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int signal_add_callback(int signum, void (*callback)(void *privdata), void *privdata)
|
||||
{
|
||||
struct signal_entry *entry = malloc(sizeof(struct signal_entry));
|
||||
if (entry == NULL) {
|
||||
log_print(LOG_WARN, "%s(): out of memory", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
entry->signum = signum;
|
||||
entry->deleted = 0;
|
||||
entry->callback = callback;
|
||||
entry->privdata = privdata;
|
||||
list_add_tail(&entry->list, &callback_list);
|
||||
|
||||
struct sigaction sig_action = {
|
||||
.sa_handler = sig_handler,
|
||||
};
|
||||
|
||||
if (sigaction(signum, &sig_action, NULL) < 0) {
|
||||
log_print(LOG_WARN, "%s(): sigaction(%d)", __FUNCTION__, signum);
|
||||
list_del(&entry->list);
|
||||
free(entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sig_event(int fd, void *privdata)
|
||||
{
|
||||
unsigned char signum;
|
||||
int len = read(fd, &signum, 1);
|
||||
if (len <= 0) {
|
||||
log_print(LOG_WARN, "%s(): read()", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct signal_entry *search, *tmp;
|
||||
list_for_each_entry_safe(search, tmp, &callback_list, list) {
|
||||
if (search->deleted) {
|
||||
list_del(&search->list);
|
||||
free(search);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (search->signum == signum)
|
||||
search->callback(search->privdata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int signal_init(void)
|
||||
{
|
||||
if (pipe(sig_pipe) < 0) {
|
||||
log_print(LOG_ERROR, "%s(): pipe()", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(sig_pipe[0], F_SETFD, FD_CLOEXEC) < 0) {
|
||||
log_print(LOG_WARN, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(sig_pipe[1], F_SETFD, FD_CLOEXEC) < 0) {
|
||||
log_print(LOG_WARN, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
event_add_readfd(NULL, sig_pipe[0], sig_event, NULL);
|
||||
return 0;
|
||||
}
|
12
signals.h
12
signals.h
@ -1,12 +0,0 @@
|
||||
#ifndef _SIGNALS_H
|
||||
#define _SIGNALS_H
|
||||
|
||||
#define SIG_DEFAULT 0x00
|
||||
#define SIG_IGNORE 0x01
|
||||
|
||||
int signal_remove_callback(int signum, int type);
|
||||
int signal_add_callback(int signum, void (*callback)(void *privdata), void *privdata);
|
||||
|
||||
int signal_init(void);
|
||||
|
||||
#endif // _SIGNALS_H
|
117
sockaddr.c
117
sockaddr.c
@ -1,117 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 07/2007 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.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; version 2 of the License *
|
||||
* *
|
||||
* 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. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
int parse_sockaddr(const char *addr, struct sockaddr_in *sa)
|
||||
{
|
||||
char *buf = strdup(addr);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
char *tmp;
|
||||
char *ipstr = strtok_r(buf, ":", &tmp);
|
||||
if (ipstr == NULL) {
|
||||
free(buf);
|
||||
return -2;
|
||||
}
|
||||
|
||||
sa->sin_family = AF_INET;
|
||||
if (inet_pton(AF_INET, ipstr, &sa->sin_addr) <= 0) {
|
||||
free(buf);
|
||||
return -3;
|
||||
}
|
||||
|
||||
char *portstr = strtok_r(NULL, " \r\n", &tmp);
|
||||
if (portstr == NULL) {
|
||||
free(buf);
|
||||
return -4;
|
||||
}
|
||||
|
||||
int port = atoi(portstr);
|
||||
if (port < 0 || port > 65535) {
|
||||
free(buf);
|
||||
return -5;
|
||||
}
|
||||
|
||||
sa->sin_port = htons(port);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_subnet(const char *addr, struct in_addr *net, struct in_addr *mask)
|
||||
{
|
||||
char *buf = strdup(addr);
|
||||
if (buf == NULL)
|
||||
return -1;
|
||||
|
||||
char *tmp;
|
||||
char *netstr = strtok_r(buf, "/", &tmp);
|
||||
if (netstr == NULL) {
|
||||
free(buf);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, netstr, net) <= 0) {
|
||||
free(buf);
|
||||
return -3;
|
||||
}
|
||||
|
||||
char *maskstr = strtok_r(NULL, " \r\n", &tmp);
|
||||
if (maskstr == NULL) {
|
||||
mask->s_addr = ~0;
|
||||
|
||||
} else if (inet_pton(AF_INET, maskstr, mask) <= 0) {
|
||||
int maskbits = atoi(maskstr);
|
||||
if (maskbits < 0 || maskbits > 32) {
|
||||
free(buf);
|
||||
return -4;
|
||||
}
|
||||
|
||||
mask->s_addr = htonl(~0 << (32 - maskbits));
|
||||
}
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_sockaddr(char *buf, int size, struct sockaddr_in *addr)
|
||||
{
|
||||
return snprintf(buf, size, "%s:%d", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
||||
}
|
||||
|
||||
char * get_sockaddr_buf(struct sockaddr_in *addr)
|
||||
{
|
||||
static char ret[24];
|
||||
get_sockaddr(ret, sizeof(ret), addr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int same_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b)
|
||||
{
|
||||
return !((a->sin_family ^ b->sin_family) |
|
||||
(a->sin_addr.s_addr ^ b->sin_addr.s_addr) |
|
||||
(a->sin_port ^ b->sin_port));
|
||||
}
|
14
sockaddr.h
14
sockaddr.h
@ -1,14 +0,0 @@
|
||||
#ifndef _SOCKADDR_H_
|
||||
#define _SOCKADDR_H_
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
int parse_sockaddr(const char *addr, struct sockaddr_in *sa);
|
||||
int parse_subnet(const char *addr, struct in_addr *net, struct in_addr *mask);
|
||||
|
||||
int get_sockaddr(char *buf, int size, struct sockaddr_in *addr);
|
||||
char * get_sockaddr_buf(struct sockaddr_in *addr);
|
||||
|
||||
int same_sockaddr(struct sockaddr_in *a, struct sockaddr_in *b);
|
||||
|
||||
#endif /* _SOCKADDR_H_ */
|
Loading…
Reference in New Issue
Block a user