/*
 *========================================================================
 * $Id: xmlsysd.h 163 2005-09-14 22:54:20Z rgb $
 *
 * See copyright in copyright.h and the accompanying file COPYING
 *========================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>
#include <math.h>
#include <pwd.h>
#include <sys/file.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <sys/un.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <utmp.h>
#include <netdb.h>
#include "copyright.h"

/* 
 * This contains an enumeration and definition of all commands
 * recognized by the daemon.  It is split off so that it can be
 * included in client tools so that they, too, can access the
 * commands in a uniform way.
 */
#include "commands.h"

/*
 * Needed to define List and ListElement structs (linked list interface).
 */
#include "list.h"

/* the main gnome include */
/* #include <gnome.h> */

/* libxml includes */
#include <libxml2/libxml/tree.h>
#include <libxml2/libxml/parser.h>

#define TRUE -1
#define FALSE 0
#define YES -1
#define NO 0
#define STDOUT stdout
#define STDERR stderr
/* 
 * Three important sizes: 1K, 4K (one page), 64K 
 * Remember, memory is cheap and plentiful.
 */
#define K 1024
#define K4 4096
#define K64 65536
#define MAXFIELDNUMBER 20

 /*
  *========================================================================
  * Debug enum -- one per separate component, no particular order
  *========================================================================
  */
 typedef enum {
   D_QUIET,
   D_ALL,
   D_MAIN,
   D_DAEMON,
   D_PARSECL,
   D_STARTUP,
   D_INIT,
   D_WORK,
   D_PARSE,
   D_READLINE,
   D_SENDLINE,
   D_SENDSTATS,
   D_GETPROC,
   D_LLISTS,
   D_QUIT,
   D_NET,
   D_PIDS,
   N_DEBUG
 } Debug;

 /*
  *========================================================================
  * Subroutine Prototypes
  *========================================================================
  */
 void parsecl(int,char **);
 void sigchld_handler(int);
 void Usage();
 void xmlsysd_work_loop();
 void init_stat();
 void get_stat();
 void get_system_time(xmlNodePtr system);
 void get_system_identity(xmlNodePtr system);
 void get_system_users(xmlNodePtr system);
 void get_proc_stat(xmlNodePtr proc);
 void get_proc_meminfo(xmlNodePtr proc);
 void get_proc_net_dev(xmlNodePtr proc);
 void get_proc_loadavg(xmlNodePtr proc);
 void get_proc_cpuinfo(xmlNodePtr proc);
 void get_proc_version(xmlNodePtr proc);
 void get_proc_sysvipc(xmlNodePtr proc);

/*
 * Standard globals.  Note we cannot use outbuf for input/strtok as
 * strtok processes the line in place.
 */
 int verbose;
 int daemonmode,port;
 int server_fd, serverlen, client_fd, nconnxns;
 int input_fd,output_fd,error_fd;
 uint clientlen;
 /* FILE *input_fd,*output_fd,*error_fd; */
 int initialized;	/* Flag to force init to run first */

 /* 
  * Global pointer to the xml doc in which we build and manipulate
  * the xml image of proc and other stats until we send it.  Note
  * that it is a pointer to memory that must be freed after EACH USE
  * or we'll leak sieve-like.
  */
 xmlDocPtr doc;
 xmlNodePtr docroot;
 char outbuf[K64];
 char hostname[K];
 char hostip[K];
 char clientname[K];
 char statbuf[K];
 char pidpath[K];
 /* char sensor[BUFLEN]; Cruft? Needed by lm-sensors (PROC_SENSORS) */
 char **fields;	/* for parsing via parse() */
 long int interval;


 /* 
  * This defines some flags to control just what the daemon sends and how.
  * Each is sort of documented in place.
  */
 typedef struct {

   int compress;	/* Do we compress xml output? */
   int whitespace;	/* Do we squeeze out whitespace? */

   /* 
    * All the following toggle various components of the return.
    * Some of these are only needed "once" in a typical monitoring
    * session anyway and can be pulled from the init return (which
    * always sends "everything").  Future developers should note
    * the 1:1 correspondance between these flags and "get_XXX_YYYY.c"
    * sources and calls.
    */

   /* system call stuff */
   int identity;	/* Do we update system identity? */
   int time;		/* Do we update system time? */
   int users;		/* Do we update system users? */
   /* proc-derived stuff */
   int cpuinfo;		/* Do we update proc cpuinfo? */
   int loadavg;		/* Do we update proc loadavg? */
   int meminfo;		/* Do we update proc meminfo? */
   int net;		/* Do we update proc net? */
   int stat;		/* Do we update proc stat? */
   int sysvipc;		/* Do we update proc shared memory stuff? */
   int uptime;		/* Do we update proc uptime? */
   int version;		/* Do we update proc (kernel) version? */
   /* Processes (in /proc/XXXXX where XXXXX is a pid) */
   int pids;		/* Do we update pids at all? */
   int running;		/* if so, running PIDs or all? */
   int root;		/* including those owned by root? */
   int pidstats;	/* send stat, statm? */
   int cmdline;         /* send cmdline? */
   int min_runtime;	/* Display only jobs with > this many seconds */
   List *userlist;	/* A linked list of usernames to watch */
   List *uidlist;	/* A linked list of uids to watch */
   List *tasklist;	/* A linked list of tasknames to watch */
 } Dctl;
 Dctl dctl;		/* daemon control flags */
 Dctl dctl_save;	/* a place to save them during a sendall */

 /*
  * Globals for socket pair creation
  */
 struct sockaddr_in serverINETaddress;
 struct sockaddr_in clientINETaddress;

 /*
  * The following need to be kept in absolute sync.  Each supported
  * proc source file needs to be enumerated, listed by path, and the vector
  * of file descriptors adjusted (automagically) so it will hold all
  * of them.
  */
 typedef enum { 
   PROC_STAT,
   PROC_MEMINFO,
   PROC_NET_DEV,
   PROC_NET_SOCKSTAT,
   PROC_LOADAVG,
   PROC_CPUINFO,
   PROC_VERSION,
   PROC_SYSVIPC_MSG,
   PROC_SYSVIPC_SEM,
   PROC_SYSVIPC_SHM,
   PROC_UPTIME,
   N_SOURCES
 } Sources;

 static char *procpaths[] = {
  "/proc/stat",
  "/proc/meminfo",
  "/proc/net/dev",
  "/proc/net/sockstat",
  "/proc/loadavg",
  "/proc/cpuinfo",
  "/proc/version",
  "/proc/sysvipc/msg",
  "/proc/sysvipc/sem",
  "/proc/sysvipc/shm",
  "/proc/uptime",
  "n_sources"
 };

 FILE *stat_fd[N_SOURCES];
 FILE *sendstat_fd;

 /*
  * This is supposed to enumerate the possible modes of operation of
  * xmlsysd, except that I still haven't written a multicast mode.  It's 
  * there, though, if anyone feels inspired.
  */
 typedef enum {
   FORK,
   INETD,
   MCAST,
   N_MODES
 } Modes;

