/*  $Id: innd.h,v 1.98 2003/02/13 13:47:51 alexk Exp $
**
**  Many of the data types used here have abbreviations, such as CT
**  for CHANNELTYPE.  Here are a list of the conventions and meanings:
**
**    ART   A news article
**    CHAN  An I/O channel
**    CS    Channel state
**    CT    Channel type
**    FNL   Funnel, into which other feeds pour
**    FT    Feed type -- how a site gets told about new articles
**    ICD   In-core data (primarily the active and sys files)
**    LC    Local NNTP connection-receiving channel
**    CC    Control channel (used by ctlinnd)
**    NC    NNTP client channel
**    NG    Newsgroup
**    NGH   Newgroup hashtable
**    PROC  A process (used to feed a site)
**    PS    Process state
**    RC    Remote NNTP connection-receiving channel
**    RCHAN A channel in "read" state
**    SITE  Something that gets told when we get an article
**    WCHAN A channel in "write" state
**    WIP   Work-In-Progress, keeps track of articles before committed.
*/

#ifndef INND_H
#define INND_H 1

#include "config.h"
#include "portable/time.h"
#include "portable/socket.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <syslog.h> 
#include <sys/stat.h>

#include "inn/buffer.h"
#include "inn/history.h"
#include "inn/messages.h"
#include "inn/timer.h"
#include "libinn.h"
#include "nntp.h"
#include "paths.h"
#include "storage.h"

/* TCL defines EXTERN, so undef it after inclusion since we use it. */
#if DO_TCL
# include <tcl.h>
# undef EXTERN
#endif

BEGIN_DECLS

typedef short	SITEIDX;
#define NOSITE ((SITEIDX) -1)

/*
**  Various constants.
*/

/* Used for storing group subscriptions for feeds. */
#define SUB_DEFAULT		false
#define SUB_NEGATE		'!'
#define SUB_POISON		'@'

/* Special characters for newsfeeds entries. */
#define NF_FIELD_SEP            ':'
#define NF_SUBFIELD_SEP         '/'


/*
**  Server's operating mode.
*/
typedef enum _OPERATINGMODE {
  OMrunning,
  OMpaused,
  OMthrottled
} OPERATINGMODE;


typedef struct _LISTBUFFER {
  char	*   Data;
  int	    DataLength;
  char  **  List;
  int	    ListLength;
} LISTBUFFER;

/*
**  What program to handoff a connection to.
*/
typedef enum _HANDOFF {
  HOnnrpd,
  HOnntpd
} HANDOFF;


/*
**  Header types.
*/
typedef enum _ARTHEADERTYPE {
  HTreq,  /* Drop article if this is missing		  */
  HTobs,  /* obsolete header but keep untouched		  */
  HTstd,  /* Standard optional header			  */
  HTsav	  /* Save header, but may be deleted from article */
} ARTHEADERTYPE;


/*
**  Entry in the header table.
*/
typedef struct _ARTHEADER {
  const char     *  Name;
  ARTHEADERTYPE	    Type;
  int		    Size;  /* Length of Name. */
} ARTHEADER;


/*
**  Header content
*/
typedef struct _HDRCONTENT {
  char  *  Value;   /* don't copy, shows where it begins */
  int	   Length;  /* Length of Value(tailing CRLF is not
			   included.  -1 if duplicated */
} HDRCONTENT;


/*
**  A way to index into the header table.
*/
#define HDR_FOUND(_x)		(hc[(_x)].Length > 0)
#define HDR_PARSE_START(_x)	hc[(_x)].Value[hc[_x].Length] = '\0'
#define HDR(_x)			(hc[(_x)].Value)
/* HDR_LEN does not includes trailing "\r\n" */
#define HDR_LEN(_x)		(hc[(_x)].Length)
#define HDR_PARSE_END(_x)	hc[(_x)].Value[hc[_x].Length] = '\r'


#define HDR__APPROVED		0
#define HDR__CONTROL		1
#define HDR__DATE		2
#define HDR__DISTRIBUTION	3
#define HDR__EXPIRES		4
#define HDR__FROM		5
#define HDR__LINES		6
#define HDR__MESSAGE_ID		7
#define HDR__NEWSGROUPS		8
#define HDR__PATH		9
#define HDR__REPLY_TO		10
#define HDR__SENDER		11
#define HDR__SUBJECT		12
#define HDR__SUPERSEDES		13
#define HDR__BYTES		14
#define HDR__ALSOCONTROL	15
#define HDR__REFERENCES		16
#define HDR__XREF		17
#define HDR__KEYWORDS		18
#define HDR__XTRACE		19
#define HDR__DATERECEIVED	20
#define HDR__POSTED		21
#define HDR__POSTINGVERSION	22
#define HDR__RECEIVED		23
#define HDR__RELAYVERSION	24
#define HDR__NNTPPOSTINGHOST	25
#define HDR__FOLLOWUPTO		26
#define HDR__ORGANIZATION	27
#define HDR__CONTENTTYPE	28
#define HDR__CONTENTBASE	29
#define HDR__CONTENTDISPOSITION	30
#define HDR__XNEWSREADER	31
#define HDR__XMAILER		32
#define HDR__XNEWSPOSTER	33
#define HDR__XCANCELLEDBY	34
#define HDR__XCANCELEDBY	35
#define HDR__CANCELKEY		36
#define HDR__USER_AGENT		37
#define HDR__X_ORIGINAL_MESSAGE_ID		38

#define MAX_ARTHEADER		39

/*
**  Miscellaneous data we want to keep on an article.  All the fields
**  are not always valid.
*/
typedef struct _ARTDATA {
  int		  Body;			/* where body begins in article
					   it indicates offset from bp->Data */
  char	      *   Poster;		/* Sender otherwise From in article */
  char	      *   Replyto;		/* Reply-To otherwise From in article */
  time_t	  Posted;		/* when article posted */
  time_t	  Arrived;		/* when article arrived */
  time_t	  Expires;		/* when article should be expired */
  int		  Lines;		/* number of body lines */
  int		  HeaderLines;		/* number of header lines */
  long		  BytesValue;		/* size of stored article, "\r\n" is
					   counted as 1 byte */
  char		  Bytes[16];		/* generated Bytes header */
  int		  BytesLength;		/* generated Bytes header length */
  char	      *   BytesHeader;		/* where Bytes header begins in
					   received article */
  char		  TokenText[(sizeof(TOKEN) * 2) + 3];
					/* token of stored article */
  LISTBUFFER	  Newsgroups;		/* newsgroup list */
  int		  Groupcount;		/* number of newsgroups */
  int		  Followcount;		/* number of folloup to newsgroups */
  char	      *   Xref;			/* generated Xref header */
  int		  XrefLength;		/* generated Xref header length */
  int		  XrefBufLength;	/* buffer length of generated Xref
					   header */
  LISTBUFFER	  Distribution;		/* distribution list */
  const char  *   Feedsite;		/* who gives me this article */
  int		  FeedsiteLength;	/* length of Feedsite */
  LISTBUFFER	  Path;			/* path name list */
  int		  StoredGroupLength;	/* 1st newsgroup name in Xref */
  char	      *   Replic;		/* replication data */
  int		  ReplicLength;		/* length of Replic */
  HASH	      *   Hash;			/* Message-ID hash */
  struct buffer	  Headers;		/* buffer for headers which will be sent
					   to site */
  struct buffer	  Overview;		/* buffer for overview data */
  int		  CRwithoutLF;		/* counter for '\r' without '\n' */
  int		  LFwithoutCR;		/* counter for '\n' without '\r' */
  int		  CurHeader;		/* where current header starts.
					   this is used for folded header
					   it indicates offset from bp->Data */
  bool		  NullHeader;		/* contains NULL in current header    */
  int		  LastTerminator;	/* where last '.' exists.  only set if
					   it exists at the begining of line
					   it indicates offset from bp->Data */
  int		  LastCR;		/* where last CR exists
					   it indicates offset from bp->Data */
  int		  LastCRLF;		/* where last CRLF exists.
					   indicates where last LF exists
					   it indicates offset from bp->Data */
  HDRCONTENT	  HdrContent[MAX_ARTHEADER];
					/* includes system headers info */
  bool            AddAlias;             /* Whether Pathalias should be added
                                           to this article */
  bool            Hassamepath;          /* Whether this article matches Path */
} ARTDATA;

/*
**  Set of channel types.
*/
typedef enum _CHANNELTYPE {
  CTany,
  CTfree,
  CTremconn,
  CTreject,
  CTnntp,
  CTlocalconn,
  CTcontrol,
  CTfile,
  CTexploder,
  CTprocess
} CHANNELTYPE;


/*
**  The state a channel is in.  Interpretation of this depends on the
**  channel's type.  Used mostly by CTnntp channels.
*/
typedef enum _CHANNELSTATE {
  CSerror,
  CSwaiting,
  CSgetcmd,
  CSgetauth,
  CSwritegoodbye,
  CSwriting,
  CSpaused,
  CSgetheader,
  CSgetbody,
  CSgotarticle,
  CSgotlargearticle,
  CSnoarticle,
  CSeatarticle,
  CSeatcommand,
  CSgetxbatch,
  CScancel
} CHANNELSTATE;

#define SAVE_AMT	10	/* used for eating article/command */

/*
**  I/O channel, the heart of the program.  A channel has input and output
**  buffers, and functions to call when there is input to be read, or when
**  all the output was been written.  Many callback functions take a
**  pointer to a channel, so set up a typedef for that.
*/
#define PRECOMMITCACHESIZE 128
struct _CHANNEL;
typedef void (*innd_callback_t)(struct _CHANNEL *);

typedef struct _CHANNEL {
  CHANNELTYPE	       Type;
  CHANNELSTATE	       State;
  int		       fd;
  bool		       Skip;
  bool		       Streaming;
  bool		       NoResendId;
  bool		       privileged;
  bool		       Nolist;
  unsigned long	       Duplicate;
  unsigned long	       Unwanted_s;
  unsigned long	       Unwanted_f;
  unsigned long	       Unwanted_d;
  unsigned long	       Unwanted_g;
  unsigned long	       Unwanted_u;
  unsigned long	       Unwanted_o;
  float		       Size;
  float		       DuplicateSize;
  unsigned long	       Check;
  unsigned long	       Check_send;
  unsigned long	       Check_deferred;
  unsigned long	       Check_got;
  unsigned long	       Check_cybercan;
  unsigned long	       Takethis;
  unsigned long	       Takethis_Ok;
  unsigned long	       Takethis_Err;
  unsigned long	       Ihave;
  unsigned long	       Ihave_Duplicate;
  unsigned long	       Ihave_Deferred;
  unsigned long	       Ihave_SendIt;
  unsigned long	       Ihave_Cybercan;
  int		       Reported;
  long		       Received;
  long		       Refused;
  long		       Rejected;
  int		       BadWrites;
  int		       BadReads;
  int		       BlockedWrites;
  int		       BadCommands;
  time_t	       LastActive;
  time_t	       NextLog;
  struct sockaddr_storage Address;
  innd_callback_t      Reader;
  innd_callback_t      WriteDone;
  time_t	       Waketime;
  time_t	       Started;
  innd_callback_t      Waker;
  void		    *  Argument;
  void		    *  Event;
  struct buffer	       In;
  struct buffer	       Out;
  bool		       Tracing;
  struct buffer	       Sendid;
  HASH		       CurrentMessageIDHash;
  struct _WIP	    *  PrecommitWIP[PRECOMMITCACHESIZE];
  int		       PrecommitiCachenext;
  int		       XBatchSize;
  int		       LargeArtSize;
  int		       LargeCmdSize;
  int		       ActiveCnx;
  int		       MaxCnx;
  int		       HoldTime;
  time_t	       ArtBeg;
  int		       ArtMax;
  int		       Start;		/* where current cmd/article starts
					   it indicates offset from bp->Data */
  int		       Next;		/* next pointer to read
					   it indicates offset from bp->Data */
  char		       Error[SMBUF];	/* error buffer */
  ARTDATA	       Data;		/* used for processing article */
  struct _CHANNEL      *nextcp;		/* linked list for each incoming site */
} CHANNEL;

#define	DEFAULTNGBOXSIZE	64

/*
**  A newsgroup has a name in different formats, and a high-water count,
**  also kept in different formats.  It also has a list of sites that
**  get this group.
*/
typedef struct _NEWSGROUP {
  long			Start;	     /* Offset into the active file  */
  char		     *  Name;
  int			NameLength;
  ARTNUM		Last;
  ARTNUM		Filenum;     /* File name to use             */
  int			Lastwidth;
  int			PostCount;   /* Have we already put it here? */
  char		     *  LastString;
  char		     *  Rest;	     /* Flags, NOT NULL TERMINATED   */
  SITEIDX		nSites;
  int		     *  Sites;
  SITEIDX		nPoison;
  int		     *  Poison;
  struct _NEWSGROUP  *  Alias;
} NEWSGROUP;


/*
**  How a site is fed.
*/
typedef enum _FEEDTYPE {
  FTerror,
  FTfile,
  FTchannel,
  FTexploder,
  FTfunnel,
  FTlogonly,
  FTprogram
} FEEDTYPE;


/*
**  A site may reject something in its subscription list if it has
**  too many hops, or a bad distribution.
*/
typedef struct _SITE {
  const char  *   Name;
  char	      *   Entry;
  int		  NameLength;
  char	      **  Exclusions;
  char	      **  Distributions;
  char	      **  Patterns;
  bool		  Poison;
  bool		  PoisonEntry;
  bool		  Sendit;
  bool		  Seenit;
  bool		  IgnoreControl;
  bool		  DistRequired;
  bool		  IgnorePath;
  bool		  ControlOnly;
  bool		  DontWantNonExist;
  bool		  NeedOverviewCreation;
  bool		  FeedwithoutOriginator;
  bool		  DropFiltered;
  int		  Hops;
  int		  Groupcount;
  int		  Followcount;
  int		  Crosscount;
  FEEDTYPE	  Type;
  NEWSGROUP   *   ng;
  bool		  Spooling;
  char	      *   SpoolName;
  bool		  Working;
  long		  StartWriting;
  long		  StopWriting;
  long		  StartSpooling;
  char	      *   Param;
  char		  FileFlags[FEED_MAXFLAGS + 1];
  long		  MaxSize;
  long		  MinSize;
  int		  Nice;
  CHANNEL     *   Channel;
  bool		  IsMaster;
  int		  Master;
  int		  Funnel;
  bool		  FNLwantsnames;
  struct buffer	  FNLnames;
  int		  Process;
  pid_t		  pid;
  long		  Flushpoint;
  struct buffer	  Buffer;
  bool		  Buffered;
  char	      **  Originator;
  int		  Next;
  int		  Prev;
} SITE;


/*
**  A process is something we start up to send articles.
*/
typedef enum _PROCSTATE {
  PSfree,
  PSrunning,
  PSdead
} PROCSTATE;


/*
**  We track our children and collect them synchronously.
*/
typedef struct _PROCESS {
  PROCSTATE	State;
  pid_t		Pid;
  int		Status;
  time_t	Started;
  time_t	Collected;
  int		Site;
} PROCESS;

/*
**  A work in progress entry, an article that we've been offered but haven't
**  received yet.
*/
typedef struct _WIP {
  HASH		MessageID;	/* Hash of the messageid.  Doing it like
				   this saves us from haveing to allocate
				   and deallocate memory a lot, and also
				   means lookups are faster. */ 
  time_t	Timestamp;	/* Time we last looked at this MessageID */
  CHANNEL	*Chan;		/* Channel that this message is associated
				   with */
  struct _WIP	*Next;		/* Next item in this bucket */
} WIP;

/*
**  Supported timers.  If you add new timers to this list, also add them to
**  the list of tags in chan.c.
*/
enum timer {
    TMR_IDLE = TMR_APPLICATION, /* Server is completely idle. */
    TMR_ARTCLEAN,               /* Analyzing an incoming article. */
    TMR_ARTWRITE,               /* Writing an article. */
    TMR_ARTCNCL,                /* Processing a cancel message. */
    TMR_SITESEND,               /* Sending an article to feeds. */
    TMR_OVERV,                  /* Generating overview information. */
    TMR_PERL,                   /* Perl filter. */
    TMR_PYTHON,                 /* Python filter. */
    TMR_NNTPREAD,               /* Reading NNTP data from the network. */
    TMR_ARTPARSE,               /* Parsing an article. */
    TMR_ARTLOG,                 /* Logging article disposition. */
    TMR_DATAMOVE,               /* Moving data. */
    TMR_MAX
};



/*
**  In-line macros for efficiency.
**
**  Set or append data to a channel's output buffer.
*/
#define WCHANset(cp, p, l)      buffer_set(&(cp)->Out, (p), (l))
#define WCHANappend(cp, p, l)   buffer_append(&(cp)->Out, (p), (l))

/*
**  Mark that an I/O error occurred, and block if we got too many.
*/
#define IOError(WHEN, e)                    \
  do {                                      \
    if (--ErrorCount <= 0 || (e) == ENOSPC) \
      ThrottleIOError(WHEN);                \
  } while (0)


/*
**  Global data.
**
** Do not change "extern" to "EXTERN" in the Global data.  The ones
** marked with "extern" are initialized in innd.c.  The ones marked
** with "EXTERN" are not explicitly initialized in innd.c.
*/
#if defined(DEFINE_DATA)
# define EXTERN		/* NULL */
#else
# define EXTERN		extern
#endif
extern const ARTHEADER	ARTheaders[MAX_ARTHEADER];
extern bool		BufferedLogs;
EXTERN bool		AnyIncoming;
extern bool		Debug;
EXTERN bool		ICDneedsetup;
EXTERN bool		NeedHeaders;
EXTERN bool		NeedOverview;
EXTERN bool		NeedPath;
EXTERN bool		NeedStoredGroup;
EXTERN bool		NeedReplicdata;
extern bool		NNRPTracing;
extern bool		StreamingOff;
extern bool		Tracing;
EXTERN struct buffer	Path;
EXTERN struct buffer	Pathalias;
EXTERN char	     *  ModeReason;	/* NNTP reject message   */
EXTERN char	     *  NNRPReason;	/* NNRP reject message   */
EXTERN char	     *  Reservation;	/* Reserved lock message */
EXTERN char	     *  RejectReason;	/* NNTP reject message   */
EXTERN FILE	     *  Errlog;
EXTERN FILE	     *  Log;
extern char		LogName[];
extern int		ErrorCount;
EXTERN int		ICDactivedirty;
EXTERN int		MaxOutgoing;
EXTERN int		nGroups;
EXTERN SITEIDX		nSites;
EXTERN int		PROCneedscan;
EXTERN NEWSGROUP    **	GroupPointers;
EXTERN NEWSGROUP    *	Groups;
extern OPERATINGMODE	Mode;
EXTERN sig_atomic_t	GotTerminate;
EXTERN SITE	    *	Sites;
EXTERN SITE		ME;
EXTERN struct timeval	TimeOut;
EXTERN TIMEINFO		Now;		/* Reasonably accurate time     */
EXTERN bool		ThrottledbyIOError;
EXTERN char	    *   NCgreeting;
EXTERN struct history   *History;

/*
** Table size for limiting incoming connects.  Do not change the table
** size unless you look at the code manipulating it in rc.c.
*/
#define REMOTETABLESIZE	128

/*
** Setup the default values.  The REMOTETIMER being zero turns off the
** code to limit incoming connects.
*/
#define REMOTELIMIT	2
#define REMOTETIMER	0
#define REMOTETOTAL	60
#define REJECT_TIMEOUT	10
extern int		RemoteLimit;	/* Per host limit. */
extern time_t		RemoteTimer;	/* How long to remember connects. */
extern int		RemoteTotal;	/* Total limit. */


/*
**  Function declarations.
*/
extern void	        InndHisOpen(void);
extern void             InndHisClose(void);
extern bool             InndHisWrite(const char *key, time_t arrived,
				     time_t posted, time_t expires,
				     TOKEN *token);
extern bool             InndHisRemember(const char *key);
extern void             InndHisLogStats(void);
extern bool		FormatLong(char *p, unsigned long value, int width);
extern bool		NeedShell(char *p, const char **av, const char **end);
extern char	    **	CommaSplit(char *text);
extern void		SetupListBuffer(int size, LISTBUFFER *list);
extern char         *	MaxLength(const char *p, const char *q);
extern pid_t		Spawn(int niceval, int fd0, int fd1, int fd2,
			      char * const av[]);
extern void		CleanupAndExit(int x, const char *why);
extern void		FileGlue(char *p, const char *n1, char c, const char *n2);
extern void		JustCleanup(void);
extern void		ThrottleIOError(const char *when);
extern void		ThrottleNoMatchError(void);
extern void		ReopenLog(FILE *F);
extern void		xchown(char *p);

extern bool		ARTidok(const char *MessageID);
extern bool		ARTreadschema(void);
extern const char   *	ARTreadarticle(char *files);
extern char	    *   ARTreadheader(char *files);
extern bool		ARTpost(CHANNEL *cp);
extern void		ARTcancel(const ARTDATA *Data,
				  const char *MessageID, bool Trusted);
extern void		ARTclose(void);
extern void		ARTsetup(void);
extern void		ARTprepare(CHANNEL *cp);
extern void		ARTparse(CHANNEL *cp);

extern bool		CHANsleeping(CHANNEL *cp);
extern CHANNEL      *	CHANcreate(int fd, CHANNELTYPE Type,
				   CHANNELSTATE State,
				   innd_callback_t Reader,
				   innd_callback_t WriteDone);
extern CHANNEL      *	CHANiter(int *cp, CHANNELTYPE Type);
extern CHANNEL      *	CHANfromdescriptor(int fd);
extern char	    *   CHANname(const CHANNEL *cp);
extern int		CHANreadtext(CHANNEL *cp);
extern void		CHANclose(CHANNEL *cp, const char *name);
extern void		CHANreadloop(void);
extern void		CHANsetup(int i);
extern void		CHANshutdown(void);
extern void		CHANtracing(CHANNEL *cp, bool Flag);
extern void		CHANsetActiveCnx(CHANNEL *cp);

extern void		RCHANadd(CHANNEL *cp);
extern void		RCHANremove(CHANNEL *cp);

extern void		SCHANadd(CHANNEL *cp, time_t Waketime, void *Event,
				 innd_callback_t Waker, void *Argument);
extern void		SCHANremove(CHANNEL *cp);
extern void		SCHANwakeup(void *Event);

extern bool		WCHANflush(CHANNEL *cp);
extern void		WCHANadd(CHANNEL *cp);
extern void		WCHANremove(CHANNEL *cp);
extern void		WCHANsetfrombuffer(CHANNEL *cp, struct buffer *bp);

extern void		CCcopyargv(char *av[]);
extern const char   *	CCaddhist(char *av[]);
extern const char   *	CCblock(OPERATINGMODE NewMode, char *reason);
extern const char   *	CCcancel(char *av[]);
extern const char   *	CCcheckfile(char *av[]);

extern bool		ICDnewgroup(char *Name, char *Rest);
extern char	    *   ICDreadactive(char **endp);
extern bool		ICDchangegroup(NEWSGROUP *ngp, char *Rest);
extern void		ICDclose(void);
extern bool		ICDrenumberactive(void);
extern bool		ICDrmgroup(NEWSGROUP *ngp);
extern void		ICDsetup(bool StartSites);
extern void		ICDwrite(void);
extern void		ICDwriteactive(void);

extern void		CCclose(void);
extern void		CCsetup(void);

extern void             KEYgenerate(HDRCONTENT *, const char *body,
                                    const char *orig, size_t length);

extern void		LCclose(void);
extern void		LCsetup(void);

extern int		NGsplit(char *p, int size, LISTBUFFER *List);
extern NEWSGROUP    *	NGfind(const char *Name);
extern void		NGclose(void);
extern CHANNEL	    *	NCcreate(int fd, bool MustAuthorize, bool IsLocal);
extern void		NGparsefile(void);
extern bool		NGrenumber(NEWSGROUP *ngp);
extern bool		NGlowmark(NEWSGROUP *ngp, long lomark);

extern void		NCclearwip(CHANNEL *cp);
extern void		NCclose(void);
extern void		NCsetup(void);
extern void		NCwritereply(CHANNEL *cp, const char *text);
extern void		NCwriteshutdown(CHANNEL *cp, const char *text);

/* perl.c */
extern char	    *	PLartfilter(const ARTDATA *Data, char *artBody, long artLen, int lines);
extern char	    *   PLmidfilter(char *messageID);
extern void		PLmode(OPERATINGMODE mode, OPERATINGMODE NewMode,
			       char *reason);
extern char         *   PLstats(void);
extern void		PLxsinit(void);

extern int		PROCwatch(pid_t pid, int site);
extern void		PROCunwatch(int process);
/* extern void		PROCclose(bool Quickly); */
extern void		PROCscan(void);
extern void		PROCsetup(int i);

extern int		RClimit(CHANNEL *cp);
extern bool		RCnolimit(CHANNEL *cp);
extern bool		RCauthorized(CHANNEL *cp, char *pass);
extern int		RCcanpost(CHANNEL *cp, char *group);
extern char	    *	RChostname(const CHANNEL *cp);
extern char	    *	RClabelname(CHANNEL *cp);
extern void		RCclose(void);
extern void		RChandoff(int fd, HANDOFF h);
extern void		RCreadlist(void);
extern void		RCsetup(int i);

extern bool		SITEfunnelpatch(void);
extern bool		SITEsetup(SITE *sp);
extern bool		SITEwantsgroup(SITE *sp, char *name);
extern bool		SITEpoisongroup(SITE *sp, char *name);
extern char	    **	SITEreadfile(const bool ReadOnly);
extern SITE	    *	SITEfind(const char *p);
extern SITE	    *	SITEfindnext(const char *p, SITE *sp);
extern const char   *	SITEparseone(char *Entry, SITE *sp,
				     char *subbed, char *poison);
extern void		SITEchanclose(CHANNEL *cp);
extern void		SITEdrop(SITE *sp);
extern void		SITEflush(SITE *sp, const bool Restart);
extern void		SITEflushall(const bool Restart);
extern void		SITEforward(SITE *sp, const char *text);
extern void		SITEfree(SITE *sp);
extern void		SITEinfo(struct buffer *bp, SITE *sp, bool Verbose);
extern void		SITEparsefile(bool StartSite);
extern void		SITEprocdied(SITE *sp, int process, PROCESS *pp);
extern void		SITEsend(SITE *sp, ARTDATA *Data);
extern void		SITEwrite(SITE *sp, const char *text);

extern void		STATUSinit(void);
extern void		STATUSmainloophook(void);

extern void		WIPsetup(void);
extern WIP	    *	WIPnew(const char *messageid, CHANNEL *cp);
extern void		WIPprecomfree(CHANNEL *cp);
extern void		WIPfree(WIP *wp);
extern bool		WIPinprogress(const char *msgid, CHANNEL *cp,
				      bool Add);
extern WIP	    *	WIPbyid(const char *mesageid);
extern WIP	    *	WIPbyhash(const HASH hash);

/*
**  TCL globals and functions
*/
#if DO_TCL
extern Tcl_Interp   *	TCLInterpreter;
extern bool		TCLFilterActive;
extern struct buffer *	TCLCurrArticle;
extern ARTDATA	    *	TCLCurrData;

extern void		TCLfilter(bool value);
extern void		TCLreadfilter(void);
extern void		TCLsetup(void);
extern void		TCLclose(void);
#endif /* DO_TCL */

/*
**  Python globals and functions
*/
#if DO_PYTHON
extern bool		PythonFilterActive;

void			PYfilter(bool value);
extern const char   *	PYcontrol(char **av);
extern int		PYreadfilter(void);
extern char	    *	PYartfilter(const ARTDATA *Data, char *artBody, long artLen, int lines);
extern char	    *	PYmidfilter(char *messageID, int msglen);
extern void		PYmode(OPERATINGMODE mode, OPERATINGMODE newmode,
			       char *reason);
extern void		PYsetup(void);
extern void		PYclose(void);
#endif /* DO_PYTHON */

END_DECLS

#endif /* INND_H */
