]> jfr.im git - solanum.git/blame - modules/core/m_join.c
Merge pull request #33 from Argure/master
[solanum.git] / modules / core / m_join.c
CommitLineData
212380e3
AC
1/*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_join.c: Joins a channel.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
f4a80ce6 24 * $Id: m_join.c 3494 2007-05-27 13:07:27Z jilles $
212380e3
AC
25 */
26
27#include "stdinc.h"
212380e3
AC
28#include "channel.h"
29#include "client.h"
30#include "common.h"
31#include "hash.h"
4562c604 32#include "match.h"
212380e3
AC
33#include "ircd.h"
34#include "numeric.h"
35#include "send.h"
36#include "s_serv.h"
37#include "s_conf.h"
38#include "s_newconf.h"
39#include "msg.h"
40#include "parse.h"
41#include "modules.h"
212380e3 42#include "packet.h"
acdf71d9 43#include "chmode.h"
7e132ff0 44#include "ratelimit.h"
212380e3
AC
45
46static int m_join(struct Client *, struct Client *, int, const char **);
47static int ms_join(struct Client *, struct Client *, int, const char **);
8cc12805 48static int ms_sjoin(struct Client *, struct Client *, int, const char **);
212380e3
AC
49
50static int h_can_create_channel;
51static int h_channel_join;
52
53struct Message join_msgtab = {
54 "JOIN", 0, 0, 0, MFLG_SLOW,
55 {mg_unreg, {m_join, 2}, {ms_join, 2}, mg_ignore, mg_ignore, {m_join, 2}}
56};
57
8cc12805
VY
58struct Message sjoin_msgtab = {
59 "SJOIN", 0, 0, 0, MFLG_SLOW,
1766edef 60 {mg_unreg, mg_ignore, mg_ignore, {ms_sjoin, 4}, mg_ignore, mg_ignore}
8cc12805
VY
61};
62
63mapi_clist_av1 join_clist[] = { &join_msgtab, &sjoin_msgtab, NULL };
212380e3
AC
64
65mapi_hlist_av1 join_hlist[] = {
66 { "can_create_channel", &h_can_create_channel },
67 { "channel_join", &h_channel_join },
68 { NULL, NULL },
69};
70
f4a80ce6 71DECLARE_MODULE_AV1(join, NULL, NULL, join_clist, join_hlist, NULL, "$Revision: 3494 $");
212380e3 72
f4a80ce6 73static void do_join_0(struct Client *client_p, struct Client *source_p);
212380e3 74static int check_channel_name_loc(struct Client *source_p, const char *name);
35bfe0e6 75static void send_join_error(struct Client *source_p, int numeric, const char *name);
212380e3
AC
76
77static void set_final_mode(struct Mode *mode, struct Mode *oldmode);
78static void remove_our_modes(struct Channel *chptr, struct Client *source_p);
79
8cc12805 80static void remove_ban_list(struct Channel *chptr, struct Client *source_p,
8afeb720 81 rb_dlink_list * list, char c, int mems);
8cc12805 82
212380e3
AC
83static char modebuf[MODEBUFLEN];
84static char parabuf[MODEBUFLEN];
8cc12805 85static const char *para[MAXMODEPARAMS];
212380e3 86static char *mbuf;
8cc12805 87static int pargs;
212380e3
AC
88
89/* Check what we will forward to, without sending any notices to the user
90 * -- jilles
91 */
92static struct Channel *
93check_forward(struct Client *source_p, struct Channel *chptr,
765d839d 94 char *key, int *err)
212380e3
AC
95{
96 int depth = 0, i;
d9af501a 97 const char *next = NULL;
765d839d
EM
98
99 /* The caller (m_join) is only interested in the reason
100 * for the original channel.
101 */
102 if ((*err = can_join(source_p, chptr, key, &next)) == 0)
103 return chptr;
212380e3 104
6a85e665
JT
105 /* User is +Q, or forwarding disabled */
106 if (IsNoForward(source_p) || !ConfigChannel.use_forward)
212380e3
AC
107 return NULL;
108
109 while (depth < 16)
110 {
97532cfa
JT
111 if (next == NULL)
112 return NULL;
765d839d 113 chptr = find_channel(next);
212380e3
AC
114 /* Can only forward to existing channels */
115 if (chptr == NULL)
116 return NULL;
117 /* Already on there, show original error message */
118 if (IsMember(source_p, chptr))
119 return NULL;
120 /* Juped. Sending a warning notice would be unfair */
121 if (hash_find_resv(chptr->chname))
122 return NULL;
123 /* Don't forward to +Q channel */
124 if (chptr->mode.mode & MODE_DISFORWARD)
125 return NULL;
765d839d 126 i = can_join(source_p, chptr, key, &next);
212380e3
AC
127 if (i == 0)
128 return chptr;
212380e3
AC
129 depth++;
130 }
131
132 return NULL;
133}
134
135/*
136 * m_join
212380e3
AC
137 * parv[1] = channel
138 * parv[2] = channel password (key)
139 */
140static int
141m_join(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
142{
143 static char jbuf[BUFSIZE];
765d839d 144 struct Channel *chptr = NULL, *chptr2 = NULL;
212380e3
AC
145 struct ConfItem *aconf;
146 char *name;
147 char *key = NULL;
095efcf0 148 const char *modes;
212380e3
AC
149 int i, flags = 0;
150 char *p = NULL, *p2 = NULL;
151 char *chanlist;
152 char *mykey;
212380e3
AC
153
154 jbuf[0] = '\0';
155
156 /* rebuild the list of channels theyre supposed to be joining.
157 * this code has a side effect of losing keys, but..
158 */
159 chanlist = LOCAL_COPY(parv[1]);
4a2651e5 160 for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
212380e3
AC
161 {
162 /* check the length and name of channel is ok */
163 if(!check_channel_name_loc(source_p, name) || (strlen(name) > LOC_CHANNELLEN))
164 {
165 sendto_one_numeric(source_p, ERR_BADCHANNAME,
166 form_str(ERR_BADCHANNAME), (unsigned char *) name);
167 continue;
168 }
169
f4a80ce6
JT
170 /* join 0 parts all channels */
171 if(*name == '0' && (name[1] == ',' || name[1] == '\0') && name == chanlist)
172 {
173 (void) strcpy(jbuf, "0");
174 continue;
175 }
176
212380e3 177 /* check it begins with # or &, and local chans are disabled */
341f971e
SB
178 else if(!IsChannelName(name) ||
179 ( ConfigChannel.disable_local_channels && name[0] == '&'))
212380e3
AC
180 {
181 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
182 form_str(ERR_NOSUCHCHANNEL), name);
183 continue;
184 }
185
186 /* see if its resv'd */
187 if(!IsExemptResv(source_p) && (aconf = hash_find_resv(name)))
188 {
189 sendto_one_numeric(source_p, ERR_BADCHANNAME,
190 form_str(ERR_BADCHANNAME), name);
191
192 /* dont warn for opers */
193 if(!IsExemptJupe(source_p) && !IsOper(source_p))
194 sendto_realops_snomask(SNO_SPY, L_NETWIDE,
195 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
196 source_p->name, source_p->username,
63aecfb9 197 source_p->orighost, name, aconf->passwd);
212380e3
AC
198 /* dont update tracking for jupe exempt users, these
199 * are likely to be spamtrap leaves
200 */
201 else if(IsExemptJupe(source_p))
202 aconf->port--;
203
204 continue;
205 }
206
207 if(splitmode && !IsOper(source_p) && (*name != '&') &&
208 ConfigChannel.no_join_on_split)
209 {
210 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
211 me.name, source_p->name, name);
212 continue;
213 }
214
215 if(*jbuf)
216 (void) strcat(jbuf, ",");
1f9de103 217 (void) rb_strlcat(jbuf, name, sizeof(jbuf));
212380e3
AC
218 }
219
220 if(parc > 2)
221 {
222 mykey = LOCAL_COPY(parv[2]);
4a2651e5 223 key = rb_strtok_r(mykey, ",", &p2);
212380e3
AC
224 }
225
4a2651e5
VY
226 for(name = rb_strtok_r(jbuf, ",", &p); name;
227 key = (key) ? rb_strtok_r(NULL, ",", &p2) : NULL, name = rb_strtok_r(NULL, ",", &p))
212380e3
AC
228 {
229 hook_data_channel_activity hook_info;
230
f4a80ce6
JT
231 /* JOIN 0 simply parts all channels the user is in */
232 if(*name == '0' && !atoi(name))
233 {
234 if(source_p->user->channel.head == NULL)
235 continue;
236
237 do_join_0(&me, source_p);
238 continue;
239 }
240
212380e3
AC
241 /* look for the channel */
242 if((chptr = find_channel(name)) != NULL)
243 {
244 if(IsMember(source_p, chptr))
245 continue;
246
247 flags = 0;
248 }
249 else
250 {
251 hook_data_client_approval moduledata;
252
253 moduledata.client = source_p;
254 moduledata.approved = 0;
255
256 call_hook(h_can_create_channel, &moduledata);
257
544cde90 258 if(moduledata.approved != 0)
212380e3 259 {
35bfe0e6
JT
260 if(moduledata.approved != ERR_CUSTOM)
261 send_join_error(source_p,
262 moduledata.approved,
263 name);
212380e3
AC
264 continue;
265 }
266
267 if(splitmode && !IsOper(source_p) && (*name != '&') &&
268 ConfigChannel.no_create_on_split)
269 {
270 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
271 me.name, source_p->name, name);
272 continue;
273 }
274
275 flags = CHFL_CHANOP;
276 }
277
5b96d9a6 278 if((rb_dlink_list_length(&source_p->user->channel) >=
212380e3
AC
279 (unsigned long) ConfigChannel.max_chans_per_user) &&
280 (!IsOper(source_p) ||
5b96d9a6 281 (rb_dlink_list_length(&source_p->user->channel) >=
212380e3
AC
282 (unsigned long) ConfigChannel.max_chans_per_user * 3)))
283 {
284 sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
285 me.name, source_p->name, name);
cddbab51 286 continue;
212380e3
AC
287 }
288
212380e3
AC
289 if(chptr == NULL) /* If I already have a chptr, no point doing this */
290 {
291 chptr = get_or_create_channel(source_p, name, NULL);
292
293 if(chptr == NULL)
294 {
295 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
296 me.name, source_p->name, name);
212380e3
AC
297 continue;
298 }
299 }
300
765d839d
EM
301 /* If check_forward returns NULL, they couldn't join and there wasn't a usable forward channel. */
302 if(!(chptr2 = check_forward(source_p, chptr, key, &i)))
212380e3 303 {
765d839d
EM
304 /* might be wrong, but is there any other better location for such?
305 * see extensions/chm_operonly.c for other comments on this
306 * -- dwr
307 */
308 if(i != ERR_CUSTOM)
35bfe0e6 309 send_join_error(source_p, i, name);
765d839d 310 continue;
212380e3 311 }
765d839d
EM
312 else if(chptr != chptr2)
313 sendto_one_numeric(source_p, ERR_LINKCHANNEL, form_str(ERR_LINKCHANNEL), name, chptr2->chname);
314
315 chptr = chptr2;
212380e3 316
ff91faaf
JT
317 if(flags == 0 &&
318 !IsOper(source_p) && !IsExemptSpambot(source_p))
cf3564d6
JT
319 check_spambot_warning(source_p, name);
320
212380e3
AC
321 /* add the user to the channel */
322 add_user_to_channel(chptr, source_p, flags);
323 if (chptr->mode.join_num &&
e3354945 324 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
212380e3
AC
325 {
326 chptr->join_count = 0;
e3354945 327 chptr->join_delta = rb_current_time();
212380e3
AC
328 }
329 chptr->join_count++;
330
7e132ff0
KB
331 /* credit user for join */
332 credit_client_join(source_p);
333
212380e3
AC
334 /* we send the user their join here, because we could have to
335 * send a mode out next.
336 */
805cfa5a 337 send_channel_join(chptr, source_p);
212380e3
AC
338
339 /* its a new channel, set +nt and burst. */
340 if(flags & CHFL_CHANOP)
341 {
e3354945 342 chptr->channelts = rb_current_time();
212380e3
AC
343 chptr->mode.mode |= MODE_TOPICLIMIT;
344 chptr->mode.mode |= MODE_NOPRIVMSGS;
095efcf0 345 modes = channel_modes(chptr, &me);
212380e3 346
095efcf0
JT
347 sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s %s",
348 me.name, chptr->chname, modes);
212380e3 349
db2545b1
JT
350 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
351 ":%s SJOIN %ld %s %s :@%s",
352 me.id, (long) chptr->channelts,
353 chptr->chname, modes, source_p->id);
212380e3
AC
354 }
355 else
356 {
212380e3 357 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
bee3b671 358 ":%s JOIN %ld %s +",
212380e3 359 use_id(source_p), (long) chptr->channelts,
bee3b671 360 chptr->chname);
212380e3
AC
361 }
362
363 del_invite(chptr, source_p);
364
365 if(chptr->topic != NULL)
366 {
367 sendto_one(source_p, form_str(RPL_TOPIC), me.name,
368 source_p->name, chptr->chname, chptr->topic);
369
370 sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
371 me.name, source_p->name, chptr->chname,
0cce01d3
JT
372 chptr->topic_info,
373 (unsigned long)chptr->topic_time);
212380e3
AC
374 }
375
376 channel_member_names(chptr, source_p, 1);
377
212380e3
AC
378 hook_info.client = source_p;
379 hook_info.chptr = chptr;
380 hook_info.key = key;
381 call_hook(h_channel_join, &hook_info);
382 }
383
384 return 0;
385}
386
387/*
388 * ms_join
35835646
JT
389 * parv[1] = channel TS
390 * parv[2] = channel
391 * parv[3] = "+", formerly channel modes but now unused
392 * alternatively, a single "0" parameter parts all channels
212380e3
AC
393 */
394static int
395ms_join(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
396{
397 struct Channel *chptr;
bee3b671 398 static struct Mode mode;
212380e3
AC
399 time_t oldts;
400 time_t newts;
401 int isnew;
212380e3 402 int keep_our_modes = YES;
637c4932 403 rb_dlink_node *ptr, *next_ptr;
212380e3 404
f4a80ce6
JT
405 /* special case for join 0 */
406 if((parv[1][0] == '0') && (parv[1][1] == '\0') && parc == 2)
407 {
408 do_join_0(client_p, source_p);
409 return 0;
410 }
411
212380e3
AC
412 if(parc < 4)
413 return 0;
414
415 if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
416 return 0;
417
418 /* joins for local channels cant happen. */
419 if(parv[2][0] == '&')
420 return 0;
421
422 mbuf = modebuf;
423 mode.key[0] = mode.forward[0] = '\0';
424 mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
425
212380e3
AC
426 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
427 return 0;
428
429 newts = atol(parv[1]);
430 oldts = chptr->channelts;
212380e3
AC
431
432#ifdef IGNORE_BOGUS_TS
433 if(newts < 800000000)
434 {
435 sendto_realops_snomask(SNO_DEBUG, L_ALL,
436 "*** Bogus TS %ld on %s ignored from %s",
437 (long) newts, chptr->chname, client_p->name);
438 newts = (oldts == 0) ? oldts : 800000000;
439 }
440#else
441 /* making a channel TS0 */
442 if(!isnew && !newts && oldts)
443 {
444 sendto_channel_local(ALL_MEMBERS, chptr,
445 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to 0",
446 me.name, chptr->chname, chptr->chname, (long) oldts);
447 sendto_realops_snomask(SNO_GENERAL, L_ALL,
448 "Server %s changing TS on %s from %ld to 0",
449 source_p->name, chptr->chname, (long) oldts);
450 }
451#endif
452
453 if(isnew)
454 chptr->channelts = newts;
455 else if(newts == 0 || oldts == 0)
456 chptr->channelts = 0;
457 else if(newts == oldts)
458 ;
459 else if(newts < oldts)
460 {
461 keep_our_modes = NO;
462 chptr->channelts = newts;
463 }
212380e3 464
212380e3
AC
465 /* Lost the TS, other side wins, so remove modes on this side */
466 if(!keep_our_modes)
467 {
bee3b671
JT
468 set_final_mode(&mode, &chptr->mode);
469 chptr->mode = mode;
212380e3 470 remove_our_modes(chptr, source_p);
637c4932 471 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
212380e3
AC
472 {
473 del_invite(chptr, ptr->data);
474 }
bee3b671
JT
475 /* If setting -j, clear join throttle state -- jilles */
476 chptr->join_count = chptr->join_delta = 0;
212380e3
AC
477 sendto_channel_local(ALL_MEMBERS, chptr,
478 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
479 me.name, chptr->chname, chptr->chname,
480 (long) oldts, (long) newts);
1117fbd3
JT
481 /* Update capitalization in channel name, this makes the
482 * capitalization timestamped like modes are -- jilles */
483 strcpy(chptr->chname, parv[2]);
bee3b671
JT
484 if(*modebuf != '\0')
485 sendto_channel_local(ALL_MEMBERS, chptr,
486 ":%s MODE %s %s %s",
487 source_p->servptr->name,
488 chptr->chname, modebuf, parabuf);
489 *modebuf = *parabuf = '\0';
6fb6bd15
AC
490
491 /* since we're dropping our modes, we want to clear the mlock as well. --nenolod */
492 set_channel_mlock(client_p, source_p, chptr, NULL, FALSE);
212380e3
AC
493 }
494
212380e3
AC
495 if(!IsMember(source_p, chptr))
496 {
497 add_user_to_channel(chptr, source_p, CHFL_PEON);
498 if (chptr->mode.join_num &&
e3354945 499 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
212380e3
AC
500 {
501 chptr->join_count = 0;
e3354945 502 chptr->join_delta = rb_current_time();
212380e3
AC
503 }
504 chptr->join_count++;
805cfa5a 505 send_channel_join(chptr, source_p);
212380e3
AC
506 }
507
212380e3 508 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
bee3b671
JT
509 ":%s JOIN %ld %s +",
510 source_p->id, (long) chptr->channelts, chptr->chname);
212380e3
AC
511 return 0;
512}
513
8cc12805
VY
514static int
515ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
516{
8cc12805
VY
517 static char buf_uid[BUFSIZE];
518 static const char empty_modes[] = "0";
519 struct Channel *chptr;
520 struct Client *target_p, *fakesource_p;
521 time_t newts;
522 time_t oldts;
523 static struct Mode mode, *oldmode;
524 const char *modes;
525 int args = 0;
526 int keep_our_modes = 1;
527 int keep_new_modes = 1;
528 int fl;
529 int isnew;
890423fb 530 int mlen_uid;
8cc12805
VY
531 int len_nick;
532 int len_uid;
533 int len;
534 int joins = 0;
535 const char *s;
8cc12805
VY
536 char *ptr_uid;
537 char *p;
538 int i, joinc = 0, timeslice = 0;
539 static char empty[] = "";
540 rb_dlink_node *ptr, *next_ptr;
541
542 if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
543 return 0;
544
545 /* SJOIN's for local channels can't happen. */
546 if(*parv[2] == '&')
547 return 0;
548
549 modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
550 pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
551
552 /* Hide connecting server on netburst -- jilles */
553 if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
554 fakesource_p = &me;
555 else
556 fakesource_p = source_p;
557
558 mbuf = modebuf;
559 newts = atol(parv[1]);
560
561 s = parv[3];
562 while (*s)
563 {
564 switch (*(s++))
565 {
8cc12805 566 case 'f':
f427c8b0 567 rb_strlcpy(mode.forward, parv[4 + args], sizeof(mode.forward));
8cc12805
VY
568 args++;
569 if(parc < 5 + args)
570 return 0;
571 break;
572 case 'j':
573 sscanf(parv[4 + args], "%d:%d", &joinc, &timeslice);
574 args++;
575 mode.join_num = joinc;
576 mode.join_time = timeslice;
577 if(parc < 5 + args)
578 return 0;
579 break;
580 case 'k':
f427c8b0 581 rb_strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
8cc12805
VY
582 args++;
583 if(parc < 5 + args)
584 return 0;
585 break;
586 case 'l':
587 mode.limit = atoi(parv[4 + args]);
588 args++;
589 if(parc < 5 + args)
590 return 0;
591 break;
efccc22c
VY
592 default:
593 if(chmode_flags[(int) *s] != 0)
594 {
595 mode.mode |= chmode_flags[(int) *s];
596 }
8cc12805
VY
597 }
598 }
599
600 if(parv[args + 4])
601 {
602 s = parv[args + 4];
603
604 /* remove any leading spaces */
605 while (*s == ' ')
606 s++;
607 }
608 else
609 s = "";
610
611 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
612 return 0; /* channel name too long? */
613
614
615 oldts = chptr->channelts;
616 oldmode = &chptr->mode;
617
618#ifdef IGNORE_BOGUS_TS
619 if(newts < 800000000)
620 {
621 sendto_realops_snomask(SNO_DEBUG, L_ALL,
622 "*** Bogus TS %ld on %s ignored from %s",
623 (long) newts, chptr->chname, client_p->name);
624
625 newts = (oldts == 0) ? oldts : 800000000;
626 }
627#else
628 if(!isnew && !newts && oldts)
629 {
630 sendto_channel_local(ALL_MEMBERS, chptr,
631 ":%s NOTICE %s :*** Notice -- TS for %s "
632 "changed from %ld to 0",
633 me.name, chptr->chname, chptr->chname, (long) oldts);
634 sendto_realops_snomask(SNO_GENERAL, L_ALL,
635 "Server %s changing TS on %s from %ld to 0",
636 source_p->name, chptr->chname, (long) oldts);
637 }
638#endif
639
640 if(isnew)
641 chptr->channelts = newts;
642
643 else if(newts == 0 || oldts == 0)
644 chptr->channelts = 0;
645 else if(newts == oldts)
646 ;
647 else if(newts < oldts)
648 {
649 /* If configured, kick people trying to join +i/+k
650 * channels by recreating them on split servers.
a1574df4
JT
651 * If the source has sent EOB, assume this is some
652 * sort of hack by services. If cmode +i is set,
653 * services can send kicks if needed; if the key
654 * differs, services cannot kick in a race-free
655 * manner so do so here.
8cc12805
VY
656 * -- jilles */
657 if (ConfigChannel.kick_on_split_riding &&
a1574df4
JT
658 ((!HasSentEob(source_p) &&
659 mode.mode & MODE_INVITEONLY) ||
8cc12805
VY
660 (mode.key[0] != 0 && irccmp(mode.key, oldmode->key) != 0)))
661 {
662 struct membership *msptr;
663 struct Client *who;
664 int l = rb_dlink_list_length(&chptr->members);
8cc12805
VY
665
666 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
667 {
668 msptr = ptr->data;
669 who = msptr->client_p;
670 sendto_one(who, ":%s KICK %s %s :Net Rider",
671 me.name, chptr->chname, who->name);
672
673 sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
674 ":%s KICK %s %s :Net Rider",
675 me.id, chptr->chname,
676 who->id);
8cc12805
VY
677 remove_user_from_channel(msptr);
678 if (--l == 0)
679 break;
680 }
681 if (l == 0)
682 {
683 /* Channel was emptied, create a new one */
684 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
685 return 0; /* oops! */
686
8cc12805
VY
687 oldmode = &chptr->mode;
688 }
689 }
690 keep_our_modes = NO;
691 chptr->channelts = newts;
692 }
693 else
694 keep_new_modes = NO;
695
696 if(!keep_new_modes)
697 mode = *oldmode;
698 else if(keep_our_modes)
699 {
700 mode.mode |= oldmode->mode;
701 if(oldmode->limit > mode.limit)
702 mode.limit = oldmode->limit;
703 if(strcmp(mode.key, oldmode->key) < 0)
704 strcpy(mode.key, oldmode->key);
705 if(oldmode->join_num > mode.join_num ||
706 (oldmode->join_num == mode.join_num &&
707 oldmode->join_time > mode.join_time))
708 {
709 mode.join_num = oldmode->join_num;
710 mode.join_time = oldmode->join_time;
711 }
712 if(irccmp(mode.forward, oldmode->forward) < 0)
713 strcpy(mode.forward, oldmode->forward);
714 }
715 else
716 {
717 /* If setting -j, clear join throttle state -- jilles */
718 if (!mode.join_num)
719 chptr->join_count = chptr->join_delta = 0;
720 }
721
722 set_final_mode(&mode, oldmode);
723 chptr->mode = mode;
724
725 /* Lost the TS, other side wins, so remove modes on this side */
726 if(!keep_our_modes)
727 {
728 remove_our_modes(chptr, fakesource_p);
729 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
730 {
731 del_invite(chptr, ptr->data);
732 }
7b22c84f
JT
733
734 if(rb_dlink_list_length(&chptr->banlist) > 0)
735 remove_ban_list(chptr, fakesource_p, &chptr->banlist, 'b', ALL_MEMBERS);
736 if(rb_dlink_list_length(&chptr->exceptlist) > 0)
737 remove_ban_list(chptr, fakesource_p, &chptr->exceptlist,
738 'e', ONLY_CHANOPS);
739 if(rb_dlink_list_length(&chptr->invexlist) > 0)
740 remove_ban_list(chptr, fakesource_p, &chptr->invexlist,
741 'I', ONLY_CHANOPS);
742 if(rb_dlink_list_length(&chptr->quietlist) > 0)
743 remove_ban_list(chptr, fakesource_p, &chptr->quietlist,
744 'q', ALL_MEMBERS);
745 chptr->bants++;
746
8cc12805
VY
747 sendto_channel_local(ALL_MEMBERS, chptr,
748 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
749 me.name, chptr->chname, chptr->chname,
750 (long) oldts, (long) newts);
751 /* Update capitalization in channel name, this makes the
752 * capitalization timestamped like modes are -- jilles */
753 strcpy(chptr->chname, parv[2]);
6fb6bd15
AC
754
755 /* since we're dropping our modes, we want to clear the mlock as well. --nenolod */
756 set_channel_mlock(client_p, source_p, chptr, NULL, FALSE);
8cc12805
VY
757 }
758
759 if(*modebuf != '\0')
760 sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
761 fakesource_p->name, chptr->chname, modebuf, parabuf);
762
763 *modebuf = *parabuf = '\0';
764
765 if(parv[3][0] != '0' && keep_new_modes)
766 modes = channel_modes(chptr, source_p);
767 else
768 modes = empty_modes;
769
8cc12805
VY
770 mlen_uid = rb_sprintf(buf_uid, ":%s SJOIN %ld %s %s :",
771 use_id(source_p), (long) chptr->channelts, parv[2], modes);
772 ptr_uid = buf_uid + mlen_uid;
773
774 mbuf = modebuf;
775 para[0] = para[1] = para[2] = para[3] = empty;
776 pargs = 0;
777 len_nick = len_uid = 0;
778
779 /* if theres a space, theres going to be more than one nick, change the
780 * first space to \0, so s is just the first nick, and point p to the
781 * second nick
782 */
783 if((p = strchr(s, ' ')) != NULL)
784 {
785 *p++ = '\0';
786 }
787
788 *mbuf++ = '+';
789
790 while (s)
791 {
792 fl = 0;
793
794 for (i = 0; i < 2; i++)
795 {
796 if(*s == '@')
797 {
798 fl |= CHFL_CHANOP;
799 s++;
800 }
801 else if(*s == '+')
802 {
803 fl |= CHFL_VOICE;
804 s++;
805 }
806 }
807
808 /* if the client doesnt exist or is fake direction, skip. */
809 if(!(target_p = find_client(s)) ||
810 (target_p->from != client_p) || !IsPerson(target_p))
811 goto nextnick;
812
813 /* we assume for these we can fit at least one nick/uid in.. */
814
815 /* check we can fit another status+nick+space into a buffer */
8cc12805
VY
816 if((mlen_uid + len_uid + IDLEN + 3) > (BUFSIZE - 3))
817 {
818 *(ptr_uid - 1) = '\0';
819 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
820 ptr_uid = buf_uid + mlen_uid;
821 len_uid = 0;
822 }
823
824 if(keep_new_modes)
825 {
826 if(fl & CHFL_CHANOP)
827 {
8cc12805
VY
828 *ptr_uid++ = '@';
829 len_nick++;
830 len_uid++;
831 }
832 if(fl & CHFL_VOICE)
833 {
8cc12805
VY
834 *ptr_uid++ = '+';
835 len_nick++;
836 len_uid++;
837 }
838 }
839
840 /* copy the nick to the two buffers */
8cc12805
VY
841 len = rb_sprintf(ptr_uid, "%s ", use_id(target_p));
842 ptr_uid += len;
843 len_uid += len;
844
845 if(!keep_new_modes)
846 fl = 0;
847
848 if(!IsMember(target_p, chptr))
849 {
850 add_user_to_channel(chptr, target_p, fl);
805cfa5a 851 send_channel_join(chptr, target_p);
8cc12805
VY
852 joins++;
853 }
854
855 if(fl & CHFL_CHANOP)
856 {
857 *mbuf++ = 'o';
858 para[pargs++] = target_p->name;
859
860 /* a +ov user.. bleh */
861 if(fl & CHFL_VOICE)
862 {
863 /* its possible the +o has filled up MAXMODEPARAMS, if so, start
864 * a new buffer
865 */
866 if(pargs >= MAXMODEPARAMS)
867 {
868 *mbuf = '\0';
869 sendto_channel_local(ALL_MEMBERS, chptr,
870 ":%s MODE %s %s %s %s %s %s",
871 fakesource_p->name, chptr->chname,
872 modebuf,
873 para[0], para[1], para[2], para[3]);
874 mbuf = modebuf;
875 *mbuf++ = '+';
876 para[0] = para[1] = para[2] = para[3] = NULL;
877 pargs = 0;
878 }
879
880 *mbuf++ = 'v';
881 para[pargs++] = target_p->name;
882 }
883 }
884 else if(fl & CHFL_VOICE)
885 {
886 *mbuf++ = 'v';
887 para[pargs++] = target_p->name;
888 }
889
890 if(pargs >= MAXMODEPARAMS)
891 {
892 *mbuf = '\0';
893 sendto_channel_local(ALL_MEMBERS, chptr,
894 ":%s MODE %s %s %s %s %s %s",
895 fakesource_p->name,
896 chptr->chname,
897 modebuf, para[0], para[1], para[2], para[3]);
898 mbuf = modebuf;
899 *mbuf++ = '+';
900 para[0] = para[1] = para[2] = para[3] = NULL;
901 pargs = 0;
902 }
903
904 nextnick:
905 /* p points to the next nick */
906 s = p;
907
908 /* if there was a trailing space and p was pointing to it, then we
909 * need to exit.. this has the side effect of breaking double spaces
910 * in an sjoin.. but that shouldnt happen anyway
911 */
912 if(s && (*s == '\0'))
913 s = p = NULL;
914
915 /* if p was NULL due to no spaces, s wont exist due to the above, so
916 * we cant check it for spaces.. if there are no spaces, then when
917 * we next get here, s will be NULL
918 */
919 if(s && ((p = strchr(s, ' ')) != NULL))
920 {
921 *p++ = '\0';
922 }
923 }
924
925 *mbuf = '\0';
926 if(pargs)
927 {
928 sendto_channel_local(ALL_MEMBERS, chptr,
929 ":%s MODE %s %s %s %s %s %s",
930 fakesource_p->name, chptr->chname, modebuf,
931 para[0], CheckEmpty(para[1]),
932 CheckEmpty(para[2]), CheckEmpty(para[3]));
933 }
934
935 if(!joins && !(chptr->mode.mode & MODE_PERMANENT) && isnew)
936 {
937 destroy_channel(chptr);
938
939 return 0;
940 }
941
942 /* Keep the colon if we're sending an SJOIN without nicks -- jilles */
943 if (joins)
944 {
8cc12805
VY
945 *(ptr_uid - 1) = '\0';
946 }
947
948 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
8cc12805 949
8cc12805
VY
950 return 0;
951}
952
f4a80ce6
JT
953/*
954 * do_join_0
955 *
956 * inputs - pointer to client doing join 0
957 * output - NONE
958 * side effects - Use has decided to join 0. This is legacy
959 * from the days when channels were numbers not names. *sigh*
f4a80ce6
JT
960 */
961static void
962do_join_0(struct Client *client_p, struct Client *source_p)
963{
964 struct membership *msptr;
965 struct Channel *chptr = NULL;
5b96d9a6 966 rb_dlink_node *ptr;
f4a80ce6
JT
967
968 /* Finish the flood grace period... */
969 if(MyClient(source_p) && !IsFloodDone(source_p))
970 flood_endgrace(source_p);
971
f4a80ce6 972 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s JOIN 0", use_id(source_p));
f4a80ce6 973
f4a80ce6
JT
974 while((ptr = source_p->user->channel.head))
975 {
4eb9a3ca
JT
976 if(MyConnect(source_p) &&
977 !IsOper(source_p) && !IsExemptSpambot(source_p))
978 check_spambot_warning(source_p, NULL);
979
f4a80ce6
JT
980 msptr = ptr->data;
981 chptr = msptr->chptr;
982 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
983 source_p->name,
984 source_p->username, source_p->host, chptr->chname);
985 remove_user_from_channel(msptr);
986 }
987}
988
212380e3
AC
989static int
990check_channel_name_loc(struct Client *source_p, const char *name)
991{
6865c0b0
JT
992 const char *p;
993
212380e3
AC
994 s_assert(name != NULL);
995 if(EmptyString(name))
996 return 0;
997
998 if(ConfigFileEntry.disable_fake_channels && !IsOper(source_p))
999 {
6865c0b0 1000 for(p = name; *p; ++p)
212380e3 1001 {
6865c0b0 1002 if(!IsChanChar(*p) || IsFakeChanChar(*p))
212380e3
AC
1003 return 0;
1004 }
1005 }
1006 else
1007 {
6865c0b0 1008 for(p = name; *p; ++p)
212380e3 1009 {
6865c0b0 1010 if(!IsChanChar(*p))
212380e3
AC
1011 return 0;
1012 }
1013 }
1014
6865c0b0
JT
1015 if(ConfigChannel.only_ascii_channels)
1016 {
1017 for(p = name; *p; ++p)
1018 if(*p < 33 || *p > 126)
1019 return 0;
1020 }
1021
212380e3
AC
1022 return 1;
1023}
1024
35bfe0e6
JT
1025/* send_join_error()
1026 *
1027 * input - client to send to, reason, channel name
1028 * output - none
1029 * side effects - error message sent to client
1030 */
1031static void
1032send_join_error(struct Client *source_p, int numeric, const char *name)
1033{
1034 /* This stuff is necessary because the form_str macro only
1035 * accepts constants.
1036 */
1037 switch (numeric)
1038 {
1039#define NORMAL_NUMERIC(i) \
1040 case i: \
1041 sendto_one(source_p, form_str(i), \
1042 me.name, source_p->name, name); \
1043 break
1044
1045 NORMAL_NUMERIC(ERR_BANNEDFROMCHAN);
1046 NORMAL_NUMERIC(ERR_INVITEONLYCHAN);
1047 NORMAL_NUMERIC(ERR_BADCHANNELKEY);
1048 NORMAL_NUMERIC(ERR_CHANNELISFULL);
1049 NORMAL_NUMERIC(ERR_NEEDREGGEDNICK);
1050 NORMAL_NUMERIC(ERR_THROTTLE);
1051
1052 default:
1053 sendto_one_numeric(source_p, numeric,
1054 "%s :Cannot join channel", name);
1055 break;
1056 }
1057}
1058
212380e3
AC
1059static void
1060set_final_mode(struct Mode *mode, struct Mode *oldmode)
1061{
1062 int dir = MODE_QUERY;
1063 char *pbuf = parabuf;
1064 int len;
1065 int i;
1066
1067 /* ok, first get a list of modes we need to add */
efccc22c 1068 for (i = 0; i < 256; i++)
212380e3 1069 {
efccc22c 1070 if((mode->mode & chmode_flags[i]) && !(oldmode->mode & chmode_flags[i]))
212380e3
AC
1071 {
1072 if(dir != MODE_ADD)
1073 {
1074 *mbuf++ = '+';
1075 dir = MODE_ADD;
1076 }
efccc22c 1077 *mbuf++ = i;
212380e3
AC
1078 }
1079 }
1080
1081 /* now the ones we need to remove. */
efccc22c 1082 for (i = 0; i < 256; i++)
212380e3 1083 {
efccc22c 1084 if((oldmode->mode & chmode_flags[i]) && !(mode->mode & chmode_flags[i]))
212380e3
AC
1085 {
1086 if(dir != MODE_DEL)
1087 {
1088 *mbuf++ = '-';
1089 dir = MODE_DEL;
1090 }
efccc22c 1091 *mbuf++ = i;
212380e3
AC
1092 }
1093 }
1094
1095 if(oldmode->limit && !mode->limit)
1096 {
1097 if(dir != MODE_DEL)
1098 {
1099 *mbuf++ = '-';
1100 dir = MODE_DEL;
1101 }
1102 *mbuf++ = 'l';
1103 }
1104 if(oldmode->key[0] && !mode->key[0])
1105 {
1106 if(dir != MODE_DEL)
1107 {
1108 *mbuf++ = '-';
1109 dir = MODE_DEL;
1110 }
1111 *mbuf++ = 'k';
7cdb0a09 1112 len = rb_sprintf(pbuf, "%s ", oldmode->key);
212380e3
AC
1113 pbuf += len;
1114 }
1115 if(oldmode->join_num && !mode->join_num)
1116 {
1117 if(dir != MODE_DEL)
1118 {
1119 *mbuf++ = '-';
1120 dir = MODE_DEL;
1121 }
1122 *mbuf++ = 'j';
1123 }
1124 if(oldmode->forward[0] && !mode->forward[0])
1125 {
1126 if(dir != MODE_DEL)
1127 {
1128 *mbuf++ = '-';
1129 dir = MODE_DEL;
1130 }
1131 *mbuf++ = 'f';
1132 }
1133 if(mode->limit && oldmode->limit != mode->limit)
1134 {
1135 if(dir != MODE_ADD)
1136 {
1137 *mbuf++ = '+';
1138 dir = MODE_ADD;
1139 }
1140 *mbuf++ = 'l';
7cdb0a09 1141 len = rb_sprintf(pbuf, "%d ", mode->limit);
212380e3
AC
1142 pbuf += len;
1143 }
1144 if(mode->key[0] && strcmp(oldmode->key, mode->key))
1145 {
1146 if(dir != MODE_ADD)
1147 {
1148 *mbuf++ = '+';
1149 dir = MODE_ADD;
1150 }
1151 *mbuf++ = 'k';
7cdb0a09 1152 len = rb_sprintf(pbuf, "%s ", mode->key);
212380e3
AC
1153 pbuf += len;
1154 }
1155 if(mode->join_num && (oldmode->join_num != mode->join_num || oldmode->join_time != mode->join_time))
1156 {
1157 if(dir != MODE_ADD)
1158 {
1159 *mbuf++ = '+';
1160 dir = MODE_ADD;
1161 }
1162 *mbuf++ = 'j';
7cdb0a09 1163 len = rb_sprintf(pbuf, "%d:%d ", mode->join_num, mode->join_time);
212380e3
AC
1164 pbuf += len;
1165 }
2da6f6eb
JT
1166 if(mode->forward[0] && strcmp(oldmode->forward, mode->forward) &&
1167 ConfigChannel.use_forward)
212380e3
AC
1168 {
1169 if(dir != MODE_ADD)
1170 {
1171 *mbuf++ = '+';
1172 dir = MODE_ADD;
1173 }
1174 *mbuf++ = 'f';
7cdb0a09 1175 len = rb_sprintf(pbuf, "%s ", mode->forward);
212380e3
AC
1176 pbuf += len;
1177 }
1178 *mbuf = '\0';
1179}
1180
1181/*
1182 * remove_our_modes
1183 *
1184 * inputs -
1185 * output -
1186 * side effects -
1187 */
1188static void
1189remove_our_modes(struct Channel *chptr, struct Client *source_p)
1190{
1191 struct membership *msptr;
5b96d9a6 1192 rb_dlink_node *ptr;
212380e3
AC
1193 char lmodebuf[MODEBUFLEN];
1194 char *lpara[MAXMODEPARAMS];
1195 int count = 0;
1196 int i;
1197
1198 mbuf = lmodebuf;
1199 *mbuf++ = '-';
1200
1201 for(i = 0; i < MAXMODEPARAMS; i++)
1202 lpara[i] = NULL;
1203
5b96d9a6 1204 RB_DLINK_FOREACH(ptr, chptr->members.head)
212380e3
AC
1205 {
1206 msptr = ptr->data;
1207
1208 if(is_chanop(msptr))
1209 {
1210 msptr->flags &= ~CHFL_CHANOP;
1211 lpara[count++] = msptr->client_p->name;
1212 *mbuf++ = 'o';
1213
1214 /* +ov, might not fit so check. */
1215 if(is_voiced(msptr))
1216 {
1217 if(count >= MAXMODEPARAMS)
1218 {
1219 *mbuf = '\0';
1220 sendto_channel_local(ALL_MEMBERS, chptr,
1221 ":%s MODE %s %s %s %s %s %s",
7bf78de0 1222 source_p->name, chptr->chname,
212380e3
AC
1223 lmodebuf, lpara[0], lpara[1],
1224 lpara[2], lpara[3]);
1225
1226 /* preserve the initial '-' */
1227 mbuf = lmodebuf;
1228 *mbuf++ = '-';
1229 count = 0;
1230
1231 for(i = 0; i < MAXMODEPARAMS; i++)
1232 lpara[i] = NULL;
1233 }
1234
1235 msptr->flags &= ~CHFL_VOICE;
1236 lpara[count++] = msptr->client_p->name;
1237 *mbuf++ = 'v';
1238 }
1239 }
1240 else if(is_voiced(msptr))
1241 {
1242 msptr->flags &= ~CHFL_VOICE;
1243 lpara[count++] = msptr->client_p->name;
1244 *mbuf++ = 'v';
1245 }
1246 else
1247 continue;
1248
1249 if(count >= MAXMODEPARAMS)
1250 {
1251 *mbuf = '\0';
1252 sendto_channel_local(ALL_MEMBERS, chptr,
1253 ":%s MODE %s %s %s %s %s %s",
7bf78de0 1254 source_p->name, chptr->chname, lmodebuf,
212380e3
AC
1255 lpara[0], lpara[1], lpara[2], lpara[3]);
1256 mbuf = lmodebuf;
1257 *mbuf++ = '-';
1258 count = 0;
1259
1260 for(i = 0; i < MAXMODEPARAMS; i++)
1261 lpara[i] = NULL;
1262 }
1263 }
1264
1265 if(count != 0)
1266 {
1267 *mbuf = '\0';
1268 sendto_channel_local(ALL_MEMBERS, chptr,
1269 ":%s MODE %s %s %s %s %s %s",
7bf78de0 1270 source_p->name, chptr->chname, lmodebuf,
212380e3
AC
1271 EmptyString(lpara[0]) ? "" : lpara[0],
1272 EmptyString(lpara[1]) ? "" : lpara[1],
1273 EmptyString(lpara[2]) ? "" : lpara[2],
1274 EmptyString(lpara[3]) ? "" : lpara[3]);
1275
1276 }
1277}
8cc12805
VY
1278
1279/* remove_ban_list()
1280 *
1281 * inputs - channel, source, list to remove, char of mode, caps needed
1282 * outputs -
1283 * side effects - given list is removed, with modes issued to local clients
8cc12805
VY
1284 */
1285static void
1286remove_ban_list(struct Channel *chptr, struct Client *source_p,
8afeb720 1287 rb_dlink_list * list, char c, int mems)
8cc12805
VY
1288{
1289 static char lmodebuf[BUFSIZE];
1290 static char lparabuf[BUFSIZE];
1291 struct Ban *banptr;
1292 rb_dlink_node *ptr;
1293 rb_dlink_node *next_ptr;
1294 char *pbuf;
1295 int count = 0;
1296 int cur_len, mlen, plen;
1297
1298 pbuf = lparabuf;
1299
1300 cur_len = mlen = rb_sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
1301 mbuf = lmodebuf + mlen;
1302
1303 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
1304 {
1305 banptr = ptr->data;
1306
1307 /* trailing space, and the mode letter itself */
23f6b63a
JT
1308 plen = strlen(banptr->banstr) +
1309 (banptr->forward ? strlen(banptr->forward) + 1 : 0) + 2;
8cc12805
VY
1310
1311 if(count >= MAXMODEPARAMS || (cur_len + plen) > BUFSIZE - 4)
1312 {
1313 /* remove trailing space */
1314 *mbuf = '\0';
1315 *(pbuf - 1) = '\0';
1316
1317 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
8cc12805
VY
1318
1319 cur_len = mlen;
1320 mbuf = lmodebuf + mlen;
1321 pbuf = lparabuf;
1322 count = 0;
1323 }
1324
1325 *mbuf++ = c;
1326 cur_len += plen;
23f6b63a
JT
1327 if (banptr->forward)
1328 pbuf += rb_sprintf(pbuf, "%s$%s ", banptr->banstr, banptr->forward);
1329 else
1330 pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr);
8cc12805
VY
1331 count++;
1332
1333 free_ban(banptr);
1334 }
1335
1336 *mbuf = '\0';
1337 *(pbuf - 1) = '\0';
1338 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
8cc12805
VY
1339
1340 list->head = list->tail = NULL;
1341 list->length = 0;
1342}