/*
 *	openupsd.h -- global stuff
 *	Copyright (C) 2002-2003 Fred Barnes <frmb2@ukc.ac.uk>
 *
 *	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; 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.
 *
 *	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.
 */

#ifndef __OPENUPSD_H
#define __OPENUPSD_H

/*{{{  generic stuff*/
#if defined(HAVE_SYSLOG_H) && defined(HAVE_SYSLOG)
#define SUPPORT_SYSLOG 1
#else
#undef SUPPORT_SYSLOG
#endif

#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif

/*}}}*/
/*{{{  UPS state stuff (specifically for watching for power-issues)*/
#define UPSD_BAT_WEAK		0x01
#define UPSD_BAT_WEAK_MASK	UPSD_BAT_WEAK
#define UPSD_BAT_DISCHARGE	0x02
#define UPSD_BAT_DISCHARGE_MASK	UPSD_BAT_DISCHARGE

#define UPSD_OUT_INVERTER	0x01
#define UPSD_OUT_INVERTER_MASK	UPSD_OUT_INVERTER

#define UPSD_ST_OVERHEAT	0x01
#define UPSD_ST_ONBATTERY	0x02
#define UPSD_ST_OUTPUTBAD	0x04
#define UPSD_ST_OVERLOAD	0x08
#define UPSD_ST_BYPASSBAD	0x10
#define UPSD_ST_OUTPUTOFF	0x20
#define UPSD_ST_CHARGERBAD	0x40
#define UPSD_ST_UPSOFF		0x80
#define UPSD_ST_FANFAIL		0x100
#define UPSD_ST_FUSEBREAK	0x200
#define UPSD_ST_FAULT		0x400
#define UPSD_ST_AWAITPOWER	0x800
#define UPSD_ST_BUZZERON	0x1000

/* field constants, used to access particular members of this structure (in a round-about way) */
#define UPSD_DS_MODEL		0	/* model name */
#define UPSD_DS_BAT_COND	1	/* battery condition (UPSD_BAT_WEAK) */
#define UPSD_DS_BAT_IS		2	/* battery charge/discharge (UPSD_BAD_DISCHARGE) */
#define UPSD_DS_BAT_VOLTS	3	/* battery volts */
#define UPSD_DS_BAT_TEMP	4	/* battery temperature */
#define UPSD_DS_BAT_CHARGE	5	/* battery charge */
#define UPSD_DS_IN_FREQ		6	/* input frequency */
#define UPSD_DS_IN_VOLTS	7	/* input voltage */
#define UPSD_DS_OUT_FROM	8	/* output from (UPSD_OUT_INVERTER) */
#define UPSD_DS_OUT_FREQ	9	/* output frequency */
#define UPSD_DS_OUT_VOLTS	10	/* output voltage */
#define UPSD_DS_OUT_LOAD	11	/* output load */
#define UPSD_DS_STATUS		12	/* status field (UPSD_ST_...) */

#define UPSD_DS_NUMFIELDS	13	/* number of fields */

#define UPSD_DS_STRINGS		{"model","battery-condition","battery-is","battery-voltage","battery-temperature",\
				 "battery-charge","input-frequency","input-voltage","output-from","output-frequency",\
				 "output-voltage","output-load","status-field",NULL}

typedef struct TAG_openupsd_ds_t {
	char model_name[32];		/* NULL terminated model name */
	unsigned int bat_flags;		/* UPSD_BAT_..  battery status */
	int x_bvolts;			/* battery volts * 10 */
	int btemp, bcharge;		/* battery temperature (deg C) and charge (percent) */
	int x_ifreq, x_ivolts;		/* input frequency * 10 and voltage * 10 */
	int x_ofreq, x_ovolts;		/* output frequency * 10 and voltage * 10 */
	unsigned int out_flags;		/* UPSD_OUT_..  output status (only one thing atm) */
	int out_load;			/* output load (percent) */
	unsigned int st_flags;		/* UPSD_ST_.. status flags */
	char *devname;			/* pointer to the device name (inside an openupsd_sdev_t or openupsd_netcli_t) */
} openupsd_ds_t;

#define UPSD_ALARM_POLL		1	/* poll the device */
#define UPSD_ALARM_RECONNECT	2	/* attempt (outgoing) client reconnection */
#define UPSD_ALARM_MAXINT	3	/* for deciding whether internal/external alarm */

#define UPSD_ACTION_EXEC	1	/* execute something */
#define UPSD_ACTION_LOG		2	/* log something */

#define UPSD_CMP_EQ		1
#define UPSD_CMP_NE		2
#define UPSD_CMP_LT		3
#define UPSD_CMP_LE		4
#define UPSD_CMP_GT		5
#define UPSD_CMP_GE		6

struct TAG_openupsd_trigger_t;	/* forward */
struct TAG_openupsd_alarm_t;	/* forward */

typedef struct TAG_openupsd_inv_t {
	struct TAG_openupsd_inv_t *next, *prev;	/* prev/next in the invalidators list */
	struct TAG_openupsd_trigger_t *when;	/* when this one occurs */
	struct TAG_openupsd_trigger_t *trash;	/* which one to trash */
} openupsd_inv_t;

typedef struct TAG_openupsd_trigger_t {
	struct TAG_openupsd_trigger_t *next, *prev;	/* prev/next in the triggers list */
	char *name;			/* smalloc()d (user) name of trigger */
	int trig;			/* UPSD_DS_.. field involved */
	int comp;			/* UPSD_CMP_.. comparison involved */
	void *rhs;			/* what's being compared -- this will either be an (int) or a smalloc()d (char *), depending on the field */
	DYNARRAY(openupsd_inv_t *,inv);	/* invalidators for this alarm */
} openupsd_trigger_t;

typedef struct {
	int pid;			/* PID of process */
	int out_fd;			/* output file-descriptor */
	char outbuf[256];		/* output buffer (to collect lines in) */
	int bytesout;			/* number of bytes in buffer */
} openupsd_eenv_t;

typedef struct TAG_openupsd_exec_t {
	struct TAG_openupsd_exec_t *next, *prev;	/* prev/next when on the "running" list */
	char *path_to_run;		/* path to executable */
	DYNARRAY(char*, args);		/* arguments (including path first) */
	struct TAG_openupsd_alarm_t *alarm;	/* alarm with which this is associated */
	openupsd_eenv_t *env;		/* environment (fds, etc.) associated with running process */
} openupsd_exec_t;

typedef struct TAG_openupsd_alarm_t {
	struct TAG_openupsd_alarm_t *next, *prev;	/* prev/next in the (time-sorted) queue */
	time_t time;			/* time this goes off at */
	openupsd_trigger_t *alarm;	/* trigger that sets this off */
	int action;			/* UPSD_ACTION_.. indicator */
	void *xdata;			/* links to serial device for internal POLL alarm, to netcli device for internal RECONNECT alarm, or to openupsd_exec_t for ACTION_EXEC */
	char *devname;			/* for the action-queue only -- the device that generated this */
	int initial;			/* whether this alarm should be generated initially (only meaningful for static alarms) */
} openupsd_alarm_t;

/*}}}*/
/*{{{  text-output file info*/

typedef struct TAG_openupsd_ofile_t {
	struct TAG_openupsd_ofile_t *next, *prev;	/* prev/next in the output file list */
	char *fname;					/* smalloc()'d output file name */
} openupsd_ofile_t;

/*}}}*/
/*{{{  networking support structs.*/

typedef struct {
	unsigned long allow_net, allow_mask;	/* network byte-order network and netmask */
} openupsd_netnet_t;

typedef struct {
	struct sockaddr_in sin;			/* the remote address */
	int fd;					/* file-descriptor of remote client */
	char *outbuf;				/* output buffer */
	int bufsize;				/* buffer size (needed by srealloc) */
	int left;				/* amount still to send */
	int gone;				/* amount already gone */
} openupsd_rclient_t;

typedef struct TAG_openupsd_netsvr_t {
	struct TAG_openupsd_netsvr_t *next, *prev;	/* prev/next in the net-server list */
	struct sockaddr_in listen_host;		/* listen for connections on this address/port */
	int fd;					/* server socket */
	DYNARRAY(openupsd_netnet_t*, allow);	/* array of networks/netmasks to explicitly allow connections from */
	DYNARRAY(openupsd_netnet_t*, disallow);	/* array of networks/netmasks to explicitly deny connections from */
	DYNARRAY(openupsd_rclient_t*, clients);	/* array of remotely connected clients */
} openupsd_netsvr_t;

#define UPSD_NETCLI_INACTIVE 0
#define UPSD_NETCLI_CONNECTING 1
#define UPSD_NETCLI_CONNECTED 2

typedef struct TAG_openupsd_netcli_t {
	struct TAG_openupsd_netcli_t *next, *prev;	/* prev/next in the net-client list */
	char *name;				/* name associated with this */
	int fd;					/* client socket */
	int state;				/* client state */
	time_t retry;				/* seconds between retries (defaults to 60) */
	struct sockaddr_in ups_host;		/* host/port the client connects to (TCP) */
	char *inbuf;				/* input buffer */
	int bufsize;				/* input buffer size */
	int inbytes;				/* number of bytes in buffer */
	DYNARRAY(openupsd_ofile_t*, outfiles);	/* array of output files for this remote device */
	DYNARRAY(openupsd_netsvr_t*, outtcpsvrs); /* array of output servers for re-notify */
	DYNARRAY(openupsd_alarm_t*, alarms);	/* array of alarms for this */
	DYNARRAY(int, triggered);		/* array that follows "alarms" indicating which ones are currently active */
} openupsd_netcli_t;

/*}}}*/
/*{{{  serial device info*/

typedef struct TAG_openupsd_sdev_t {
	struct TAG_openupsd_sdev_t *next, *prev;	/* prev/next in the device list */
	char *name;			/* smalloc()'d user-specified name for the device */
	char *device;			/* smalloc()'d "/dev/tty.." */
	int fd;				/* descriptor */
	int inter_poll_sec;		/* seconds between polls for data */
	int s_baud;			/* baud rate */
	int s_data, s_stop;		/* data and stop bit counts */
	char s_parity;			/* parity 'N', 'E', 'O', 'M' or 'S'  (none, even, odd, mark, space) */
	struct termios saved_state;	/* saved state of the serial device */
	DYNARRAY(openupsd_ofile_t*, outfiles);	/* array of output files for this device */
	DYNARRAY(openupsd_netsvr_t*, outtcpsvrs); /* array of output servers for re-notify */
	DYNARRAY(openupsd_alarm_t*, alarms);	/* array of alarms for this */
	DYNARRAY(int, triggered);		/* array that follows "alarms" indicating which ones are currently active */
} openupsd_sdev_t;

/*}}}*/
/*{{{  openupsd_t struct*/

typedef struct {
	openupsd_sdev_t *sdev;		/* serial devices */
	openupsd_netcli_t *netcli;	/* network client list */
	openupsd_netsvr_t *netsvr;	/* network server list (for listening for connections) */
	openupsd_ofile_t *outfiles;	/* list of all output files */
	char *conffile;			/* config file (might be NULL) */
	int verbose;			/* be verbose ? */
	int daemonise;			/* become a daemon ? */
#ifdef SUPPORT_SYSLOG
	int use_syslog;			/* use syslog for messages ? */
#endif
	char *logfilename;		/* smalloc()'d name of a logfile, if one was specified */
	FILE *logfile;			/* otherwise we might have been told to use some log file somewhere else (NULL if syslog/none)*/
	char *pidfilename;		/* smalloc()'d name of a pidfile, if one was specified */
	openupsd_alarm_t *salarms;	/* "static" alarms (user config) */
	openupsd_alarm_t *aalarms;	/* "active" alarms (things that will happen soon) */
	openupsd_trigger_t *trigs;	/* list of all triggers */
	openupsd_inv_t *invds;		/* list of all invalidators */
	openupsd_exec_t *proclist;	/* list of currently running programs (waiting for termination) */
} openupsd_t;

/*}}}*/
/*{{{  external decls*/

extern char *progname;			/* program name minus leading path (points in argv) */

/* note: use LOG_{INFO,DEBUG,...} for `urgency' below */
extern int parse_config (openupsd_t *upsinfo, FILE *errstream);					/* cfg.c */
extern void openupsd_log (openupsd_t *upsinfo, int urgency, const char *fmt, ...);		/* openupsd.c */

/*}}}*/


#endif	/* !__OPENUPSD_H */



syntax highlighted by Code2HTML, v. 0.9.1