1 /*
2  * This file is copyrighted material. See the file COPYING for licensing
3  * conditions.
4  */
5 
6 /* $Id: leafnode.h,v 1.95 2008/08/07 20:19:41 emma Exp $ */
7 
8 #ifndef LEAFNODE_H
9 #define LEAFNODE_H
10 
11 #include "config.h"
12 
13 /* newer glibc needs this so it doesn't complain about _BSD_SOURCE */
14 #ifndef _DEFAULT_SOURCE
15 #define _DEFAULT_SOURCE
16 #endif
17 
18 #ifndef _GNU_SOURCE
19 #define _GNU_SOURCE
20 #endif
21 #ifndef _BSD_SOURCE
22 #define _BSD_SOURCE
23 #endif
24 
25 #include "critmem.h"
26 
27 /* I wish the world were a happy place */
28 #ifndef TRUE
29 #define TRUE (1)
30 #endif
31 #ifndef FALSE
32 #define FALSE (0)
33 #endif
34 
35 #define PLURAL(no) (((no) == 1) ? "" : "s")
36 
37 /* limits.h may contain PATH_MAX but shall not if the system has variable
38  * length limits here */
39 #include <limits.h>
40 #ifndef PATH_MAX
41 /* just some random limit - we'll use this as a starting point
42  * for dynamically growing memory only */
43 #define PATH_MAX 4096
44 #endif
45 
46 #define PORTFILENAMECSET "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-"
47 
48 #include <pcre.h>
49 #include <stdarg.h>		/* va_list */
50 #include <stdio.h>		/* FILE * */
51 #include <setjmp.h>		/* sigjmp_buf */
52 #include "system.h"		/* time.h */
53 
54 #ifdef HAVE_AP_CONFIG_H
55 #define AP_CONFIG_H
56 #endif
57 
58 #include <errno.h>
59 
60 /* from strdup.c */
61 #ifndef HAVE_STRDUP
62 char *strdup(const char *);
63 #endif
64 
65 /* from snprintf.c */
66 #ifndef HAVE_WORKING_SNPRINTF
67 int ln_snprintf(char *str, size_t n, const char *format, ...)
68 #ifdef __GNUC__
69     __attribute__ ((format(printf, 3, 4)))
70 #endif
71     ;
72 int ln_vsnprintf(char *str, size_t n, const char *format, va_list ap);
73 #define snprintf ln_snprintf
74 #define vsnprintf ln_vsnprintf
75 #endif
76 
77 int xsnprintf(/*@out@*/ char *str, size_t n, const char *format, ...)
78 #ifdef __GNUC__
79     __attribute__ ((format(printf, 3, 4)))
80 #endif
81     ;
82 
83 /* map LOG_NEWS onto LOG_DAEMON where the former doesn't exist */
84 #include <syslog.h>
85 #if !defined( LOG_NEWS )
86 #define LOG_NEWS LOG_DAEMON
87 #endif
88 /* define LOG_CONS if missing */
89 #if !defined( LOG_CONS )
90 #define LOG_CONS 0		/* if it isn't supported, make do without */
91 #endif
92 
93 #define SECONDS_PER_DAY ( 24L * 60 * 60 )
94 
95 /* Limit on the number of message bodies marked for download per group. */
96 #define BODY_DOWNLOAD_LIMIT 2048
97 
98 /* initialize global variables */
99 int initvars(char *progname);
100 
101 /* converts a message-id to a file name, the return value points into
102    a static array */
103 #define LOOKUP_FREE ((const char *)-2)
104 /*@dependent@*/ const char *lookup(const char *msgid);
105 
106 /*@dependent@*/
107 char *getaline(FILE * f);	/* reads one line, regardless of length */
108 /*@dependent@*/
109 char *mgetaline(FILE * f);      /* dito, with timeout */
110 void mgetaline_settimeout(unsigned int);      /* set timeout for mgetaline */
111 extern sigjmp_buf timeout;
112 extern void timer(int sig);
113 
114 /* changes (and optionally creates) directory */
115 int chdirgroup(const char *group, int creatdir);
116 
117 /*
118  * newsgroup management
119  */
120 struct newsgroup {
121     unsigned long first;
122     unsigned long last;
123     char *name;
124     char *desc;
125     time_t age;
126 };
127 
128 int isinteresting(const char *groupname);
129 void insertgroup(const char *name, long unsigned first, long unsigned last,
130 		 time_t date);
131 extern void changegroupdesc(const char *groupname, const char *description);
132 extern void newgroupdesc(const char *groupname, const char *description);
133 void mergegroups(void);
134 /*@null@*//*@dependent@*/
135 struct newsgroup *xfindgroup(struct newsgroup *active, const char *name,
136 	unsigned long size);
137 /*@null@*//*@dependent@*/
138 struct newsgroup *findgroup(const char *name);
139 void readactive(void);
140 int writeactive(void);
141 void fakeactive(void);
142 void freeactive(/*@null@*/ struct newsgroup *act);
143 extern char *activeread(void);
144 extern int killactiveread(void);
145 
146 extern size_t activesize;
147 /*@null@*/ extern struct newsgroup *active;
148 extern size_t oldactivesize;
149 /*@null@*/ extern struct newsgroup *oldactive;
150 
151 /* translation from message-id to article number, used in fetch and expire */
152 
153 void clearidtree(void);
154 void insertmsgid( /*@unique@*/ const char *msgid);
155 int findmsgid(const char *msgid);
156 typedef int (*tmihook)(const char *);
157 int traverseidtree(tmihook h);
158 
159 /* -----------here starts the new stuff-----------------*/
160 
161 /*
162  * a linear list of strings
163  */
164 struct stringlist {
165     struct stringlist *next;
166     char string[1];
167 };
168 
169 void
170 prependtolist(struct stringlist **list, /*@unique@*/ const char *newentry);
171 
172 /*@null@*//*@dependent@*/
173 struct stringlist **lfindinlist(struct stringlist **haystack, char *needle, size_t len);
174 	/* find a stringlist element by doing a linear search */
175 char *findinlist(struct stringlist *haystack, char *needle);
176 	/* find a string in a stringlist by doing a linear search */
177 void freelist( /*@only@*/ struct stringlist *list);
178 	/* free memory occupied by a stringlist */
179 
180 /*
181  * filterfile.c -- PCRE filtering of articles
182  */
183 void readfilter(char *filterfile);
184 void freefilter(void);
185 int dofilter(char *h);
186 
187 /*
188  * artutil.c -- handling article files
189  */
190 void store(const char *filename,
191 	   FILE * filehandle, const char *newsgroups, const char *msgid);
192 
193 /*
194  * find a certain header in an article and return it
195  */
196 /*@null@*//*@only@*/ char *getheader(const char *filename, const char *header);
197 /*@null@*//*@only@*/ char *fgetheader(FILE * f, const char *header);
198 
199 /*
200  * the strings in config.c
201  */
202 extern const char *spooldir;
203 extern const char *sysconfdir;
204 extern const char *version;
205 extern const char *lockfile;
206 
207 /*
208  * global variables from config file. These are defined in configutil.c
209  */
210 struct expire_entry {
211     struct expire_entry *next;
212     char *group;
213     time_t xtime;
214     int days;
215 };
216 
217 struct server {
218     struct server *next;
219     char *name;			/* Servername */
220     char *username;
221     char *password;
222     pcre *group_pcre;
223     unsigned int port;
224     int descriptions;		/* download descriptions as well */
225     int timeout;		/* timeout in seconds before we give up */
226     int nopost;			/* if set, do not try to post to this server */
227     int noread;			/* if set, do not try to fetch articles from
228 				   this server */
229     int updateactive;		/* update the active file of this server, BITFIELD: 1 = from command line, 2 = automatically set */
230     int post_anygroup;		/* if set, do not check if the group is on the
231 				   server, but just post */
232     int noxover;		/* if set, use XHDR for overview */
233     int only_groups_match_all;	/* if set, any unmatched group (refer to
234 				   group_pcre) prevents the post */
235 };
236 
237 extern int date_is_evil;	/* skip DATE check on servers known bad */
238 extern int stat_is_evil;	/* use HEAD instead of STAT to figure if a
239 				   posting is available upstream, workaround for broken NewsCache */
240 extern time_t expire;		/* articles not touched since this time get deleted */
241 extern int expiredays;
242 extern struct expire_entry *expire_base;
243 			/* expire for certain groups */
244 extern unsigned long artlimit;		/* max # of articles to read per group in one go */
245 extern unsigned long initiallimit;
246 			/* max # of articles to read at first time */
247 extern long crosspostlimit;
248 			/* crossposting limit, to reduce spam */
249 extern int delaybody;		/* delay download of message body */
250 extern int db_situ;		/* delaybody: keep original article number */
251 extern int debugmode;		/* log lots of stuff via syslog */
252 extern int create_all_links;
253 			/* store articles even in uninteresting groups */
254 extern int maxage;		/* max age of articles */
255 extern long maxlines;		/* max length of articles in lines */
256 extern long minlines;		/* min length of articles in lines */
257 extern unsigned long maxbytes;	/* max length of articles in bytes */
258 extern int timeout_short;	/* don't fetch groups that have been
259 				   accidentally accessed after that many days */
260 extern int timeout_long;	/* don't fetch groups that have been accessed
261 				   that many days */
262 extern int timeout_active;	/* reread active file after that many days */
263 extern int timeout_client;	/* activity timeout for clients in seconds */
264 extern int timeout_fetchnews;	/* response deadline for upstream in seconds */
265 extern int clamp_maxage;	/* limit maxage to applicable group/global expire? */
266 extern int article_despite_filter;  /* request and discard body if filterfile is defined, for high-latency, high-throughput links */
267 extern char *filterfile;	/* filename where filter resides */
268 extern struct server *servers;	/* list of servers to use */
269 extern int allowstrangers;	/* if addresses not local to our links
270 				   are allowed to connect */
271 extern int allow_8bit_headers;	/* if 8bit junk in headers is allowed */
272 extern char *newsadmin;		/* address of news administrator, default: news@%s with %s = fqdn */
273 extern unsigned long timeout_lock; /* lock file timeout */
274 
275 /*
276  * other global variables
277  */
278 #define SIZE_lineout 1024
279 extern char last_command[SIZE_lineout + 1];
280 extern char lineout[SIZE_lineout + 1];
281 
282 /* defined in nntputil.c */
283 extern /*@relnull@*/ /*@dependent@*/ FILE *nntpin;
284 extern /*@relnull@*/ /*@dependent@*/ FILE *nntpout;
285 
286 #define SIZE_s (8192)
287 #define FQDNLEN 255
288 extern char fqdn[FQDNLEN + 1];	/* my name, and my naming myself */
289 
290 extern int verbose;		/* verbosity level, for fetch and texpire */
291 extern int debug;		/* debug level */
292 
293 /*
294  * misc prototypes
295  */
296 int try_lock(unsigned long);
297 int handover_lock(pid_t);
298 void putaline(void);
299 void retry(void);
300 void readexpire(void);
301 int readconfig(int logtostderr);
302 void freeexpire(void);
303 void freeservers(void);
304 void freeconfig(void);
305 void lowercase(char *string);
306 int ngmatch(const char *pattern, const char *string);
307 void overrun(void);
308 void replaceinlist(struct stringlist **haystack, char *needle, size_t len);
309 time_t lookup_expire(char *group);
310 int lookup_expiredays(char *group);
311 int log_unlink(const char *f, int ignore_enoent);
312 
313 /* int rename(const char *old, const char *new); */
314 				/* to avoid barfing of Digital Unix */
315 
316 /*
317  * stuff from nntputil.c
318  */
319 int authenticate(const struct server*);	/* authenticate ourselves at a server */
320 /*@dependent@*//*@null@*/
321 char *lastreply(void);		/* last line frpm nntpreply */
322 int nntpreply(const struct server*);	/* decode an NNTP reply number */
323 int nntpconnect(const struct server *upstream);
324 				/* connect to upstream server */
325 void nntpdisconnect(void);	/* disconnect from upstream server */
326 void nntpquit(void);		/* send QUIT, then disconnect from upstream server */
327 void freelastreply(void);
328 
329 /*@dependent@*/
330 const char *rfctime(void);	/* An rfc type date */
331 
332 int safe_mkstemp(char *);	/* permission safe mkstemp wrapper */
333 /* from syslog.c */
334 void myopenlog(const char *ident);
335 
336 /* from mkstemp.c */
337 #ifndef HAVE_MKSTEMP
338 int mkstemp(char *);
339 #endif
340 
341 /* from getline.c */
342 #ifndef HAVE_GETLINE
343 ssize_t getline(char **, size_t *, FILE *);	/* fgets replacement */
344 #endif
345 void freegetaline(void);
346 
347 #ifndef HAVE_TIMEGM
348 time_t timegm(struct tm *tm);
349 #endif
350 
351 /* from wildmat.c */
352 int wildmat(const char *, const char *);
353 
354 /* from getfoldedline.c */
355 /*@null@*/ /*@only@*/
356 char *getfoldedline(FILE * f, char *(*reader)(FILE *));
357 /* reads one line, regardless of length, returns malloc()ed string! */
358 
359 /* from writes.c (ln-2) */
360 ssize_t writes(int fd, const char *string);
361 
362 void fixxover(void);
363 
364 /* from grouplist.c */
365 /*@null@*/ struct stringlist *get_grouplist(void);
366 
367 /* checkpeerlocal.c */
368 int checkpeerlocal(int sock);
369 
370 /* pcre_extract.c */
371 int pcre_extract(const char *input, const char *pattern, /*@out@*/ char **output, size_t num);
372 void pcre_extract_free(char **vec, int count);
373 size_t xstrlcpy(/*@out@*/ char *dst, const char *src, size_t size);
374 
375 /* xoverutil.c */
376 struct xoverinfo {
377     char *text;
378     int exists;
379 };
380 
381 /*@null@*/ extern struct xoverinfo *xoverinfo;
382 extern unsigned long xfirst;
383 extern unsigned long xlast;
384 
385 int getxover(void);		/* set xoverinfo, return 0 on error, nonzero else */
386 
387 int legalxoverline(const char *xover, /*@out@*/ const char **errmsg);
388 void freexover(void);
389 
390 /* agetcwd.c */
391 int agetcwd(/*@out@*/ char **buf, /*@out@*/ size_t *capa);
392 
393 #ifdef CHECKGROUPORDER
394 void checkgrouporder(void);
395 #endif /* CHECKGROUPORDER */
396 
397 #define SKIPLWS(p) while (*(p) && isspace((unsigned char) *(p))) { (p)++; }
398 #endif				/* #ifndef LEAFNODE_H */
399