gkrellm/server/monitor.c
Stefan Gehn 4ff218d726 Drop GLib 1.x compatibility for gkrellmd
GLib version 1 is very outdated by now and not available in any recent
Linux distribution. Keeping this code around without actually being
able to test it makes little sense so let's get rid of that.
2014-07-12 22:45:33 +02:00

2371 lines
51 KiB
C

/* GKrellM
| Copyright (C) 1999-2010 Bill Wilson
|
| Author: Bill Wilson billw@gkrellm.net
| Latest versions might be found at: http://gkrellm.net
|
|
| GKrellM 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 3 of the License, or
| (at your option) any later version.
|
| GKrellM 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, see http://www.gnu.org/licenses/
|
|
| Additional permission under GNU GPL version 3 section 7
|
| If you modify this program, or any covered work, by linking or
| combining it with the OpenSSL project's OpenSSL library (or a
| modified version of that library), containing parts covered by
| the terms of the OpenSSL or SSLeay licenses, you are granted
| additional permission to convey the resulting work.
| Corresponding Source for a non-source form of such a combination
| shall include the source code for the parts of OpenSSL used as well
| as that of the covered work.
*/
#include "gkrellmd.h"
#include "gkrellmd-private.h"
#include <inttypes.h>
GList *gkrellmd_monitor_list;
static GList *serveflag_done_list;
static struct tm gkrellmd_current_tm;
gint
gkrellm_get_timer_ticks(void)
{
return GK.timer_ticks;
}
gboolean
gkrellmd_check_client_version(GkrellmdMonitor *mon,
gint major, gint minor, gint rev)
{
GkrellmdClient *client = mon->privat->client;
if ( client->major_version > major
|| (client->major_version == major && client->minor_version > minor)
|| ( client->major_version == major && client->minor_version == minor
&& client->rev_version >= rev
)
)
return TRUE;
return FALSE;
}
void
gkrellmd_add_serveflag_done(gboolean *flag)
{
serveflag_done_list = g_list_append(serveflag_done_list, flag);
}
void
gkrellmd_set_serve_name(GkrellmdMonitor *mon, const gchar *tag)
{
GkrellmdMonitorPrivate *mp = mon->privat;
mp->serve_name = tag;
mp->serve_name_sent = FALSE;
}
void
gkrellmd_serve_data(GkrellmdMonitor *mon, gchar *line)
{
GkrellmdMonitorPrivate *mp = mon->privat;
gchar buf[128];
if (!line || !*line)
return;
if (!mp->serve_name_sent)
{
if (mp->serve_name)
{
snprintf(buf, sizeof(buf), "<%s>\n", mp->serve_name);
gkrellm_debug(DEBUG_SERVER, "%s", buf);
mp->serve_gstring = g_string_append(mp->serve_gstring, buf);
mp->serve_name_sent = TRUE;
}
else
{
g_warning("gkrellmd: %s forgot to gkrellmd_set_serve_name()\n",
mon->name);
return;
}
}
gkrellm_debug(DEBUG_SERVER,"%s", line);
mp->serve_gstring = g_string_append(mp->serve_gstring, line);
}
/* ======================================================= */
typedef struct
{
gint instance;
gulong user,
nice,
sys,
idle;
}
CpuData;
static gchar *n_cpus_setup;
static gboolean nice_time_unsupported;
static GList *cpu_list;
static GList *instance_list;
void
gkrellm_cpu_set_number_of_cpus(gint n)
{
CpuData *cpu;
GList *list;
gint i;
n_cpus_setup = g_strdup_printf("n_cpus %d\n", n);
for (i = 0; i < n; ++i)
{
cpu = g_new0(CpuData, 1);
cpu_list = g_list_append(cpu_list, cpu);
if (instance_list && (list = g_list_nth(instance_list, i)) != NULL)
cpu->instance = GPOINTER_TO_INT(list->data);
else
cpu->instance = i;
}
}
void
gkrellm_cpu_add_instance(gint instance)
{
instance_list = g_list_append(instance_list, GINT_TO_POINTER(instance));
}
void
gkrellm_cpu_nice_time_unsupported(void)
{
nice_time_unsupported = TRUE;
}
void
gkrellm_cpu_assign_composite_data(gulong user, gulong nice,
gulong sys, gulong idle)
{
return; /* let client gkrellm compute it */
}
void
gkrellm_cpu_assign_data(gint n, gulong user, gulong nice,
gulong sys, gulong idle)
{
CpuData *cpu = NULL;
GList *list;
for (list = cpu_list; list; list = list->next)
{
cpu = (CpuData *) list->data;
if (cpu->instance == n)
break;
}
if (list)
{
cpu->user = user;
cpu->nice = nice;
cpu->sys = sys;
cpu->idle = idle;
}
}
static void
update_cpu(GkrellmdMonitor *mon, gboolean first_update)
{
gkrellm_sys_cpu_read_data();
gkrellmd_need_serve(mon);
}
static void
serve_cpu_data(GkrellmdMonitor *mon, gboolean first_serve)
{
CpuData *cpu;
GList *list;
gchar buf[128];
gkrellmd_set_serve_name(mon, "cpu");
for (list = cpu_list; list; list = list->next)
{
cpu = (CpuData *) list->data;
snprintf(buf, sizeof(buf), "%d %lu %lu %lu %lu\n", cpu->instance,
cpu->user, cpu->nice, cpu->sys, cpu->idle);
gkrellmd_serve_data(mon, buf);
}
}
static void
serve_cpu_setup(GkrellmdMonitor *mon)
{
GkrellmdClient *client = mon->privat->client;
GList *list;
gchar buf[64];
gkrellmd_send_to_client(client, "<cpu_setup>\n");
for (list = instance_list; list; list = list->next)
{
snprintf(buf, sizeof(buf), "cpu_instance %d\n",
GPOINTER_TO_INT(list->data));
gkrellmd_send_to_client(client, buf);
}
gkrellmd_send_to_client(client, n_cpus_setup);
if (nice_time_unsupported)
gkrellmd_send_to_client(client, "nice_time_unsupported\n");
}
static GkrellmdMonitor cpu_monitor =
{
"cpu",
update_cpu,
serve_cpu_data,
serve_cpu_setup
};
static GkrellmdMonitor *
init_cpu_monitor(void)
{
if (gkrellm_sys_cpu_init())
return &cpu_monitor;
return NULL;
}
/* ======================================================= */
struct
{
gboolean changed;
gint n_processes,
n_running,
n_users;
gulong n_forks;
gfloat fload;
}
proc;
void
gkrellm_proc_assign_data(gint n_processes, gint n_running,
gulong n_forks, gfloat load)
{
if ( proc.n_processes != n_processes
|| proc.n_running != n_running
|| proc.n_forks != n_forks
|| proc.fload != load
)
{
proc.n_processes = n_processes;
proc.n_running = n_running;
proc.n_forks = n_forks;
proc.fload = load;
proc.changed = TRUE;
}
}
void
gkrellm_proc_assign_users(gint n_users)
{
if (proc.n_users != n_users)
{
proc.n_users = n_users;
proc.changed = TRUE;
}
}
static void
update_proc(GkrellmdMonitor *mon, gboolean first_update)
{
proc.changed = FALSE;
gkrellm_sys_proc_read_data();
if (first_update || GK.five_second_tick)
gkrellm_sys_proc_read_users();
if (proc.changed)
gkrellmd_need_serve(mon);
}
static void
serve_proc_data(GkrellmdMonitor *mon, gboolean first_serve)
{
gchar buf[128];
gkrellmd_set_serve_name(mon, "proc");
snprintf(buf, sizeof(buf), "%d %d %lu %.2f %d\n",
proc.n_processes, proc.n_running,
proc.n_forks, proc.fload, proc.n_users);
gkrellmd_serve_data(mon, buf);
}
static GkrellmdMonitor proc_monitor =
{
"proc",
update_proc,
serve_proc_data,
NULL
};
static GkrellmdMonitor *
init_proc_monitor(void)
{
if (!gkrellm_sys_proc_init())
return NULL;
serveflag_done_list = g_list_append(serveflag_done_list, &proc.changed);
return &proc_monitor;
}
/* ======================================================= */
typedef struct
{
gchar *name;
gchar *subdisk_parent;
gint order,
subdisk,
changed;
gint device_number,
unit_number;
gboolean virtual;
guint64 rb,
wb;
}
DiskData;
static GList *disk_list;
static gint n_disks;
static gboolean units_are_blocks;
static DiskData *
add_disk(const gchar *name, gint order, gint device_number, gint unit_number)
{
DiskData *disk;
GList *list;
gint i;
disk = g_new0(DiskData, 1);
disk->name = g_strdup(name);
disk->order = order;
disk->subdisk = -1;
disk->device_number = device_number;
disk->unit_number = unit_number;
if (order >= 0)
{
for (i = 0, list = disk_list; list; list = list->next, ++i)
if (disk->order < ((DiskData *) list->data)->order)
break;
disk_list = g_list_insert(disk_list, disk, i);
}
else
disk_list = g_list_append(disk_list, disk);
++n_disks;
return disk;
}
static DiskData *
add_subdisk(gchar *subdisk_name, gchar *disk_name, gint subdisk)
{
DiskData *sdisk = NULL;
DiskData *disk;
GList *list = NULL;
for (list = disk_list; list; list = list->next)
{
disk = (DiskData * ) list->data;
if (!strcmp(disk_name, disk->name))
break;
}
if (!list)
return NULL;
sdisk = g_new0(DiskData, 1);
sdisk->name = g_strdup(subdisk_name);
sdisk->subdisk_parent = g_strdup(disk_name);
sdisk->order = disk->order;
sdisk->subdisk = subdisk;
for (list = list->next; list; list = list->next)
{
disk = (DiskData * ) list->data;
if (disk->subdisk == -1 || disk->subdisk > subdisk)
break;
}
disk_list = g_list_insert_before(disk_list, list, sdisk);
++n_disks;
return sdisk;
}
static void
disk_assign_data(DiskData *disk, guint64 rb, guint64 wb, gboolean virtual)
{
if (disk)
{
if (disk->rb != rb || disk->wb != wb)
disk->changed = TRUE;
else
disk->changed = FALSE;
disk->rb = rb;
disk->wb = wb;
disk->virtual = virtual;
}
}
void
gkrellm_disk_reset_composite(void)
{
/* Don't handle this. */
}
void
gkrellm_disk_units_are_blocks(void)
{
units_are_blocks = TRUE;
}
void
gkrellm_disk_add_by_name(const gchar *name, const gchar *label)
{
gint order = -1;
if (NULL == name) // Cannot add disk without a name
return;
order = gkrellm_sys_disk_order_from_name(name);
/* FIXME: gkrellmd currently has no support for disk labels. Extend
network-protocol and server to support disks with both name and label. */
add_disk(name, order, 0, 0);
}
void
gkrellm_disk_assign_data_by_device(gint device_number, gint unit_number,
guint64 rb, guint64 wb, gboolean virtual)
{
GList *list;
DiskData *disk = NULL;
gchar *name;
gint order = -1;
for (list = disk_list; list; list = list->next)
{
disk = (DiskData * ) list->data;
if ( disk->device_number == device_number
&& disk->unit_number == unit_number
)
break;
disk = NULL;
}
if (!disk)
{
name = gkrellm_sys_disk_name_from_device(device_number,
unit_number, &order);
if (name)
disk = add_disk(name, order, device_number, unit_number);
}
disk_assign_data(disk, rb, wb, virtual);
}
void
gkrellm_disk_assign_data_nth(gint n, guint64 rb, guint64 wb, gboolean virtual)
{
DiskData *disk;
gchar name[32];
if (n < n_disks)
disk = (DiskData *) g_list_nth_data(disk_list, n);
else
{
snprintf(name, sizeof(name), "%s%c", _("Disk"), 'A' + n);
disk = add_disk(name, n, 0, 0);
}
disk_assign_data(disk, rb, wb, virtual);
}
void
gkrellm_disk_assign_data_by_name(gchar *name,
guint64 rb, guint64 wb, gboolean virtual)
{
GList *list;
DiskData *disk = NULL;
gint order = -1;
for (list = disk_list; list; list = list->next)
{
disk = (DiskData * ) list->data;
if (!strcmp(name, disk->name))
break;
disk = NULL;
}
if (!disk)
{
order = gkrellm_sys_disk_order_from_name(name);
disk = add_disk(name, order, 0, 0);
}
disk_assign_data(disk, rb, wb, virtual);
}
void
gkrellm_disk_subdisk_assign_data_by_name(gchar *subdisk_name, gchar *disk_name,
guint64 rb, guint64 wb)
{
GList *list;
DiskData *disk = NULL;
gchar *s, *endptr;
gint subdisk;
if (!subdisk_name || !disk_name)
return;
for (list = disk_list; list; list = list->next)
{
disk = (DiskData * ) list->data;
if (!strcmp(subdisk_name, disk->name))
break;
disk = NULL;
}
if (!disk)
{
/* A subdisk name is expected to be the disk_name with a number string
| appended. Eg. "hda1" is a subdisk_name of disk_name "hda"
*/
s = subdisk_name + strlen(disk_name);
subdisk = strtol(s, &endptr, 0);
if (!*s || *endptr)
return;
disk = add_subdisk(subdisk_name, disk_name, subdisk);
}
disk_assign_data(disk, rb, wb, FALSE);
}
static void
update_disk(GkrellmdMonitor *mon, gboolean first_update)
{
GList *list;
DiskData *disk = NULL;
gkrellm_sys_disk_read_data();
for (list = disk_list; list; list = list->next)
{
disk = (DiskData * ) list->data;
if (disk->changed)
{
gkrellmd_need_serve(mon);
break;
}
}
}
static void
serve_disk_data(GkrellmdMonitor *mon, gboolean first_serve)
{
DiskData *disk;
GList *list;
gchar *buf = NULL;
gkrellmd_set_serve_name(mon, "disk");
for (list = disk_list; list; list = list->next)
{
disk = (DiskData *) list->data;
if (!disk->changed && !first_serve)
continue;
if (!disk->subdisk_parent)
{
if (gkrellmd_check_client_version(mon, 2, 2, 7) && disk->virtual)
buf = g_strdup_printf("%s virtual %" PRIu64 " %" PRIu64 "\n",
disk->name, disk->rb, disk->wb);
else
buf = g_strdup_printf("%s %" PRIu64 " %" PRIu64 "\n",
disk->name, disk->rb, disk->wb);
}
else if (mon->privat->client->feature_subdisk)
buf = g_strdup_printf("%s %s %" PRIu64 " %" PRIu64 "\n",
disk->name, disk->subdisk_parent, disk->rb, disk->wb);
else
continue;
gkrellmd_serve_data(mon, buf);
g_free(buf);
buf = NULL;
}
}
static void
serve_disk_setup(GkrellmdMonitor *mon)
{
GkrellmdClient *client = mon->privat->client;
if (units_are_blocks)
gkrellmd_send_to_client(client, "<disk_setup>\nunits_are_blocks\n");
if (gkrellmd_check_client_version(mon, 2,1,3))
client->feature_subdisk = TRUE;
}
static GkrellmdMonitor disk_monitor =
{
"disk",
update_disk,
serve_disk_data,
serve_disk_setup
};
static GkrellmdMonitor *
init_disk_monitor(void)
{
if (gkrellm_sys_disk_init())
return &disk_monitor;
return NULL;
}
/* ======================================================= */
#include "../src/inet.h"
typedef struct
{
ActiveTCP tcp;
gboolean alive,
new_connection;
}
InetData;
static GList *inet_list,
*inet_dead_list;
static gboolean inet_unsupported,
inet_new;
void
gkrellm_inet_log_tcp_port_data(gpointer data)
{
GList *list;
InetData *in;
ActiveTCP *tcp, *active_tcp = NULL;
gchar *ap, *aap;
gint slen;
tcp = (ActiveTCP *) data;
for (list = inet_list; list; list = list->next)
{
in = (InetData *) list->data;
active_tcp = &in->tcp;
if (tcp->family == AF_INET)
{
ap = (char *)&tcp->remote_addr;
aap = (char *)&active_tcp->remote_addr;
slen = sizeof(struct in_addr);
}
#if defined(INET6)
else if (tcp->family == AF_INET6)
{
ap = (char *)&tcp->remote_addr6;
aap = (char *)&active_tcp->remote_addr6;
slen = sizeof(struct in6_addr);
}
#endif
else
return;
if ( memcmp(aap, ap, slen) == 0
&& active_tcp->remote_port == tcp->remote_port
&& active_tcp->local_port == tcp->local_port
)
{
in->alive = TRUE; /* Old alive connection still alive */
return;
}
}
inet_new = TRUE;
in = g_new0(InetData, 1);
in->tcp = *tcp;
in->alive = TRUE;
in->new_connection = TRUE;
inet_list = g_list_append(inet_list, in);
}
static void
update_inet(GkrellmdMonitor *mon, gboolean first_update)
{
GList *list;
InetData *in;
static gint check_tcp;
if (!first_update && !GK.second_tick)
return;
if (first_update || check_tcp == 0)
{
gkrellm_free_glist_and_data(&inet_dead_list);
inet_new = FALSE;
for (list = inet_list; list; list = list->next)
{
in = (InetData *) list->data;
in->alive = FALSE;
in->new_connection = FALSE;
}
gkrellm_sys_inet_read_tcp_data();
for (list = inet_list; list; )
{
in = (InetData *) list->data;
if (!in->alive)
{
if (list == inet_list)
inet_list = inet_list->next;
list = g_list_remove(list, in);
inet_dead_list = g_list_append(inet_dead_list, in);
}
else
list = list->next;
}
if (inet_new || inet_dead_list)
gkrellmd_need_serve(mon);
}
check_tcp = (check_tcp + 1) % _GK.inet_interval;
}
static void
serve_inet_data(GkrellmdMonitor *mon, gboolean first_serve)
{
InetData *in;
ActiveTCP *tcp;
GList *list;
gchar buf[128], *cp;
#if defined(INET6) && defined(HAVE_GETADDRINFO)
struct sockaddr_in6 sin6;
char addrbuf[NI_MAXHOST];
#endif
if (inet_new || first_serve)
{
gkrellmd_set_serve_name(mon, "inet");
for (list = inet_list; list; list = list->next)
{
in = (InetData *) list->data;
tcp = &in->tcp;
if ( tcp->family == AF_INET
&& (in->new_connection || first_serve)
)
{
cp = inet_ntoa(tcp->remote_addr);
snprintf(buf, sizeof(buf), "+0 %x %s:%x\n",
tcp->local_port, cp, tcp->remote_port);
}
#if defined(INET6) && defined(HAVE_GETADDRINFO)
else if (tcp->family == AF_INET6
&& (in->new_connection || first_serve))
{
memset(&sin6, 0, sizeof(sin6));
memcpy(&sin6.sin6_addr, &tcp->remote_addr6,
sizeof(struct in6_addr));
sin6.sin6_family = AF_INET6;
#ifdef SIN6_LEN
sin6.sin6_len = sizeof(struct sockaddr_in6);
#endif
if (getnameinfo((struct sockaddr *)&sin6,
sizeof(struct sockaddr_in6),
addrbuf, sizeof(addrbuf),
NULL, 0,
NI_NUMERICHOST|NI_WITHSCOPEID)
!= 0)
continue;
snprintf(buf, sizeof(buf), "+6 %x [%s]:%x\n",
tcp->local_port, addrbuf,
tcp->remote_port);
}
#endif
else
continue;
gkrellmd_serve_data(mon, buf);
}
}
if (!first_serve)
{
gkrellmd_set_serve_name(mon, "inet");
for (list = inet_dead_list; list; list = list->next)
{
in = (InetData *) list->data;
tcp = &in->tcp;
if (tcp->family == AF_INET)
{
cp = inet_ntoa(tcp->remote_addr);
snprintf(buf, sizeof(buf), "-0 %x %s:%x\n",
tcp->local_port, cp, tcp->remote_port);
}
#if defined(INET6) && defined(HAVE_GETADDRINFO)
else if (tcp->family == AF_INET6)
{
memset(&sin6, 0, sizeof(sin6));
memcpy(&sin6.sin6_addr, &tcp->remote_addr6,
sizeof(struct in6_addr));
sin6.sin6_family = AF_INET6;
#ifdef SIN6_LEN
sin6.sin6_len = sizeof(struct sockaddr_in6);
#endif
if (getnameinfo((struct sockaddr *)&sin6,
sizeof(struct sockaddr_in6),
addrbuf, sizeof(addrbuf),
NULL, 0,
NI_NUMERICHOST|NI_WITHSCOPEID)
!= 0)
continue;
snprintf(buf, sizeof(buf), "-6 %x [%s]:%x\n",
tcp->local_port, addrbuf,
tcp->remote_port);
}
#endif
else
continue;
gkrellmd_serve_data(mon, buf);
}
}
}
static void
serve_inet_setup(GkrellmdMonitor *mon)
{
GkrellmdClient *client = mon->privat->client;
if (inet_unsupported)
gkrellmd_send_to_client(client, "<inet_setup>\ninet_unsupported\n");
}
static GkrellmdMonitor inet_monitor =
{
"inet",
update_inet,
serve_inet_data,
serve_inet_setup
};
static GkrellmdMonitor *
init_inet_monitor(void)
{
if (_GK.inet_interval > 0 && gkrellm_sys_inet_init())
return &inet_monitor;
inet_unsupported = TRUE;
return NULL;
}
/* ======================================================= */
#define TIMER_TYPE_NONE 0
#define TIMER_TYPE_PPP 1
#define TIMER_TYPE_IPPP 2
typedef struct
{
gchar *name;
gboolean changed,
up,
up_prev,
up_event,
down_event;
gboolean timed_changed;
time_t up_time;
gulong rx,
tx;
}
NetData;
static NetData *net_timer;
static GList *net_list,
*net_sys_list;
static time_t net_timer0;
static gint net_timer_type;
static gboolean net_use_routed;
gchar *
gkrellm_net_mon_first(void)
{
gchar *name = NULL;
net_sys_list = net_list;
if (net_sys_list)
{
name = ((NetData *) (net_sys_list->data))->name;
net_sys_list = net_sys_list->next;
}
return name;
}
gchar *
gkrellm_net_mon_next(void)
{
gchar *name = NULL;
if (net_sys_list)
{
name = ((NetData *) (net_sys_list->data))->name;
net_sys_list = net_sys_list->next;
}
return name;
}
void
gkrellm_net_use_routed(gboolean real_routed /* not applicable in server */)
{
net_use_routed = TRUE;
}
static NetData *
net_new(gchar *name)
{
NetData *net;
net = g_new0(NetData, 1);
net->name = g_strdup(name);
net_list = g_list_append(net_list, net);
if (net_timer_type != TIMER_TYPE_NONE && !strcmp(_GK.net_timer, net->name))
net_timer = net;
return net;
}
void
gkrellm_net_assign_data(gchar *name, gulong rx, gulong tx)
{
GList *list;
NetData *net;
for (list = net_list; list; list = list->next)
{
net = (NetData *) list->data;
if (!strcmp(net->name, name))
{
if (net->rx != rx || net->tx != tx)
net->changed = TRUE;
else
net->changed = FALSE;
break;
}
}
if (!list)
net = net_new(name);
if (GK.second_tick && !net_use_routed)
net->up = TRUE;
net->rx = rx;
net->tx = tx;
}
void
gkrellm_net_routed_event(gchar *name, gboolean routed)
{
GList *list;
NetData *net;
for (list = net_list; list; list = list->next)
{
net = (NetData *) list->data;
if (!strcmp(net->name, name))
break;
}
if (!list)
net = net_new(name);
if (routed)
net->up_event = TRUE;
else
net->down_event = TRUE;
net->up = routed;
}
void
gkrellm_net_add_timer_type_ppp(gchar *name)
{
if (!_GK.net_timer || !name)
return;
if (name && !strncmp(_GK.net_timer, name, strlen(name) - 1))
net_timer_type = TIMER_TYPE_PPP;
}
void
gkrellm_net_add_timer_type_ippp(gchar *name)
{
if (!_GK.net_timer || !name)
return;
if (name && !strncmp(_GK.net_timer, name, strlen(name) - 1))
net_timer_type = TIMER_TYPE_IPPP;
}
void
gkrellm_net_set_lock_directory(gchar *dir)
{
/* Not supported remotely */
}
static void
update_net(GkrellmdMonitor *mon, gboolean first_update)
{
GList *list;
NetData *net;
gint up_time = 0;
if (GK.second_tick)
{
if (!net_use_routed)
{
for (list = net_list; list; list = list->next)
{
net = (NetData *) list->data;
net->up_prev = net->up;
net->up = FALSE;
}
}
else
gkrellm_sys_net_check_routes();
}
gkrellm_sys_net_read_data();
if (GK.second_tick && !net_use_routed)
{
for (list = net_list; list; list = list->next)
{
net = (NetData *) list->data;
if (net->up && !net->up_prev)
net->up_event = TRUE;
else if (!net->up && net->up_prev)
net->down_event = TRUE;
}
}
if (net_timer && GK.second_tick)
{
if (net_timer_type == TIMER_TYPE_PPP)
{
struct stat st;
gchar buf[256];
if (net_timer->up_event)
{
snprintf(buf, sizeof(buf), "/var/run/%s.pid", net_timer->name);
if (g_stat(buf, &st) == 0)
net_timer0 = st.st_mtime;
else
time(&net_timer0);
}
if (net_timer->up)
up_time = (int) (time(0) - net_timer0);
}
else if (net_timer_type == TIMER_TYPE_IPPP)
{
/* get all isdn status from its connect state because the
| net_timer->up can be UP even with isdn line not connected.
| Can't get time history if gkrellmd started after connects.
*/
static gboolean old_connected;
gboolean connected;
connected = gkrellm_sys_net_isdn_online();
if (connected && !old_connected)
time(&net_timer0); /* New session just started */
old_connected = connected;
up_time = (int) (time(0) - net_timer0);
}
if (up_time != net_timer->up_time)
net_timer->timed_changed = TRUE;
net_timer->up_time = up_time;
}
gkrellmd_need_serve(mon); /* serve func checks for changed */
}
static void
serve_net_data(GkrellmdMonitor *mon, gboolean first_serve)
{
NetData *net;
GList *list;
gchar buf[128];
gboolean fake_up_event;
gkrellmd_set_serve_name(mon, "net");
for (list = net_list; list; list = list->next)
{
net = (NetData *) list->data;
if (net->changed || first_serve)
{
snprintf(buf, sizeof(buf), "%s %lu %lu\n", net->name, net->rx, net->tx);
gkrellmd_serve_data(mon, buf);
}
}
/* Since the server transmits changes only, use the routed interface
| to the client regardless if the sysdep code uses routed.
*/
if (GK.second_tick || first_serve)
{
gkrellmd_set_serve_name(mon, "net_routed");
for (list = net_list; list; list = list->next)
{
net = (NetData *) list->data;
fake_up_event = (first_serve && net->up);
if (net->up_event || net->down_event || fake_up_event)
{
snprintf(buf, sizeof(buf), "%s %d\n", net->name,
fake_up_event ? TRUE : net->up_event);
gkrellmd_serve_data(mon, buf);
}
if (mon->privat->client->last_client)
net->up_event = net->down_event = FALSE;
}
}
if (net_timer && GK.second_tick)
{
if (net_timer->timed_changed || first_serve)
{
gkrellmd_set_serve_name(mon, "net_timer");
snprintf(buf, sizeof(buf), "%s %d\n", net_timer->name, (gint)net_timer->up_time);
gkrellmd_serve_data(mon, buf);
}
}
}
static void
serve_net_setup(GkrellmdMonitor *mon)
{
GkrellmdClient *client = mon->privat->client;
gchar buf[128];
/* The client <-> server link always uses routed mode, but the client
| needs to know if server sysdep uses routed for config purposes.
*/
if (net_use_routed)
gkrellmd_send_to_client(client, "<net_setup>\nnet_use_routed\n");
if (net_timer_type != TIMER_TYPE_NONE)
{
snprintf(buf, sizeof(buf),
"<net_setup>\nnet_timer %s\n", _GK.net_timer);
gkrellmd_send_to_client(client, buf);
}
}
static GkrellmdMonitor net_monitor =
{
"net",
update_net,
serve_net_data,
serve_net_setup
};
static GkrellmdMonitor *
init_net_monitor(void)
{
net_timer_type = TIMER_TYPE_NONE;
if (gkrellm_sys_net_init())
return &net_monitor;
return NULL;
}
/* ======================================================= */
struct
{
gboolean mem_changed;
guint64 total,
used,
free,
shared,
buffers,
cached;
gboolean swap_changed;
guint64 swap_total,
swap_used;
gulong swap_in,
swap_out;
}
mem;
void
gkrellm_mem_assign_data(guint64 total, guint64 used, guint64 free,
guint64 shared, guint64 buffers, guint64 cached)
{
if ( mem.total != total
|| mem.used != used
|| mem.free != free
|| mem.shared != shared
|| mem.buffers != buffers
|| mem.cached != cached
)
{
mem.total = total;
mem.used = used;
mem.free = free;
mem.shared = shared;
mem.buffers = buffers;
mem.cached = cached;
mem.mem_changed = TRUE;
}
}
void
gkrellm_swap_assign_data(guint64 total, guint64 used,
gulong swap_in, gulong swap_out)
{
if ( mem.swap_total != total
|| mem.swap_used != used
|| mem.swap_in != swap_in
|| mem.swap_out != swap_out
)
{
mem.swap_total = total;
mem.swap_used = used;
mem.swap_in = swap_in;
mem.swap_out = swap_out;
mem.swap_changed = TRUE;
}
}
static void
update_mem(GkrellmdMonitor *mon, gboolean first_update)
{
mem.mem_changed = mem.swap_changed = FALSE;
gkrellm_sys_swap_read_data();
if (first_update || GK.five_second_tick)
gkrellm_sys_mem_read_data();
if (mem.mem_changed || mem.swap_changed)
gkrellmd_need_serve(mon);
}
static void
serve_mem_data(GkrellmdMonitor *mon, gboolean first_serve)
{
gchar buf[128];
if (mem.mem_changed || first_serve)
{
gkrellmd_set_serve_name(mon, "mem");
snprintf(buf, sizeof(buf), "%" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
mem.total, mem.used, mem.free,
mem.shared, mem.buffers, mem.cached);
gkrellmd_serve_data(mon, buf);
}
if (mem.swap_changed || first_serve)
{
gkrellmd_set_serve_name(mon, "swap");
snprintf(buf, sizeof(buf), "%" PRIu64 " %" PRIu64 " %lu %lu\n",
mem.swap_total, mem.swap_used,
mem.swap_in, mem.swap_out);
gkrellmd_serve_data(mon, buf);
}
}
static GkrellmdMonitor mem_monitor =
{
"mem",
update_mem,
serve_mem_data,
NULL
};
static GkrellmdMonitor *
init_mem_monitor(void)
{
if (!gkrellm_sys_mem_init())
return NULL;
serveflag_done_list = g_list_append(serveflag_done_list, &mem.mem_changed);
serveflag_done_list = g_list_append(serveflag_done_list,&mem.swap_changed);
return &mem_monitor;
}
/* ======================================================= */
typedef struct
{
gboolean busy,
deleted,
is_mounted,
is_nfs,
changed;
gchar *directory,
*device,
*type,
*options;
glong blocks,
bavail,
bfree,
bsize;
}
Mount;
static GList *mounts_list,
*fstab_list;
static gboolean nfs_check,
fs_check,
fs_need_serve,
fstab_list_modified,
mounts_list_modified,
mounting_unsupported;
static gchar *remote_fs_types[] =
{
"cifs",
"nfs",
"smbfs"
};
void
gkrellm_fs_setup_eject(gchar *eject_tray, gchar *close_tray,
void (*eject_func)(), void (*close_func)())
{
/* Not supported remotely */
}
void
gkrellm_fs_add_to_mounts_list(gchar *dir, gchar *dev, gchar *type)
{
GList *list;
Mount *m;
gint i;
for (list = mounts_list; list; list = list->next)
{
m = (Mount *) list->data;
if ( !strcmp(m->directory, dir)
&& !strcmp(m->device, dev)
&& !strcmp(m->type, type)
)
break;
}
if (!list)
{
m = g_new0(Mount, 1);
m->directory = g_strdup(dir);
m->device = g_strdup(dev);
m->type = g_strdup(type);
mounts_list = g_list_append(mounts_list, m);
mounts_list_modified = TRUE;
serveflag_done_list = g_list_append(serveflag_done_list, &m->changed);
for (i = 0; i < (sizeof(remote_fs_types) / sizeof(gchar *)); ++i)
{
if (!strcmp(m->type, remote_fs_types[i]))
{
m->is_nfs = TRUE;
break;
}
}
}
m->is_mounted = TRUE;
}
void
gkrellm_fs_add_to_fstab_list(gchar *dir, gchar *dev, gchar *type, gchar *opt)
{
Mount *m;
m = g_new0(Mount, 1);
m->directory = g_strdup(dir);
m->device = g_strdup(dev);
m->type = g_strdup(type);
fstab_list = g_list_append(fstab_list, m);
}
void
gkrellm_fs_assign_fsusage_data(gpointer pointer,
glong blocks, glong bavail, glong bfree, glong bsize)
{
Mount *m = (Mount *) pointer;
if ( m->blocks != blocks
|| m->bavail != bavail
|| m->bfree != bfree
|| m->bsize != bsize
)
{
m->blocks = blocks;
m->bavail = bavail;
m->bfree = bfree;
m->bsize = bsize;
m->changed = TRUE;
}
}
void
gkrellm_fs_mounting_unsupported(void)
{
mounting_unsupported = TRUE;
}
static void
refresh_mounts_list(void)
{
GList *list;
Mount *m;
for (list = mounts_list; list; list = list->next)
((Mount *) list->data)->is_mounted = FALSE;
gkrellm_sys_fs_get_mounts_list();
for (list = mounts_list; list; )
{
m = (Mount *) list->data;
if (!m->is_mounted)
{
if (list == mounts_list)
mounts_list = mounts_list->next;
list = g_list_remove_link(list, list);
g_free(m->directory);
g_free(m->device);
g_free(m->type);
serveflag_done_list = g_list_remove(serveflag_done_list,
&m->changed);
if (m->busy)
m->deleted = TRUE;
else
g_free(m);
mounts_list_modified = TRUE;
}
else
list = list->next;
}
}
static void
refresh_fstab_list(void)
{
Mount *m;
while (fstab_list)
{
m = (Mount *) fstab_list->data;
g_free(m->directory);
g_free(m->device);
g_free(m->type);
g_free(m);
fstab_list = g_list_remove(fstab_list, fstab_list->data);
}
gkrellm_sys_fs_get_fstab_list();
fstab_list_modified = TRUE;
}
static gpointer
get_fsusage_thread(void *data)
{
Mount *m = (Mount *) data;
gkrellm_sys_fs_get_fsusage(m, m->directory);
if (m->deleted)
g_free(m);
else
{
if (m->changed)
fs_need_serve = TRUE;
m->busy = FALSE;
}
return NULL;
}
static void
update_fs(GkrellmdMonitor *mon, gboolean first_update)
{
GList *list;
Mount *m;
static gint check_tick;
if (fs_need_serve) /* Asynchronous change in fsusage thread? */
gkrellmd_need_serve(mon);
fs_need_serve = FALSE;
if (GK.second_tick)
++check_tick;
fs_check = !(check_tick % _GK.fs_interval);
if (_GK.nfs_interval > 0)
nfs_check = !(check_tick % _GK.nfs_interval);
else
nfs_check = 0;
if (!first_update && (!GK.second_tick || (!fs_check && !nfs_check)))
return;
refresh_mounts_list();
for (list = mounts_list; list; list = list->next)
{
m = (Mount *) list->data;
if (fs_check && !m->is_nfs)
gkrellm_sys_fs_get_fsusage(m, m->directory);
else if (nfs_check && m->is_nfs && !m->busy)
{
m->busy = TRUE;
g_thread_new("get_fsusage", get_fsusage_thread, m);
}
}
if (first_update || gkrellm_sys_fs_fstab_modified())
refresh_fstab_list();
gkrellmd_need_serve(mon);
}
static void
serve_fs_data(GkrellmdMonitor *mon, gboolean first_serve)
{
Mount *m;
GList *list;
gchar buf[128];
if (mounts_list_modified || first_serve)
{
gkrellmd_set_serve_name(mon, "fs_mounts");
gkrellmd_serve_data(mon, ".clear\n");
for (list = mounts_list; list; list = list->next)
{
m = (Mount *) list->data;
snprintf(buf, sizeof(buf), "%s %s %s %ld %ld %ld %ld\n",
m->directory, m->device, m->type,
m->blocks, m->bavail, m->bfree, m->bsize);
/*gkrellm_debug(DEBUG_SERVER,
"Adding mount-line for %s to serve-data\n", m->directory);*/
gkrellmd_serve_data(mon, buf);
}
}
else
{
gkrellmd_set_serve_name(mon, "fs");
for (list = mounts_list; list; list = list->next)
{
m = (Mount *) list->data;
if (!m->changed)
continue;
snprintf(buf, sizeof(buf), "%s %s %ld %ld %ld %ld\n",
m->directory, m->device,
m->blocks, m->bavail, m->bfree, m->bsize);
/*gkrellm_debug(DEBUG_SERVER,
"Updating fs %s in serve-data\n", m->directory);*/
gkrellmd_serve_data(mon, buf);
}
}
if (fstab_list_modified || first_serve)
{
gkrellmd_set_serve_name(mon, "fs_fstab");
gkrellmd_serve_data(mon, ".clear\n");
for (list = fstab_list; list; list = list->next)
{
m = (Mount *) list->data;
snprintf(buf, sizeof(buf), "%s %s %s\n",
m->directory, m->device, m->type);
/*gkrellm_debug(DEBUG_SERVER,
"Adding fstab-line for %s to serve-data\n", m->directory);*/
gkrellmd_serve_data(mon, buf);
}
}
}
static void
serve_fs_setup(GkrellmdMonitor *mon)
{
GkrellmdClient *client = mon->privat->client;
if (mounting_unsupported)
gkrellmd_send_to_client(client, "<fs_setup>\nmounting_unsupported\n");
}
static GkrellmdMonitor fs_monitor =
{
"fs",
update_fs,
serve_fs_data,
serve_fs_setup
};
static GkrellmdMonitor *
init_fs_monitor(void)
{
if (!gkrellm_sys_fs_init())
return NULL;
serveflag_done_list =
g_list_append(serveflag_done_list, &fstab_list_modified);
serveflag_done_list =
g_list_append(serveflag_done_list, &mounts_list_modified);
return &fs_monitor;
}
/* ======================================================= */
typedef struct
{
gboolean changed,
have_data;
gint id;
gboolean present,
on_line,
charging;
gint percent;
gint time_left;
}
Battery;
static GList *battery_list;
static Battery *composite_battery;
static Battery *
battery_nth(gint n)
{
Battery *bat;
static gint n_batteries;
if (n > 10)
return NULL;
if (n < 0)
{
if (!composite_battery)
{
bat = g_new0(Battery, 1);
battery_list = g_list_prepend(battery_list, bat);
bat->id = GKRELLM_BATTERY_COMPOSITE_ID;
composite_battery = bat;
serveflag_done_list = g_list_append(serveflag_done_list,
&composite_battery->changed);
}
return composite_battery;
}
if (composite_battery)
++n;
while ((bat = (Battery *)g_list_nth_data(battery_list, n)) == NULL)
{
bat = g_new0(Battery, 1);
battery_list = g_list_append(battery_list, bat);
bat->id = n_batteries++;
serveflag_done_list = g_list_append(serveflag_done_list,
&bat->changed);
}
return bat;
}
void
gkrellm_battery_assign_data(gint id, gboolean present, gboolean on_line,
gboolean charging, gint percent, gint time_left)
{
Battery *bat;
bat = battery_nth(id);
if (!bat)
return;
if ( present != bat->present
|| on_line != bat->on_line
|| charging != bat->charging
|| percent != bat->percent
|| time_left != bat->time_left
)
{
bat->present = present;
bat->on_line = on_line;
bat->charging = charging;
bat->percent = percent;
bat->time_left = time_left;
bat->changed = TRUE;
}
bat->have_data = TRUE;
}
gint
gkrellm_battery_full_cap_fallback()
{
return 5000; /* XXX Linux ACPI bug not handled by server */
}
static void
update_battery(GkrellmdMonitor *mon, gboolean first_update)
{
GList *list;
Battery *bat;
if (!first_update && !GK.five_second_tick)
return;
for (list = battery_list; list; list = list->next)
{
bat = (Battery *) list->data;
bat->have_data = FALSE;
bat->changed = FALSE;
}
gkrellm_sys_battery_read_data();
for (list = battery_list; list; list = list->next)
{
bat = (Battery *) list->data;
if (!bat->have_data && bat->present)
{
bat->present = FALSE;
bat->changed = TRUE;
}
if (bat->changed)
gkrellmd_need_serve(mon);
}
}
static void
serve_battery_data(GkrellmdMonitor *mon, gboolean first_serve)
{
Battery *bat;
GList *list;
gchar buf[128];
gkrellmd_set_serve_name(mon, "battery");
for (list = battery_list; list; list = list->next)
{
bat = (Battery *) list->data;
if ( (!bat->changed && !first_serve)
|| ( !gkrellmd_check_client_version(mon, 2,1,9)
&& bat->id > 0
)
)
continue;
snprintf(buf, sizeof(buf), "%d %d %d %d %d %d\n",
bat->present, bat->on_line, bat->charging,
bat->percent, bat->time_left, bat->id);
gkrellmd_serve_data(mon, buf);
}
}
static void
serve_battery_setup(GkrellmdMonitor *mon)
{
GkrellmdClient *client = mon->privat->client;
gkrellm_sys_battery_read_data();
if (battery_list)
gkrellmd_send_to_client(client,
"<battery_setup>\nbattery_available\n");
}
static GkrellmdMonitor battery_monitor =
{
"battery",
update_battery,
serve_battery_data,
serve_battery_setup
};
static GkrellmdMonitor *
init_battery_monitor(void)
{
if (!gkrellm_sys_battery_init())
return NULL;
return &battery_monitor;
}
/* ======================================================= */
typedef struct
{
gboolean changed;
gint type;
gchar *path; /* Pathname to sensor data or device file */
gchar *id_name; /* These 4 are unique sensor identification */
gint id; /* of a particular sensor type */
gint iodev; /* One or any combination may be used. */
gint inter;
gchar *vref;
gchar *default_label;
gint group;
gfloat factor;
gfloat offset;
gfloat raw_value;
}
Sensor;
static GList *sensors_list;
static gboolean thread_busy,
sensors_need_serve;
static gpointer
read_sensors(void *data)
{
GList *list;
Sensor *sensor;
gfloat tmp;
gboolean need_serve = FALSE;
for (list = sensors_list; list; list = list->next)
{
sensor = (Sensor *) list->data;
tmp = sensor->raw_value;
if (sensor->type == SENSOR_TEMPERATURE)
gkrellm_sys_sensors_get_temperature(sensor->path, sensor->id,
sensor->iodev, sensor->inter, &sensor->raw_value);
else if (sensor->type == SENSOR_FAN)
gkrellm_sys_sensors_get_fan(sensor->path, sensor->id,
sensor->iodev, sensor->inter, &sensor->raw_value);
else if (sensor->type == SENSOR_VOLTAGE)
gkrellm_sys_sensors_get_voltage(sensor->path, sensor->id,
sensor->iodev, sensor->inter, &sensor->raw_value);
if (sensor->raw_value != tmp)
{
sensor->changed = TRUE;
need_serve = TRUE;
}
else
sensor->changed = FALSE;
}
thread_busy = FALSE;
sensors_need_serve = need_serve; /* Thread, so set after data collected */
return NULL;
}
static void
run_sensors_thread(void)
{
if (thread_busy)
return;
thread_busy = TRUE;
g_thread_new("read_sensors", read_sensors, NULL);
}
void
gkrellm_sensors_config_migrate_connect(gboolean (*func)(), gint sysdep_version)
{
}
void
gkrellm_sensors_update_volt_order_base(void)
{
}
void
gkrellm_sensors_set_group(gpointer sr, gint group)
{
Sensor *sensor = (Sensor *) sr;
if (sensor)
sensor->group = group;
}
void
gkrellm_sensors_sysdep_option(gchar *keyword, gchar *label, void (*func)())
{
}
/* A sensor within a type is uniquely identified by its id_name.
| A sysdep interface may additionally use any of the triple integer
| set (id, iodev, inter) for internal identification.
| Monitor code here uses path to read the sensor values, but id_name is only
| passed to the client since that is all that is needed for identification
| (the client is no longer interfacing to sysdep code).
*/
gpointer
gkrellm_sensors_add_sensor(gint type, gchar *sensor_path, gchar *id_name,
gint id, gint iodev, gint inter,
gfloat factor, gfloat offset, gchar *vref, gchar *default_label)
{
Sensor *sensor;
if (!id_name || !*id_name || type < 0 || type > 2)
return NULL;
sensor = g_new0(Sensor, 1);
sensor->id_name = g_strdup(id_name);
if (sensor_path)
sensor->path = g_strdup(sensor_path);
else
sensor->path = g_strdup(id_name);
sensor->vref = g_strdup(vref ? vref : "NONE");
sensor->default_label = g_strdup(default_label ? default_label : "NONE");
sensor->factor = factor;
sensor->offset = offset;
sensor->type = type;
sensor->id = id;
sensor->iodev = iodev;
sensor->inter = inter;
sensors_list = g_list_append(sensors_list, sensor);
return sensor;
}
static void
update_sensors(GkrellmdMonitor *mon, gboolean first_update)
{
if (sensors_need_serve) /* Asynchronously set in thread */
gkrellmd_need_serve(mon);
sensors_need_serve = FALSE;
if (!GK.five_second_tick && !first_update)
return;
if (first_update)
read_sensors(NULL); /* No thread on first read */
else
run_sensors_thread();
}
static void
serve_sensors_data(GkrellmdMonitor *mon, gboolean first_serve)
{
Sensor *sr;
GList *list;
gchar buf[128];
gboolean sensor_disk_ok;
gkrellmd_set_serve_name(mon, "sensors");
sensor_disk_ok = gkrellmd_check_client_version(mon, 2,2,0);
for (list = sensors_list; list; list = list->next)
{
sr = (Sensor *) list->data;
if (sr->group == SENSOR_GROUP_DISK && !sensor_disk_ok)
continue;
if (sr->changed || first_serve)
{
snprintf(buf, sizeof(buf), "%d \"%s\" %d %d %d %.2f\n",
sr->type, sr->id_name,
sr->id, sr->iodev, sr->inter, sr->raw_value);
gkrellmd_serve_data(mon, buf);
}
}
}
static void
serve_sensors_setup(GkrellmdMonitor *mon)
{
GkrellmdClient *client = mon->privat->client;
GList *list;
Sensor *s;
gchar buf[256];
gboolean sensor_disk_ok;
gkrellmd_send_to_client(client, "<sensors_setup>\n");
sensor_disk_ok = gkrellmd_check_client_version(mon, 2,2,0);
for (list = sensors_list; list; list = list->next)
{
s = (Sensor *) list->data;
if (s->group == SENSOR_GROUP_DISK && !sensor_disk_ok)
continue;
if (sensor_disk_ok)
snprintf(buf, sizeof(buf), "%d \"%s\" %d %d %d %.4f %.4f \"%s\" \"%s\" %d\n",
s->type, s->id_name,
s->id, s->iodev, s->inter,
s->factor, s->offset, s->vref, s->default_label, s->group);
else
snprintf(buf, sizeof(buf), "%d \"%s\" %d %d %d %.4f %.4f \"%s\" \"%s\"\n",
s->type, s->id_name,
s->id, s->iodev, s->inter,
s->factor, s->offset, s->vref, s->default_label);
gkrellmd_send_to_client(client, buf);
}
}
static GkrellmdMonitor sensors_monitor =
{
"sensors",
update_sensors,
serve_sensors_data,
serve_sensors_setup
};
static GkrellmdMonitor *
init_sensors_monitor(void)
{
if (!gkrellm_sys_sensors_init())
return NULL;
return &sensors_monitor;
}
/* ======================================================= */
static time_t base_uptime,
up_seconds;
static gulong up_minutes = -1;
void
gkrellm_uptime_set_base_uptime(time_t base)
{
base_uptime = base;
}
static void
update_uptime(GkrellmdMonitor *mon, gboolean first_update)
{
gint prev_up;
if (GK.ten_second_tick || up_minutes < 0 || first_update)
{
prev_up = up_minutes;
up_seconds = gkrellm_sys_uptime_read_uptime();
if (up_seconds > 0)
up_minutes = (gint) (up_seconds / 60);
else
up_minutes = (gint)(time(0) - _GK.start_time + base_uptime) / 60;
if (up_minutes != prev_up)
gkrellmd_need_serve(mon);
}
}
static void
serve_uptime_data(GkrellmdMonitor *mon, gboolean first_serve)
{
gchar buf[128];
gkrellmd_set_serve_name(mon, "uptime");
snprintf(buf, sizeof(buf), "%lu\n", (gulong) up_minutes);
gkrellmd_serve_data(mon, buf);
}
static GkrellmdMonitor uptime_monitor =
{
"uptime",
update_uptime,
serve_uptime_data,
NULL
};
static GkrellmdMonitor *
init_uptime_monitor(void)
{
if (!gkrellm_sys_uptime_init())
return NULL;
return &uptime_monitor;
}
/* ======================================================= */
static void
send_time(GkrellmdClient *client)
{
struct tm *t;
gchar buf[128];
t = &gkrellmd_current_tm;
snprintf(buf, sizeof(buf), "<time>\n%d %d %d %d %d %d %d %d %d\n",
t->tm_sec, t->tm_min, t->tm_hour,
t->tm_mday, t->tm_mon, t->tm_year,
t->tm_wday, t->tm_yday, t->tm_isdst);
gkrellmd_send_to_client(client, buf);
}
/* ======================================================= */
void
gkrellmd_plugin_serve_setup(GkrellmdMonitor *mon, gchar *name, gchar *line)
{
GkrellmdClient *client = mon->privat->client;
gchar buf[256];
if (!mon || !name || !line)
return;
gkrellmd_send_to_client(client, "<plugin_setup>\n");
snprintf(buf, sizeof(buf), "%s %s\n", name, line);
gkrellmd_send_to_client(client, buf);
}
static void
add_monitor(GkrellmdMonitor *mon)
{
if (!mon)
return;
mon->privat = g_new0(GkrellmdMonitorPrivate, 1);
mon->privat->serve_gstring = g_string_new("");
gkrellmd_monitor_list = g_list_append(gkrellmd_monitor_list, mon);
}
void
gkrellmd_load_monitors(void)
{
GList *list;
GkrellmdMonitor *mon;
add_monitor(init_sensors_monitor());
add_monitor(init_cpu_monitor());
add_monitor(init_proc_monitor());
add_monitor(init_disk_monitor());
add_monitor(init_net_monitor());
add_monitor(init_inet_monitor());
add_monitor(init_mem_monitor());
add_monitor(init_fs_monitor());
add_monitor(gkrellmd_init_mail_monitor());
add_monitor(init_battery_monitor());
add_monitor(init_uptime_monitor());
list = gkrellmd_plugins_load();
if (_GK.list_plugins)
exit(0);
if (_GK.log_plugins)
g_message("%s\n", plugin_install_log ? plugin_install_log :
_("No plugins found\n"));
for ( ; list; list = list->next)
{
mon = (GkrellmdMonitor *) list->data;
mon->privat->serve_gstring = g_string_new("");
mon->privat->is_plugin = TRUE;
gkrellmd_monitor_list = g_list_append(gkrellmd_monitor_list, mon);
}
}
void
gkrellmd_need_serve(GkrellmdMonitor *mon)
{
if (mon)
mon->privat->need_serve = TRUE;
}
gint
gkrellmd_update_monitors(void)
{
GList *list, *c_list;
GkrellmdMonitor *mon;
GkrellmdMonitorPrivate *mp;
GkrellmdClient *client;
struct tm *pCur;
static time_t time_prev;
gchar buf[64];
static gboolean first_update = TRUE;
static GString *serve_gstring;
time(&_GK.time_now);
GK.second_tick = (_GK.time_now == time_prev) ? FALSE : TRUE;
time_prev = _GK.time_now;
if (GK.second_tick)
{
pCur = localtime(&_GK.time_now);
GK.two_second_tick = ((pCur->tm_sec % 2) == 0) ? TRUE : FALSE;
GK.five_second_tick = ((pCur->tm_sec % 5) == 0) ? TRUE : FALSE;
GK.ten_second_tick = ((pCur->tm_sec % 10) == 0) ? TRUE : FALSE;
GK.minute_tick = (pCur->tm_min != gkrellmd_current_tm.tm_min);
gkrellmd_current_tm = *pCur;
}
else
{
GK.two_second_tick = FALSE;
GK.five_second_tick = FALSE;
GK.ten_second_tick = FALSE;
GK.minute_tick = FALSE;
}
for (list = gkrellmd_monitor_list; list; list = list->next)
{
mon = (GkrellmdMonitor *) list->data;
if (mon->update_monitor)
(*(mon->update_monitor))(mon, first_update);
}
++GK.timer_ticks;
if (!serve_gstring)
serve_gstring = g_string_new("");
for (c_list = gkrellmd_client_list; c_list; c_list = c_list->next)
{
client = (GkrellmdClient *) c_list->data;
client->last_client = !c_list->next;
if (!client->served)
gkrellmd_send_to_client(client, "<initial_update>\n");
for (list = gkrellmd_monitor_list; list; list = list->next)
{
mon = (GkrellmdMonitor *) list->data;
mp = mon->privat;
if (!mon->serve_data || (!mp->need_serve && client->served))
continue;
mp->client = client;
mp->serve_name_sent = FALSE;
(*(mon->serve_data))(mon, client->served ? FALSE : TRUE);
if (mp->serve_gstring->len > 0)
{
serve_gstring =
g_string_append(serve_gstring, mp->serve_gstring->str);
mp->serve_gstring = g_string_truncate(mp->serve_gstring, 0);
}
}
gkrellmd_send_to_client(client, serve_gstring->str);
serve_gstring = g_string_truncate(serve_gstring, 0);
if (GK.minute_tick || !client->served)
send_time(client);
else if (GK.second_tick)
{
snprintf(buf, sizeof(buf), "<.%d>\n", gkrellmd_current_tm.tm_sec);
gkrellmd_send_to_client(client, buf);
}
if (!client->served)
gkrellmd_send_to_client(client, "</initial_update>\n");
client->served = TRUE;
}
for (list = gkrellmd_monitor_list; list; list = list->next)
{
mon = (GkrellmdMonitor *) list->data;
mp = mon->privat;
mp->need_serve = FALSE;
}
for (list = serveflag_done_list; list; list = list->next)
*((gboolean *) list->data) = FALSE;
first_update = FALSE;
return TRUE;
}
void
gkrellmd_serve_setup(GkrellmdClient *client)
{
GList *list;
GkrellmdMonitor *mon;
struct lconv *lc;
gchar buf[32], *s, *name;
gkrellmd_send_to_client(client, "<gkrellmd_setup>\n");
s = g_strdup_printf("<version>\ngkrellmd %d.%d.%d%s\n",
GKRELLMD_VERSION_MAJOR, GKRELLMD_VERSION_MINOR,
GKRELLMD_VERSION_REV, GKRELLMD_EXTRAVERSION);
gkrellmd_send_to_client(client, s);
g_free(s);
lc = localeconv();
snprintf(buf, sizeof(buf), "%c\n", *lc->decimal_point);
s = g_strconcat("<decimal_point>\n", buf, "\n", NULL);
gkrellmd_send_to_client(client, s);
g_free(s);
for (list = gkrellmd_monitor_list; list; list = list->next)
{
mon = (GkrellmdMonitor *) list->data;
mon->privat->client = client;
if (mon->serve_setup)
(*(mon->serve_setup))(mon);
}
name = gkrellm_sys_get_host_name();
s = g_strconcat("<hostname>\n", name, "\n", NULL);
gkrellmd_send_to_client(client, s);
g_free(s);
name = gkrellm_sys_get_system_name();
s = g_strconcat("<sysname>\n", name, "\n", NULL);
gkrellmd_send_to_client(client, s);
g_free(s);
send_time(client);
gkrellmd_send_to_client(client, "<monitors>\n");
for (list = gkrellmd_monitor_list; list; list = list->next)
{
mon = (GkrellmdMonitor *) list->data;
snprintf(buf, sizeof(buf), "%s\n", mon->name);
gkrellmd_send_to_client(client, buf);
}
snprintf(buf, sizeof(buf), "%d\n", _GK.io_timeout);
s = g_strconcat("<io_timeout>\n", buf, "\n", NULL);
gkrellmd_send_to_client(client, s);
g_free(s);
snprintf(buf, sizeof(buf), "%d\n", _GK.reconnect_timeout);
s = g_strconcat("<reconnect_timeout>\n", buf, "\n", NULL);
gkrellmd_send_to_client(client, s);
g_free(s);
gkrellmd_send_to_client(client, "</gkrellmd_setup>\n");
}
void
gkrellmd_client_input_connect(GkrellmdMonitor *mon,
void (*func)(GkrellmdClient *, gchar *))
{
mon->privat->client_input_func = func;
}
void
gkrellmd_client_read(gint fd, gint nbytes)
{
GList *list;
GkrellmdClient *client = NULL;
GkrellmdMonitor *mon;
GkrellmdMonitorPrivate *mp;
gchar buf[513], *s, *e;
gint n, buflen;
for (list = gkrellmd_client_list; list; list = list->next)
{
client = (GkrellmdClient *) list->data;
if (client->fd != fd)
continue;
if (!client->input_gstring)
client->input_gstring = g_string_new("");
buflen = sizeof(buf) - 1;
while (nbytes > 0)
{
n = (nbytes > buflen) ? buflen : nbytes;
n = recv(fd, buf, n, 0);
if (n <= 0)
break;
nbytes -= n;
buf[n] = '\0';
client->input_gstring =
g_string_append(client->input_gstring, buf);
}
break;
}
if (!list)
return;
while (gkrellmd_getline_from_gstring(&client->input_gstring,
buf, sizeof(buf) - 1))
{
if (*buf == '<')
{
client->input_func = NULL;
s = buf + 1;
for (list = gkrellmd_monitor_list; list; list = list->next)
{
mon = (GkrellmdMonitor *) list->data;
mp = mon->privat;
if (!mp->serve_name)
continue;
n = strlen(mp->serve_name);
e = s + n;
if (*e == '>' && !strncmp(mp->serve_name, s, n))
{
client->input_func = mp->client_input_func;
break;
}
}
}
else if (client->input_func)
(*client->input_func)(client, buf);
// printf("%s: %s", client->hostname, buf);
}
}