1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 1999-2021 Free Software Foundation, Inc.
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 3 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General
15    Public License along with this library.  If not, see
16    <http://www.gnu.org/licenses/>. */
17 
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <sieve-priv.h>
27 
28 int
mu_sieve_registry_require(mu_sieve_machine_t mach,const char * name,enum mu_sieve_record type)29 mu_sieve_registry_require (mu_sieve_machine_t mach, const char *name,
30 			   enum mu_sieve_record type)
31 {
32   mu_sieve_registry_t *reg;
33 
34   reg = mu_sieve_registry_lookup (mach, name, type);
35   if (!reg)
36     {
37       void *handle = mu_sieve_load_ext (mach, name);
38       if (!handle)
39 	return 1;
40       reg = mu_sieve_registry_lookup (mach, name, type);
41       if (!reg)
42 	return 1;
43       reg->handle = handle;
44     }
45 
46   reg->required = 1;
47   return 0;
48 }
49 
50 
51 static void
regunload(void * data)52 regunload (void *data)
53 {
54   mu_sieve_registry_t *reg = data;
55   mu_sieve_unload_ext (reg->handle);
56 }
57 
58 static int
regcmp(void const * a,void const * b)59 regcmp (void const *a, void const *b)
60 {
61   mu_sieve_registry_t const *rega = a;
62   mu_sieve_registry_t const *regb = b;
63   if (rega->type != regb->type)
64     return rega->type - regb->type;
65   return strcmp (rega->name, regb->name);
66 }
67 
68 mu_sieve_registry_t *
mu_sieve_registry_add(mu_sieve_machine_t mach,const char * name)69 mu_sieve_registry_add (mu_sieve_machine_t mach, const char *name)
70 {
71   mu_sieve_registry_t *reg;
72   int rc;
73 
74   if (!mach->registry)
75     {
76       rc = mu_list_create (&mach->registry);
77       if (rc)
78 	{
79 	  mu_sieve_error (mach, "mu_list_create: %s", mu_strerror (rc));
80 	  mu_sieve_abort (mach);
81 	}
82       mu_list_set_destroy_item (mach->registry, regunload);
83       mu_list_set_comparator (mach->registry, regcmp);
84     }
85   reg = mu_sieve_malloc (mach, sizeof (*reg));
86   reg->name = name;
87   reg->handle = NULL;
88   reg->required = 0;
89   memset (&reg->v, 0, sizeof reg->v);
90   rc = mu_list_append (mach->registry, reg);
91   if (rc)
92     {
93       mu_sieve_error (mach, "mu_list_append: %s", mu_strerror (rc));
94       mu_sieve_abort (mach);
95     }
96   return reg;
97 }
98 
99 mu_sieve_registry_t *
mu_sieve_registry_lookup(mu_sieve_machine_t mach,const char * name,enum mu_sieve_record type)100 mu_sieve_registry_lookup (mu_sieve_machine_t mach, const char *name,
101 			  enum mu_sieve_record type)
102 {
103   mu_sieve_registry_t key, *reg;
104   int rc;
105 
106   key.name = name;
107   key.type = type;
108 
109   rc = mu_list_locate (mach->registry, &key, (void**) &reg);
110   if (rc == MU_ERR_NOENT)
111     return NULL;
112   else if (rc)
113     {
114       mu_sieve_error (mach, _("registry lookup failed: %s"), mu_strerror (rc));
115       mu_sieve_abort (mach);
116     }
117   return reg;
118 }
119 
120 void
mu_sieve_register_test_ext(mu_sieve_machine_t mach,const char * name,mu_sieve_handler_t handler,mu_sieve_data_type * req_args,mu_sieve_data_type * opt_args,mu_sieve_tag_group_t * tags,int required)121 mu_sieve_register_test_ext (mu_sieve_machine_t mach,
122 			    const char *name, mu_sieve_handler_t handler,
123 			    mu_sieve_data_type *req_args,
124 			    mu_sieve_data_type *opt_args,
125 			    mu_sieve_tag_group_t *tags, int required)
126 {
127   mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name);
128 
129   reg->type = mu_sieve_record_test;
130   reg->required = required;
131   reg->v.command.handler = handler;
132   reg->v.command.req_args = req_args;
133   reg->v.command.opt_args = opt_args;
134   reg->v.command.tags = tags;
135 }
136 
137 void
mu_sieve_register_test(mu_sieve_machine_t mach,const char * name,mu_sieve_handler_t handler,mu_sieve_data_type * arg_types,mu_sieve_tag_group_t * tags,int required)138 mu_sieve_register_test (mu_sieve_machine_t mach,
139 			const char *name, mu_sieve_handler_t handler,
140 			mu_sieve_data_type *arg_types,
141 			mu_sieve_tag_group_t *tags, int required)
142 {
143   return mu_sieve_register_test_ext (mach, name, handler,
144 				     arg_types, NULL,
145 				     tags,
146 				     required);
147 }
148 
149 void
mu_sieve_register_action_ext(mu_sieve_machine_t mach,const char * name,mu_sieve_handler_t handler,mu_sieve_data_type * req_args,mu_sieve_data_type * opt_args,mu_sieve_tag_group_t * tags,int required)150 mu_sieve_register_action_ext (mu_sieve_machine_t mach,
151 			      const char *name, mu_sieve_handler_t handler,
152 			      mu_sieve_data_type *req_args,
153 			      mu_sieve_data_type *opt_args,
154 			      mu_sieve_tag_group_t *tags, int required)
155 {
156   mu_sieve_registry_t *reg = mu_sieve_registry_add (mach, name);
157 
158   reg->type = mu_sieve_record_action;
159   reg->required = required;
160   reg->v.command.handler = handler;
161   reg->v.command.req_args = req_args;
162   reg->v.command.opt_args = opt_args;
163   reg->v.command.tags = tags;
164 }
165 
166 void
mu_sieve_register_action(mu_sieve_machine_t mach,const char * name,mu_sieve_handler_t handler,mu_sieve_data_type * arg_types,mu_sieve_tag_group_t * tags,int required)167 mu_sieve_register_action (mu_sieve_machine_t mach,
168 			  const char *name, mu_sieve_handler_t handler,
169 			  mu_sieve_data_type *arg_types,
170 			  mu_sieve_tag_group_t *tags, int required)
171 {
172   return mu_sieve_register_action_ext (mach, name, handler,
173 				       arg_types, NULL,
174 				       tags,
175 				       required);
176 }
177