📄 client.c
字号:
/* GKrellM| Copyright (C) 1999-2006 Bill Wilson|| Author: Bill Wilson billw@gkrellm.net| Latest versions might be found at: http://gkrellm.net|| This program is free software which I release under the GNU General Public| License. You may redistribute and/or modify this program under the terms| of that license as published by the Free Software Foundation; either| version 2 of the License, or (at your option) any later version.|| This program is distributed in the hope that it will be useful,| but WITHOUT ANY WARRANTY; without even the implied warranty of| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the| GNU General Public License for more details. Version 2 is in the| COPYRIGHT file in the top level directory of this distribution.| | To get a copy of the GNU General Puplic License, write to the Free Software| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include "gkrellm.h"#include "gkrellm-private.h"#include "gkrellm-sysdeps.h"#if !defined(WIN32)#include <sys/socket.h>#include <utime.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#else#define uint32_t u_long#include <winsock2.h>#endif#include <errno.h>#if defined(__linux__)#if defined(__GLIBC__) && ((__GLIBC__>2)||(__GLIBC__==2 && __GLIBC_MINOR__>=1))#define HAVE_GETADDRINFO 1#endif#endif#if defined(__FreeBSD__)#if __FreeBSD_version >= 400000#define HAVE_GETADDRINFO 1#endif#endif#if defined(__OpenBSD__)#define HAVE_GETADDRINFO 1#endif#if defined(__NetBSD__)#define HAVE_GETADDRINFO 1#endif#if defined(__solaris__)/* getaddrinfo is related to IPv6 stuff */# include <netconfig.h># if defined(NC_INET6)# define HAVE_GETADDRINFO 1# endif#endiftypedef struct { gchar *key; void (*func)(); } KeyTable;static gint server_major_version, server_minor_version, server_rev_version;static gint client_input_id, client_fd;static gboolean server_alive;static gchar server_buf[4097];static gint buf_index;static gchar locale_decimal_point;static gchar server_decimal_point = '.';static gboolean need_locale_fix = FALSE;gbooleangkrellm_client_check_server_version(gint major, gint minor, gint rev) { if ( server_major_version > major || (server_major_version == major && server_minor_version > minor) || ( server_major_version == major && server_minor_version == minor && server_rev_version >= rev ) ) return TRUE; return FALSE; } /* There can be a locale decimal point mismatch with the server. */static voidlocale_fix(gchar *buf) { gchar *s; for (s = buf; *s; ++s) if (*s == server_decimal_point) *s = locale_decimal_point; }/* ================================================================= *//* CPU */typedef struct { gint instance; gulong user, nice, sys, idle; } Cpu;static GList *cpu_list, *instance_list;static gint n_cpus = 1;static gboolean nice_time_supported = TRUE;static voidclient_cpu_line_from_server(gchar *line) { GList *list; Cpu *cpu = NULL; gint n; guint64 user, nice, sys, idle; sscanf(line, "%d %llu %llu %llu %llu", &n, &user, &nice, &sys, &idle); for (list = cpu_list; list; list = list->next) { cpu = (Cpu *) list->data; if (cpu->instance == n) break; } if (list) { cpu->user = user; cpu->nice = nice; cpu->sys = sys; cpu->idle = idle; } }static voidcpu_read_data(void) { Cpu *cpu; GList *list; for (list = cpu_list; list; list = list->next) { cpu = (Cpu *) list->data; gkrellm_cpu_assign_data(cpu->instance, cpu->user, cpu->nice, cpu->sys, cpu->idle); } }static voidclient_sys_cpu_init(void) { GList *list; Cpu *cpu; gint n; /* Do initialization based on info received in client_cpu_setup(). Here | we need to get the same effective work done as would be done in the | sysdep gkrellm_sys_cpu_init() when not running in client mode. */ for (n = 0; n < n_cpus; ++ n) { cpu = g_new0(Cpu, 1); if (instance_list && (list = g_list_nth(instance_list, n)) != NULL) { cpu->instance = GPOINTER_TO_INT(list->data); gkrellm_cpu_add_instance(cpu->instance); } else cpu->instance = n; cpu_list = g_list_append(cpu_list, cpu); } gkrellm_cpu_set_number_of_cpus(n_cpus); if (!nice_time_supported) gkrellm_cpu_nice_time_unsupported(); /* Diverting the cpu_read_data function in cpu.c causes the cpu monitor | to not call the gkrellm_sys_cpu_init() sysdep function and also to call | our client cpu_read_data function instead of gkrellm_sys_cpu_read_data() */ gkrellm_cpu_client_divert(cpu_read_data); }static voidclient_cpu_setup(gchar *line) { gint instance; if (!strncmp(line, "n_cpus", 6)) sscanf(line, "%*s %d", &n_cpus); else if (!strncmp(line, "cpu_instance", 12)) { sscanf(line, "%*s %d", &instance); instance_list = g_list_append(instance_list, GINT_TO_POINTER(instance)); } else if (!strcmp(line, "nice_time_unsupported")) nice_time_supported = FALSE; }/* ================================================================= */static struct { gint n_processes, n_running, n_users; gulong n_forks; gfloat load; } proc;static voidclient_proc_line_from_server(gchar *line) { if (need_locale_fix) locale_fix(line); sscanf(line, "%d %d %lu %f %d", &proc.n_processes, &proc.n_running, &proc.n_forks, &proc.load, &proc.n_users); }static voidread_proc_data(void) { gkrellm_proc_assign_data(proc.n_processes, proc.n_running, proc.n_forks, proc.load); }static voidread_user_data(void) { gkrellm_proc_assign_users(proc.n_users); }static voidclient_sys_proc_init(void) { gkrellm_proc_client_divert(read_proc_data, read_user_data); }/* ================================================================= */typedef struct { gchar *name; gchar *subdisk_parent; guint64 rblk, wblk; gboolean virtual; } DiskData;static GList *disk_list;static gboolean units_are_blocks;static voidclient_disk_line_from_server(gchar *line) { DiskData *disk = NULL; GList *list; gchar name[16], s1[32], s2[32], s3[32]; guint64 rblk, wblk; gint n; gboolean virtual = FALSE; n = sscanf(line, "%15s %31s %31s %31s", name, s1, s2, s3); if (n == 4) { if ( gkrellm_client_check_server_version(2, 2, 7) && !strcmp(s1, "virtual") ) { virtual = TRUE; s1[0] = '\0'; } rblk = strtoull(s2, NULL, 0); wblk = strtoull(s3, NULL, 0); } else if (n == 3) { rblk = strtoull(s1, NULL, 0); wblk = strtoull(s2, NULL, 0); s1[0] = '\0'; } else return; for (list = disk_list; list; list = list->next) { disk = (DiskData *) list->data; if (!strcmp(disk->name, name)) break; } if (!list) { disk = g_new0(DiskData, 1); disk->name = g_strdup(name); if (s1[0]) /* I expect server to send in order */ disk->subdisk_parent = g_strdup(s1); disk_list = g_list_append(disk_list, disk); } if (disk) { disk->rblk = rblk; disk->wblk = wblk; disk->virtual = virtual; } }static voidread_disk_data(void) { GList *list; DiskData *disk; for (list = disk_list; list; list = list->next) { disk = (DiskData *) list->data; if (disk->subdisk_parent) gkrellm_disk_subdisk_assign_data_by_name(disk->name, disk->subdisk_parent, disk->rblk, disk->wblk); else gkrellm_disk_assign_data_by_name(disk->name, disk->rblk, disk->wblk, disk->virtual); } }static gintorder_from_name(gchar *name) { return -1; }static voidclient_sys_disk_init(void) { gkrellm_disk_client_divert(read_disk_data, NULL, order_from_name); if (units_are_blocks) gkrellm_disk_units_are_blocks(); /* Disk monitor config needs to know will be using assign by name */ gkrellm_disk_assign_data_by_name(NULL, 0, 0, FALSE); }static voidclient_disk_setup(gchar *line) { if (!strcmp(line, "units_are_blocks")) units_are_blocks = TRUE; }/* ================================================================= */typedef struct { gchar *name; gboolean up_event, down_event; gint up_time; gulong rx, tx; } NetData;static NetData *net_timer;static GList *net_list;static gchar *net_timer_name;static gboolean net_server_use_routed;static voidclient_net_line_from_server(gchar *line) { GList *list; NetData *net; gchar name[32]; guint64 rx, tx; sscanf(line, "%31s %llu %llu", name, &rx, &tx); for (list = net_list; list; list = list->next) { net = (NetData *) list->data; if (!strcmp(name, net->name)) { net->rx = rx; net->tx = tx; break; } } if (!list) { net = g_new0(NetData, 1); net->name = g_strdup(name); net_list = g_list_append(net_list, net); net->rx = rx; net->tx = tx; if (net_timer_name && !strcmp(net_timer_name, net->name)) net_timer = net; } }static voidclient_net_routed_line_from_server(gchar *line) { GList *list; NetData *net = NULL; gchar name[32]; gboolean routed; sscanf(line, "%31s %d", name, &routed); for (list = net_list; list; list = list->next) { net = (NetData *) list->data; if (!strcmp(name, net->name)) break; } if (!list) { net = g_new0(NetData, 1); net->name = g_strdup(name); net_list = g_list_append(net_list, net); } if (net) { if (routed) net->up_event = TRUE; else net->down_event = TRUE; } }gintgkrellm_client_server_get_net_timer(void) { return net_timer ? net_timer->up_time : 0; }static voidclient_net_timer_line_from_server(gchar *line) { gchar name[32]; if (!net_timer) return; sscanf(line, "%s %d", name, &net_timer->up_time); }static voidcheck_net_routes(void) { GList *list; NetData *net; for (list = net_list; list; list = list->next) { net = (NetData *) list->data; if (net->up_event || net->down_event) gkrellm_net_routed_event(net->name, net->up_event); net->up_event = net->down_event = FALSE; } }static voidread_net_data(void) { GList *list; NetData *net; for (list = net_list; list; list = list->next) { net = (NetData *) list->data; gkrellm_net_assign_data(net->name, net->rx, net->tx); } } /* gkrellmd to gkrellm server/client interface always uses the net routed | mode regardless if the server uses routed in its sysdep code. */static voidclient_sys_net_init(void) { gkrellm_net_client_divert(read_net_data, check_net_routes, NULL); gkrellm_net_use_routed(net_server_use_routed); if (net_timer_name) gkrellm_net_server_has_timer(); }static voidclient_net_setup(gchar *line) { gchar buf[32]; /* This is the server sysdep net_use_routed value. The client <-> server | link always uses routed mode. */ if (!strcmp(line, "net_use_routed")) net_server_use_routed = TRUE; if (!strncmp(line, "net_timer", 9)) { sscanf(line, "%*s %31s\n", buf); net_timer_name = g_strdup(buf); } }/* ================================================================= */#include "../src/inet.h"static GList *inet_list;static gboolean inet_unsupported;static voidclient_inet_line_from_server(gchar *line) { GList *list; ActiveTCP tcp, *t; gchar *ap, *aap;#if defined(INET6) && defined(HAVE_GETADDRINFO) struct addrinfo hints, *res; gchar buf[NI_MAXHOST];#else gchar buf[128];#endif gint n, slen; if (*(line + 1) == '0') { n = sscanf(line + 3, "%x %127[^:]:%x", &tcp.local_port, buf, &tcp.remote_port); if (n != 3 || inet_aton(buf, &tcp.remote_addr) == 0) return; tcp.family = AF_INET; }#if defined(INET6) && defined(HAVE_GETADDRINFO) else if (*(line + 1) == '6') {#define STR(x) #x#define XSTR(x) STR(x) n = sscanf(line + 3, "%x [%" XSTR(NI_MAXHOST) "[^]]]:%x", &tcp.local_port, buf, &tcp.remote_port); if (n != 3) return; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; if (getaddrinfo(buf, NULL, &hints, &res) != 0) return; memcpy(&tcp.remote_addr6, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, sizeof(struct in6_addr)); freeaddrinfo(res); tcp.family = AF_INET6; }#endif if (*line == '+') { t = g_new0(ActiveTCP, 1); *t = tcp; inet_list = g_list_append(inet_list, t); } else if (*line == '-') { for (list = inet_list; list; list = list->next) { t = (ActiveTCP *) list->data; if (t->family == AF_INET) { ap = (gchar *) &t->remote_addr; aap = (gchar *) &tcp.remote_addr; slen = sizeof(struct in_addr); }#if defined(INET6) else if (t->family == AF_INET6) { ap = (gchar *) &t->remote_addr6; aap = (gchar *) &tcp.remote_addr6; slen = sizeof(struct in6_addr); }#endif else return; if ( memcmp(aap, ap, slen) == 0 && tcp.remote_port == t->remote_port && tcp.local_port == t->local_port ) { g_free(t); inet_list = g_list_remove_link(inet_list, list); break; } } } }static voidread_tcp_data(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -