/*
 * This file is copyrighted material. See the file COPYING for licensing
 * conditions.
 */

/* $Id: leafnode.h,v 1.93 2005/06/08 14:06:15 emma Exp $ */

#ifndef LEAFNODE_H
#define LEAFNODE_H

#include "critmem.h"

/* I wish the world were a happy place */
#ifndef TRUE
#define TRUE (1)
#endif
#ifndef FALSE
#define FALSE (0)
#endif

#define PLURAL(no) (((no) == 1) ? "" : "s")

/* limits.h may contain PATH_MAX but shall not if the system has variable
 * length limits here */
#include <limits.h>
#ifndef PATH_MAX
/* just some random limit - we'll use this as a starting point
 * for dynamically growing memory only */
#define PATH_MAX 4096
#endif

#define PORTFILENAMECSET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-"

#include <pcre.h>
#include <stdarg.h>		/* va_list */
#include <stdio.h>		/* FILE * */
#include <setjmp.h>		/* sigjmp_buf */
#include "system.h"		/* time.h */

#include "config.h"		/* FreeSGI barfs on #ifdef HAVE_CONFIG_H */

#ifdef HAVE_AP_CONFIG_H
#define AP_CONFIG_H
#endif

#ifdef HAVE_ERRNO_H
#include <errno.h>
#include <sys/errno.h>
#endif
#ifndef HAVE_ERRNO_H
extern int errno;
#endif				/* HAVE_ERRNO_H */

/* from strdup.c */
#ifndef HAVE_STRDUP
char *strdup(const char *);
#endif

/* from snprintf.c */
#ifndef HAVE_WORKING_SNPRINTF
int ln_snprintf(char *str, size_t n, const char *format, ...)
#ifdef __GNUC__
    __attribute__ ((format(printf, 3, 4)))
#endif
    ;
int ln_vsnprintf(char *str, size_t n, const char *format, va_list ap);
#define snprintf ln_snprintf
#define vsnprintf ln_vsnprintf
#endif

int xsnprintf(/*@out@*/ char *str, size_t n, const char *format, ...)
#ifdef __GNUC__
    __attribute__ ((format(printf, 3, 4)))
#endif
    ;

/* map LOG_NEWS onto LOG_DAEMON where the former doesn't exist */
#include <syslog.h>
#if !defined( LOG_NEWS )
#define LOG_NEWS LOG_DAEMON
#endif
/* define LOG_CONS if missing */
#if !defined( LOG_CONS )
#define LOG_CONS 0		/* if it isn't supported, make do without */
#endif

#define SECONDS_PER_DAY ( 24L * 60 * 60 )

/* Limit on the number of message bodies marked for download per group. */
#define BODY_DOWNLOAD_LIMIT 2048

/* initialize global variables */
int initvars(char *progname);

/* converts a message-id to a file name, the return value points into
   a static array */
#define LOOKUP_FREE ((const char *)-2)
/*@dependent@*/ const char *lookup(const char *msgid);

/*@dependent@*/
char *getaline(FILE * f);	/* reads one line, regardless of length */
/*@dependent@*/
char *mgetaline(FILE * f);      /* dito, with timeout */
void mgetaline_settimeout(unsigned int);      /* set timeout for mgetaline */
extern sigjmp_buf timeout;
extern RETSIGTYPE timer(int sig);

/* changes (and optionally creates) directory */
int chdirgroup(const char *group, int creatdir);

/*
 * newsgroup management
 */
struct newsgroup {
    unsigned long first;
    unsigned long last;
    char *name;
    char *desc;
    time_t age;
};

int isinteresting(const char *groupname);
void insertgroup(const char *name, long unsigned first, long unsigned last,
		 time_t date);
extern void changegroupdesc(const char *groupname, const char *description);
extern void newgroupdesc(const char *groupname, const char *description);
void mergegroups(void);
/*@null@*//*@dependent@*/
struct newsgroup *xfindgroup(struct newsgroup *active, const char *name,
	unsigned long size);
/*@null@*//*@dependent@*/
struct newsgroup *findgroup(const char *name);
void readactive(void);
int writeactive(void);
void fakeactive(void);
void freeactive(/*@null@*/ struct newsgroup *act);
extern char *activeread(void);
extern int killactiveread(void);

extern size_t activesize;
/*@null@*/ extern struct newsgroup *active;
extern size_t oldactivesize;
/*@null@*/ extern struct newsgroup *oldactive;

/* translation from message-id to article number, used in fetch and expire */

void clearidtree(void);
void insertmsgid( /*@unique@*/ const char *msgid);
int findmsgid(const char *msgid);
typedef int (*tmihook)(const char *);
int traverseidtree(tmihook h);

/* -----------here starts the new stuff-----------------*/

/*
 * a linear list of strings
 */
struct stringlist {
    struct stringlist *next;
    char string[1];
};

void
prependtolist(struct stringlist **list, /*@unique@*/ const char *newentry);

/*@null@*//*@dependent@*/
struct stringlist **lfindinlist(struct stringlist **haystack, char *needle, size_t len);
	/* find a stringlist element by doing a linear search */
char *findinlist(struct stringlist *haystack, char *needle);
	/* find a string in a stringlist by doing a linear search */
void freelist( /*@only@*/ struct stringlist *list);
	/* free memory occupied by a stringlist */

/*
 * filterfile.c -- PCRE filtering of articles
 */
void readfilter(char *filterfile);
void freefilter(void);
int dofilter(char *h);

/*
 * artutil.c -- handling article files
 */
void store(const char *filename,
	   FILE * filehandle, const char *newsgroups, const char *msgid);

/*
 * find a certain header in an article and return it
 */
/*@null@*//*@only@*/ char *getheader(const char *filename, const char *header);
/*@null@*//*@only@*/ char *fgetheader(FILE * f, const char *header);

/*
 * the strings in config.c
 */
extern const char *spooldir;
extern const char *sysconfdir;
extern const char *version;
extern const char *lockfile;

/*
 * global variables from config file. These are defined in configutil.c
 */
struct expire_entry {
    struct expire_entry *next;
    char *group;
    time_t xtime;
    int days;
};

struct server {
    struct server *next;
    char *name;			/* Servername */
    char *username;
    char *password;
    pcre *group_pcre;
    unsigned int port;
    int descriptions;		/* download descriptions as well */
    int timeout;		/* timeout in seconds before we give up */
    int nopost;			/* if set, do not try to post to this server */
    int noread;			/* if set, do not try to fetch articles from
				   this server */
    int updateactive;		/* update the active file of this server */
    int post_anygroup;		/* if set, do not check if the group is on the
				   server, but just post */
    int noxover;		/* if set, use XHDR for overview */
    int only_groups_match_all;	/* if set, any unmatched group (refer to
				   group_pcre) prevents the post */
};

extern int date_is_evil;	/* skip DATE check on servers known bad */
extern int stat_is_evil;	/* use HEAD instead of STAT to figure if a
				   posting is available upstream, workaround for broken NewsCache */
extern time_t expire;		/* articles not touched since this time get deleted */
extern int expiredays;
extern struct expire_entry *expire_base;
			/* expire for certain groups */
extern unsigned long artlimit;		/* max # of articles to read per group in one go */
extern unsigned long initiallimit;
			/* max # of articles to read at first time */
extern long crosspostlimit;
			/* crossposting limit, to reduce spam */
extern int delaybody;		/* delay download of message body */
extern int db_situ;		/* delaybody: keep original article number */
extern int debugmode;		/* log lots of stuff via syslog */
extern int create_all_links;
			/* store articles even in uninteresting groups */
extern int maxage;		/* max age of articles */
extern long maxlines;		/* max length of articles in lines */
extern long minlines;		/* min length of articles in lines */
extern unsigned long maxbytes;	/* max length of articles in bytes */
extern int timeout_short;	/* don't fetch groups that have been
				   accidentally accessed after that many days */
extern int timeout_long;	/* don't fetch groups that have been accessed
				   that many days */
extern int timeout_active;	/* reread active file after that many days */
extern int timeout_client;	/* activity timeout for clients in seconds */
extern int timeout_fetchnews;	/* response deadline for upstream in seconds */
extern int clamp_maxage;	/* limit maxage to applicable group/global expire? */
extern int article_despite_filter;  /* request and discard body if filterfile is defined, for high-latency, high-throughput links */
extern char *filterfile;	/* filename where filter resides */
extern struct server *servers;	/* list of servers to use */
extern int allowstrangers;	/* if addresses not local to our links
				   are allowed to connect */
extern int allow_8bit_headers;	/* if 8bit junk in headers is allowed */
extern char *newsadmin;		/* address of news administrator, default: news@%s with %s = fqdn */
extern unsigned long timeout_lock; /* lock file timeout */

/*
 * other global variables
 */
#define SIZE_lineout 1024
extern char last_command[SIZE_lineout + 1];
extern char lineout[SIZE_lineout + 1];

/* defined in nntputil.c */
extern /*@relnull@*/ /*@dependent@*/ FILE *nntpin;
extern /*@relnull@*/ /*@dependent@*/ FILE *nntpout;

#define SIZE_s (8192)
#define FQDNLEN 255
extern char fqdn[FQDNLEN + 1];	/* my name, and my naming myself */

extern int verbose;		/* verbosity level, for fetch and texpire */
extern int debug;		/* debug level */

/*
 * misc prototypes
 */
int try_lock(unsigned long);
int handover_lock(pid_t);
void putaline(void);
void retry(void);
void readexpire(void);
int readconfig(int logtostderr);
void freeexpire(void);
void freeservers(void);
void freeconfig(void);
void lowercase(char *string);
int ngmatch(const char *pattern, const char *string);
void overrun(void);
void replaceinlist(struct stringlist **haystack, char *needle, size_t len);
time_t lookup_expire(char *group);
int lookup_expiredays(char *group);
int log_unlink(const char *f, int ignore_enoent);

/* int rename(const char *old, const char *new); */
				/* to avoid barfing of Digital Unix */

/*
 * stuff from nntputil.c
 */
int authenticate(const struct server*);	/* authenticate ourselves at a server */
/*@dependent@*//*@null@*/
char *lastreply(void);		/* last line frpm nntpreply */
int nntpreply(const struct server*);	/* decode an NNTP reply number */
int nntpconnect(const struct server *upstream);
				/* connect to upstream server */
void nntpdisconnect(void);	/* disconnect from upstream server */
void nntpquit(void);		/* send QUIT, then disconnect from upstream server */
void freelastreply(void);

/*@dependent@*/
const char *rfctime(void);	/* An rfc type date */

int safe_mkstemp(char *);	/* permission safe mkstemp wrapper */
/* from syslog.c */
void myopenlog(const char *ident);

/* from mkstemp.c */
#ifndef HAVE_MKSTEMP
int mkstemp(char *);
#endif

/* from getline.c */
#ifndef HAVE_GETLINE
ssize_t getline(char **, size_t *, FILE *);	/* fgets replacement */
#endif
void freegetaline(void);

#ifndef HAVE_TIMEGM
time_t timegm(struct tm *tm);
#endif

/* from mysetvbuf.c */
int mysetvbuf(FILE *stream, char *buf, int mode, size_t size);

/* from wildmat.c */
int wildmat(const char *, const char *);

/* from mysetvbuf.c */
int mysetvbuf(FILE *stream, char *buf, int mode , size_t size);

/* from getfoldedline.c */
/*@null@*/ /*@only@*/
char *getfoldedline(FILE * f, char *(*reader)(FILE *));
/* reads one line, regardless of length, returns malloc()ed string! */

/* from writes.c (ln-2) */
ssize_t writes(int fd, const char *string);

void fixxover(void);

/* from grouplist.c */
/*@null@*/ struct stringlist *get_grouplist(void);

/* checkpeerlocal.c */
int checkpeerlocal(int sock);

/* pcre_extract.c */
int pcre_extract(const char *input, const char *pattern, /*@out@*/ char **output, size_t num);
void pcre_extract_free(char **vec, int count);
size_t xstrlcpy(/*@out@*/ char *dst, const char *src, size_t size);

/* xoverutil.c */
struct xoverinfo {
    char *text;
    int exists;
};

/*@null@*/ extern struct xoverinfo *xoverinfo;
extern unsigned long xfirst;
extern unsigned long xlast;

int getxover(void);		/* set xoverinfo, return 0 on error, nonzero else */

int legalxoverline(const char *xover, /*@out@*/ const char **errmsg);
void freexover(void);

/* agetcwd.c */
int agetcwd(/*@out@*/ char **buf, /*@out@*/ size_t *capa);

#ifdef CHECKGROUPORDER
void checkgrouporder(void);
#endif /* CHECKGROUPORDER */

#define SKIPLWS(p) while (*(p) && isspace((unsigned char) *(p))) { (p)++; }
#endif				/* #ifndef LEAFNODE_H */


syntax highlighted by Code2HTML, v. 0.9.1