1 |
/* |
2 |
* ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd) |
3 |
* |
4 |
* Copyright (c) 1997-2020 ircd-hybrid development team |
5 |
* |
6 |
* This program is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation; either version 2 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* This program is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 |
19 |
* USA |
20 |
*/ |
21 |
|
22 |
/*! \file isupport.c |
23 |
* \brief Contains functions pertaining to RPL_ISUPPORT. |
24 |
* \version $Id$ |
25 |
*/ |
26 |
|
27 |
#include "stdinc.h" |
28 |
#include "list.h" |
29 |
#include "ircd.h" |
30 |
#include "conf.h" |
31 |
#include "send.h" |
32 |
#include "numeric.h" |
33 |
#include "client.h" |
34 |
#include "irc_string.h" |
35 |
#include "memory.h" |
36 |
#include "isupport.h" |
37 |
#include "channel.h" |
38 |
#include "channel_mode.h" |
39 |
#include "parse.h" |
40 |
|
41 |
|
42 |
/* Used for building up the isupport string, |
43 |
* used with init_isupport, add_isupport, delete_isupport |
44 |
*/ |
45 |
struct Isupport |
46 |
{ |
47 |
dlink_node node; |
48 |
char *name; |
49 |
char *options; |
50 |
int number; |
51 |
}; |
52 |
|
53 |
static dlink_list isupport_list; |
54 |
static dlink_list isupport_list_lines; |
55 |
|
56 |
/* |
57 |
* isupport_init() |
58 |
* |
59 |
* input - NONE |
60 |
* output - NONE |
61 |
* side effects - Must be called before isupport is enabled |
62 |
*/ |
63 |
void |
64 |
isupport_init(void) |
65 |
{ |
66 |
isupport_add("BOT", "B", -1); |
67 |
isupport_add("CALLERID", NULL, -1); |
68 |
isupport_add("CASEMAPPING", "ascii", -1); |
69 |
isupport_add("DEAF", "D", -1); |
70 |
isupport_add("KICKLEN", NULL, KICKLEN); |
71 |
isupport_add("MODES", NULL, MAXMODEPARAMS); |
72 |
isupport_add("PREFIX", "(ohv)" CMEMBER_STATUS_FLAGS, -1); |
73 |
isupport_add("STATUSMSG", CMEMBER_STATUS_FLAGS, -1); |
74 |
isupport_add("EXCEPTS", NULL, -1); |
75 |
isupport_add("INVEX", NULL, -1); |
76 |
} |
77 |
|
78 |
/* |
79 |
* isupport_add() |
80 |
* |
81 |
* input - name of supported function |
82 |
* - options if any |
83 |
* - number if any |
84 |
* output - NONE |
85 |
* side effects - Each supported item must call this when activated |
86 |
*/ |
87 |
void |
88 |
isupport_add(const char *name, const char *options, int n) |
89 |
{ |
90 |
dlink_node *node = NULL; |
91 |
struct Isupport *support = NULL; |
92 |
|
93 |
DLINK_FOREACH(node, isupport_list.head) |
94 |
{ |
95 |
support = node->data; |
96 |
if (irccmp(support->name, name) == 0) |
97 |
{ |
98 |
xfree(support->name); |
99 |
xfree(support->options); |
100 |
break; |
101 |
} |
102 |
} |
103 |
|
104 |
if (node == NULL) |
105 |
{ |
106 |
support = xcalloc(sizeof(*support)); |
107 |
dlinkAddTail(support, &support->node, &isupport_list); |
108 |
} |
109 |
|
110 |
support->name = xstrdup(name); |
111 |
if (options) |
112 |
support->options = xstrdup(options); |
113 |
support->number = n; |
114 |
|
115 |
isupport_rebuild(); |
116 |
} |
117 |
|
118 |
/* |
119 |
* isupport_delete() |
120 |
* |
121 |
* input - name of supported function |
122 |
* output - NONE |
123 |
* side effects - Each supported item must call this when deactivated |
124 |
*/ |
125 |
void |
126 |
isupport_delete(const char *name) |
127 |
{ |
128 |
dlink_node *node = NULL; |
129 |
|
130 |
DLINK_FOREACH(node, isupport_list.head) |
131 |
{ |
132 |
struct Isupport *support = node->data; |
133 |
|
134 |
if (irccmp(support->name, name) == 0) |
135 |
{ |
136 |
dlinkDelete(node, &isupport_list); |
137 |
xfree(support->name); |
138 |
xfree(support->options); |
139 |
xfree(support); |
140 |
break; |
141 |
} |
142 |
} |
143 |
|
144 |
isupport_rebuild(); |
145 |
} |
146 |
|
147 |
/* |
148 |
* issuport_rebuild() |
149 |
* |
150 |
* input - NONE |
151 |
* output - NONE |
152 |
* side effects - Destroy the isupport MessageFile lines, and rebuild. |
153 |
*/ |
154 |
void |
155 |
isupport_rebuild(void) |
156 |
{ |
157 |
char isupportbuffer[IRCD_BUFSIZE]; |
158 |
char *p = isupportbuffer; |
159 |
dlink_node *node = NULL, *node_next = NULL; |
160 |
int n = 0; |
161 |
int tokens = 0; |
162 |
size_t len = 0; |
163 |
size_t reserve = strlen(me.name) + HOSTLEN + strlen(numeric_form(RPL_ISUPPORT)); |
164 |
|
165 |
DLINK_FOREACH_SAFE(node, node_next, isupport_list_lines.head) |
166 |
{ |
167 |
dlinkDelete(node, &isupport_list_lines); |
168 |
xfree(node->data); |
169 |
free_dlink_node(node); |
170 |
} |
171 |
|
172 |
DLINK_FOREACH(node, isupport_list.head) |
173 |
{ |
174 |
struct Isupport *support = node->data; |
175 |
|
176 |
p += (n = sprintf(p, "%s", support->name)); |
177 |
len += n; |
178 |
|
179 |
if (support->options) |
180 |
{ |
181 |
p += (n = sprintf(p, "=%s", support->options)); |
182 |
len += n; |
183 |
} |
184 |
|
185 |
if (support->number > 0) |
186 |
{ |
187 |
p += (n = sprintf(p, "=%d", support->number)); |
188 |
len += n; |
189 |
} |
190 |
|
191 |
*p++ = ' '; |
192 |
len++; |
193 |
*p = '\0'; |
194 |
|
195 |
if (++tokens == (MAXPARA-2) || len >= (sizeof(isupportbuffer)-reserve)) |
196 |
{ /* arbritrary for now */ |
197 |
if (*--p == ' ') |
198 |
*p = '\0'; |
199 |
|
200 |
dlinkAddTail(xstrdup(isupportbuffer), make_dlink_node(), &isupport_list_lines); |
201 |
p = isupportbuffer; |
202 |
len = 0; |
203 |
n = 0; |
204 |
tokens = 0; |
205 |
} |
206 |
} |
207 |
|
208 |
if (len) |
209 |
{ |
210 |
if (*--p == ' ') |
211 |
*p = '\0'; |
212 |
dlinkAddTail(xstrdup(isupportbuffer), make_dlink_node(), &isupport_list_lines); |
213 |
} |
214 |
} |
215 |
|
216 |
/* isupport_show() |
217 |
* |
218 |
* inputs - pointer to client |
219 |
* output - NONE |
220 |
* side effects - display to client what we support (for them) |
221 |
*/ |
222 |
void |
223 |
isupport_show(struct Client *client) |
224 |
{ |
225 |
dlink_node *node; |
226 |
|
227 |
DLINK_FOREACH(node, isupport_list_lines.head) |
228 |
sendto_one_numeric(client, &me, RPL_ISUPPORT, node->data); |
229 |
} |