/*
 * ++Copyright Released Product++
 *
 * Copyright (c) 1994, 1995 Sources of Supply Corporation ("SOS").
 * All rights reserved.
 *
 * The SOS Released Product License Agreement specifies the terms and
 * conditions for redistribution.  You may find the License Agreement
 * in the file LICENSE.
 *
 * SOS Corporation
 * 461 5th Ave.; 16th floor
 * New York, NY 10017
 *
 * +1 800 SOS UNIX
 * <sos-info@soscorp.com>
 *
 * --Copyright Released Product--
 */

/*
 * libsos library interface
 */

#ifndef _sos_h_
#define _sos_h_

#include "unix_decl.h"


/**********************************************************************
 *			    Common defines			      *
 **********************************************************************/


/* Check for string equality with unix-like return codes */
#define SOS_STREQ(a,b) ( !strcmp(a,b) )

#ifndef SOS_FALSE
#define SOS_FALSE 0
#define SOS_TRUE (!SOS_FALSE)
#endif

#define SOS_NORMAL_LINE 128
#define SOS_WHITESPACE " \t\n"

/* Configuration file: get with default */
static char *__sos_gwd_tmp;
#define SOS_GWD(key, default) (((__sos_gwd_tmp = sos_config_getnext(config, key, SOS_CONFIG_FORWARD, SOS_CONFIG_STATIC)) != NULL)?__sos_gwd_tmp:default)

/* Environment: get with default */
#define SOS_ENV_GWD(key, default) (((__sos_gwd_tmp = getenv(key)) != NULL)?__sos_gwd_tmp:default)



/**********************************************************************
 *			  Common structures			      *
 **********************************************************************/


/* SOS string type (same as bs_string) */
struct sos_buffer_t
{
  char *str;			/* pointer to actual data (null terminated) */
  int len;			/* Length of buffer (amount allocated) */
};
typedef struct sos_buffer_t sos_buffer;
typedef struct sos_buffer_t sos_string;


/* SOS connection information type */
struct sos_conninfo
{
  char *printhost;
  int port;
  struct in_addr addr;
  int fd;
};



/**********************************************************************
 *		    Configuration file information		      *
 **********************************************************************/


/* Config file data type */
typedef char *sos_config_value;

/* Config file key type */
typedef char *sos_config_key;


/* One config file element */
typedef struct sos_config_value_struct
{
  sos_config_value value;	/* The value of this particular Config line */

  struct sos_config_value_struct *next;
  struct sos_config_value_struct *prev;
} sos_config_value_t;


/* High level config file information */
typedef struct sos_config_key_struct
{
  sos_config_key key;		/* Key read from the config file */
  int no_direction_yet;		/* TRUE until after first call to getnext() */
  int num_values;		/* Number of values for the key. */

  sos_config_value_t *current;
  sos_config_value_t *first;
  sos_config_value_t *last;

  struct sos_config_key_struct *next;
} sos_config_key_t;

typedef struct sos_config 
{
  char filename[MAXPATHLEN];	/* Config file name */
  sos_config_key_t *key_list;	/* Config data struct */
} *sos_config_t;



/**********************************************************************
 *			  Relay Information			      *
 **********************************************************************/


/* Auxiliary information about data we are relaying */
struct sos_bdr_auxinfo
{
  int veclen;			/* Vector length */
  int totbuf;			/* Total number of buffers */
  int buflen;			/* Default buffer length */
  int align;			/* Buffer alignment (must be power of 2) */
  int offset;			/* Offset from alignment above */
  int common_exit;		/* Return when *any* connection closes */
  int fullread;			/* Fill all read buffers before writing */
};


/* Data about a file descriptor (including function used to perform I/O on it) */
struct sos_bdr_fdinfo
{
  int fd;
  int (*iofun) (int fd, void *buf, __SIZE_TYPE__ nbyte);
};


/* Information about ring buffer contining queued data */
struct sos_bdr_bdinfo
{
  struct iovec *curWbuf;	/* Current write buffers (may be offset) */
  struct iovec *fullbuf;	/* Non-modified buffers */
  int cur_write_hand;		/* Where to start writing from */
  int cur_read_hand;		/* Where to start copying to */
};


/* Information about list of free buffers */
struct sos_bdr_freelist_t		/* Relay buffer pool */
{
  caddr_t *free;		/* Actual buffers which are free */
  int numfree;			/* Used for fast deallocation */
};


/* Information about file descriptors and their current state */
struct sos_bdr_fdpair
{
  struct sos_bdr_fdinfo rinfo;
  struct sos_bdr_fdinfo winfo;
  int shutdown;			/* 0 - running, 1 - need to shutdown, 2 - shutdown */
  struct iovec curRbuf;		/* Current read buffer */
  struct sos_bdr_bdinfo bd;	/* Queue of data to be written */
  int nbytes;			/* Number of bytes read in */
  int (*filter) (struct sos_bdr_fdpair ** relayptr,
		 int *relaycount,
		 struct sos_bdr_auxinfo * auxinfoptr,
		 struct sos_bdr_freelist_t * freelistptr,
		 struct sos_bdr_freelist_t * dupfreeptr,
		 int current,
		 int bytes);
};



/**********************************************************************
 *			 Readline Information			      *
 **********************************************************************/


#define MAX_EOLSEQ 8
struct sos_readline_t
{
  int echo;			/* -1 noecho, 0 echo, [1-255]-echo that character */
  int wantalert;		/* Want user beep on error */
  int wantedit;			/* Want to enable editing */
  int wantnull;			/* Want to allow zero characters in output line? */
  int escape_char;		/* If you see this character, enter into escape mode */
  /* 0-255 means insert that character.  -1 means exit, else cont */
  int (*escape_mode) (FILE * in, FILE * out, unsigned char escape_char);
  sos_string eolseq[MAX_EOLSEQ]; /* End of Line string */
  int numeolseq;		/* Number of EOL strings */
};



/**********************************************************************
 *			   SKID Information			      *
 **********************************************************************/


#define SOS_SKID_ALICE	0
#define SOS_SKID_BOB	1



/**********************************************************************
 *			  Option Negotiation			      *
 **********************************************************************/


/*
 * Possible return values
 */
#define SOS_OPT_OK  0		/* Successfull negotiation (one-way) */
#define SOS_OPT_ESYS -1		/* System error */
#define SOS_OPT_EPROTO -2	/* Protocol error */
#define SOS_OPT_INCOMP -3	/* Incompatible preferences -- negot aborted */
#define SOS_OPT_ENOINIT -4	/* Initialization routine not called */


/*
 * Option states
 */
#define SOS_OPT_OFF 0
#define SOS_OPT_ON 1


/*
 * Option predispositions
 */
#define SOS_OPT_MUST 1
#define SOS_OPT_PREFER 2
#define SOS_OPT_PREFER_NOT 3
#define SOS_OPT_MUST_NOT 4


#define SOS_OPT_LPREF 1
#define SOS_OPT_PPREF 2
#define SOS_OPT_STATE 3

#define SOS_OPT_END "opt end"

#define SOS_OPT_SEND_LOCAL 4
#define SOS_OPT_CLOSE 5
#define SOS_OPT_NO_CLOSE 6

#define SOS_OPT_WINNER 7
#define SOS_OPT_LOSER 8


/**********************************************************************
 *			  SOSLOG Information			      *
 **********************************************************************/


/* LOGGING LEVELS */
#ifdef _sys_syslog_h
#define SOSLOG_EMERG LOG_EMERG
#define SOSLOG_ALERT LOG_ALERT
#define SOSLOG_CRIT LOG_CRIT
#define SOSLOG_ERR LOG_ERR
#define SOSLOG_WARNING LOG_WARNING
#define SOSLOG_NOTICE LOG_NOTICE
#define SOSLOG_INFO LOG_INFO
#define SOSLOG_DEBUG LOG_DEBUG
#else				/* Use our own values */
#define SOSLOG_EMERG 	0
#define SOSLOG_ALERT 	1
#define SOSLOG_CRIT 	2
#define SOSLOG_ERR   	3
#define SOSLOG_WARNING	4
#define SOSLOG_NOTICE	5
#define SOSLOG_INFO	6
#define SOSLOG_DEBUG	7
#endif


/* LOGGING TYPES */
#define SOSLOG_TYPE_EVENT	0
#define SOSLOG_TYPE_CONDITION	1


/* PERROR DISPOSITIONS */
#define SOSLOG_PERROR		1
#define SOSLOG_NO_PERROR	0


/* Some usefull MACROS */
#define SOSLOG_PROTOCOL SOSLOG_WARNING, SOSLOG_TYPE_EVENT, SOSLOG_NO_PERROR
#define SOSLOG_SYS_ERROR SOSLOG_ERR, SOSLOG_TYPE_CONDITION, SOSLOG_NO_PERROR
#define SOSLOG_SYS_PERROR SOSLOG_ERR, SOSLOG_TYPE_CONDITION, SOSLOG_PERROR
#define SOSLOG_AUTH_ERROR SOSLOG_ERR, SOSLOG_TYPE_EVENT, SOSLOG_NO_PERROR
#define SOSLOG_AUTH_FAILURE SOSLOG_NOTICE, SOSLOG_TYPE_EVENT, SOSLOG_NO_PERROR
#define SOSLOG_AUTH_SUCCESS SOSLOG_INFO, SOSLOG_TYPE_EVENT, SOSLOG_NO_PERROR


/* Maximum information to be logged */
#define SOSLOG_BUFSIZ	256


/* Whether you log debug messages or not */
extern int soslog_debug;



/**********************************************************************
 *		    Configuration file information		      *
 **********************************************************************/


#define SOS_CONFIG_NULL 0


/*
 * If a key has multiple values, then these macros describe in which direction
 * to traverse the list when applying sos_config_getnext()
 */
#define SOS_CONFIG_FORWARD 1
#define SOS_CONFIG_REVERSE 2
#define SOS_CONFIG_STATIC 3


/*
 * These macros tell sos_config_getnext() how to prepare for the next call.
 * (ie the semantic of chain).
 */
#define SOS_CONFIG_LINEAR 4
#define SOS_CONFIG_CIRCULAR 5
#define SOS_CONFIG_AUTORESET 6



/**********************************************************************
 *			  Errno file information		      *
 **********************************************************************/
#define SOS_ERRNO_NOERR 0
#define SOS_ERRNO_SYS 1
#define SOS_ERRNO_EINVAL 2



/**********************************************************************
 *			 Fairtoss file information		      *
 **********************************************************************/
#define SOS_FAIRTOSS_LOSE 0
#define SOS_FAIRTOSS_WIN 1

/**********************************************************************
 *			Random Identity information		      *
 **********************************************************************/
#define SOS_IDENT_ALICE 1
#define SOS_IDENT_BOB 2


/*********************************************************************
 *                            SecureNets                             *
 *********************************************************************/


typedef void *SOS_Snets;

struct sos_netmask
{
  int good;
  struct in_addr addr;
  struct in_addr mask;
};



/**********************************************************************
 *			  SOS Statfs Information		      *
 **********************************************************************/
/*
 * XXX --  Interpretations of bsize vary greatly with operating system.
 * SOS has chosen to define bsize as "Transfer size" and f_fsize as
 * fundamental file system size (cf BSDI if possible).
 *
 * Better behaved OS's will give you the available inodes for the
 * non-superuser.  If this infomation is available, we return it in ffree.
 */
struct sos_fsinfo {
  sos_fslong_t f_fsize;		/* Fundamental size */
  sos_fslong_t f_blocks;	/* Number of blocks in the file system */
  sos_fslong_t f_bfree;		/* Total number free blocks */
  sos_fslong_t f_bavail;	/* Blocks available to non-super user */
  sos_fslong_t f_files;		/* Total file nodes in file system */
  sos_fslong_t f_ffree;		/* Total availble inodes */
};



/**********************************************************************
 *			    Function prototypes			      *
 **********************************************************************/


/* Authenticator system based on static hashes */
extern unsigned char *sos_statichash(unsigned char salt[4], unsigned char *password);

/* Authenticator system based on dynamic hashes (challenge/response) */
extern unsigned char *sos_dynamichash(char *salt, unsigned char challenge[8], unsigned char *password);


/* Allocate a sos_string */
extern sos_string *sos_allocstr(sos_string * buf, int size);

/* free a sos_string */
extern void sos_freestr(sos_string * buf);


/* Turn first CR/LF found into a NULL */
extern char *sos_rip(char *x);
extern char *sos_fixcrnl(char *x, int stripnl);


/* Get the fully qualified (local) host name */
extern char *sos_fqhname(char *name, int namelen);


/* Get a hostent no matter what we are passed */
extern struct hostent *sos_gethbyfoo(char *x);

/* Get a hostent in the make-conn style (dotted quads are raw) */
extern struct hostent *sos_getmcbyfoo(char *x);

/* Get an address no matter what we are passed */
extern int sos_getabyfoo(char *x, struct in_addr *addr);

/* Get a host name no matter what we are passed */
extern char *sos_getnbyfoo(char *x, char *buf, int blen);

/* Get a service number no matter what we are passed */
extern int sos_getsbyfoo(char *x);

/* Get peer name info */
extern int sos_getpeername(int sourcefd, struct sos_conninfo *sourceinfo);

/* Make a sos_conninfo struct from arbitrary string */
extern int sos_makeprinthost(int fd, int port, char *hoststr, struct sos_conninfo *conninfo);

/* Make a sos_conninfo struct from arbitrary sockaddr_in */
extern int sos_makeprinthostfromaddr(int fd, int port, struct sockaddr_in *, struct sos_conninfo *conninfo);

/* Gen a SOS hostname from a in_addr into a static buffer */
extern char *sos_getnbyaddr(struct in_addr in);


/* Return days since the epoch (or more generally, number of days in seconds */
extern time_t sos_days(time_t secs);

/* Return date from days */
extern char *sos_daydate(time_t days, char *buf, int blen);

/* Return day from date */
extern time_t sos_dateday(char *buf, int blen);

/* Return the current time suitable for prompts (like ctime) */
extern char *sos_prompttime(char *buf, int blen);

/* Return a 822 date */
extern char *sos_sendmail_arpadate(char *ud);


/* Get len bytes of random data into buf (len must be % 4) */
extern int sos_get_rand(unsigned char *buf, int len);

/* Get an int's of random data */
unsigned int sos_get_intrand();

/* Probably not needed to be exposed, but... */
unsigned int sos_rand_pmmcg(unsigned int seed);


/* XDR encoding (to sos_string) */
extern sos_string *sos_xdr_sencode(char *fmt,... /*VARARGS */ );

/* XDR encoding with write over the wire */
extern int sos_xdr_wencode(int fd, int (*wfun) (int fd, caddr_t buf, __SIZE_TYPE__ len), char *fmt,... /*VARARGS */ );

/* XDR decoding (from string) */
extern int sos_xdr_sdecode(char *buf, char *fmt,... /*VARARGS */ );

/* XDR decoding with read from the wire */
extern int sos_xdr_wdecode(int fd, int (*rfun) (int fd, caddr_t buf, __SIZE_TYPE__ len), char *fmt,... /*VARARGS */ );

/* free the internal static buffer used by XDR */
extern void sos_xdr_freebuf();


/* Prepare for soslog */
extern void open_soslog(const char *, int allow_debugging);

/* Log a message */
extern void soslog(int, int, int, const char *,... /*VARARGS */ );

/* va_list version of same */
extern void vsoslog(int, int, int, const char *, va_list args);

/* End soslog */
extern void close_soslog();


/* Connection building routine */
extern int sos_make_conn(char *hoststring, char *port,int timeout_val, int socopts, FILE *verbose);
extern int sos_nmake_conn(char *hoststring, int port, int timeout_val, int socopts, FILE *verbose);

/* Reception building routine */
extern int sos_get_conn(struct in_addr *intf, int port, int socopts, struct sos_conninfo *info);

/* Convert string to lower case */
extern void sos_strtolower(char *p);

/* Convert sos_string to lower case */
extern void sos_sosstrtolower(sos_string * p);

/* Perform strstr on string (faster than BSD code) */
extern char *sos_strstr(char *s1, char *s2);

/* Perform strstr on sos_string */
extern char *sos_sosstrstr(sos_string * s1, sos_string * s2);


/* Read a config file and return a handle to the data */
extern sos_config_t sos_config_read(char *filename);

/* Get a key value constrained by certain semantics */
extern sos_config_value sos_config_getnext(sos_config_t config,
					   sos_config_key key,
					   int direction,
					   int semantic);

/* Erase and destroy the config structure */
extern void sos_config_destroy_list(sos_config_t config);

/* Reload the config file pointed to by config or read filename */
extern sos_config_t sos_config_reload(sos_config_t config, char *filename);

/* Relay data between various file descriptor pairs */
extern int sos_bdrelay(struct sos_bdr_fdpair *(relay[]), int *count, struct sos_bdr_auxinfo *auxinfo);


/* Read a line of data */
extern int sos_readline(FILE * in, FILE * out, sos_string * line, struct sos_readline_t *opts);

/* Readline with timeouts */
extern int sos_readline_timeout(FILE * in, FILE * out, sos_string * line, struct sos_readline_t *opts, struct sigaction *readtimeout, int timeout);


/* Perform SKID authentication */
extern int sos_skid_with_ident(int fd, int SOSmode, char *key, int (*readf) (int, caddr_t, __SIZE_TYPE__), int (*writef) (int, caddr_t, __SIZE_TYPE__));

extern int sos_skid(int fd, char *key, int (*readf) (int, caddr_t, __SIZE_TYPE__), int (*writef) (int, caddr_t, __SIZE_TYPE__));

/* Set predispositions from config file. */
extern int sos_opt_config_predisp(sos_config_t config, char *key);

/* Set an option value (allocating a new structure if necessary ) */
extern int sos_opt_set_value(char *name, int field, int value);

/* Symetrically exchange option preferences until both sides agree to end */
extern int sos_opt_exchange_prefs (int readpeer,
				   int (*rfun)(int fd, caddr_t buf, __SIZE_TYPE__ len),
				   int writepeer,
				   int (*wfun)(int fd, caddr_t buf, __SIZE_TYPE__ len) );

/* Print out the current options strutctures (usefull debugging tool) */
extern void sos_opt_print_opts();

/* Resolve options to their final state (on or off) based peers' preferences */
extern int sos_opt_resolv_negot(int am_winner);

/* High level negotitation routine. Does all of the network work for you */
extern int sos_negotiate_options(int readpeer,
				 int (*rfun)(int fd, caddr_t buf, __SIZE_TYPE__ len),
				 int writepeer,
				 int (*wfun)(int fd, caddr_t buf, __SIZE_TYPE__ len) );

/* Return the state of the a given option name */
extern int sos_opt_get_state(char *name);

/* Toss a coin fairly -- return toss result */
extern int sos_fairtoss(unsigned long *Fairword,
			int readpeer,
		       int (*rfun) (int, caddr_t,  __SIZE_TYPE__ ),
		       int writepeer,
		       int (*wfun) (int, caddr_t, __SIZE_TYPE__ ) );

/* Toss a coin fairly and return win/lose status */
extern int sos_fairtoss_win_lose(int readpeer,
		       int (*rfun) (int, caddr_t,  __SIZE_TYPE__ ),
		       int writepeer,
		       int (*wfun) (int, caddr_t, __SIZE_TYPE__ ) );

/* Initialize a SecureNets database */
extern SOS_Snets sos_InitSecureNets();

/* Delete a SecureNets database */
extern void sos_FreeSecureNets(SOS_Snets old);

/* Add a network information to the database */
extern int sos_AddSecureNets(SOS_Snets snets, struct sos_netmask *mask);

/* Check an address to see if it is valid */
extern int sos_CheckSecureNets(SOS_Snets snets, struct in_addr test);

/* Check a file descriptor to see if it is valid */
extern int sos_CheckSecureNets_fd(SOS_Snets snets, int fd);

/* Create and load a SecureNets from a sos config file */
extern SOS_Snets sos_LoadSecureNets_Config(sos_config_t config, char *key);

/* Create and load a SecureNets from a SecureNets file */
extern SOS_Snets sos_LoadSecureNets_File(char *file);


/* Set the I/O timeout value used in the I/O routines */
extern void sos_set_io_timeout(int timeout);

/* Platform `independent' statfs routines -- cf GNU for the right way!! */
extern int sos_statfs(char *path, struct sos_fsinfo *fsinfo);
extern int sos_fstatfs(int fd, struct sos_fsinfo *fsinfo);
extern sos_fslong_t sos_blocksize_convert(sos_fslong_t num_blocks,
					  sos_fslong_t from,
					  sos_fslong_t to);


/* Initialize for proctitle */
extern int sos_initProcTitle(int argc, char ***argv, 
			     char ***envp, char **program);

/* Set the process title */
extern int sos_setProcTitle(char *fmt, ...);

/* Randomly determine and identity for non-symetric protocols */
extern int sos_alice_bob(int readpeer,
			 int (*rfun) (int, caddr_t,  __SIZE_TYPE__ ),
			 int writepeer,
			 int (*wfun) (int, caddr_t, __SIZE_TYPE__ ) );

/* Size of fd table */
extern int sos_getdtablesize();

/* Terminal functions */
int sos_tty_echooff(int fd, struct termios *termsave);
int sos_tty_echoon(int fd, struct termios *termsave);
int sos_tty_rawoff(int fd, struct termios *termsave);
int sos_tty_rawon(int fd, struct termios *termsave);
int sos_tty_get(int fd, struct termios *termsave);
int sos_tty_set(int fd, struct termios *termnew, struct termios *termsave);

/* Event queue information */
int sos_event_enqueue(dict_h equeue, time_t when, void (*event)(void *args), void *args, void **handle);
int sos_event_check(dict_h equeue);
dict_h sos_event_createq();


/* util.c routines that may disappear RSN!! Keep your eyes open */
/* util.c */
extern int sosBIOwrite(int fd, caddr_t addr, __SIZE_TYPE__ len);
extern int sosBIOread(int fd, caddr_t addr, __SIZE_TYPE__ len);
extern int sosWrite(int fd, caddr_t addr, __SIZE_TYPE__ len);
extern int sosRead(int fd, caddr_t addr, __SIZE_TYPE__ len);
extern int sosRawWrite(int fd, caddr_t addr, __SIZE_TYPE__ len);
extern int sosRawRead(int fd, caddr_t addr, __SIZE_TYPE__ len);
extern void sos_encrypt_on_init_fun();
extern int sos_encrypt_init(char *key,int fd);

#endif				/* _sos_h_ */
