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