2376 lines
51 KiB
C
2376 lines
51 KiB
C
/* GKrellM
|
|
| Copyright (C) 1999-2014 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)
|
|
{
|
|
GThread *gth;
|
|
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;
|
|
gth = g_thread_new("get_fsusage", get_fsusage_thread, m);
|
|
g_thread_unref(gth);
|
|
}
|
|
}
|
|
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)
|
|
{
|
|
GThread *gth;
|
|
|
|
if (thread_busy)
|
|
return;
|
|
thread_busy = TRUE;
|
|
gth = g_thread_new("read_sensors", read_sensors, NULL);
|
|
g_thread_unref(gth);
|
|
}
|
|
|
|
|
|
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);
|
|
}
|
|
}
|