File: artutil.c

package info (click to toggle)
leafnode 1.11.11-1
  • links: PTS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 2,468 kB
  • sloc: ansic: 10,914; sh: 1,748; xml: 628; makefile: 291; perl: 84; sed: 4
file content (180 lines) | stat: -rw-r--r-- 3,948 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
libutil -- stuff dealing with articles

Written by Cornelius Krasel <krasel@wpxx02.toxi.uni-wuerzburg.de>.
Copyright 1998, 1999.

See file COPYING for restrictions on the use of this software.
*/

#include "leafnode.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <sys/stat.h>
#include <unistd.h>
#include "mastring.h"
#include "ln_log.h"

/**
 * find a header in an article and return it, without its name.
 */
char *
fgetheader(FILE * f, const char *header)
{
    char *hdr, *p;
    size_t hlen;

    if (!header || !*header || header[(hlen = strlen(header))-1] != ':') {
	syslog(LOG_CRIT, "internal error in %s:%d", __FILE__, __LINE__); /* RATS: ignore */
	abort(); /* header must end with a colon */
    }

    if (!f)
	return NULL;
    rewind(f);
    debug = 0;
    hdr = NULL;
    while ((p = getfoldedline(f, getaline)) && *p) {
	/* read only headers */
	char *q = p;
	if ((strncasecmp(q, header, hlen) == 0)) {
	    q += hlen;
	    while (q && *q && isspace((unsigned char)*q))
		q++;
	    hdr = critstrdup(q, "fgetheader");
	    free(p); p = NULL;
	    break;
	}
	free(p); p = NULL;
    }
    if (p) free(p);
    debug = debugmode;
    rewind(f);
    return hdr;
}

char *
getheader(const char *filename, const char *header)
{
    FILE *f;
    char *hdr;
    struct stat st;

    if ((f = fopen(filename, "r")) == NULL)
	return NULL;
    if (fstat(fileno(f), &st) || !S_ISREG(st.st_mode)) {
	(void)fclose(f);
	return NULL;
    }
    hdr = fgetheader(f, header);
    fclose(f);
    return hdr;
}

/*
 * store articles in newsgroups which are already stored in
 * $SPOOLDIR/message.id/
 */
void
store(const char *filename,
      FILE * filehandle, const char *ngs, const char *msgid)
{
    char tmp[50]; /* RATS: ignore */
    static struct newsgroup *cg;
    static struct newsgroup *cg_active;
    /* Ken Shan: we must not try to reuse the cg pointer,
     * it becomes invalid as the "active" pointer is realloc()ed. */
    mastr *xrefincase = mastr_new(4096);
    char *p;
    char *q;
    char *newsgroups = critstrdup(ngs, "store");

    if (verbose > 2)
	printf(".storing %s: %s\n", msgid, newsgroups);

    p = newsgroups;
    while (p && *p) {
	q = strchr(p, ',');
	if (q)
	    *q++ = '\0';
	SKIPLWS(p);
	if (*p) {
	    if (!cg || cg_active != active || strcmp(cg->name, p)) {
		cg = findgroup(p);
		cg_active = active;
		if (cg) {
		    if (isinteresting(cg->name) || create_all_links) {
			if (!chdirgroup(p, FALSE))
			    cg->first = cg->last + 1;

			if (!chdirgroup(p, TRUE)) {
			    ln_log(LNLOG_SERR, LNLOG_CTOP, 
				    "cannot create group directory for %s",
				    cg->name);
			    cg = NULL;
			}
		    } else {
			cg = NULL;
		    }
		}
	    }

	    /* cg may have become NULL if we don't want to store */
	    if (cg) {
		int r;

		if (cg->first < 1)
		    cg->first = 1;

		if (cg->last < cg->first)
		    cg->last = cg->first++;

		if (!chdirgroup(p, FALSE)) {
		    /* error */
		    p = q;
		    continue;
		}
		do {
		    sprintf(tmp, "%lu", ++cg->last);
		    errno = 0;
		} while ((r = link(filename, tmp)) < 0 && errno == EEXIST);
		if (r == 0 && verbose > 2)
		    printf("..as article %lu in %s\n", cg->last, cg->name);
		if (r < 0)
		    syslog(LOG_ERR, "error linking %s into %s: %m",
			   filename, p);
		else {
		    mastr_vcat(xrefincase, " ", cg->name, ":", tmp, NULL);
		}
	    } else {
		if (verbose > 2)
		    printf("..discarding unknown group %s\n", p);
	    }
	}
	p = q;
    }
    fprintf(filehandle, "Xref: %s%s\n", fqdn, mastr_str(xrefincase));
    free(newsgroups);
    mastr_delete(xrefincase);
}

#ifdef TEST
int verbose = 0;
int debug = 0;

int main(int argc, char **argv[]) {
    char *t;

    if (argc != 3) {
	fprintf(stderr, "usage: %s file header:\n", argv[0]);
	exit(1);
    }

    t = getheader(argv[1], argv[2]);
    printf("header %s in %s is:\n%s\n", argv[2], argv[1], t ? t : "(NULL)");
    exit(0);
}
#endif