chiark / gitweb /
Fix memory management of argument to open_input_file
[inn-innduct.git] / lib / defdist.c
1 /*  $Id: defdist.c 6135 2003-01-19 01:15:40Z rra $
2 **
3 */
4
5 #include "config.h"
6 #include "clibrary.h"
7 #include <ctype.h>
8 #include <errno.h>
9
10 #include "inn/innconf.h"
11 #include "libinn.h"
12 #include "paths.h"
13
14
15 typedef struct _DDENTRY {
16     char        *Pattern;
17     char        *Value;
18     int         Weight;
19 } DDENTRY;
20
21 struct _DDHANDLE {
22     int         Count;
23     DDENTRY     *Entries;
24     DDENTRY     *Current;
25 };
26 typedef struct _DDHANDLE        DDHANDLE;
27
28 struct _DDHANDLE *
29 DDstart(FILE *FromServer, FILE *ToServer)
30 {
31     DDHANDLE    *h;
32     DDENTRY     *ep;
33     FILE        *F;
34     char        buff[BUFSIZ];
35     char        *p;
36     char        *q;
37     char        *path;
38     int         i;
39     int         fd;
40     char        *name = NULL;
41
42     /* Open the file. */
43     path = concatpath(innconf->pathetc, _PATH_DISTPATS);
44     F = fopen(path, "r");
45     free(path);
46     if (F == NULL) {
47         /* Not available locally; try remotely. */
48         if (FromServer == NULL || ToServer == NULL)
49             /* We're probably nnrpd running on the server and the
50              * file isn't installed.  Oh well. */
51             return NULL;
52         name = concatpath(innconf->pathtmp, _PATH_TEMPACTIVE);
53         fd = mkstemp(name);
54         if (fd < 0)
55             return NULL;
56         close(fd);
57         if ((F = CA_listopen(name, FromServer, ToServer,
58                     "distrib.pats")) == NULL)
59             return NULL;
60     }
61
62     /* Count lines. */
63     for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++)
64         continue;
65
66     /* Allocate space for the handle. */
67     if ((h = xmalloc(sizeof(DDHANDLE))) == NULL) {
68         i = errno;
69         fclose(F);
70         if (name != NULL)
71             unlink(name);
72         errno = i;
73         return NULL;
74     }
75     h->Count = 0;
76     h->Current = NULL;
77     if (i == 0) {
78         return NULL ;
79     } else if ((h->Entries = xmalloc(sizeof(DDENTRY) * i)) == NULL) {
80         i = errno;
81         free(h);
82         fclose(F);
83         if (name != NULL)
84             unlink(name);
85         errno = i;
86         return NULL;
87     }
88
89     fseeko(F, 0, SEEK_SET);
90     for (ep = h->Entries; fgets(buff, sizeof buff, F) != NULL; ) {
91         if ((p = strchr(buff, '\n')) != NULL)
92             *p = '\0';
93         if (buff[0] == '\0' || buff[0] == '#')
94             continue;
95         if ((p = strchr(buff, ':')) == NULL
96          || (q = strchr(p + 1, ':')) == NULL)
97             continue;
98         *p++ = '\0';
99         ep->Weight = atoi(buff);
100         ep->Pattern = xstrdup(p);
101         q = strchr(ep->Pattern, ':');
102         *q++ = '\0';
103         ep->Value = q;
104         ep++;
105     }
106     h->Count = ep - h->Entries;
107
108     fclose(F);
109     if (name != NULL)
110         unlink(name);
111     return h;
112 }
113
114
115 void
116 DDcheck(DDHANDLE *h, char *group)
117 {
118     DDENTRY     *ep;
119     int         i;
120     int         w;
121
122     if (h == NULL || group == NULL)
123         return;
124
125     w = h->Current ? h->Current->Weight : -1;
126     for (ep = h->Entries, i = h->Count; --i >= 0; ep++)
127         if (ep->Weight > w && uwildmat(group, ep->Pattern)) {
128             h->Current = ep;
129             w = ep->Weight;
130         }
131 }
132
133
134 char *
135 DDend(DDHANDLE *h)
136 {
137     static char NIL[] = "";
138     char        *p;
139     int         i;
140     DDENTRY     *ep;
141
142     if (h == NULL) {
143         p = NIL;
144         return xstrdup(p);
145     }
146
147     if (h->Current == NULL)
148         p = NIL;
149     else
150         p = h->Current->Value;
151     p = xstrdup(p);
152
153     for (ep = h->Entries, i = h->Count; --i >= 0; ep++)
154         free(ep->Pattern);
155     free(h->Entries);
156     free(h);
157     return p;
158 }
159
160 #if     defined(TEST)
161 int
162 main(int ac, char *av[])
163 {
164     struct _DDHANDLE    *h;
165     char                *p;
166     FILE                *FromServer;
167     FILE                *ToServer;
168     char                buff[SMBUF];
169
170     if (NNTPremoteopen(NNTP_PORT, &FromServer, &ToServer, buff) < 0) {
171         if ((p = strchr(buff, '\n')) != NULL)
172             *p = '\0';
173         if ((p = strchr(buff, '\r')) != NULL)
174             *p = '\0';
175         if (buff[0])
176             fprintf(stderr, "%s\n", buff);
177         else
178             perror("Can't connect");
179         exit(1);
180     }
181
182     if ((h = DDstart(FromServer, ToServer)) == NULL)
183         perror("Init failed, proceeding anyway");
184     while ((p = *++av) != NULL)
185         DDcheck(h, p);
186     p = DDend(h);
187     printf(">%s<\n", p);
188     exit(0);
189     /* NOTREACHED */
190 }
191 #endif  /* defined(TEST) */