leafnode  1.12.0
About: Leafnode is a store & forward NNTP proxy for small (dialup) sites.
  Fossies Dox: leafnode-1.12.0.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

configutil.c
Go to the documentation of this file.
1/*
2libutil -- read config file
3
4Written by Arnt Gulbrandsen <agulbra@troll.no> and copyright 1995
5Troll Tech AS, Postboks 6133 Etterstad, 0602 Oslo, Norway, fax +47
622646949.
7Modified by Cornelius Krasel <krasel@wpxx02.toxi.uni-wuerzburg.de>
8and Randolf Skerka <Randolf.Skerka@gmx.de>.
9Copyright of the modifications 1997.
10Modified by Kent Robotti <robotti@erols.com>. Copyright of the
11modifications 1998.
12Modified by Markus Enzenberger <enz@cip.physik.uni-muenchen.de>.
13Copyright of the modifications 1998.
14Modified by Cornelius Krasel <krasel@wpxx02.toxi.uni-wuerzburg.de>.
15Copyright of the modifications 1998, 1999.
16Modified and copyright of the modifications 2002 by Ralf Wildenhues
17<ralf.wildenhues@gmx.de>.
18Modified and copyright of the modifications 2001 - 2021 by Matthias Andree
19<matthias.andree@gmx.de>.
20
21See file COPYING for restrictions on the use of this software.
22*/
23
24#include "leafnode.h"
25#include "validatefqdn.h"
26#include "ln_log.h"
27#include "strlcpy.h"
28
29#include <ctype.h>
30#include <errno.h>
31#include <sys/types.h>
32#include <limits.h>
33#include <netdb.h>
34#include <netinet/in.h>
35#ifndef __LCLINT__
36#include <arpa/inet.h>
37#endif
38#include <stdlib.h>
39#include <stdio.h>
40#include <string.h>
41#include <syslog.h>
42#include <unistd.h>
43#include <sys/stat.h>
44#include <sys/resource.h>
45
46#define COREFILESIZE 1024*1024*64
47#define TOKENSIZE 4096
48
49#include "groupselect.h"
50
51#ifndef min
52#define min(a,b) ((a < b) ? (a) : (b))
53#endif
54
55/*
56 * misc. global variables, documented in leafnode.h
57 */
58time_t expire = 0;
59int expiredays = 0;
61unsigned long artlimit = 0;
62unsigned long initiallimit = 0;
65int delaybody = 0;
66int db_situ = 0;
67int debugmode = 0; /* if 1, log lots of stuff via syslog */
68int maxage = 10;
70long maxlines = 0;
71long minlines = 0;
72unsigned long maxbytes = 0;
73static int linebuffer = 0; /* if 1, make stdout and stderr explicitly
74 line buffered, GNU libc makes them fully buffered
75 if redirected to files */
79int timeout_client = 15*60; /* when newsreader is idle for this many seconds, disconnect */
80int timeout_fetchnews = 5*60; /* wait at most this many seconds for server replies in fetchnews */
81int clamp_maxage = 1; /* if 1, maxage will be lowered to
82 * groupexpire or expire if the
83 * applicable parameter is lower than
84 * maxage, to prevent duplicate fetches
85 * after a premature exit of
86 * fetchnews. */
89struct server *servers = NULL;
92unsigned long timeout_lock = 5UL;
93
94/** parse the line in \a l, breaking it into param and value at the "="
95 * delimiter. The right-hand side can be quoted with double quotes,
96 * inside these a backslash escapes a quote that is part of the string.
97 * \return success
98 */
99static int parse_line(
100 /*@unique@*/ char *l /** input, will be modified */,
101 /*@out@*/ char *param /** output, left-hand side */,
102 /*@out@*/ char *value /** output, right-hand side */);
103
104/* parse a line, destructively */
105static int
106parse_line(char *l, char *param, char *value)
107{
108 char *p, *start;
109 size_t le, len;
110 enum modes { plain, quoted } mode = plain;
111
112 p = l;
113 /* skip leading spaces, read parameter */
114 SKIPLWS(p);
115 le = strcspn(p, "=#");
116 /* strip trailing space */
117 while(le && strchr(" \t", p[le-1])) le--;
118 len = min(le, TOKENSIZE - 1);
119 if (!len) return 0;
120 memcpy(param, p, len);
121 param[len] = '\0';
122 p += le;
123
124 SKIPLWS(p);
125 if (*p++ != '=')
126 return 0;
127 SKIPLWS(p);
128
129 /* strip trailing blanks from input */
130 le = strlen(p);
131 while (le--) {
132 if (p[le] == ' ' || p[le] == '\t')
133 p[le] = '\0';
134 else
135 break;
136 }
137
138 start = value;
139 /* read value */
140 for (le = 0 ; le < TOKENSIZE - 1 ; le ++) {
141 char c = *p++;
142 if (mode == plain) {
143 if (c == '#' || c == '\0') {
144 /* strip trailing blanks */
145 while(value > start && strchr(" \t", value[-1])) value--;
146 break;
147 }
148 if (c == '"') { mode = quoted; continue; }
149 *value++ = c;
150 } else if (mode == quoted) {
151 if (c == '\\') {
152 if (*p) {
153 *value++ = *p++; continue;
154 } else
155 return 0;
156 }
157 if (c == '\0') return 0;
158 if (c == '"') break;
159 *value++ = c;
160 } else {
161 abort();
162 }
163 }
164 *value = '\0';
165 return 1;
166}
167
168/*
16905/25/97 - T. Sweeney - Modified to read user name and password for AUTHINFO.
170 Security questionable as password is stored in
171 plaintext in insecure file.
1721999-07-15 - Matthias Andree
173 Set p and q defaults to 0
174*/
175
176/* parses value into timeout_lock, returns 0 for success, -1 for error */
178 const char *value, /* input */
179 const char *source /* where did value come from */) {
180 char *t;
181 unsigned long u;
182
183 errno = 0;
184 u = strtoul(value, &t, 10);
185 if ((u != 0 || errno == 0)
186 && t > value
187 && (!*t || isspace((unsigned char)*t)))
188 {
189 timeout_lock = u;
190 if (debugmode) {
191 if (timeout_lock) {
192 syslog(LOG_DEBUG,
193 "%s: waiting %lu second%s for lockfile",
195 } else {
196 syslog(LOG_DEBUG,
197 "%s: waiting indefinitely for lockfile", source);
198 }
199 }
200 return 0;
201 } else {
202 ln_log(LNLOG_SERR, LNLOG_CTOP, "error: cannot parse lockfile value \"%s\" from %s", value, source);
203 return -1;
204 }
205}
206
207int
208readconfig(int logtostderr)
209{
210 struct server *p = 0, *q = 0;
211 struct rlimit corelimit;
212 struct expire_entry *ent = NULL, *prev = NULL;
213 FILE *f;
214 char *l;
215 char *param, *value;
216 char s[SIZE_s + 1];
217 unsigned long curline = 0;
218
219 artlimit = 0;
220 param = critmalloc(TOKENSIZE, "allocating space for parsing");
221 value = critmalloc(TOKENSIZE, "allocating space for parsing");
222
223 xsnprintf(s, SIZE_s, "%s/config", sysconfdir);
224 if ((f = fopen(s, "r")) == NULL) {
225 syslog(LOG_ERR, "cannot open %s", s);
226 free(param);
227 free(value);
228 return 0;
229 }
230 while ((l = getaline(f))) {
231 ++curline;
232 if (parse_line(l, param, value)) {
233 if (strcmp("username", param) == 0) {
234 if (p) {
235 if (p->username != NULL)
236 free(p->username);
237 p->username = critstrdup(value, "readconfig");
238 if (debugmode)
239 syslog(LOG_DEBUG, "config: found username for %s",
240 p->name);
241 } else
242 syslog(LOG_ERR, "config: no server for username %s", value);
243 } else if (strcmp("password", param) == 0) {
244 if (p) {
245 if (p->password != NULL)
246 free(p->password);
247 p->password = critstrdup(value, "readconfig");
248 if (debugmode)
249 syslog(LOG_DEBUG, "config: found password for %s",
250 p->name);
251 } else
252 syslog(LOG_ERR, "config: no server for password");
253 } else if (strcmp("timeout", param) == 0) {
254 if (p) {
255 p->timeout = atoi(value);
256 if (debugmode)
257 syslog(LOG_DEBUG, "config: timeout is %d second%s",
258 p->timeout, PLURAL(p->timeout));
259 } else
260 syslog(LOG_ERR, "config: no server for timeout");
261 } else if (strcmp("allowSTRANGERS", param) == 0) {
262 if (value && strlen(value)) {
263 if (atoi(value) == 42)
264 allowstrangers = 1;
265 if (debugmode)
266 syslog(LOG_DEBUG,
267 "config: allowstrangers is %s",
268 allowstrangers ? "set" : "unset");
269 }
270 } else if (strcmp("create_all_links", param) == 0) {
271 if (value && strlen(value)) {
272 create_all_links = atoi(value);
274 syslog(LOG_DEBUG,
275 "config: link articles in all groups");
276 }
277 } else if (strcmp("expire", param) == 0) {
278 int i = atoi(value);
279 if (i >= (INT_MAX / SECONDS_PER_DAY))
280 i = (INT_MAX / SECONDS_PER_DAY) - 1;
281 if (i <= 0) {
282 ln_log(LNLOG_SERR, LNLOG_CTOP, "config: expire must be positive, not %d, abort", i);
283 exit(1);
284 }
285 expiredays = i;
286 expire = time(NULL) - (time_t) (SECONDS_PER_DAY * i);
287 if (debugmode)
288 syslog(LOG_DEBUG, "config: expire is %d day%s", i, PLURAL(i));
289 } else if (strcmp("newsadmin", param) == 0) {
290 if (debugmode)
291 syslog(LOG_DEBUG, "config: newsadmin is %s", value);
292 newsadmin = critstrdup(value, "readconfig");
293 } else if (strcmp("filterfile", param) == 0) {
294 if (debugmode)
295 syslog(LOG_DEBUG, "config: filterfile is %s", value);
296 filterfile = critstrdup(value, "readconfig");
297 } else if ((strcmp("hostname", param) == 0) ||
298 (strcmp("fqdn", param) == 0)) {
299 if (debugmode)
300 syslog(LOG_DEBUG, "config: hostname is %s", value);
301 (void)xstrlcpy(fqdn, value, sizeof(fqdn));
302 } else if ((strcmp("maxcrosspost", param) == 0) ||
303 (strcmp("maxgroups", param) == 0)) {
304 /* maxgroups is for compatibility with leafnode+ */
305 crosspostlimit = strtol(value, NULL, 10);
306 if (debugmode)
307 syslog(LOG_DEBUG, "config: crosspostlimit is %ld group%s",
309 } else if (strcmp("article_despite_filter", param) == 0) {
310 article_despite_filter = atoi(value) ? 1 : 0;
311 if (debugmode)
312 syslog(LOG_DEBUG, "config: article_despite_filter is %s",
313 article_despite_filter ? "TRUE" : "FALSE");
314 } else if (strcmp("clamp_maxage", param) == 0) {
315 clamp_maxage = atoi(value);
316 if (debugmode)
317 syslog(LOG_DEBUG, "config: clamp_maxage is %s",
318 clamp_maxage ? "TRUE" : "FALSE");
319 } else if (strcmp("maxlines", param) == 0) {
320 maxlines = strtol(value, NULL, 10);
321 if (debugmode)
322 syslog(LOG_DEBUG, "config: postings have max. %ld line%s",
324 } else if (strcmp("minlines", param) == 0) {
325 minlines = strtol(value, NULL, 10);
326 if (debugmode)
327 syslog(LOG_DEBUG, "config: postings have min. %ld line%s",
329 } else if (strcmp("maxbytes", param) == 0) {
330 maxbytes = strtoul(value, NULL, 10);
331 if (debugmode)
332 syslog(LOG_DEBUG,
333 "config: postings have max. %lu byte%s",
335 } else if (strcmp("linebuffer", param) == 0) {
336 linebuffer = atoi(value);
337 if (debugmode)
338 syslog(LOG_DEBUG, "config: linebuffer is %d", linebuffer);
339 } else if (strcmp("allow_8bit_headers", param) == 0) {
340 allow_8bit_headers = atoi(value);
341 if (debugmode)
342 syslog(LOG_DEBUG, "config: allow_8bit_headers is %d",
344 } else if (strcmp("debugmode", param) == 0) {
345 int d;
346 d = atoi(value);
347 debugmode = d > debugmode ? d : debugmode;
348 if (debugmode)
349 syslog(LOG_DEBUG, "config: debugmode is %d", debugmode);
350 } else if (strcmp("delaybody_in_situ", param) == 0) {
351 db_situ = atoi(value);
352 if (debugmode)
353 syslog(LOG_DEBUG, "config: delaybody_in_situ is %d (default 0)",
354 db_situ);
355 } else if (strcmp("delaybody", param) == 0) {
356 delaybody = atoi(value);
357 if (debugmode)
358 syslog(LOG_DEBUG, "config: delaybody is %d (default 0)",
359 delaybody);
360 } else if (strcmp("timeout_short", param) == 0) {
361 timeout_short = atoi(value);
362 if (debugmode)
363 syslog(LOG_DEBUG, "config: timeout_short is %d day%s",
365 } else if (strcmp("timeout_long", param) == 0) {
366 timeout_long = atoi(value);
367 if (debugmode)
368 syslog(LOG_DEBUG, "config: timeout_long is %d day%s",
370 } else if (strcmp("timeout_active", param) == 0) {
371 timeout_active = atoi(value);
372 if (debugmode)
373 syslog(LOG_DEBUG, "config: timeout_active is %d day%s",
375 } else if (strcmp("timeout_client", param) == 0) {
376 timeout_client = atoi(value);
377 if (debugmode)
378 syslog(LOG_DEBUG, "config: timeout_client is %d second%s",
380 } else if (strcmp("timeout_fetchnews", param) == 0) {
381 timeout_fetchnews = atoi(value);
382 if (debugmode)
383 syslog(LOG_DEBUG, "config: timeout_fetchnews is %d second%s",
385 } else if (strcmp("timeout_lock", param) == 0) {
386 read_timeout_lock(value, "config");
387 } else if (strncmp("groupexpire", param, 11) == 0) {
388 char *m;
389 m = param;
390 while (*m && !(isspace((unsigned char)*m)))
391 m++;
392 while (isspace((unsigned char)*m))
393 m++;
394 if (m && *m) {
395 time_t e, i = (time_t) atol(value);
396 if (i >= (INT_MAX / SECONDS_PER_DAY))
397 i = (INT_MAX / SECONDS_PER_DAY) - 1;
398 if (debugmode) {
399 if ((long)i < 0)
400 syslog(LOG_DEBUG,
401 "config: groupexpire for %s is %ld (never)",
402 m, (long)i);
403 else if (i == 0) {
404 fprintf(stderr,
405 "config: groupexpire for %s is 0, which is treated as \"use the default expire\"\n", m);
406 syslog(LOG_INFO,
407 "config: groupexpire for %s is 0, which is treated as \"use the default expire\"",
408 m);
409 } else
410 syslog(LOG_DEBUG,
411 "config: groupexpire for %s is %ld day%s",
412 m, (long)i, PLURAL(i));
413 }
414 e = time(NULL) - (time_t) (SECONDS_PER_DAY * i);
415 ent = (struct expire_entry *)
416 critmalloc(sizeof(struct expire_entry), "readconfig");
417 ent->group = critstrdup(m, "readconfig");
418 ent->days = i;
419 ent->xtime = e;
420 ent->next = prev;
421 prev = ent;
422 }
423 } else if ((strcmp("maxage", param) == 0) ||
424 (strcmp("maxold", param) == 0)) {
425 /* maxold is for compatibility with leafnode+ */
426 maxage = atoi(value);
427#if LONG_MAX / 86400 <= INT_MAX
428 if (maxage > LONG_MAX / 86400)
429 {
430 maxage = 24854; /* 32-bit: LONG_MAX / 86400 - 1 */
432 "warning: config: maxage cannot exceed %d, "
433 "please fix %s", maxage, s);
434 }
435#endif
436 if (debugmode)
437 syslog(LOG_DEBUG, "config: maxage is %d", maxage);
438 } else if (strcmp("maxfetch", param) == 0) {
439 artlimit = strtoul(value, NULL, 10);
440 if (debugmode)
441 syslog(LOG_DEBUG, "config: maxfetch is %lu", artlimit);
442 } else if (strcmp("port", param) == 0) {
443 unsigned long pp = strtoul(value, NULL, 10);
444 if (p) {
445 if (pp == 0 || pp > 65535) {
446 syslog(LOG_ERR,
447 "config: invalid port number for nntpport %s",
448 value);
449 } else {
450 p->port = (unsigned int)pp;
451 if (debugmode)
452 syslog(LOG_DEBUG, "config: nntpport is %u",
453 p->port);
454 }
455 } else {
456 syslog(LOG_ERR, "config: no server for nntpport %s", value);
457 }
458 } else if (strcmp("noactive", param) == 0) {
459 long tmp;
460 errno = 0;
461 tmp = strtol(value,NULL,10);
462 if (errno) {
463 syslog(LOG_ERR, "config: invalid value \"%s\" for noactive", value);
464 } else {
465 if (p) {
466 p->updateactive = !tmp;
467 if (debugmode)
468 syslog(LOG_DEBUG, "config: %s active file updates for %s",
469 p->updateactive ? "enabled" : "no", p->name);
470 } else {
471 syslog(LOG_ERR, "config: no server for noactive = %s",
472 value);
473 }
474 }
475 } else if (strcmp("noxover", param) == 0) {
476 if (p) {
477 p->noxover = TRUE;
478 if (debugmode)
479 syslog(LOG_DEBUG, "config: no XOVER for %s",
480 p->name);
481 } else
482 syslog(LOG_ERR, "config: no server for noxover = %s", value);
483 } else if (strcmp("nodesc", param) == 0) {
484 if (p) {
485 p->descriptions = !atoi(value);
486 if (debugmode)
487 syslog(LOG_DEBUG, "config: %s LIST NEWSGROUPS for %s",
488 p->descriptions ? "enabled" : "no", p->name);
489 } else
490 syslog(LOG_ERR, "config: no server for nodesc = %s", value);
491 } else if (strcmp("nopost", param) == 0) {
492 if (p) {
493 p->nopost = atoi(value);
494 if (debugmode)
495 syslog(LOG_DEBUG, "config: nopost for %s is %d",
496 p->name, p->nopost);
497 } else
498 syslog(LOG_ERR, "config: no server for nopost = %s", value);
499 } else if (strcmp("post_anygroup", param) == 0) {
500 if (p) {
501 p->post_anygroup = atoi(value);
502 if (debugmode)
503 syslog(LOG_DEBUG, "config: post_anygroup for %s is %d",
504 p->name, p->nopost);
505 } else
506 syslog(LOG_ERR, "config: no server for post_anygroup = %s", value);
507 } else if (strcmp("noread", param) == 0) {
508 if (p) {
509 p->noread = atoi(value);
510 if (debugmode)
511 syslog(LOG_DEBUG, "config: noread for %s is %d",
512 p->name, p->noread);
513 } else
514 syslog(LOG_ERR, "config: no server for noread = %s", value);
515 } else if (strcmp("only_groups_match_all", param) == 0) {
516 if (p) {
517 p->only_groups_match_all = atoi(value);
518 if (debugmode)
519 syslog(LOG_DEBUG, "config: only_groups_match_all for %s is %d",
521 } else
522 syslog(LOG_ERR, "config: no server for only_groups_match_all = %s", value);
523 } else if (strcmp("initialfetch", param) == 0) {
524 initiallimit = strtoul(value, NULL, 10);
525 if (debugmode)
526 syslog(LOG_DEBUG, "config: initialfetch is %lu",
528 } else if ((strcmp("server", param) == 0) ||
529 (strcmp("supplement", param) == 0)) {
530 if (debugmode)
531 syslog(LOG_DEBUG, "config: server is %s", value);
532 p = (struct server *)critmalloc(sizeof(struct server),
533 "allocating space for server");
534 p->name = critstrdup(value, "readconfig");
535 p->descriptions = TRUE;
536 p->next = NULL;
537 p->timeout = 30; /* default 30 seconds */
538 p->port = 0;
539 p->username = NULL;
540 p->password = NULL;
541 p->nopost = 0;
542 p->noread = 0;
543 p->noxover = 0;
544 p->post_anygroup = 0;
545 p->updateactive = TRUE;
546 p->group_pcre = NULL;
548 if (servers == NULL)
549 servers = p;
550 else
551 q->next = p;
552 q = p;
553 } else if (0 == strcmp("only_groups_pcre", param)) {
554 pcre2_code_8 *re = gs_compile((unsigned char *)value);
555 if (!re) exit(2);
556 if (p) {
557 p->group_pcre = re;
558 if (debugmode)
559 syslog(LOG_DEBUG, "config: only_groups_pcre for %s is %s",
560 p->name, value);
561 } else {
562 free(re);
563 syslog(LOG_ERR, "config: no server for nopost = %s", value);
564 }
565 } else {
567 "config: unknown line %lu: \"%s = %s\"", curline,
568 param, value);
569 }
570 } else {
571 size_t i;
572 if ((i = strspn(l, " \t")) < strlen(l) && l[i] != '#') {
574 "config: malformatted line %lu: \"%s\"", curline,
575 l);
576 }
577 }
578 }
579 if (maxage != 0 && maxage > expiredays && clamp_maxage == 0) {
581 "config: maxage (%d) > expire (%d). This can cause duplicate download. Please fix your configuration, maxage must not be greater than expire.",
583 exit(1);
584 }
586
587 if (!newsadmin) {
588 const char t[] = NEWS_USER;
589 newsadmin = critmalloc(strlen(fqdn) + strlen(t) + 2, "readconfig");
590 strcpy(newsadmin, t); /* RATS: ignore */
591 strcat(newsadmin, "@");
592 strcat(newsadmin, fqdn); /* RATS: ignore */
593 }
594
595 expire_base = ent;
596 fclose(f);
597 free(param);
598 free(value);
599
600 if (servers == NULL) {
601 syslog(LOG_ERR, "no server declaration in config file");
602 return 0;
603 }
604 if (!expire)
605 syslog(LOG_ERR, "no expire declaration in config file");
606
607 /* check for duplicate server configurations */
608 {
609 unsigned short port = 0;
610 struct servent *sp = getservbyname("nntp", "tcp");
611 if (sp) port = ntohs(sp->s_port);
612
613 for (p = servers; p ; p=p->next) {
614 for (q = p->next ; q ; q=q->next) {
615 unsigned short pp = p->port, qp = q->port;
616 if (!pp) pp = port;
617 if (!qp) qp = port;
618 if (!pp || !qp) {
619 syslog(LOG_ERR, "Cannot resolve service \"nntp\" protocol \"tcp\".");
620 fprintf(stderr, "Cannot resolve service \"nntp\" protocol \"tcp\".\n");
621 return 0;
622 }
623 if (pp != qp) continue;
624 if (strcasecmp(p->name, q->name)) continue;
625 syslog(LOG_ERR, "Duplicate definition for server %s port %u", p->name, (unsigned int)pp);
626 fprintf(stderr, "Duplicate definition for server %s port %u\n", p->name, (unsigned int)pp);
627 return 0;
628 }
629 }
630 }
631
632 if (debugmode > 1) {
633 getrlimit(RLIMIT_CORE, &corelimit);
634 corelimit.rlim_cur = COREFILESIZE;
635 if (setrlimit(RLIMIT_CORE, &corelimit) < 0 && debugmode)
636 syslog(LOG_DEBUG, "Changing core file size failed: %m");
637 corelimit.rlim_cur = 0;
638 getrlimit(RLIMIT_CORE, &corelimit);
639 if (debugmode)
640 syslog(LOG_DEBUG, "Core file size: %d", (int)corelimit.rlim_cur);
641 }
642
643 l = getenv("LN_LOCK_TIMEOUT");
644 if (l && *l)
645 read_timeout_lock(l, "LN_LOCK_TIMEOUT");
646
647 if (linebuffer) {
648 fflush(stdout);
649 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
650 fflush(stderr);
651 setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
652 }
653
654 validatefqdn(logtostderr);
655
656 if (debugmode && verbose) {
657 puts("");
658 puts("WARNING: Make sure that syslog.conf captures news.debug logging");
659 puts("-------- and obtain your debug output from syslog.");
660 puts("WARNING: The screen output below is not sufficient. Check syslog!");
661 puts("");
662 sleep(3);
663 }
664 return 1;
665}
666
667/*
6681997-05-27 - T. Sweeney - Find a group in the expireinfo linked list and return
669 its expire time. Otherwise, return zero.
670*/
671static struct expire_entry *
673{
674 struct expire_entry *a;
675
676 a = expire_base;
677 while (a != NULL) {
678 if (ngmatch(a->group, group) == 0)
679 return a;
680 a = a->next;
681 }
682 return NULL;
683}
684
685static void
686freeserver(struct server *a) {
687 if (a->group_pcre) pcre2_code_free_8(a->group_pcre);
688 if (a->name) free(a->name);
689 if (a->username) free(a->username);
690 if (a->password) free(a->password);
691 free(a);
692}
693
694void /* exported for exclusive use in nntpd.c */
696 struct server *i = servers, *n;
697
698 while(i != NULL) {
699 n = i->next;
700 freeserver(i);
701 i = n;
702 }
703 servers = NULL;
704}
705
706
707void
709{
710 struct expire_entry *a, *b;
711
712 a = expire_base;
713 while(a)
714 {
715 b = a->next;
716 free(a->group);
717 free(a);
718 a = b;
719 }
720}
721
722void freeconfig(void) {
723 freeservers();
724 if (newsadmin)
725 free(newsadmin);
726 freefilter();
727 if (filterfile)
728 free(filterfile);
729 freegetaline();
730 freeexpire();
731 (void)lookup(LOOKUP_FREE);
733}
734
735time_t lookup_expire(char *group)
736{
737 struct expire_entry *e;
739 if (e) return e->xtime;
740 return 0;
741}
742
744{
745 struct expire_entry *e;
747 if (e) return e->days;
748 return 0;
749}
int verbose
Definition: applyfilter.c:31
int debug
Definition: applyfilter.c:30
static int read_timeout_lock(const char *value, const char *source)
Definition: configutil.c:177
static struct expire_entry * lookup_expireent(char *group)
Definition: configutil.c:672
char * filterfile
Definition: configutil.c:88
unsigned long maxbytes
Definition: configutil.c:72
void freeexpire(void)
Definition: configutil.c:708
int allowstrangers
Definition: configutil.c:87
time_t expire
Definition: configutil.c:58
unsigned long timeout_lock
Definition: configutil.c:92
static void freeserver(struct server *a)
Definition: configutil.c:686
long crosspostlimit
Definition: configutil.c:63
char * newsadmin
Definition: configutil.c:91
int clamp_maxage
Definition: configutil.c:81
int timeout_fetchnews
Definition: configutil.c:80
void freeservers(void)
Definition: configutil.c:695
int debugmode
Definition: configutil.c:67
time_t lookup_expire(char *group)
Definition: configutil.c:735
static int parse_line(char *l, char *param, char *value)
Definition: configutil.c:106
int timeout_long
Definition: configutil.c:76
int article_despite_filter
Definition: configutil.c:69
int lookup_expiredays(char *group)
Definition: configutil.c:743
unsigned long artlimit
Definition: configutil.c:61
int timeout_short
Definition: configutil.c:77
int db_situ
Definition: configutil.c:66
int timeout_client
Definition: configutil.c:79
int maxage
Definition: configutil.c:68
int delaybody
Definition: configutil.c:65
struct server * servers
Definition: configutil.c:89
#define min(a, b)
Definition: configutil.c:52
int expiredays
Definition: configutil.c:59
int readconfig(int logtostderr)
Definition: configutil.c:208
void freeconfig(void)
Definition: configutil.c:722
int timeout_active
Definition: configutil.c:78
static int linebuffer
Definition: configutil.c:73
#define TOKENSIZE
Definition: configutil.c:47
struct expire_entry * expire_base
Definition: configutil.c:60
unsigned long initiallimit
Definition: configutil.c:62
long maxlines
Definition: configutil.c:70
int create_all_links
Definition: configutil.c:64
#define COREFILESIZE
Definition: configutil.c:46
int allow_8bit_headers
Definition: configutil.c:90
long minlines
Definition: configutil.c:71
char * critstrdup(const char *source, const char *message)
Definition: critmem.c:92
char * critmalloc(size_t size, const char *message)
Definition: critmem.c:61
void freefilter(void)
Definition: filterutil.c:113
char * getaline(FILE *f)
Definition: getaline.c:84
void freegetaline(void)
Definition: getaline.c:89
pcre2_code_8 * gs_compile(const unsigned char *regex)
Definition: groupselect.c:9
#define PLURAL(no)
Definition: leafnode.h:35
const char * sysconfdir
#define SKIPLWS(p)
Definition: leafnode.h:398
void freelastreply(void)
Definition: nntputil.c:154
#define LOOKUP_FREE
Definition: leafnode.h:104
#define SECONDS_PER_DAY
Definition: leafnode.h:94
#define SIZE_s
Definition: leafnode.h:287
char fqdn[255+1]
Definition: miscutil.c:58
const char * lookup(const char *msgid)
Definition: miscutil.c:306
#define TRUE
Definition: leafnode.h:29
int ngmatch(const char *pattern, const char *string)
Definition: miscutil.c:792
int xsnprintf(char *str, size_t n, const char *format,...)
Definition: miscutil.c:798
size_t xstrlcpy(char *dst, const char *src, size_t size)
Definition: miscutil.c:812
void ln_log(int sev, int ctx, const char *format,...)
Definition: ln_log.c:103
#define LNLOG_SERR
Definition: ln_log.h:13
#define LNLOG_SWARNING
Definition: ln_log.h:14
#define LNLOG_CTOP
Definition: ln_log.h:22
#define len
Definition: mastring.c:31
mode_t mode
Definition: miscutil.c:126
static struct newsgroup * group
Definition: nntpd.c:73
Definition: leafnode.h:211
time_t xtime
Definition: leafnode.h:214
int days
Definition: leafnode.h:215
char * group
Definition: leafnode.h:213
struct expire_entry * next
Definition: leafnode.h:212
char * password
Definition: leafnode.h:222
char * username
Definition: leafnode.h:221
pcre2_code_8 * group_pcre
Definition: leafnode.h:223
int updateactive
Definition: leafnode.h:230
char * name
Definition: leafnode.h:220
unsigned int port
Definition: leafnode.h:224
int descriptions
Definition: leafnode.h:225
int only_groups_match_all
Definition: leafnode.h:234
int noread
Definition: leafnode.h:228
int timeout
Definition: leafnode.h:226
int noxover
Definition: leafnode.h:233
struct server * next
Definition: leafnode.h:219
int nopost
Definition: leafnode.h:227
int post_anygroup
Definition: leafnode.h:231
void validatefqdn(int logtostdout)
Definition: validatefqdn.c:103