/*
 * $Id: procstatd.h,v 1.9 1999/07/15 05:30:24 rgb Exp $
 *
 * procd - Copyright (c) 1998 by Robert G. Brown, rgb@phy.duke.edu
 *         GPL version 2b (b for beverage) granted.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 *
 * procd - A daemon to extract statistics from /proc/stat and publish them
 *         on demand via a socket connection.  This daemon forks an
 *         instantiation of itself to handle each request and then dies
 *         when the line is dropped
 */


#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 <sys/file.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <utmp.h>
#include <netdb.h>

#define TRUE -1
#define FALSE 0
#define YES -1
#define NO 0
#define STDOUT stdout
#define STDERR stderr
#define MAXLINE 65535
#define MAXPATH 1024
/* 
 * BUFLEN needs to be at least one MTU.  I pick one block size in case one
 * wants to send a message that spans several packets.  ANY HACKS OF THIS
 * CODE TO SEND ADDITIONAL INFORMATION HAD BETTER RESPECT THIS OR CHANGE
 * THE LIMIT!
 */
#define BUFLEN 4096	
#define MAXFIELDNUMBER 20

void parsecl(int,char **);
void send_proc(char *);
void send_numusers();
void send_localtime();
void send_list();
void send_error(char *);
void handlemessages();
void init_statlist();
void get_statlist();
void eval_statlist();
void send_statlist();
void print_statlist(FILE *);
void init_jobslist();
void get_and_send_jobslist();
void init_quiklist();
void get_and_send_quiklist();
void quit();
int parse(char *, char **, int, int);

/*
 * Standard globals.  Note we cannot use outbuf for input/strtok as
 * strtok processes the line in place.
 */
extern int verbose;
extern int daemonmode,port;
extern int server_fd, serverlen, client_fd, clientlen;
extern int input_fd,output_fd,error_fd;
extern int buflen;
extern char outbuf[BUFLEN];
extern char hostname[BUFLEN];
extern char hostip[BUFLEN];
extern char clientname[BUFLEN];
extern char statbuf[BUFLEN];
extern char **fields;	/* for parsing via parse() */
extern long int interval;

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

 /* 
  * IDENT MUST BE FIRST!  This is because it isn't displayed with a unique
  * identifier.  This is dumb.  In fact, this is so dumb that I'll fix it
  * right soon.  Every field needs an identifier so that parsing code is
  * transparent...
  */
 typedef enum { 
   IDENT,
   VERSION,
   CPU,
   CPU_USER,
   CPU_NICE,
   CPU_SYS,
   CPU_IDLE,
   CPU0,
   CPU0_USER,
   CPU0_NICE,
   CPU0_SYS,
   CPU0_IDLE,
   CPU1,
   CPU1_USER,
   CPU1_NICE,
   CPU1_SYS,
   CPU1_IDLE,
   CPU2,
   CPU2_USER,
   CPU2_NICE,
   CPU2_SYS,
   CPU2_IDLE,
   CPU3,
   CPU3_USER,
   CPU3_NICE,
   CPU3_SYS,
   CPU3_IDLE,
   LOAD1,
   LOAD5,
   LOAD15,
   PROC,
   CONTEXT,
   SWAP,
   SWAP_IN,
   SWAP_OUT,
   PAGE,
   PAGE_IN,
   PAGE_OUT,
   DISK,
   INTR,
   MEM_TOTAL,
   MEM_USED,
   MEM_FREE,
   MEM_SHARED,
   MEM_BUFF,
   MEM_CACHE,
   MEM_SWAP_TOTAL,
   MEM_SWAP_USED,
   MEM_SWAP_FREE,
   ETH0,
   ETH0_ERR,
   ETH0_RX,
   ETH0_RX_ERR,
   ETH0_TX,
   ETH0_TX_ERR,
   ETH1,
   ETH1_ERR,
   ETH1_RX,
   ETH1_RX_ERR,
   ETH1_TX,
   ETH1_TX_ERR,
   ETH2,
   ETH2_ERR,
   ETH2_RX,
   ETH2_RX_ERR,
   ETH2_TX,
   ETH2_TX_ERR,
   ETH3,
   ETH3_ERR,
   ETH3_RX,
   ETH3_RX_ERR,
   ETH3_TX,
   ETH3_TX_ERR,
   TEMP,
   USERS,
   TIME,
   UPTIME,
   SHM_NUM,
   SHM_TOT,
   SEM_NUM,
   SEM_TOT,
   MSG_NUM,
   MSG_TOT,
#if defined(__XXYYZZ__)
   FS_GOODCNX,
   FS_BADCNX,
#endif
   FS_AMDSTAT,
   N_STATS
 } Statistics;

 typedef enum { 
   PROC_VERSION,
   PROC_STAT,
   PROC_LOADAVG,
   PROC_MEMINFO,
   PROC_NET_DEV,
   PROC_SENSORS,
   PROC_LM78,
   PROC_UPTIME,
   SYS_DATA,
   IPCS,
   FS_CONNECT,
   N_SOURCES
 } Sources;

 typedef enum {
   FORK,
   INETD,
   MCAST,
   N_MODES
 } Modes;

extern FILE *stat_fd[N_SOURCES];
extern FILE *sendstat_fd;

/*
 * This is essential.  This struct is the one true hash for each statistic.
 */
 typedef struct {
   char name[64];	/* The name of the statistic */
   int source;		/* The source of the statistic */
   int avail;		/* Is the statistic available? */
   double current;	/* Current value of statistic */
   double previous;	/* Previous value of statistic */
   double rate;		/* (current-previous)/time */
 } Stathash ;

extern Stathash stats[N_STATS];

/*
 * To handle kernel revisions
 */
 typedef struct {
   int major;
   int minor;
   int revision;
 } Kernel ;

extern Kernel kernel;
