2015-09-15 18:15:12 +04:30
|
|
|
/*-
|
|
|
|
* Copyright (c) 2015, Babak Farrokhi
|
|
|
|
* All rights reserved.
|
2015-09-16 09:39:43 +04:30
|
|
|
*
|
2015-09-15 18:15:12 +04:30
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are met:
|
2015-09-16 09:39:43 +04:30
|
|
|
*
|
2015-09-15 18:15:12 +04:30
|
|
|
* * Redistributions of source code must retain the above copyright notice, this
|
|
|
|
* list of conditions and the following disclaimer.
|
2015-09-16 09:39:43 +04:30
|
|
|
*
|
2015-09-15 18:15:12 +04:30
|
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
|
|
* and/or other materials provided with the distribution.
|
2015-09-16 09:39:43 +04:30
|
|
|
*
|
2015-09-15 18:15:12 +04:30
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2015-09-12 18:48:43 +04:30
|
|
|
*/
|
|
|
|
|
2015-09-12 18:37:46 +04:30
|
|
|
#include <sys/cdefs.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/time.h>
|
2015-09-12 23:14:30 +04:30
|
|
|
#include <sys/file.h>
|
2015-09-12 18:37:46 +04:30
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <net/if.h>
|
2015-10-27 11:55:56 +03:30
|
|
|
#include <ifaddrs.h>
|
|
|
|
|
|
|
|
#ifdef __linux__
|
|
|
|
# define AF_LINK AF_PACKET
|
|
|
|
#else
|
2015-09-12 18:37:46 +04:30
|
|
|
#include <net/if_var.h>
|
|
|
|
#include <net/if_types.h>
|
2015-10-27 11:55:56 +03:30
|
|
|
#endif
|
2015-09-12 18:37:46 +04:30
|
|
|
|
|
|
|
#include <err.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sysexits.h>
|
|
|
|
#include <unistd.h>
|
2015-10-21 11:29:05 +03:30
|
|
|
#include <time.h>
|
|
|
|
#include <pidutil.h>
|
|
|
|
|
|
|
|
#ifdef __MACH__
|
|
|
|
#include <sys/time.h>
|
|
|
|
#define CLOCK_REALTIME 0
|
|
|
|
#endif
|
2015-09-12 18:37:46 +04:30
|
|
|
|
2015-10-27 11:55:56 +03:30
|
|
|
#ifdef __linux__
|
|
|
|
/*
|
|
|
|
* * Structure describing information about an interface
|
|
|
|
* * which may be of interest to management entities.
|
|
|
|
* */
|
|
|
|
struct if_data {
|
|
|
|
/* generic interface information */
|
|
|
|
u_char ifi_type; /* ethernet, tokenring, etc */
|
|
|
|
u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */
|
|
|
|
u_char ifi_addrlen; /* media address length */
|
|
|
|
u_char ifi_hdrlen; /* media header length */
|
|
|
|
u_char ifi_link_state; /* current link state */
|
|
|
|
u_char ifi_vhid; /* carp vhid */
|
|
|
|
u_char ifi_baudrate_pf; /* baudrate power factor */
|
|
|
|
u_char ifi_datalen; /* length of this data struct */
|
|
|
|
u_long ifi_mtu; /* maximum transmission unit */
|
|
|
|
u_long ifi_metric; /* routing metric (external only) */
|
|
|
|
u_long ifi_baudrate; /* linespeed */
|
|
|
|
/* volatile statistics */
|
|
|
|
u_long ifi_ipackets; /* packets received on interface */
|
|
|
|
u_long ifi_ierrors; /* input errors on interface */
|
|
|
|
u_long ifi_opackets; /* packets sent on interface */
|
|
|
|
u_long ifi_oerrors; /* output errors on interface */
|
|
|
|
u_long ifi_collisions; /* collisions on csma interfaces */
|
|
|
|
u_long ifi_ibytes; /* total number of octets received */
|
|
|
|
u_long ifi_obytes; /* total number of octets sent */
|
|
|
|
u_long ifi_imcasts; /* packets received via multicast */
|
|
|
|
u_long ifi_omcasts; /* packets sent via multicast */
|
|
|
|
u_long ifi_iqdrops; /* dropped on input, this interface */
|
|
|
|
u_long ifi_noproto; /* destined for unsupported protocol */
|
|
|
|
uint64_t ifi_hwassist; /* HW offload capabilities, see IFCAP */
|
|
|
|
time_t ifi_epoch; /* uptime at attach or stat reset */
|
|
|
|
struct timeval ifi_lastchange; /* time of last administrative change */
|
|
|
|
#ifdef _IFI_OQDROPS
|
|
|
|
u_long ifi_oqdrops; /* dropped on output */
|
|
|
|
#endif /* _IFI_OQFROPS */
|
|
|
|
};
|
|
|
|
#endif /* __linux __ */
|
|
|
|
|
2015-09-12 18:37:46 +04:30
|
|
|
#define IFA_STAT(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
|
2015-09-13 14:44:01 +04:30
|
|
|
#define RESOLUTION 10
|
2015-09-12 18:37:46 +04:30
|
|
|
|
|
|
|
struct iftot {
|
2015-09-16 09:39:43 +04:30
|
|
|
u_long ift_ip; /* input packets */
|
|
|
|
u_long ift_ie; /* input errors */
|
|
|
|
u_long ift_id; /* input drops */
|
|
|
|
u_long ift_op; /* output packets */
|
|
|
|
u_long ift_oe; /* output errors */
|
|
|
|
u_long ift_od; /* output drops */
|
|
|
|
u_long ift_co; /* collisions */
|
|
|
|
u_long ift_ib; /* input bytes */
|
|
|
|
u_long ift_ob; /* output bytes */
|
2015-09-12 18:37:46 +04:30
|
|
|
};
|
|
|
|
|
2015-09-13 16:15:52 +04:30
|
|
|
/* Globals */
|
2015-09-16 09:39:43 +04:30
|
|
|
char *program_name = "ifstatd_";
|
|
|
|
char *interface;
|
|
|
|
char *pid_filename;
|
|
|
|
char *cache_filename;
|
|
|
|
struct pidfh *pfh;
|
2015-09-15 18:15:12 +04:30
|
|
|
|
2015-10-21 11:29:05 +03:30
|
|
|
#ifdef __MACH__
|
|
|
|
/* clock_gettime is not implemented on OSX */
|
|
|
|
int
|
|
|
|
clock_gettime(int clk_id, struct timespec *t)
|
|
|
|
{
|
|
|
|
struct timeval now;
|
|
|
|
int rv = gettimeofday(&now, NULL);
|
|
|
|
|
|
|
|
if (rv)
|
|
|
|
return rv;
|
|
|
|
t->tv_sec = now.tv_sec;
|
|
|
|
t->tv_nsec = now.tv_usec * 1000;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
/*
|
|
|
|
* Prepare for a clean shutdown
|
|
|
|
*/
|
2015-09-16 12:14:02 +04:30
|
|
|
void
|
2015-09-16 09:33:31 +04:30
|
|
|
daemon_shutdown()
|
2015-09-15 18:15:12 +04:30
|
|
|
{
|
|
|
|
pidfile_remove(pfh);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Act upon receiving signals
|
|
|
|
*/
|
2015-09-16 12:14:02 +04:30
|
|
|
void
|
2015-09-16 09:33:31 +04:30
|
|
|
signal_handler(int sig)
|
2015-09-15 18:15:12 +04:30
|
|
|
{
|
2015-09-16 09:33:31 +04:30
|
|
|
switch (sig) {
|
|
|
|
|
|
|
|
case SIGHUP:
|
|
|
|
case SIGINT:
|
|
|
|
case SIGTERM:
|
|
|
|
daemon_shutdown();
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2015-09-15 18:15:12 +04:30
|
|
|
}
|
|
|
|
}
|
2015-09-12 18:37:46 +04:30
|
|
|
|
|
|
|
/*
|
|
|
|
* Obtain stats for interface(s).
|
|
|
|
*/
|
2015-09-16 12:14:02 +04:30
|
|
|
static void
|
2015-09-16 09:33:31 +04:30
|
|
|
fill_iftot(struct iftot *st)
|
|
|
|
{
|
|
|
|
struct ifaddrs *ifap, *ifa;
|
2015-09-16 09:39:43 +04:30
|
|
|
bool found = false;
|
2015-09-16 09:33:31 +04:30
|
|
|
|
|
|
|
if (getifaddrs(&ifap) != 0)
|
|
|
|
err(EX_OSERR, "getifaddrs");
|
|
|
|
|
|
|
|
bzero(st, sizeof(*st));
|
|
|
|
|
|
|
|
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
|
|
|
|
if (ifa->ifa_addr->sa_family != AF_LINK)
|
|
|
|
continue;
|
|
|
|
if (interface) {
|
|
|
|
if (strcmp(ifa->ifa_name, interface) == 0)
|
|
|
|
found = true;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
st->ift_ip += IFA_STAT(ipackets);
|
|
|
|
st->ift_ib += IFA_STAT(ibytes);
|
|
|
|
st->ift_op += IFA_STAT(opackets);
|
|
|
|
st->ift_ob += IFA_STAT(obytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (interface && found == false)
|
|
|
|
err(EX_DATAERR, "interface %s not found", interface);
|
|
|
|
|
|
|
|
freeifaddrs(ifap);
|
2015-09-12 18:37:46 +04:30
|
|
|
}
|
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
/*
|
|
|
|
* Print out munin plugin configuration
|
|
|
|
*/
|
2015-09-16 12:14:02 +04:30
|
|
|
int
|
2015-09-16 09:33:31 +04:30
|
|
|
config(char *iface)
|
2015-09-12 18:37:46 +04:30
|
|
|
{
|
2015-09-16 09:39:43 +04:30
|
|
|
printf(
|
|
|
|
"graph_order rbytes obytes\n"
|
|
|
|
"graph_title %s Interface (%d seconds sampling)\n"
|
|
|
|
"graph_category network\n"
|
|
|
|
"graph_vlabel bits per second\n"
|
|
|
|
"update_rate %d\n"
|
|
|
|
"graph_data_size custom 1d, %ds for 1w, 1m for 1t, 5m for 1y\n"
|
|
|
|
"rbytes.label received\n"
|
|
|
|
"rbytes.type DERIVE\n"
|
|
|
|
"rbytes.graph no\n"
|
|
|
|
"rbytes.cdef rbytes,8,*\n"
|
|
|
|
"rbytes.min 0\n"
|
|
|
|
"obytes.label bps\n"
|
|
|
|
"obytes.type DERIVE\n"
|
|
|
|
"obytes.negative rbytes\n"
|
|
|
|
"obytes.cdef obytes,8,*\n"
|
|
|
|
"obytes.min 0\n"
|
|
|
|
"obytes.draw AREA\n"
|
|
|
|
,iface, RESOLUTION, RESOLUTION, RESOLUTION
|
|
|
|
);
|
2015-09-16 09:33:31 +04:30
|
|
|
|
|
|
|
return (0);
|
2015-09-12 18:37:46 +04:30
|
|
|
}
|
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
/*
|
|
|
|
* Wait for a certain amount of time
|
|
|
|
*/
|
2015-09-16 12:14:02 +04:30
|
|
|
time_t
|
2015-09-16 09:33:31 +04:30
|
|
|
wait_for(int seconds)
|
|
|
|
{
|
2015-09-13 12:06:28 +04:30
|
|
|
|
2015-09-12 23:14:30 +04:30
|
|
|
struct timespec tp;
|
2015-09-16 09:39:43 +04:30
|
|
|
|
2015-10-25 16:17:24 +03:30
|
|
|
bzero(&tp, sizeof(tp));
|
|
|
|
|
2015-09-12 23:14:30 +04:30
|
|
|
clock_gettime(CLOCK_REALTIME, &tp);
|
|
|
|
|
2015-09-16 09:39:43 +04:30
|
|
|
time_t current_epoch = tp.tv_sec;
|
|
|
|
long nsec_to_sleep = 1000 * 1000 * 1000 - tp.tv_nsec;
|
2015-09-12 23:14:30 +04:30
|
|
|
|
|
|
|
/* Only sleep if needed */
|
|
|
|
if (nsec_to_sleep > 0) {
|
2015-09-13 12:06:28 +04:30
|
|
|
tp.tv_sec = seconds - 1;
|
2015-09-12 23:14:30 +04:30
|
|
|
tp.tv_nsec = nsec_to_sleep;
|
|
|
|
nanosleep(&tp, NULL);
|
|
|
|
}
|
|
|
|
return current_epoch + seconds;
|
2015-09-12 18:37:46 +04:30
|
|
|
}
|
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
/*
|
|
|
|
* Daemonize and persist pid
|
|
|
|
*/
|
2015-09-16 12:14:02 +04:30
|
|
|
int
|
2015-09-16 09:33:31 +04:30
|
|
|
daemon_start()
|
2015-09-12 18:37:46 +04:30
|
|
|
{
|
2015-09-16 09:39:43 +04:30
|
|
|
struct iftot ift, *tot;
|
|
|
|
time_t epoch;
|
2015-09-15 18:15:12 +04:30
|
|
|
struct sigaction sig_action;
|
2015-09-16 09:39:43 +04:30
|
|
|
sigset_t sig_set;
|
|
|
|
pid_t otherpid;
|
2015-09-16 12:14:02 +04:30
|
|
|
int curPID;
|
2015-09-12 18:37:46 +04:30
|
|
|
|
|
|
|
tot = &ift;
|
|
|
|
|
2015-09-16 09:39:43 +04:30
|
|
|
char *no_fork = getenv("no_fork");
|
|
|
|
|
2015-09-16 09:33:31 +04:30
|
|
|
if (!no_fork || strcmp("1", no_fork)) {
|
2015-09-15 18:15:12 +04:30
|
|
|
|
|
|
|
/* Check if parent process id is set */
|
2015-09-16 09:33:31 +04:30
|
|
|
if (getppid() == 1) {
|
2015-09-15 18:15:12 +04:30
|
|
|
/* PPID exists, therefore we are already a daemon */
|
2015-09-16 09:33:31 +04:30
|
|
|
return (EXIT_FAILURE);
|
2015-09-15 18:15:12 +04:30
|
|
|
}
|
|
|
|
/* Check if we can acquire the pid file */
|
|
|
|
pfh = pidfile_open(pid_filename, 0600, &otherpid);
|
|
|
|
|
|
|
|
if (pfh == NULL) {
|
|
|
|
if (errno == EEXIST) {
|
2015-09-16 09:39:43 +04:30
|
|
|
errx(EXIT_FAILURE, "Daemon already running, pid: %jd.", (intmax_t)otherpid);
|
2015-09-15 18:15:12 +04:30
|
|
|
}
|
|
|
|
warn("Cannot open or create pidfile: %s", pid_filename);
|
|
|
|
}
|
2015-09-16 12:14:02 +04:30
|
|
|
/* start daemonizing */
|
|
|
|
curPID = fork();
|
|
|
|
|
|
|
|
switch (curPID) {
|
|
|
|
case 0: /* This process is the child */
|
|
|
|
break;
|
|
|
|
case -1: /* fork() failed, should exit */
|
|
|
|
return (EXIT_FAILURE);
|
|
|
|
default: /* fork() successful, should exit */
|
2015-09-16 09:33:31 +04:30
|
|
|
return (EXIT_SUCCESS);
|
2015-09-15 18:15:12 +04:30
|
|
|
}
|
2015-09-16 12:14:02 +04:30
|
|
|
|
2015-09-12 23:14:30 +04:30
|
|
|
/* we are the child, complete the daemonization */
|
|
|
|
|
|
|
|
/* Close standard IO */
|
2015-09-13 14:23:10 +04:30
|
|
|
fclose(stdin);
|
|
|
|
fclose(stdout);
|
|
|
|
fclose(stderr);
|
2015-09-12 23:14:30 +04:30
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
/* Block unnecessary signals */
|
|
|
|
sigemptyset(&sig_set);
|
2015-09-16 09:39:43 +04:30
|
|
|
sigaddset(&sig_set, SIGCHLD); /* ignore child - i.e. we
|
|
|
|
* don't need to wait for it */
|
2015-09-16 09:33:31 +04:30
|
|
|
sigaddset(&sig_set, SIGTSTP); /* ignore Tty stop signals */
|
2015-09-16 09:39:43 +04:30
|
|
|
sigaddset(&sig_set, SIGTTOU); /* ignore Tty background
|
|
|
|
* writes */
|
2015-09-16 09:33:31 +04:30
|
|
|
sigaddset(&sig_set, SIGTTIN); /* ignore Tty background reads */
|
2015-09-16 09:39:43 +04:30
|
|
|
sigprocmask(SIG_BLOCK, &sig_set, NULL); /* Block the above
|
|
|
|
* specified signals */
|
2015-09-15 18:15:12 +04:30
|
|
|
|
|
|
|
/* Catch necessary signals */
|
|
|
|
sig_action.sa_handler = signal_handler;
|
|
|
|
sigemptyset(&sig_action.sa_mask);
|
|
|
|
sig_action.sa_flags = 0;
|
|
|
|
|
|
|
|
sigaction(SIGTERM, &sig_action, NULL);
|
|
|
|
sigaction(SIGHUP, &sig_action, NULL);
|
|
|
|
sigaction(SIGINT, &sig_action, NULL);
|
|
|
|
|
2015-09-12 23:14:30 +04:30
|
|
|
/* create new session and process group */
|
2015-09-16 12:14:02 +04:30
|
|
|
if (setsid() < 0)
|
|
|
|
return (EXIT_FAILURE);
|
2015-09-16 09:33:31 +04:30
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
/* persist pid */
|
|
|
|
pidfile_write(pfh);
|
2015-09-12 23:14:30 +04:30
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
}
|
2015-09-16 09:39:43 +04:30
|
|
|
FILE *cache_file = fopen(cache_filename, "a");
|
2015-09-12 23:14:30 +04:30
|
|
|
|
2015-09-13 14:44:01 +04:30
|
|
|
/* looping to collect traffic stat every RESOLUTION seconds */
|
2015-09-16 09:33:31 +04:30
|
|
|
while (1) {
|
2015-09-12 23:14:30 +04:30
|
|
|
|
2015-09-16 09:33:31 +04:30
|
|
|
epoch = wait_for(RESOLUTION);
|
2015-09-12 23:14:30 +04:30
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
flockfile(cache_file);
|
2015-09-12 23:14:30 +04:30
|
|
|
|
|
|
|
fill_iftot(tot);
|
2015-09-16 09:39:43 +04:30
|
|
|
fprintf(cache_file, "obytes.value %ld:%lu\nrbytes.value %ld:%lu\n", epoch, tot->ift_ob, epoch, tot->ift_ib);
|
2015-09-12 23:14:30 +04:30
|
|
|
fflush(cache_file);
|
|
|
|
|
2015-09-15 18:15:12 +04:30
|
|
|
funlockfile(cache_file);
|
2015-09-16 09:33:31 +04:30
|
|
|
}
|
2015-09-12 23:14:30 +04:30
|
|
|
|
|
|
|
fclose(cache_file);
|
2015-09-16 09:33:31 +04:30
|
|
|
return (0);
|
2015-09-12 23:14:30 +04:30
|
|
|
}
|
|
|
|
|
2015-09-16 12:14:02 +04:30
|
|
|
int
|
2015-09-16 09:33:31 +04:30
|
|
|
fetch()
|
2015-09-12 23:14:30 +04:30
|
|
|
{
|
|
|
|
/* this should return data from cache file */
|
2015-09-16 09:39:43 +04:30
|
|
|
FILE *cache_file = fopen(cache_filename, "r+");
|
2015-09-13 14:23:10 +04:30
|
|
|
|
|
|
|
/* lock */
|
2015-09-15 18:15:12 +04:30
|
|
|
flockfile(cache_file);
|
2015-09-13 14:23:10 +04:30
|
|
|
|
|
|
|
/* cat the cache_file to stdout */
|
2015-09-16 09:39:43 +04:30
|
|
|
char buffer[1024];
|
|
|
|
|
2015-09-13 14:23:10 +04:30
|
|
|
while (fgets(buffer, 1024, cache_file)) {
|
|
|
|
printf("%s", buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
ftruncate(fileno(cache_file), 0);
|
|
|
|
fclose(cache_file);
|
2015-09-12 18:37:46 +04:30
|
|
|
|
2015-09-16 09:33:31 +04:30
|
|
|
return (0);
|
2015-09-12 18:37:46 +04:30
|
|
|
}
|
|
|
|
|
2015-09-16 12:14:02 +04:30
|
|
|
int
|
2015-09-16 09:33:31 +04:30
|
|
|
main(int argc, char *argv[])
|
2015-09-12 18:37:46 +04:30
|
|
|
{
|
2015-09-13 14:23:10 +04:30
|
|
|
if (argv[0] && argv[0][0])
|
|
|
|
program_name = argv[0];
|
|
|
|
|
|
|
|
/* figure out program name */
|
|
|
|
while (strchr(program_name, '/')) {
|
2015-09-16 09:33:31 +04:30
|
|
|
program_name = strchr(program_name, '/') + 1;
|
2015-09-13 14:23:10 +04:30
|
|
|
}
|
2015-09-16 09:33:31 +04:30
|
|
|
|
2015-09-13 14:23:10 +04:30
|
|
|
/* extract interface name from plugin name */
|
2015-09-16 09:33:31 +04:30
|
|
|
if (strchr(program_name, '_')) {
|
|
|
|
interface = strchr(program_name, '_') + 1;
|
2015-09-13 14:23:10 +04:30
|
|
|
}
|
2015-09-16 09:39:43 +04:30
|
|
|
/*
|
|
|
|
* program should always run with a valid executable name
|
|
|
|
*/
|
2015-09-13 14:44:01 +04:30
|
|
|
if (strlen(interface) < 1) {
|
2015-09-13 16:15:52 +04:30
|
|
|
errx(EX_USAGE, "Please run from symlink");
|
2015-09-13 14:23:10 +04:30
|
|
|
}
|
2015-09-12 23:14:30 +04:30
|
|
|
/* resolve paths */
|
2015-09-16 09:39:43 +04:30
|
|
|
char *MUNIN_PLUGSTATE = getenv("MUNIN_PLUGSTATE");
|
2015-09-12 18:37:46 +04:30
|
|
|
|
|
|
|
/* Default is current directory */
|
2015-09-16 09:33:31 +04:30
|
|
|
if (!MUNIN_PLUGSTATE)
|
|
|
|
MUNIN_PLUGSTATE = ".";
|
2015-09-12 18:37:46 +04:30
|
|
|
|
2015-09-16 09:33:31 +04:30
|
|
|
asprintf(&pid_filename, "%s/%s.pid", MUNIN_PLUGSTATE, program_name);
|
2015-09-13 16:15:52 +04:30
|
|
|
asprintf(&cache_filename, "%s/%s.value", MUNIN_PLUGSTATE, program_name);
|
2015-09-12 18:37:46 +04:30
|
|
|
|
|
|
|
if (argc > 1) {
|
2015-09-16 09:39:43 +04:30
|
|
|
char *first_arg = argv[1];
|
|
|
|
|
2015-09-16 09:33:31 +04:30
|
|
|
if (!strcmp(first_arg, "config")) {
|
2015-09-12 19:02:13 +04:30
|
|
|
return config(interface);
|
2015-09-12 18:37:46 +04:30
|
|
|
}
|
2015-09-16 09:33:31 +04:30
|
|
|
if (!strcmp(first_arg, "acquire")) {
|
2015-09-15 18:15:12 +04:30
|
|
|
return daemon_start();
|
2015-09-12 18:37:46 +04:30
|
|
|
}
|
|
|
|
}
|
|
|
|
return fetch();
|
|
|
|
}
|