ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/modules/nickserv/collide.c
Revision: 3389
Committed: Fri Apr 25 14:12:15 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 7322 byte(s)
Log Message:
- Imported ircservices-5.1.24

File Contents

# Content
1 /* Routines related to nickname colliding.
2 *
3 * IRC Services is copyright (c) 1996-2009 Andrew Church.
4 * E-mail: <achurch@achurch.org>
5 * Parts written by Andrew Kempe and others.
6 * This program is free but copyrighted software; see the file GPL.txt for
7 * details.
8 */
9
10 #include "services.h"
11 #include "modules.h"
12 #include "language.h"
13 #include "timeout.h"
14
15 #include "nickserv.h"
16 #include "ns-local.h"
17
18 /*************************************************************************/
19
20 static int cb_collide = -1;
21
22
23 /* Structure used for collide/release/433 timeouts */
24
25 static struct my_timeout {
26 struct my_timeout *next, *prev;
27 NickInfo *ni;
28 Timeout *to;
29 int type;
30 } *my_timeouts;
31
32
33 static void timeout_collide(Timeout *t);
34 static void timeout_release(Timeout *t);
35 static void timeout_send_433(Timeout *t);
36
37 /*************************************************************************/
38 /*************************************************************************/
39
40 /* Collide a nick. */
41
42 void collide_nick(NickInfo *ni, int from_timeout)
43 {
44 if (!ni->user)
45 return;
46 if (!from_timeout) {
47 rem_ns_timeout(ni, TO_COLLIDE, 1);
48 rem_ns_timeout(ni, TO_SEND_433, 1);
49 }
50 if (call_callback_1(cb_collide, ni->user) > 0)
51 return;
52 if (NSForceNickChange) {
53 char *guestnick = make_guest_nick();
54 notice_lang(s_NickServ, ni->user, FORCENICKCHANGE_NOW, guestnick);
55 send_nickchange_remote(ni->nick, guestnick);
56 ni->status |= NS_GUESTED;
57 return;
58 } else {
59 notice_lang(s_NickServ, ni->user, DISCONNECT_NOW);
60 kill_user(s_NickServ, ni->nick, "Nick kill enforced");
61 introduce_enforcer(ni);
62 }
63 }
64
65 /*************************************************************************/
66
67 /* Introduce an enforcer for a given nick. */
68
69 void introduce_enforcer(NickInfo *ni)
70 {
71 char realname[NICKMAX+16]; /*Long enough for s_NickServ + " Enforcement"*/
72
73 snprintf(realname, sizeof(realname), "%s Enforcement", s_NickServ);
74 send_nick(ni->nick, NSEnforcerUser, NSEnforcerHost, ServerName,
75 realname, enforcer_modes);
76 ni->status |= NS_KILL_HELD;
77 add_ns_timeout(ni, TO_RELEASE, NSReleaseTimeout);
78 }
79
80 /*************************************************************************/
81
82 /* Release hold on a nick. */
83
84 void release_nick(NickInfo *ni, int from_timeout)
85 {
86 if (!from_timeout)
87 rem_ns_timeout(ni, TO_RELEASE, 1);
88 send_cmd(ni->nick, "QUIT");
89 ni->status &= ~NS_KILL_HELD;
90 }
91
92 /*************************************************************************/
93
94 /* Add a collide/release/433 timeout. */
95
96 void add_ns_timeout(NickInfo *ni, int type, time_t delay)
97 {
98 Timeout *to;
99 struct my_timeout *t;
100 void (*timeout_routine)(Timeout *);
101
102 if (!ni) {
103 log("BUG: NULL NickInfo in add_ns_timeout (type=%d delay=%ld)",
104 type, (long)delay);
105 return;
106 }
107 if (type == TO_COLLIDE)
108 timeout_routine = timeout_collide;
109 else if (type == TO_RELEASE)
110 timeout_routine = timeout_release;
111 else if (type == TO_SEND_433)
112 timeout_routine = timeout_send_433;
113 else {
114 module_log("BUG: unknown timeout type %d! ni=%p (%s), delay=%ld",
115 type, ni, ni->nick, (long)delay);
116 return;
117 }
118 to = add_timeout(delay, timeout_routine, 0);
119 to->data = ni;
120 t = smalloc(sizeof(*t));
121 LIST_INSERT(t, my_timeouts);
122 t->ni = ni;
123 t->to = to;
124 t->type = type;
125 ni->usecount++; /* make sure it isn't deleted when we're not looking */
126 }
127
128 /*************************************************************************/
129
130 /* Remove a collide/release timeout from our private list. If del_to is
131 * nonzero, also delete the associated timeout. If type == -1, delete
132 * timeouts of all types. If ni == NULL, delete all timeouts of the given
133 * type(s).
134 */
135
136 void rem_ns_timeout(NickInfo *ni, int type, int del_to)
137 {
138 struct my_timeout *t, *t2;
139
140 LIST_FOREACH_SAFE (t, my_timeouts, t2) {
141 if ((!ni || t->ni == ni) && (type < 0 || t->type == type)) {
142 LIST_REMOVE(t, my_timeouts);
143 if (del_to)
144 del_timeout(t->to);
145 put_nickinfo(t->ni); /* cancel usecount++ above */
146 free(t);
147 }
148 }
149 }
150
151 /*************************************************************************/
152 /*************************************************************************/
153
154 /* Collide a nick on timeout. */
155
156 static void timeout_collide(Timeout *t)
157 {
158 NickInfo *ni = t->data;
159 int idented = 0;
160
161 if (ni) {
162 if (ni->nickgroup != 0) {
163 NickGroupInfo *ngi = get_ngi(ni);
164 idented = (ngi && (nick_identified(ni) || nick_ident_nomail(ni)));
165 put_nickgroupinfo(ngi);
166 }
167 } else {
168 log("BUG: NULL NickInfo in timeout_collide");
169 return;
170 }
171 /* If they identified or don't exist anymore, don't kill them. */
172 if (!(idented || !ni->user || ni->user->my_signon > t->settime)) {
173 /* The RELEASE timeout will always add to the beginning of the
174 * list, so we won't see it. Which is fine because it can't be
175 * triggered yet anyway. */
176 collide_nick(ni, 1);
177 }
178 rem_ns_timeout(ni, TO_COLLIDE, 0);
179 }
180
181 /*************************************************************************/
182
183 /* Release a nick on timeout. */
184
185 static void timeout_release(Timeout *t)
186 {
187 NickInfo *ni = t->data;
188
189 if (!ni) {
190 log("BUG: NULL NickInfo in timeout_release");
191 return;
192 }
193 release_nick(ni, 1);
194 rem_ns_timeout(ni, TO_RELEASE, 0);
195 }
196
197 /*************************************************************************/
198
199 /* Send a 433 (nick in use) numeric to the given user. */
200
201 static void timeout_send_433(Timeout *t)
202 {
203 NickInfo *ni = t->data;
204 User *u;
205
206 if (!ni) {
207 log("BUG: NULL NickInfo in timeout_send_433");
208 return;
209 }
210 /* If they identified or don't exist anymore, don't send the 433. */
211 if (!((nick_identified(ni) || nick_ident_nomail(ni))
212 || !(u = get_user(ni->nick))
213 || u->my_signon > t->settime)
214 ) {
215 if (ni->status & NS_VERBOTEN) {
216 send_cmd(ServerName, "433 %s %s :Nickname may not be used",
217 ni->nick, ni->nick);
218 } else {
219 send_cmd(ServerName, "433 %s %s :Nickname is registered to"
220 " someone else", ni->nick, ni->nick);
221 }
222 }
223 rem_ns_timeout(ni, TO_SEND_433, 0);
224 }
225
226 /*************************************************************************/
227 /*************************************************************************/
228
229 int init_collide(void)
230 {
231 cb_collide = register_callback("collide");
232 if (cb_collide < 0) {
233 module_log("collide: Unable to register callbacks");
234 exit_collide();
235 return 0;
236 }
237 return 1;
238 }
239
240 /*************************************************************************/
241
242 void exit_collide()
243 {
244 rem_ns_timeout(NULL, -1, 1);
245 unregister_callback(cb_collide);
246 }
247
248 /*************************************************************************/
249
250 /*
251 * Local variables:
252 * c-file-style: "stroustrup"
253 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
254 * indent-tabs-mode: nil
255 * End:
256 *
257 * vim: expandtab shiftwidth=4:
258 */