|
- /***************************************************************************
- * Copyright (C) 05/2009 by Olaf Rempel *
- * razzor@kopf-tisch.de *
- * *
- * This program 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; version 2 of the License *
- * *
- * 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. *
- * *
- * 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., *
- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- ***************************************************************************/
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
-
- #include <sys/socket.h>
-
- #include "configfile.h"
- #include "event.h"
- #include "logging.h"
- #include "unixsocket.h"
- #include "usvdevice.h"
-
- #define DEFAULT_SOCKET "alix-usvd.sock"
- #define SENDMAIL "/usr/sbin/sendmail -t"
-
- enum {
- STATE_IDLE = 0x01,
- STATE_TEST = 0x02,
- STATE_CHARGE = 0x04,
- STATE_DISCHARGE = 0x08,
- STATE_POWEROFF = 0x10,
- };
-
- static struct event_fd *listen_event;
- static struct event_timeout *timeout_event;
-
- static const char *mail_from;
- static const char *mail_to;
-
- static char * state2str(int state)
- {
- switch (state) {
- case STATE_IDLE:
- return "IDLE";
-
- case STATE_TEST:
- return "TEST";
-
- case STATE_CHARGE:
- return "CHARGE";
-
- case STATE_DISCHARGE:
- return "DISCHARGE";
-
- case STATE_POWEROFF:
- return "POWEROFF";
-
- default:
- return "UNKNOWN";
- }
- }
-
- static int str2state(char *buf)
- {
- int state = -1;
- if (strncasecmp(buf, "IDLE", 4) == 0)
- state = STATE_IDLE;
-
- else if (strncasecmp(buf, "TEST", 4) == 0)
- state = STATE_TEST;
-
- else if (strncasecmp(buf, "CHARGE", 6) == 0)
- state = STATE_CHARGE;
-
- else if (strncasecmp(buf, "DISCHARGE", 9) == 0)
- state = STATE_DISCHARGE;
-
- else if (strncasecmp(buf, "POWEROFF", 8) == 0)
- state = STATE_POWEROFF;
-
- return state;
- }
-
- static int usvstate_update(int state, struct usvdev_status *status)
- {
- static int old_state;
-
- if (status != NULL)
- state = status->state;
-
- if (state == old_state)
- return state;
-
- log_print(LOG_INFO, "usv state changed: %s => %s", state2str(old_state), state2str(state));
-
- if (mail_to != NULL) {
- FILE *mail = popen(SENDMAIL, "w");
- if (mail != NULL) {
- fprintf(mail, "From: %s\n", mail_from);
- fprintf(mail, "To: %s\n", mail_to);
- fprintf(mail, "Subject: alix-usvd state change: %s => %s\n\n",
- state2str(old_state), state2str(state));
-
- if (status != NULL) {
- fprintf(mail, "Current USV status:\n");
- fprintf(mail, "Ibat: %1.3lf mA\nUbat: %2.3lf V\nUin : %2.3lf V\n\n",
- status->ibat / 1000.0, status->ubat / 1000.0, status->uin / 1000.0);
- }
-
- fprintf(mail, "Faithfully yours, etc.\n");
- fclose(mail);
- }
- }
-
- old_state = state;
- return state;
- }
-
- static int unix_read_cb(int fd, void *privdata)
- {
- char buf[64];
- int len = read(fd, buf, sizeof(buf));
- if (len < 0)
- return -1;
-
- int new_state = str2state(buf);
- if (new_state != -1) {
- usvdev_setstate(new_state);
- new_state = usvstate_update(new_state, NULL);
-
- int len = snprintf(buf, sizeof(buf), "%s", state2str(new_state));
- write(fd, buf, len);
-
- } else if (strncasecmp(buf, "status", 6) == 0) {
-
- struct usvdev_status status;
- if (usvdev_getstatus(&status) == 0)
- usvstate_update(-1, &status);
-
- int len = snprintf(buf, sizeof(buf), "%s:%d:%d:%d",
- state2str(status.state),
- (short)status.ibat, status.ubat, status.uin);
- write(fd, buf, len);
- }
-
- close(fd);
- return -1;
- }
-
- static int status_interval(void *privdata)
- {
- struct usvdev_status status;
- if (usvdev_getstatus(&status) < 0)
- return 0;
-
- usvstate_update(-1, &status);
- return 0;
- }
-
- static int unix_accept_cb(int fd, void *privdata)
- {
- int con = accept(fd, NULL, NULL);
- if (con < 0) {
- log_print(LOG_ERROR, "unix_accept_cb: accept()");
- return 0;
- }
-
- event_add_readfd(NULL, con, unix_read_cb, NULL);
- return 0;
- }
-
- int usvstate_init(void)
- {
- const char *socket_path = config_get_string("global", "socket", DEFAULT_SOCKET);
- int sockfd = unix_listen(socket_path);
- if (sockfd < 0)
- return -1;
-
- listen_event = event_add_readfd(NULL, sockfd, unix_accept_cb, NULL);
- if (listen_event == NULL) {
- close(sockfd);
- return -1;
- }
-
- int interval = config_get_int("global", "check-interval", 60);
- struct timeval tv = { .tv_sec = interval, .tv_usec = 0 };
-
- timeout_event = event_add_timeout(&tv, status_interval, NULL);
-
- mail_from = config_get_string("alerts", "mail-from", NULL);
- mail_to = config_get_string("alerts", "mail-to", NULL);
-
- usvstate_update(-1, NULL);
- return 0;
- }
-
- int usvstate_close(void)
- {
- event_remove_timeout(timeout_event);
-
- event_remove_fd(listen_event);
- close(event_get_fd(listen_event));
-
- return 0;
- }
|