1/* $NetBSD$ */ 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 103BH_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 116void 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 124int 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 151int 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 193int 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 220int 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