1 /* $Id: nodetree.c,v 1.11 2011/08/28 12:25:20 sbajic Exp $ */
2
3 /*
4 DSPAM
5 COPYRIGHT (C) 2002-2012 DSPAM PROJECT
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU Affero General Public License as
9 published by the Free Software Foundation, either version 3 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Affero General Public License for more details.
16
17 You should have received a copy of the GNU Affero General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20 */
21
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #ifndef _WIN32
25 #include <pwd.h>
26 #endif
27
28 #include "nodetree.h"
29 #include "util.h"
30 #include "error.h"
31 #include "libdspam_objects.h"
32 #include "language.h"
33
34 /* nt_node_create (used internally) to allocate space for a new node */
nt_node_create(void * data)35 struct nt_node * nt_node_create (void *data) {
36 struct nt_node *node;
37 if ((node = (struct nt_node *) malloc (sizeof (struct nt_node))) == 0)
38 {
39 LOG (LOG_CRIT, ERR_MEM_ALLOC);
40 exit (1);
41 }
42 node->ptr = data;
43 node->next = (struct nt_node *) NULL;
44 return (node);
45 }
46
47 /* nt_create allocates space for and initializes a nodetree */
48 struct nt *
nt_create(int nodetype)49 nt_create (int nodetype)
50 {
51 struct nt *nt = (struct nt *) malloc (sizeof (struct nt));
52 if (nt == NULL)
53 {
54 LOG (LOG_CRIT, ERR_MEM_ALLOC);
55 return NULL;
56 }
57 nt->first = (struct nt_node *) NULL;
58 nt->insert = (struct nt_node *) NULL;
59 nt->items = 0;
60 nt->nodetype = nodetype;
61 return (nt);
62 }
63
64 /* nt_destroy methodically destroys a nodetree, freeing resources */
65 void
nt_destroy(struct nt * nt)66 nt_destroy (struct nt *nt)
67 {
68 struct nt_node *cur, *next;
69 int i;
70 if (!nt)
71 return;
72
73 cur = nt->first;
74 for (i = 0; i < nt->items; i++)
75 {
76 next = cur->next;
77 if (nt->nodetype != NT_INDEX)
78 free (cur->ptr);
79 free (cur);
80 cur = next;
81 }
82 free (nt);
83 }
84
85 /* nt_add adds an item to the nodetree */
86 struct nt_node *
nt_add(struct nt * nt,void * data)87 nt_add (struct nt *nt, void *data)
88 {
89 struct nt_node *prev;
90 struct nt_c c;
91 struct nt_node *node = c_nt_first (nt, &c);
92 void *vptr;
93
94 if (nt->insert) {
95 prev = nt->insert;
96 } else {
97 prev = 0;
98 while (node)
99 {
100 prev = node;
101 node = node->next;
102 }
103 }
104 nt->items++;
105
106 if (nt->nodetype == NT_CHAR)
107 {
108 long size = strlen ((char *) data) + 1;
109 /* vptr is compared with 'From' and 'X-DSPAM-'even if data is shorter; but a larger buffer is allocated to prevent a comparison against garbage */
110 vptr = malloc (size < 16 ? 16 : size);
111 if (vptr == NULL)
112 {
113 LOG (LOG_CRIT, ERR_MEM_ALLOC);
114 return NULL;
115 }
116 strlcpy (vptr, data, size);
117 }
118 else
119 {
120 vptr = data;
121 }
122
123 if (prev)
124 {
125 node = nt_node_create (vptr);
126 prev->next = node;
127 nt->insert = node;
128 return (node);
129 }
130 else
131 {
132 node = nt_node_create (vptr);
133 nt->first = node;
134 nt->insert = node;
135 return (node);
136 }
137 }
138
139 /* c_nt_next returns the next item in a nodetree */
140 struct nt_node *
c_nt_next(struct nt * nt,struct nt_c * c)141 c_nt_next (struct nt *nt, struct nt_c *c)
142 {
143 struct nt_node *node = c->iter_index;
144 if (node)
145 {
146 c->iter_index = node->next;
147 return (node->next);
148 }
149 else
150 {
151 if (nt->items > 0)
152 {
153 c->iter_index = nt->first;
154 return nt->first;
155 }
156 }
157
158 return ((struct nt_node *) NULL);
159 }
160
161 /* nt_first returns the first item in a nodetree */
162 struct nt_node *
c_nt_first(struct nt * nt,struct nt_c * c)163 c_nt_first (struct nt *nt, struct nt_c *c)
164 {
165 c->iter_index = nt->first;
166 return (nt->first);
167 }
168