📄 client.c
字号:
{ struct tm *t; t = &server_time; sscanf(s, "%d %d %d %d %d %d %d %d %d", &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); }/* ================================================================= */static voidclient_server_version_setup(gchar *line) { sscanf(line, "%*s %d.%d.%d", &server_major_version, &server_minor_version, &server_rev_version); }static voidclient_hostname_setup(gchar *s) { g_free(_GK.server_hostname); _GK.server_hostname = g_strdup(s); }static voidclient_sysname_setup(gchar *s) { g_free(_GK.server_sysname); _GK.server_sysname = g_strdup(s); }KeyTable monitor_table[] = { {"sensors", client_sys_sensors_init }, {"cpu", client_sys_cpu_init }, {"proc", client_sys_proc_init }, {"disk", client_sys_disk_init }, {"net", client_sys_net_init }, {"inet", client_sys_inet_init }, {"mem", client_sys_mem_init }, {"fs", client_sys_fs_init }, {"mail", client_sys_mail_init }, {"apm", client_sys_battery_init }, {"battery", client_sys_battery_init }, {"uptime", client_sys_uptime_init }, };static gboolean setup_done; /* only one sys init */ /* Setup lines are received before monitor init functions are called, so | for plugins must save the strings until plugins are loaded. */static GList *client_plugin_setup_line_list;static voidclient_plugin_add_setup_line(gchar *line) { client_plugin_setup_line_list = g_list_append(client_plugin_setup_line_list, g_strdup(line)); } /* Plugins should call this in their gkrellm_init_plugin() function. */voidgkrellm_client_plugin_get_setup(gchar *key_name, void (*setup_func_cb)(gchar *str)) { GList *list; gchar *line, *s; gint n; if (!_GK.client_mode || !key_name || !setup_func_cb) return; for (list = client_plugin_setup_line_list; list; list = list->next) { line = (gchar *) list->data; n = strlen(key_name); s = line + n; if (!strncmp(line, key_name, n) && *s == ' ') { while (*s == ' ') ++s; (*setup_func_cb)(s); } } }static voidclient_monitor_setup(gchar *line) { void (*func)(); gchar buf[64]; gint i; gboolean found_builtin = FALSE; if (!*line || setup_done) return; for (i = 0; i < sizeof(monitor_table) / sizeof(KeyTable); ++i) { if (!strcmp(line, monitor_table[i].key)) { func = monitor_table[i].func; (*func)(); found_builtin = TRUE; break; } } /* The client mode init work of a plugin must be defered since they | aren't loaded yet. Set up so they will can get an "available" flag. */ if (!found_builtin) { snprintf(buf, sizeof(buf), "%s available", line); client_plugin_add_setup_line(buf); } }static voidclient_server_error(gchar *line) { fprintf(stderr, "gkrellmd error: %s\n", line); exit(0); }static voidlocale_sync(void) { struct lconv *lc; lc = localeconv(); locale_decimal_point = *lc->decimal_point; if (locale_decimal_point != server_decimal_point) need_locale_fix = TRUE; }static voidclient_server_decimal_point(gchar *line) { sscanf(line, "%c", &server_decimal_point); locale_sync(); }static voidclient_server_io_timeout(gchar *line) { sscanf(line, "%d", &_GK.client_server_io_timeout); if (_GK.client_server_io_timeout < 2) _GK.client_server_io_timeout = 0; }static voidclient_server_reconnect_timeout(gchar *line) { sscanf(line, "%d", &_GK.client_server_reconnect_timeout); if (_GK.client_server_reconnect_timeout < 2) _GK.client_server_reconnect_timeout = 0; }/* ================================================================= */KeyTable setup_table[] = { {"<version>", client_server_version_setup }, {"<sensors_setup>", client_sensors_setup }, {"<hostname>", client_hostname_setup }, {"<sysname>", client_sysname_setup }, {"<cpu_setup>", client_cpu_setup }, {"<disk_setup>", client_disk_setup }, {"<inet_setup>", client_inet_setup }, {"<net_setup>", client_net_setup }, {"<fs_setup>", client_fs_setup }, {"<mail_setup>", client_mail_setup }, {"<apm_setup>", client_battery_setup }, {"<battery_setup>", client_battery_setup }, {"<time>", client_time_line_from_server}, {"<monitors>", client_monitor_setup }, {"<decimal_point>", client_server_decimal_point }, {"<error>", client_server_error }, {"<io_timeout>", client_server_io_timeout}, {"<reconnect_timeout>", client_server_reconnect_timeout}, {"<plugin_setup>", client_plugin_add_setup_line}, };typedef struct { GkrellmMonitor *mon; gchar *key_name; void (*func_cb)(gchar *line); } ClientPlugin;static GList *client_plugin_serve_data_list;static GkrellmFuncclient_plugin_func(gchar *line) { GList *list; ClientPlugin *plug; void (*func)() = NULL; gchar *s; gint n; for (list = client_plugin_serve_data_list; list; list = list->next) { plug = (ClientPlugin *) list->data; n = strlen(plug->key_name); s = line + n; if (*s == '>' && !strncmp(plug->key_name, line, n)) { func = plug->func_cb; break; } } return func; }voidgkrellm_client_plugin_serve_data_connect(GkrellmMonitor *mon, gchar *key_name, void (*func_cb)(gchar *line)) { ClientPlugin *plug; if (!mon || !key_name || !func_cb) return; plug = g_new0(ClientPlugin, 1); plug->mon = mon; plug->key_name = g_strdup(key_name); plug->func_cb = func_cb; client_plugin_serve_data_list = g_list_append(client_plugin_serve_data_list, plug); }static gbooleanclient_send_to_server(gchar *buf) { gint n; if (!server_alive || client_fd < 0) return FALSE;#if defined(MSG_NOSIGNAL) n = send(client_fd, buf, strlen(buf), MSG_NOSIGNAL);#else n = send(client_fd, buf, strlen(buf), 0);#endif if (n < 0 && errno == EPIPE) { if (_GK.debug_level & DEBUG_CLIENT) printf("Write on closed pipe to gkrellmd server.\n"); server_alive = FALSE; return FALSE; } return TRUE; }gbooleangkrellm_client_send_to_server(gchar *key_name, gchar *line) { gchar *str; gboolean result; if (!key_name || !line || !*line) return FALSE; str = g_strdup_printf("<%s>\n", key_name); client_send_to_server(str); g_free(str); if (line[strlen(line) - 1] != '\n') { str = g_strdup_printf("%s\n", line); result = client_send_to_server(str); g_free(str); } else result = client_send_to_server(line); return result; }KeyTable update_table[] = { {"<cpu>", client_cpu_line_from_server}, {"<proc>", client_proc_line_from_server}, {"<disk>", client_disk_line_from_server}, {"<net>", client_net_line_from_server}, {"<net_routed>", client_net_routed_line_from_server}, {"<net_timer>", client_net_timer_line_from_server}, {"<mem>", client_mem_line_from_server}, {"<swap>", client_swap_line_from_server}, {"<fs>", client_fs_line_from_server}, {"<fs_fstab>", client_fstab_line_from_server}, {"<fs_mounts>", client_mounts_line_from_server}, {"<inet>", client_inet_line_from_server}, {"<mail>", client_mail_line_from_server}, {"<apm>", client_battery_line_from_server}, {"<battery>", client_battery_line_from_server}, {"<sensors>", client_sensors_line_from_server}, {"<time>", client_time_line_from_server}, {"<uptime>", client_uptime_line_from_server},// {"<>", client__line_from_server}, };static gintgetline(gint fd, gchar *buf, gint len) { fd_set read_fds; struct timeval tv; gchar *s; gint result, n, nread = 0; FD_ZERO(&read_fds); FD_SET(fd, &read_fds); tv.tv_usec = 0; tv.tv_sec = 15; s = buf; *s = '\0'; for (n = 0; n < len - 1; ++n) { nread = 0; result = select(fd + 1, &read_fds, NULL, NULL, &tv); if (result <= 0 || (nread = recv(fd, s, 1, 0)) != 1) break; if (*s == '\n') { *s = '\0'; break; } *++s = '\0'; } if (nread < 0 && errno != EINTR) { fprintf(stderr, "Broken server connection\n"); exit(0); } if (_GK.debug_level & DEBUG_CLIENT) printf("%s\n", buf); return n; }static voidprocess_server_line(KeyTable *table, gint table_size, gchar *line) { static void (*func)(gchar *); gint i; if (!*line || *line == '#') return; if (*line == '<') { func = NULL; if (line[1] == '.') { server_time.tm_sec = atoi(line + 2); return; } for (i = 0; i < table_size; ++i) { if (!strcmp(table[i].key, line)) { func = table[i].func; break; } } if (!func) func = client_plugin_func(line + 1); } else if (func) (*func)(line); } /* Read setup info from gkrellmd server. Stuff needed before the | client_init calls must be read here. */static voidread_server_setup(gint fd) { gchar buf[256]; gint table_size; /* Pre 2.1.6 gkrellmd does not send <decimal_point>, so put a fallback | locale_sync() here. */ locale_sync(); _GK.client_server_read_time = time(0); table_size = sizeof(setup_table) / sizeof(KeyTable); gkrellm_free_glist_and_data(&client_plugin_setup_line_list); while (1) { getline(fd, buf, sizeof(buf)); if (!strcmp(buf, "</gkrellmd_setup>")) break; process_server_line(&setup_table[0], table_size, buf); } /* Reset any data that is not cumulative. gkrellmd sends .clear tags | for fstab and mounts, but inet does not. So fix it here. */ client_inet_reset(); /* Read the initial update data */ table_size = sizeof(update_table) / sizeof(KeyTable); while (1) { getline(fd, buf, sizeof(buf)); if (!strcmp(buf, "</initial_update>")) break; process_server_line(&update_table[0], table_size, buf); } setup_done = TRUE; }voidgkrellm_client_mode_disconnect(void) { if (client_fd >= 0) close(client_fd); client_fd = -1; server_alive = FALSE; gdk_input_remove(client_input_id); client_input_id = 0; }static voidread_server_input(gpointer data, gint fd, GdkInputCondition condition) { gchar *line, *eol; gint count, n, table_size; n = sizeof(server_buf) - buf_index - 1; count = recv(fd, server_buf + buf_index, n, 0); if (count <= 0) { gkrellm_client_mode_disconnect(); return; } if (_GK.time_now > 0) _GK.client_server_read_time = _GK.time_now; server_buf[buf_index + count] = '\0'; line = server_buf; table_size = sizeof(update_table) / sizeof(KeyTable); while (*line && (eol = strchr(line, '\n')) != NULL) { *eol = '\0'; if (_GK.debug_level & DEBUG_CLIENT) printf("%s\n", line); process_server_line(&update_table[0], table_size, line); line = eol + 1; } if (line != server_buf && *line) { buf_index = strlen(line); memmove(server_buf, line, buf_index); } else if (!*line) buf_index = 0; else { buf_index += count; if (buf_index >= sizeof(server_buf) - 2) buf_index = 0; } server_buf[buf_index] = '\0'; }gintgkrellm_connect_to(gchar *server, gint server_port) { gint fd = -1;#ifdef HAVE_GETADDRINFO gint rv = 0; struct addrinfo hints, *res, *res0; gchar portnumber[6];#else struct hostent *addr; struct sockaddr_in s;#endif#ifdef HAVE_GETADDRINFO snprintf (portnumber, sizeof(portnumber), "%d", server_port); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; if ((rv = getaddrinfo(server, portnumber, &hints, &res0)) != 0) return -1; for (res = res0; res; res = res->ai_next) { if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) continue; if (_GK.debug_level & DEBUG_CLIENT) printf("\t[gkrellm_connect_to: (%d,%d,%d) %s:%d]\n", res->ai_family, res->ai_socktype, res->ai_protocol, server, server_port); if (connect(fd, res->ai_addr, res->ai_addrlen) >= 0) break;#ifdef WIN32 closesocket(fd);#else close(fd);#endif fd = -1; } freeaddrinfo(res0);#else if (_GK.debug_level & DEBUG_CLIENT) printf("\t[gkrellm_connect_to: %s:%d]\n", server, server_port); addr = gethostbyname(server); if (addr) { fd = socket(AF_INET, SOCK_STREAM, 0); if (fd >= 0) { memset(&s, 0, sizeof(s)); memcpy(&s.sin_addr.s_addr, addr->h_addr, addr->h_length); s.sin_family = AF_INET; s.sin_port = htons(server_port); if (connect(fd, (struct sockaddr *)&s, sizeof (s)) < 0) {#ifdef WIN32 closesocket(fd);#else close(fd);#endif fd = -1; } } }#endif if (fd < 0) return -1; return fd; }gbooleangkrellm_client_mode_connect(void) { gchar buf[128]; if (_GK.server_port == 0) _GK.server_port = GKRELLMD_SERVER_PORT; client_fd = gkrellm_connect_to(_GK.server, _GK.server_port); if (client_fd < 0) { printf("%s\n", _("Unable to connect.")); return FALSE; } snprintf(buf, sizeof(buf), "gkrellm %d.%d.%d%s\n", GKRELLM_VERSION_MAJOR, GKRELLM_VERSION_MINOR, GKRELLM_VERSION_REV, GKRELLM_EXTRAVERSION); send(client_fd, buf, strlen(buf), 0); /* Initial setup lines from server are read in blocking mode. */ read_server_setup(client_fd); /* Extra stuff not handled in read_server_setup() */ gkrellm_mail_local_unsupported(); /* Now switch to non blocking and set up a read handler. */ fcntl(client_fd, F_SETFL, O_NONBLOCK); client_input_id = gdk_input_add(client_fd, GDK_INPUT_READ, (GdkInputFunction) read_server_input, NULL); server_alive = TRUE; return TRUE; }static gboolean client_mode_thread_busy;gintgkrellm_client_server_connect_state(void) { if (client_mode_thread_busy) /* reconnect in progress? */ return 2; if (_GK.client_mode && client_input_id > 0) /* Currently connected? */ return 1; else if (_GK.client_mode) return 0; else return -1; }static gpointerclient_mode_connect_thread(void *data) { gkrellm_client_mode_connect(); client_mode_thread_busy = FALSE; return NULL; }voidgkrellm_client_mode_connect_thread(void) { if (client_mode_thread_busy || !_GK.client_mode) return; client_mode_thread_busy = TRUE; g_thread_create(client_mode_connect_thread, NULL, FALSE, NULL); }gbooleangkrellm_client_mode(void) { return _GK.client_mode; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -