xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/been_here.c (revision 1b9578b8c2c1f848eeb16dabbfd7d1f0d9fdefbd)
1 /*	$NetBSD: been_here.c,v 1.1.1.1 2009/06/23 10:08:45 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	been_here 3
6 /* SUMMARY
7 /*	detect repeated occurrence of string
8 /* SYNOPSIS
9 /*	#include <been_here.h>
10 /*
11 /*	BH_TABLE *been_here_init(size, flags)
12 /*	int	size;
13 /*	int	flags;
14 /*
15 /*	int	been_here_fixed(dup_filter, string)
16 /*	BH_TABLE *dup_filter;
17 /*	char	*string;
18 /*
19 /*	int	been_here(dup_filter, format, ...)
20 /*	BH_TABLE *dup_filter;
21 /*	char	*format;
22 /*
23 /*	int	been_here_check_fixed(dup_filter, string)
24 /*	BH_TABLE *dup_filter;
25 /*	char	*string;
26 /*
27 /*	int	been_here_check(dup_filter, format, ...)
28 /*	BH_TABLE *dup_filter;
29 /*	char	*format;
30 /*
31 /*	void	been_here_free(dup_filter)
32 /*	BH_TABLE *dup_filter;
33 /* DESCRIPTION
34 /*	This module implements a simple filter to detect repeated
35 /*	occurrences of character strings.
36 /*
37 /*	been_here_init() creates an empty duplicate filter.
38 /*
39 /*	been_here_fixed() looks up a fixed string in the given table, and
40 /*	makes an entry in the table if the string was not found. The result
41 /*	is non-zero (true) if the string was found, zero (false) otherwise.
42 /*
43 /*	been_here() formats its arguments, looks up the result in the
44 /*	given table, and makes an entry in the table if the string was
45 /*	not found. The result is non-zero (true) if the formatted result was
46 /*	found, zero (false) otherwise.
47 /*
48 /*	been_here_check_fixed() and been_here_check() are similar
49 /*	but do not update the duplicate filter.
50 /*
51 /*	been_here_free() releases storage for a duplicate filter.
52 /*
53 /*	Arguments:
54 /* .IP size
55 /*	Upper bound on the table size; at most \fIsize\fR strings will
56 /*	be remembered.  Specify a value <= 0 to disable the upper bound.
57 /* .IP flags
58 /*	Requests for special processing. Specify the bitwise OR of zero
59 /*	or more flags:
60 /* .RS
61 /* .IP BH_FLAG_FOLD
62 /*	Enable case-insensitive lookup.
63 /* .IP BH_FLAG_NONE
64 /*	A manifest constant that requests no special processing.
65 /* .RE
66 /* .IP dup_filter
67 /*	The table with remembered names
68 /* .IP string
69 /*	Fixed search string.
70 /* .IP format
71 /*	Format for building the search string.
72 /* LICENSE
73 /* .ad
74 /* .fi
75 /*	The Secure Mailer license must be distributed with this software.
76 /* AUTHOR(S)
77 /*	Wietse Venema
78 /*	IBM T.J. Watson Research
79 /*	P.O. Box 704
80 /*	Yorktown Heights, NY 10598, USA
81 /*--*/
82 
83 /* System library. */
84 
85 #include "sys_defs.h"
86 #include <stdlib.h>			/* 44BSD stdarg.h uses abort() */
87 #include <stdarg.h>
88 
89 /* Utility library. */
90 
91 #include <msg.h>
92 #include <mymalloc.h>
93 #include <htable.h>
94 #include <vstring.h>
95 #include <stringops.h>
96 
97 /* Global library. */
98 
99 #include "been_here.h"
100 
101 /* been_here_init - initialize duplicate filter */
102 
103 BH_TABLE *been_here_init(int limit, int flags)
104 {
105     BH_TABLE *dup_filter;
106 
107     dup_filter = (BH_TABLE *) mymalloc(sizeof(*dup_filter));
108     dup_filter->limit = limit;
109     dup_filter->flags = flags;
110     dup_filter->table = htable_create(0);
111     return (dup_filter);
112 }
113 
114 /* been_here_free - destroy duplicate filter */
115 
116 void    been_here_free(BH_TABLE *dup_filter)
117 {
118     htable_free(dup_filter->table, (void (*) (char *)) 0);
119     myfree((char *) dup_filter);
120 }
121 
122 /* been_here - duplicate detector with finer control */
123 
124 int     been_here(BH_TABLE *dup_filter, const char *fmt,...)
125 {
126     VSTRING *buf = vstring_alloc(100);
127     int     status;
128     va_list ap;
129 
130     /*
131      * Construct the string to be checked.
132      */
133     va_start(ap, fmt);
134     vstring_vsprintf(buf, fmt, ap);
135     va_end(ap);
136 
137     /*
138      * Do the duplicate check.
139      */
140     status = been_here_fixed(dup_filter, vstring_str(buf));
141 
142     /*
143      * Cleanup.
144      */
145     vstring_free(buf);
146     return (status);
147 }
148 
149 /* been_here_fixed - duplicate detector */
150 
151 int     been_here_fixed(BH_TABLE *dup_filter, const char *string)
152 {
153     char   *folded_string;
154     const char *lookup_key;
155     int     status;
156 
157     /*
158      * Special processing: case insensitive lookup.
159      */
160     if (dup_filter->flags & BH_FLAG_FOLD) {
161 	folded_string = mystrdup(string);
162 	lookup_key = lowercase(folded_string);
163     } else {
164 	folded_string = 0;
165 	lookup_key = string;
166     }
167 
168     /*
169      * Do the duplicate check.
170      */
171     if (htable_locate(dup_filter->table, lookup_key) != 0) {
172 	status = 1;
173     } else {
174 	if (dup_filter->limit <= 0
175 	    || dup_filter->limit > dup_filter->table->used)
176 	    htable_enter(dup_filter->table, lookup_key, (char *) 0);
177 	status = 0;
178     }
179     if (msg_verbose)
180 	msg_info("been_here: %s: %d", string, status);
181 
182     /*
183      * Cleanup.
184      */
185     if (folded_string)
186 	myfree(folded_string);
187 
188     return (status);
189 }
190 
191 /* been_here_check - query duplicate detector with finer control */
192 
193 int     been_here_check(BH_TABLE *dup_filter, const char *fmt,...)
194 {
195     VSTRING *buf = vstring_alloc(100);
196     int     status;
197     va_list ap;
198 
199     /*
200      * Construct the string to be checked.
201      */
202     va_start(ap, fmt);
203     vstring_vsprintf(buf, fmt, ap);
204     va_end(ap);
205 
206     /*
207      * Do the duplicate check.
208      */
209     status = been_here_check_fixed(dup_filter, vstring_str(buf));
210 
211     /*
212      * Cleanup.
213      */
214     vstring_free(buf);
215     return (status);
216 }
217 
218 /* been_here_check_fixed - query duplicate detector */
219 
220 int     been_here_check_fixed(BH_TABLE *dup_filter, const char *string)
221 {
222     char   *folded_string;
223     const char *lookup_key;
224     int     status;
225 
226     /*
227      * Special processing: case insensitive lookup.
228      */
229     if (dup_filter->flags & BH_FLAG_FOLD) {
230 	folded_string = mystrdup(string);
231 	lookup_key = lowercase(folded_string);
232     } else {
233 	folded_string = 0;
234 	lookup_key = string;
235     }
236 
237     /*
238      * Do the duplicate check.
239      */
240     status = (htable_locate(dup_filter->table, lookup_key) != 0);
241     if (msg_verbose)
242 	msg_info("been_here_check: %s: %d", string, status);
243 
244     /*
245      * Cleanup.
246      */
247     if (folded_string)
248 	myfree(folded_string);
249 
250     return (status);
251 }
252