From 181cec4348da40331b3e8ab365732c025ec149b2 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Wed, 27 Apr 2011 19:24:15 +0200 Subject: Import upstream version 0.11.0~svn1143 --- plugin_imon.c | 629 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 629 insertions(+) create mode 100644 plugin_imon.c (limited to 'plugin_imon.c') diff --git a/plugin_imon.c b/plugin_imon.c new file mode 100644 index 0000000..c0fdc29 --- /dev/null +++ b/plugin_imon.c @@ -0,0 +1,629 @@ +/* $Id: plugin_imon.c 782 2007-03-21 05:01:11Z michael $ + * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_imon.c $ + * + * imond/telmond data processing + * + * Copyright (C) 2003 Nico Wallmeier + * + * This file is part of LCD4Linux. + * + * LCD4Linux 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 2, or (at your option) + * any later version. + * + * LCD4Linux 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "config.h" +#include "debug.h" +#include "plugin.h" +#include "qprintf.h" +#include "cfg.h" +#include "hash.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include /* decl of inet_addr() */ +#include + + +static HASH TELMON; +static HASH IMON; + +static char thost[256]; +static int tport; +static char phoneb[256]; + +static char ihost[256]; +static char ipass[256]; +static int iport; + +static int fd = 0; +static int err = 0; + +/*---------------------------------------------------------------------------- + * service_connect (host_name, port) - connect to tcp-service + *---------------------------------------------------------------------------- + */ +static int service_connect(const char *host_name, const int port) +{ + struct sockaddr_in addr; + struct hostent *host_p; + int fd; + int opt = 1; + + (void) memset((char *) &addr, 0, sizeof(addr)); + + if ((addr.sin_addr.s_addr = inet_addr((char *) host_name)) == INADDR_NONE) { + host_p = gethostbyname(host_name); + if (!host_p) { + error("%s: host not found\n", host_name); + return (-1); + } + (void) memcpy((char *) (&addr.sin_addr), host_p->h_addr, host_p->h_length); + } + + addr.sin_family = AF_INET; + addr.sin_port = htons((unsigned short) port); + + /* open socket */ + if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket"); + return (-1); + } + + (void) setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &opt, sizeof(opt)); + + if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) != 0) { + (void) close(fd); + perror(host_name); + return (-1); + } + + return (fd); +} /* service_connect (char * host_name, int port) */ + + +/*---------------------------------------------------------------------------- + * send_command (int fd, char * str) - send command to imond + *---------------------------------------------------------------------------- + */ +static void send_command(const int fd, const char *str) +{ + char buf[256]; + int len = strlen(str); + + sprintf(buf, "%s\r\n", str); + write(fd, buf, len + 2); + + return; +} /* send_command (int fd, char * str) */ + + +/*---------------------------------------------------------------------------- + * get_answer (int fd) - get answer from imond + *---------------------------------------------------------------------------- + */ +static char *get_answer(const int fd) +{ + static char buf[8192]; + int len; + + len = read(fd, buf, 8192); + + if (len <= 0) { + return ((char *) NULL); + } + + while (len > 1 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) { + buf[len - 1] = '\0'; + len--; + } + + if (!strncmp(buf, "OK ", 3)) { /* OK xxxx */ + return (buf + 3); + } else if (len > 2 && !strcmp(buf + len - 2, "OK")) { + *(buf + len - 2) = '\0'; + return (buf); + } else if (len == 2 && !strcmp(buf + len - 2, "OK")) { + return (buf); + } + + return ((char *) NULL); /* ERR xxxx */ +} /* get_answer (int fd) */ + +/*---------------------------------------------------------------------------- + * get_value (char * cmd) - send command, get value + *---------------------------------------------------------------------------- + */ +static char *get_value(const char *cmd) +{ + char *answer; + + send_command(fd, cmd); + + answer = get_answer(fd); + + if (answer) { + return (answer); + } + + return (""); +} /* get_value (char * cmd, int arg) */ + + +static void phonebook(char *number) +{ + FILE *fp; + char line[256]; + + fp = fopen(phoneb, "r"); + + if (!fp) + return; + + while (fgets(line, sizeof(line), fp)) { + if (*line == '#') + continue; + if (!strncmp(line, number, strlen(number))) { + char *komma = strchr(line, ','); + char *beginn = strchr(line, '='); + if (!beginn) + return; + while (strrchr(line, '\r')) + strrchr(line, '\r')[0] = '\0'; + while (strrchr(line, '\n')) + strrchr(line, '\n')[0] = '\0'; + if (komma) + komma[0] = '\0'; + strcpy(number, beginn + 1); + break; + } + } + + fclose(fp); +} + + +static int parse_telmon() +{ + static int telmond_fd = -2; + static char oldanswer[128]; + int age; + + /* reread every 1 sec only */ + age = hash_age(&TELMON, NULL); + if (age > 0 && age <= 1000) + return 0; + + if (telmond_fd != -1) { + char telbuf[128]; + + telmond_fd = service_connect(thost, tport); + if (telmond_fd >= 0) { + int l = read(telmond_fd, telbuf, 127); + if ((l > 0) && (strcmp(telbuf, oldanswer))) { + char date[11]; + char time[11]; + char number[256]; + char msn[256]; + sscanf(telbuf, "%s %s %s %s", date, time, number, msn); + hash_put(&TELMON, "time", time); + date[4] = '\0'; + date[7] = '\0'; + qprintf(time, sizeof(time), "%s.%s.%s", date + 8, date + 5, date); + hash_put(&TELMON, "number", number); + hash_put(&TELMON, "msn", msn); + hash_put(&TELMON, "date", time); + phonebook(number); + phonebook(msn); + hash_put(&TELMON, "name", number); + hash_put(&TELMON, "msnname", msn); + } + close(telmond_fd); + strcpy(oldanswer, telbuf); + } + } + return 0; +} + + +static int configure_telmon(void) +{ + static int configured = 0; + + char *s; + + if (configured != 0) + return configured; + + hash_create(&TELMON); + + s = cfg_get("Plugin:Telmon", "Host", "127.0.0.1"); + if (*s == '\0') { + error("[Telmon] empty 'Host' entry in %s", cfg_source()); + configured = -1; + return configured; + } + strcpy(thost, s); + free(s); + + if (cfg_number("Plugin:Telmon", "Port", 5001, 1, 65536, &tport) < 0) { + error("[Telmon] no valid port definition"); + configured = -1; + return configured; + } + + s = cfg_get("Plugin:Telmon", "Phonebook", "/etc/phonebook"); + strcpy(phoneb, s); + free(s); + + configured = 1; + return configured; +} + + +static void my_telmon(RESULT * result, RESULT * arg1) +{ + char *val = NULL; + + if (configure_telmon() < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + if (parse_telmon() < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + val = hash_get(&TELMON, R2S(arg1), NULL); + if (val == NULL) + val = ""; + SetResult(&result, R_STRING, val); +} + + +void init() +{ + if (fd != 0) + return; + + fd = service_connect(ihost, iport); + + if (fd < 0) { + err++; + } else if ((ipass != NULL) && (*ipass != '\0')) { /* Passwort senden */ + char buf[40]; + qprintf(buf, sizeof(buf), "pass %s", ipass); + send_command(fd, buf); + get_answer(fd); + } +} + + +static int parse_imon(const char *cmd) +{ + /* reread every half sec only */ + int age = hash_age(&IMON, cmd); + if (age > 0 && age <= 500) + return 0; + + init(); /* establish connection */ + + if (err) + return -1; + + hash_put(&IMON, cmd, get_value(cmd)); + + return 0; +} + + +static int configure_imon(void) +{ + static int configured = 0; + + char *s; + + if (configured != 0) + return configured; + + hash_create(&IMON); + + s = cfg_get("Plugin:Imon", "Host", "127.0.0.1"); + if (*s == '\0') { + error("[Imon] empty 'Host' entry in %s", cfg_source()); + configured = -1; + return configured; + } + strcpy(ihost, s); + free(s); + + if (cfg_number("Plugin:Imon", "Port", 5000, 1, 65536, &iport) < 0) { + error("[Imon] no valid port definition"); + configured = -1; + return configured; + } + + s = cfg_get("Plugin:Imon", "Pass", ""); + strcpy(ipass, s); + free(s); + + configured = 1; + return configured; +} + + +static void my_imon_version(RESULT * result) +{ + char *val; + int age; + + if (configure_imon() < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + /* read only once */ + age = hash_age(&IMON, "version"); + if (age < 0) { + char *s; + init(); + if (err) { + SetResult(&result, R_STRING, ""); + return; + } + s = get_value("version"); + for (;;) { /* interne Versionsnummer killen */ + if (s[0] == ' ') { + s = s + 1; + break; + } + s = s + 1; + } + hash_put(&IMON, "version", s); + } + + val = hash_get(&IMON, "version", NULL); + if (val == NULL) + val = ""; + SetResult(&result, R_STRING, val); +} + + +static int parse_imon_rates(const char *channel) +{ + char buf[128], in[25], out[25]; + char *s; + int age; + + qprintf(buf, sizeof(buf), "rate %s in", channel); + + /* reread every half sec only */ + age = hash_age(&IMON, buf); + if (age > 0 && age <= 500) + return 0; + + init(); /* establish connection */ + + if (err) + return -1; + + qprintf(buf, sizeof(buf), "rate %s", channel); + s = get_value(buf); + + if (sscanf(s, "%s %s", in, out) != 2) + return -1; + + qprintf(buf, sizeof(buf), "rate %s in", channel); + hash_put(&IMON, buf, in); + qprintf(buf, sizeof(buf), "rate %s out", channel); + hash_put(&IMON, buf, out); + + return 0; +} + + +static void my_imon_rates(RESULT * result, RESULT * arg1, RESULT * arg2) +{ + char *val; + char buf[128]; + + if (configure_imon() < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + if (parse_imon_rates(R2S(arg1)) < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + qprintf(buf, sizeof(buf), "rate %s %s", R2S(arg1), R2S(arg2)); + + val = hash_get(&IMON, buf, NULL); + if (val == NULL) + val = ""; + SetResult(&result, R_STRING, val); +} + +static int parse_imon_quantity(const char *channel) +{ + char buf[256], fill1[25], in[25], fill2[25], out[25]; + char *s; + int age; + + qprintf(buf, sizeof(buf), "quantity %s in", channel); + + /* reread every half sec only */ + age = hash_age(&IMON, buf); + if (age > 0 && age <= 500) + return 0; + + init(); /* establish connection */ + + if (err) + return -1; + + qprintf(buf, sizeof(buf), "quantity %s", channel); + s = get_value(buf); + + if (sscanf(s, "%s %s %s %s", fill1, in, fill2, out) != 4) + return -1; + + qprintf(buf, sizeof(buf), "quantity %s in", channel); + hash_put(&IMON, buf, in); + qprintf(buf, sizeof(buf), "quantity %s out", channel); + hash_put(&IMON, buf, out); + + return 0; +} + +static int parse_imon_status(const char *channel) +{ + char buf[256], status[25]; + char *s; + int age; + + qprintf(buf, sizeof(buf), "status %s", channel); + + /* reread every half sec only */ + age = hash_age(&IMON, buf); + if (age > 0 && age <= 500) + return 0; + + init(); /* establish connection */ + + if (err) + return -1; + + qprintf(buf, sizeof(buf), "status %s", channel); + s = get_value(buf); + + if (sscanf(s, "%s", status) != 1) + return -1; + + qprintf(buf, sizeof(buf), "status %s", channel); + if (strcasecmp(status, "Online") == 0) + hash_put(&IMON, buf, "1"); + else + hash_put(&IMON, buf, "0"); + + return 0; +} + +static void my_imon_quantity(RESULT * result, RESULT * arg1, RESULT * arg2) +{ + char *val; + char buf[256]; + + if (configure_imon() < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + if (parse_imon_quantity(R2S(arg1)) < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + qprintf(buf, sizeof(buf), "quantity %s %s", R2S(arg1), R2S(arg2)); + + val = hash_get(&IMON, buf, NULL); + if (val == NULL) + val = ""; + SetResult(&result, R_STRING, val); +} + +static void my_imon_status(RESULT * result, RESULT * arg1) +{ + char *val; + char buf[256]; + + if (configure_imon() < 0) { + SetResult(&result, R_NUMBER, "-1"); + return; + } + + if (parse_imon_status(R2S(arg1)) < 0) { + SetResult(&result, R_STRING, "-1"); + return; + } + + qprintf(buf, sizeof(buf), "status %s", R2S(arg1)); + + val = hash_get(&IMON, buf, NULL); + if (val == NULL) + val = "-1"; + SetResult(&result, R_STRING, val); +} + +static void my_imon(RESULT * result, RESULT * arg1) +{ + char *val; + char *cmd; + + if (configure_imon() < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + cmd = R2S(arg1); + if (parse_imon(cmd) < 0) { + SetResult(&result, R_STRING, ""); + return; + } + + val = hash_get(&IMON, cmd, NULL); + if (val == NULL) + val = ""; + SetResult(&result, R_STRING, val); +} + + +int plugin_init_imon(void) +{ + AddFunction("imon", 1, my_imon); + AddFunction("imon::version", 0, my_imon_version); + AddFunction("imon::rates", 2, my_imon_rates); + AddFunction("imon::quantity", 2, my_imon_quantity); + AddFunction("imon::status", 1, my_imon_status); + AddFunction("imon::telmon", 1, my_telmon); + + return 0; +} + + +void plugin_exit_imon(void) +{ + if (fd > 0) { + send_command(fd, "quit"); + close(fd); + } + hash_destroy(&TELMON); + hash_destroy(&IMON); +} -- cgit v1.2.3