]> jfr.im git - solanum.git/blame - src/capability.c
Merge branch 'master' of git.atheme.org:/gitroot/charybdis
[solanum.git] / src / capability.c
CommitLineData
64b56afd
AC
1/*
2 * Copyright (c) 2012 William Pitcock <nenolod@dereferenced.org>.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 */
20
21#include "stdinc.h"
22#include "capability.h"
23#include "irc_dictionary.h"
24
885cd603
AC
25static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
26
64b56afd 27struct CapabilityIndex {
885cd603 28 char *name;
64b56afd
AC
29 struct Dictionary *cap_dict;
30 unsigned int highest_bit;
885cd603 31 rb_dlink_node node;
64b56afd
AC
32};
33
5058c8eb 34#define CAP_ORPHANED 0x1
f01f67f0 35#define CAP_REQUIRED 0x2
5058c8eb 36
64b56afd 37struct CapabilityEntry {
e679e389 38 char *cap;
64b56afd 39 unsigned int value;
5058c8eb 40 unsigned int flags;
64b56afd
AC
41};
42
43unsigned int
bde42c60 44capability_get(struct CapabilityIndex *idx, const char *cap)
64b56afd
AC
45{
46 struct CapabilityEntry *entry;
47
bde42c60 48 s_assert(idx != NULL);
64b56afd 49
bde42c60 50 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
5058c8eb 51 if (entry != NULL && !(entry->flags & CAP_ORPHANED))
8bedf01d 52 return (1 << entry->value);
64b56afd
AC
53
54 return 0xFFFFFFFF;
55}
56
57unsigned int
bde42c60 58capability_put(struct CapabilityIndex *idx, const char *cap)
64b56afd
AC
59{
60 struct CapabilityEntry *entry;
61
bde42c60
JT
62 s_assert(idx != NULL);
63 if (!idx->highest_bit)
8bedf01d 64 return 0xFFFFFFFF;
64b56afd 65
bde42c60 66 if ((entry = irc_dictionary_retrieve(idx->cap_dict, cap)) != NULL)
64b56afd 67 {
5058c8eb 68 entry->flags &= ~CAP_ORPHANED;
8bedf01d 69 return (1 << entry->value);
64b56afd
AC
70 }
71
72 entry = rb_malloc(sizeof(struct CapabilityEntry));
e679e389 73 entry->cap = rb_strdup(cap);
5058c8eb 74 entry->flags = 0;
bde42c60 75 entry->value = idx->highest_bit;
64b56afd 76
bde42c60 77 irc_dictionary_add(idx->cap_dict, entry->cap, entry);
64b56afd 78
bde42c60
JT
79 idx->highest_bit++;
80 if (idx->highest_bit % (sizeof(unsigned int) * 8) == 0)
81 idx->highest_bit = 0;
64b56afd 82
8bedf01d 83 return (1 << entry->value);
64b56afd
AC
84}
85
86void
bde42c60 87capability_orphan(struct CapabilityIndex *idx, const char *cap)
64b56afd
AC
88{
89 struct CapabilityEntry *entry;
90
bde42c60 91 s_assert(idx != NULL);
64b56afd 92
bde42c60 93 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
64b56afd 94 if (entry != NULL)
f01f67f0
AC
95 {
96 entry->flags &= ~CAP_REQUIRED;
5058c8eb 97 entry->flags |= CAP_ORPHANED;
f01f67f0
AC
98 }
99}
100
101void
bde42c60 102capability_require(struct CapabilityIndex *idx, const char *cap)
f01f67f0
AC
103{
104 struct CapabilityEntry *entry;
105
bde42c60 106 s_assert(idx != NULL);
f01f67f0 107
bde42c60 108 entry = irc_dictionary_retrieve(idx->cap_dict, cap);
f01f67f0
AC
109 if (entry != NULL)
110 entry->flags |= CAP_REQUIRED;
64b56afd
AC
111}
112
113static void
114capability_destroy(struct DictionaryElement *delem, void *privdata)
115{
116 s_assert(delem != NULL);
117
118 rb_free(delem->data);
119}
120
121struct CapabilityIndex *
885cd603 122capability_index_create(const char *name)
64b56afd 123{
bde42c60 124 struct CapabilityIndex *idx;
64b56afd 125
bde42c60 126 idx = rb_malloc(sizeof(struct CapabilityIndex));
885cd603 127 idx->name = rb_strdup(name);
bde42c60
JT
128 idx->cap_dict = irc_dictionary_create(strcasecmp);
129 idx->highest_bit = 1;
64b56afd 130
885cd603
AC
131 rb_dlinkAdd(idx, &idx->node, &capability_indexes);
132
bde42c60 133 return idx;
64b56afd
AC
134}
135
136void
bde42c60 137capability_index_destroy(struct CapabilityIndex *idx)
64b56afd 138{
bde42c60 139 s_assert(idx != NULL);
64b56afd 140
885cd603
AC
141 rb_dlinkDelete(&idx->node, &capability_indexes);
142
bde42c60
JT
143 irc_dictionary_destroy(idx->cap_dict, capability_destroy, NULL);
144 rb_free(idx);
64b56afd 145}
5e773521
AC
146
147const char *
bde42c60 148capability_index_list(struct CapabilityIndex *idx, unsigned int cap_mask)
5e773521
AC
149{
150 struct DictionaryIter iter;
151 struct CapabilityEntry *entry;
152 static char buf[BUFSIZE];
153 char *t = buf;
154 int tl;
155
bde42c60 156 s_assert(idx != NULL);
5e773521
AC
157
158 *t = '\0';
159
bde42c60 160 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
5e773521
AC
161 {
162 if (entry->value & cap_mask)
163 {
e915e51f 164 tl = rb_sprintf(t, "%s ", entry->cap);
5e773521
AC
165 t += tl;
166 }
167 }
168
169 t--;
170 *t = '\0';
171
172 return buf;
173}
ec3a9055
AC
174
175unsigned int
bde42c60 176capability_index_mask(struct CapabilityIndex *idx)
ec3a9055
AC
177{
178 struct DictionaryIter iter;
179 struct CapabilityEntry *entry;
180 unsigned int mask = 0;
181
bde42c60 182 s_assert(idx != NULL);
ec3a9055 183
bde42c60 184 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
ec3a9055 185 {
0582290f 186 if (!(entry->flags & CAP_ORPHANED))
8bedf01d 187 mask |= (1 << entry->value);
ec3a9055
AC
188 }
189
190 return mask;
191}
f01f67f0
AC
192
193unsigned int
bde42c60 194capability_index_get_required(struct CapabilityIndex *idx)
f01f67f0
AC
195{
196 struct DictionaryIter iter;
197 struct CapabilityEntry *entry;
198 unsigned int mask = 0;
199
bde42c60 200 s_assert(idx != NULL);
f01f67f0 201
bde42c60 202 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
f01f67f0
AC
203 {
204 if (!(entry->flags & CAP_ORPHANED) && (entry->flags & CAP_REQUIRED))
8bedf01d 205 mask |= (1 << entry->value);
f01f67f0
AC
206 }
207
208 return mask;
209}
a16910aa
AC
210
211void
212capability_index_stats(void (*cb)(const char *line, void *privdata), void *privdata)
213{
214 rb_dlink_node *node;
215 char buf[BUFSIZE];
216
217 RB_DLINK_FOREACH(node, capability_indexes.head)
218 {
219 struct CapabilityIndex *idx = node->data;
220 struct DictionaryIter iter;
221 struct CapabilityEntry *entry;
222
223 rb_snprintf(buf, sizeof buf, "'%s': allocated bits - %d", idx->name, (idx->highest_bit - 1));
224 cb(buf, privdata);
225
226 DICTIONARY_FOREACH(entry, &iter, idx->cap_dict)
227 {
228 rb_snprintf(buf, sizeof buf, "bit %d: '%s'", entry->value, entry->cap);
229 cb(buf, privdata);
230 }
231
232 rb_snprintf(buf, sizeof buf, "'%s': remaining bits - %ld", idx->name,
233 (sizeof(unsigned int) * 8) - (idx->highest_bit - 1));
234 cb(buf, privdata);
235 }
236
237 rb_snprintf(buf, sizeof buf, "%ld capability indexes", rb_dlink_list_length(&capability_indexes));
238 cb(buf, privdata);
239}