1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ `ignore' and `retain' lists of all sort.
3 *@ XXX Should these be in nam_a_grp.c?!
5 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
6 * Copyright (c) 2012 - 2016 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
9 * Copyright (c) 1980, 1993
10 * The Regents of the University of California. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #define n_FILE ignoretab
39 #ifndef HAVE_AMALGAMATION
43 /* Add a list of fields to be ignored or retained */
44 static bool_t
a_ignoretab_insert(char const **list
, struct ignoretab
*itp
,
47 static void a_ignoretab__show(struct ignoretab
*itp
, bool_t ignorret
);
48 static int a_ignoretab__cmp(void const *l
, void const *r
);
50 /* Delete a list of fields from an ignored or retained list) */
51 static bool_t
a_ignoretab_del(char const **list
, struct ignoretab
*itp
,
54 static void a_ignoretab__delall(struct ignoretab
*itp
);
55 static bool_t
a_ignoretab__del(struct ignoretab
*itp
, char const *name
);
58 a_ignoretab_insert(char const **list
, struct ignoretab
*itp
, bool_t ignorret
){
66 a_ignoretab__show(itp
, ignorret
);
68 for(ap
= list
; *ap
!= 0; ++ap
)
69 switch(n_ignoretab_insert_cp(itp
, *ap
)){
71 n_err(_("Invalid field name cannot be %s: %s\n"),
72 (ignorret
? _("ignored") : _("retained")), *ap
);
77 n_err(_("Field already %s: %s\n"),
78 (ignorret
? _("ignored") : _("retained")), *ap
);
89 a_ignoretab__show(struct ignoretab
*itp
, bool_t ignorret
){
90 struct n_ignoretab_field
*itfp
;
92 char const **ap
, **ring
;
95 if(itp
->it_count
== 0){
96 printf(_("No fields currently being %s\n"),
97 (ignorret
? _("ignored") : _("retained")));
101 ring
= salloc((itp
->it_count
+1) * sizeof *ring
);
102 for(ap
= ring
, i
= 0; i
< NELEM(itp
->it_head
); ++i
)
103 for(itfp
= itp
->it_head
[i
]; itfp
!= NULL
; itfp
= itfp
->itf_next
)
104 *ap
++ = itfp
->itf_field
;
107 qsort(ring
, itp
->it_count
, sizeof *ring
, &a_ignoretab__cmp
);
109 for(sw
= scrnwidth
, i
= 0, ap
= ring
; *ap
!= NULL
; ++ap
){
110 /* These fields are all ASCII */
115 len
= strlen(*ap
) + 2;
116 if(UICMP(z
, len
, >=, sw
- i
)){
122 printf("%s%s", pref
, *ap
);
133 a_ignoretab__cmp(void const *l
, void const *r
){
136 rv
= asccasecmp(*(char const * const *)l
, *(char const * const *)r
);
141 a_ignoretab_del(char const **list
, struct ignoretab
*itp
, bool_t ignorret
){
148 if(itp
->it_count
== 0)
149 printf(_("No fields currently being %s\n"),
150 (ignorret
? _("ignored") : _("retained")));
152 while((cp
= *list
++) != NULL
)
153 if(cp
[0] == '*' && cp
[1] == '\0')
154 a_ignoretab__delall(itp
);
155 else if(!a_ignoretab__del(itp
, cp
)){
156 n_err(_("Field not %s: %s\n"),
157 (ignorret
? _("ignored") : _("retained")), cp
);
165 a_ignoretab__delall(struct ignoretab
*itp
){
167 struct n_ignoretab_field
*itfp
, *x
;
171 if(!(isauto
= itp
->it_auto
))
172 for(i
= 0; i
< NELEM(itp
->it_head
); ++i
)
173 for(itfp
= itp
->it_head
[i
]; itfp
!= NULL
; itfp
= x
){
178 memset(itp
, 0, sizeof *itp
);
179 itp
->it_auto
= isauto
;
184 a_ignoretab__del(struct ignoretab
*itp
, char const *name
){
185 struct n_ignoretab_field
**itfpp
, *itfp
;
189 h
= torek_ihashn(name
, UIZ_MAX
) % NELEM(itp
->it_head
);
191 for(itfp
= *(itfpp
= &itp
->it_head
[h
]); itfp
!= NULL
;
192 itfpp
= &itfp
->itf_next
, itfp
= itfp
->itf_next
)
193 if(!asccasecmp(itfp
->itf_field
, name
)){
195 *itfpp
= itfp
->itf_next
;
201 return (itfp
!= NULL
);
209 rv
= !a_ignoretab_insert(v
, &ignore
[1], FAL0
);
219 rv
= !a_ignoretab_insert(v
, &ignore
[0], TRU1
);
225 c_saveretfield(void *v
){
229 rv
= !a_ignoretab_insert(v
, &saveignore
[1], FAL0
);
235 c_saveigfield(void *v
){
239 rv
= !a_ignoretab_insert(v
, &saveignore
[0], TRU1
);
245 c_fwdretfield(void *v
){
249 rv
= !a_ignoretab_insert(v
, &fwdignore
[1], FAL0
);
255 c_fwdigfield(void *v
){
259 rv
= !a_ignoretab_insert(v
, &fwdignore
[0], TRU1
);
269 rv
= !a_ignoretab_del(v
, &ignore
[0], TRU1
);
279 rv
= !a_ignoretab_del(v
, &ignore
[1], FAL0
);
285 c_unsaveignore(void *v
){
289 rv
= !a_ignoretab_del(v
, &saveignore
[0], TRU1
);
295 c_unsaveretain(void *v
){
299 rv
= !a_ignoretab_del(v
, &saveignore
[1], FAL0
);
305 c_unfwdignore(void *v
){
309 rv
= !a_ignoretab_del(v
, &fwdignore
[0], TRU1
);
315 c_unfwdretain(void *v
){
319 rv
= !a_ignoretab_del(v
, &fwdignore
[1], FAL0
);
325 is_ign(char const *field
, size_t fieldlen
, struct ignoretab igta
[2]){
334 if(igta
== allignore
)
337 b
= (igta
[1].it_count
> 0);
338 rv
= n_ignoretab_lookup((b
? &igta
[1] : &igta
[0]), field
, fieldlen
);
346 FL
struct ignoretab
*
347 n_ignoretab_creat(struct ignoretab
*self
, bool_t isauto
){
349 memset(self
, 0, sizeof *self
);
350 self
->it_auto
= isauto
;
356 n_ignoretab_gut(struct ignoretab
*self
){
358 if(!self
->it_auto
&& self
->it_count
> 0)
359 a_ignoretab__delall(self
);
364 n_ignoretab_insert(struct ignoretab
*self
, char const *dat
, size_t len
){
365 struct n_ignoretab_field
*itfp
;
370 /* Detect length as necessary, check for valid fieldname */
375 for(len
= 0; (c
= dat
[len
]) != '\0'; ++len
)
376 if(!fieldnamechar(c
))
384 for(i
= 0; i
< len
; ++i
){
386 if(!fieldnamechar(c
))
392 if(n_ignoretab_lookup(self
, dat
, len
))
394 else if(self
->it_count
== UI32_MAX
){
395 n_err(_("Hashtable size limit reached. Cannot insert: %.*s\n"),
396 (int)MIN(len
, SI32_MAX
), dat
);
404 i
= sizeof(*itfp
)-VFIELD_SIZEOF(struct n_ignoretab_field
,itf_field
) + len
;
405 itfp
= self
->it_auto
? salloc(i
) : smalloc(i
);
408 memcpy(itfp
->itf_field
, dat
, len
);
409 itfp
->itf_field
[len
] = '\0';
410 h
= torek_ihashn(dat
, len
) % NELEM(self
->it_head
);
411 itfp
->itf_next
= self
->it_head
[h
];
412 self
->it_head
[h
] = itfp
;
421 n_ignoretab_lookup(struct ignoretab
*self
, char const *dat
, size_t len
){
422 struct n_ignoretab_field
*itfp
;
428 for(itfp
= self
->it_head
[torek_ihashn(dat
, len
) % NELEM(self
->it_head
)];
429 itfp
!= NULL
; itfp
= itfp
->itf_next
)
430 if(!ascncasecmp(itfp
->itf_field
, dat
, len
))
433 return (itfp
!= NULL
);