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)  

artutil.c
Go to the documentation of this file.
1/*
2libutil -- stuff dealing with articles
3
4Written by Cornelius Krasel <krasel@wpxx02.toxi.uni-wuerzburg.de>.
5Copyright 1998, 1999.
6
7Modified and copyright of the modifications 2021 - 2010 by Matthias Andree.
8
9See file COPYING for restrictions on the use of this software.
10*/
11
12#include "leafnode.h"
13#include <ctype.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <syslog.h>
18#include <sys/stat.h>
19#include <unistd.h>
20#include "mastring.h"
21#include "ln_log.h"
22
23/**
24 * find a header in an article and return it, without its name.
25 */
26char *
27fgetheader(FILE * f, const char *header)
28{
29 char *hdr, *p;
30 size_t hlen;
31
32 if (!header || !*header || header[(hlen = strlen(header))-1] != ':') {
33 syslog(LOG_CRIT, "internal error in %s:%d", __FILE__, __LINE__); /* RATS: ignore */
34 abort(); /* header must end with a colon */
35 }
36
37 if (!f)
38 return NULL;
39 rewind(f);
40 debug = 0;
41 hdr = NULL;
42 while ((p = getfoldedline(f, getaline)) && *p) {
43 /* read only headers */
44 char *q = p;
45 if ((strncasecmp(q, header, hlen) == 0)) {
46 q += hlen;
47 while (q && *q && isspace((unsigned char)*q))
48 q++;
49 hdr = critstrdup(q, "fgetheader");
50 free(p); p = NULL;
51 break;
52 }
53 free(p); p = NULL;
54 }
55 if (p) free(p);
57 rewind(f);
58 return hdr;
59}
60
61char *
62getheader(const char *filename, const char *header)
63{
64 FILE *f;
65 char *hdr;
66 struct stat st;
67
68 if ((f = fopen(filename, "r")) == NULL)
69 return NULL;
70 if (fstat(fileno(f), &st) || !S_ISREG(st.st_mode)) {
71 (void)fclose(f);
72 return NULL;
73 }
74 hdr = fgetheader(f, header);
75 fclose(f);
76 return hdr;
77}
78
79/*
80 * store articles in newsgroups which are already stored in
81 * $SPOOLDIR/message.id/
82 */
83void
84store(const char *filename,
85 FILE * filehandle, const char *ngs, const char *msgid)
86{
87 char tmp[50]; /* RATS: ignore */
88 static struct newsgroup *cg;
89 static struct newsgroup *cg_active;
90 /* Ken Shan: we must not try to reuse the cg pointer,
91 * it becomes invalid as the "active" pointer is realloc()ed. */
92 mastr *xrefincase = mastr_new(4096);
93 char *p;
94 char *q;
95 char *newsgroups = critstrdup(ngs, "store");
96
97 if (verbose > 2)
98 printf(".storing %s: %s\n", msgid, newsgroups);
99
100 p = newsgroups;
101 while (p && *p) {
102 q = strchr(p, ',');
103 if (q)
104 *q++ = '\0';
105 SKIPLWS(p);
106 if (*p) {
107 if (!cg || cg_active != active || strcmp(cg->name, p)) {
108 cg = findgroup(p);
109 cg_active = active;
110 if (cg) {
111 if (isinteresting(cg->name) || create_all_links) {
112 if (!chdirgroup(p, FALSE))
113 cg->first = cg->last + 1;
114
115 if (!chdirgroup(p, TRUE)) {
117 "cannot create group directory for %s",
118 cg->name);
119 cg = NULL;
120 }
121 } else {
122 cg = NULL;
123 }
124 }
125 }
126
127 /* cg may have become NULL if we don't want to store */
128 if (cg) {
129 int r;
130
131 if (cg->first < 1)
132 cg->first = 1;
133
134 if (cg->last < cg->first)
135 cg->last = cg->first++;
136
137 if (!chdirgroup(p, FALSE)) {
138 /* error */
139 p = q;
140 continue;
141 }
142 do {
143 sprintf(tmp, "%lu", ++cg->last);
144 errno = 0;
145 } while ((r = link(filename, tmp)) < 0 && errno == EEXIST);
146 if (r == 0 && verbose > 2)
147 printf("..as article %lu in %s\n", cg->last, cg->name);
148 if (r < 0)
149 syslog(LOG_ERR, "error linking %s into %s: %m",
150 filename, p);
151 else {
152 mastr_vcat(xrefincase, " ", cg->name, ":", tmp, NULL);
153 }
154 } else {
155 if (verbose > 2)
156 printf("..discarding unknown group %s\n", p);
157 }
158 }
159 p = q;
160 }
161 fprintf(filehandle, "Xref: %s%s\n", fqdn, mastr_str(xrefincase));
162 free(newsgroups);
163 mastr_delete(xrefincase);
164}
165
166#ifdef TEST
167int verbose = 0;
168int debug = 0;
169
170int main(int argc, char **argv[]) {
171 char *t;
172
173 if (argc != 3) {
174 fprintf(stderr, "usage: %s file header:\n", argv[0]);
175 exit(1);
176 }
177
178 t = getheader(argv[1], argv[2]);
179 printf("header %s in %s is:\n%s\n", argv[2], argv[1], t ? t : "(NULL)");
180 exit(0);
181}
182#endif
struct newsgroup * findgroup(const char *name)
Definition: activutil.c:260
struct newsgroup * active
Definition: activutil.c:40
int main(void)
Definition: amiroot.c:12
int verbose
Definition: applyfilter.c:31
int debug
Definition: applyfilter.c:30
char * fgetheader(FILE *f, const char *header)
Definition: artutil.c:27
void store(const char *filename, FILE *filehandle, const char *ngs, const char *msgid)
Definition: artutil.c:84
char * getheader(const char *filename, const char *header)
Definition: artutil.c:62
int debugmode
Definition: configutil.c:67
int create_all_links
Definition: configutil.c:64
char * critstrdup(const char *source, const char *message)
Definition: critmem.c:92
char * getaline(FILE *f)
Definition: getaline.c:84
char * getfoldedline(FILE *f, char *(*reader)(FILE *))
Definition: getfoldedline.c:13
#define SKIPLWS(p)
Definition: leafnode.h:398
char fqdn[255+1]
Definition: miscutil.c:58
#define TRUE
Definition: leafnode.h:29
#define FALSE
Definition: leafnode.h:32
int isinteresting(const char *groupname)
Definition: miscutil.c:271
int chdirgroup(const char *group, int creatdir)
Definition: miscutil.c:446
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_CTOP
Definition: ln_log.h:22
void mastr_delete(mastr *m)
Definition: mastring.c:223
mastr * mastr_new(size_t size)
Definition: mastring.c:62
int mastr_vcat(mastr *m,...)
Definition: mastring.c:147
#define mastr_str(m)
Definition: mastring.h:57
Definition: mastring.h:28
unsigned long first
Definition: leafnode.h:122
char * name
Definition: leafnode.h:124
unsigned long last
Definition: leafnode.h:123