ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_sjoin.c
Revision: 3192
Committed: Sun Mar 23 19:46:39 2014 UTC (10 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/modules/core/m_sjoin.c
File size: 20328 byte(s)
Log Message:
- Fixed compile error in ms_sid()
- Cleaned up find_chasing(). Removed useless third 'chasing' argument.

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22 /*! \file m_sjoin.c
23 * \brief Includes required functions for processing the SJOIN command.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "channel.h"
30 #include "channel_mode.h"
31 #include "client.h"
32 #include "hash.h"
33 #include "irc_string.h"
34 #include "ircd.h"
35 #include "numeric.h"
36 #include "send.h"
37 #include "parse.h"
38 #include "modules.h"
39 #include "s_serv.h"
40 #include "conf.h"
41 #include "s_misc.h"
42
43
44 static char modebuf[MODEBUFLEN];
45 static char parabuf[MODEBUFLEN];
46 static char sendbuf[MODEBUFLEN];
47 static const char *para[MAXMODEPARAMS];
48 static char *mbuf;
49 static int pargs;
50
51 static void set_final_mode(struct Mode *, struct Mode *);
52 static void remove_our_modes(struct Channel *, struct Client *);
53 static void remove_a_mode(struct Channel *, struct Client *, int, char);
54 static void remove_ban_list(struct Channel *, struct Client *, dlink_list *, char);
55
56
57 /* ms_sjoin()
58 *
59 * parv[0] - command
60 * parv[1] - TS
61 * parv[2] - channel
62 * parv[3] - modes + n arguments (key and/or limit)
63 * parv[4+n] - flags+nick list (all in one parameter)
64 *
65 * process a SJOIN, taking the TS's into account to either ignore the
66 * incoming modes or undo the existing ones or merge them, and JOIN
67 * all the specified users while sending JOIN/MODEs to local clients
68 */
69 static int
70 ms_sjoin(struct Client *source_p, int parc, char *parv[])
71 {
72 struct Channel *chptr = NULL;
73 struct Client *target_p = NULL;
74 time_t newts;
75 time_t oldts;
76 time_t tstosend;
77 struct Mode mode, *oldmode;
78 int args = 0;
79 char keep_our_modes = 1;
80 char keep_new_modes = 1;
81 char have_many_nicks = 0;
82 int lcount;
83 char uid_prefix[4];
84 char *up = NULL;
85 int len_uid = 0;
86 int isnew = 0;
87 int buflen = 0;
88 int slen;
89 unsigned int fl;
90 char *s;
91 char *sptr;
92 char uid_buf[IRCD_BUFSIZE]; /* buffer for modes/prefixes */
93 char *uid_ptr;
94 char *p; /* pointer used making sjbuf */
95 dlink_node *m;
96 const char *servername = (ConfigServerHide.hide_servers || IsHidden(source_p)) ?
97 me.name : source_p->name;
98
99 if (IsClient(source_p) || parc < 5)
100 return 0;
101
102 if (!check_channel_name(parv[2], 0))
103 {
104 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
105 "*** Too long or invalid channel name from %s(via %s): %s",
106 source_p->name, source_p->from->name, parv[2]);
107 return 0;
108 }
109
110 modebuf[0] = '\0';
111 mbuf = modebuf;
112 pargs = 0;
113 newts = atol(parv[1]);
114
115 mode.mode = 0;
116 mode.limit = 0;
117 mode.key[0] = '\0';
118
119 for (s = parv[3]; *s; ++s)
120 {
121 switch (*s)
122 {
123 case 'c':
124 mode.mode |= MODE_NOCTRL;
125 break;
126 case 't':
127 mode.mode |= MODE_TOPICLIMIT;
128 break;
129 case 'n':
130 mode.mode |= MODE_NOPRIVMSGS;
131 break;
132 case 's':
133 mode.mode |= MODE_SECRET;
134 break;
135 case 'm':
136 mode.mode |= MODE_MODERATED;
137 break;
138 case 'i':
139 mode.mode |= MODE_INVITEONLY;
140 break;
141 case 'p':
142 mode.mode |= MODE_PRIVATE;
143 break;
144 case 'r':
145 mode.mode |= MODE_REGISTERED;
146 break;
147 case 'M':
148 mode.mode |= MODE_MODREG;
149 break;
150 case 'O':
151 mode.mode |= MODE_OPERONLY;
152 break;
153 case 'S':
154 mode.mode |= MODE_SSLONLY;
155 break;
156 case 'k':
157 strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
158 args++;
159
160 if (parc < 5 + args)
161 return 0;
162 break;
163 case 'l':
164 mode.limit = atoi(parv[4 + args]);
165 args++;
166
167 if (parc < 5 + args)
168 return 0;
169 break;
170 }
171 }
172
173 if ((chptr = hash_find_channel(parv[2])) == NULL)
174 {
175 isnew = 1;
176 chptr = make_channel(parv[2]);
177 }
178
179 parabuf[0] = '\0';
180 oldts = chptr->channelts;
181 oldmode = &chptr->mode;
182
183 if (ConfigFileEntry.ignore_bogus_ts)
184 {
185 if (newts < 800000000)
186 {
187 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
188 "*** Bogus TS %lu on %s ignored from %s(via %s)",
189 (unsigned long)newts, chptr->chname,
190 source_p->name, source_p->from->name);
191
192 newts = (oldts == 0) ? 0 : 800000000;
193 }
194 }
195 else
196 {
197 if (!newts && !isnew && oldts)
198 {
199 sendto_channel_local(ALL_MEMBERS, 0, chptr,
200 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to 0",
201 me.name, chptr->chname, chptr->chname, (unsigned long)oldts);
202 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
203 "Server %s changing TS on %s from %lu to 0",
204 source_p->name, chptr->chname, (unsigned long)oldts);
205 }
206 }
207
208 if (isnew)
209 chptr->channelts = tstosend = newts;
210 else if (newts == 0 || oldts == 0)
211 chptr->channelts = tstosend = 0;
212 else if (newts == oldts)
213 tstosend = oldts;
214 else if (newts < oldts)
215 {
216 keep_our_modes = 0;
217 chptr->channelts = tstosend = newts;
218 }
219 else
220 {
221 keep_new_modes = 0;
222 tstosend = oldts;
223 }
224
225 if (!keep_new_modes)
226 mode = *oldmode;
227 else if (keep_our_modes)
228 {
229 mode.mode |= oldmode->mode;
230 if (oldmode->limit > mode.limit)
231 mode.limit = oldmode->limit;
232 if (strcmp(mode.key, oldmode->key) < 0)
233 strcpy(mode.key, oldmode->key);
234 }
235 set_final_mode(&mode, oldmode);
236 chptr->mode = mode;
237
238 /* Lost the TS, other side wins, so remove modes on this side */
239 if (!keep_our_modes)
240 {
241 remove_our_modes(chptr, source_p);
242
243 if (chptr->topic[0])
244 {
245 set_channel_topic(chptr, "", "", 0, 0);
246 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s TOPIC %s :",
247 (IsHidden(source_p) ||
248 ConfigServerHide.hide_servers) ?
249 me.name : source_p->name, chptr->chname);
250 }
251
252 sendto_channel_local(ALL_MEMBERS, 0, chptr,
253 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to %lu",
254 me.name, chptr->chname, chptr->chname,
255 (unsigned long)oldts, (unsigned long)newts);
256 }
257
258 if (*modebuf != '\0')
259 {
260 /* This _SHOULD_ be to ALL_MEMBERS
261 * It contains only +imnpstlk, etc */
262 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s %s",
263 servername, chptr->chname, modebuf, parabuf);
264 }
265
266 if (parv[3][0] != '0' && keep_new_modes)
267 channel_modes(chptr, source_p, modebuf, parabuf);
268 else
269 {
270 modebuf[0] = '0';
271 modebuf[1] = '\0';
272 }
273
274 buflen = snprintf(uid_buf, sizeof(uid_buf), ":%s SJOIN %lu %s %s %s:",
275 source_p->id, (unsigned long)tstosend,
276 chptr->chname, modebuf, parabuf);
277 uid_ptr = uid_buf + buflen;
278
279 /* check we can fit a nick on the end, as well as \r\n and a prefix "
280 * @%+", and a space.
281 */
282 if (buflen >= (IRCD_BUFSIZE - IRCD_MAX(NICKLEN, IDLEN) - 2 - 3 - 1))
283 {
284 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
285 "Long SJOIN from server: %s(via %s) (ignored)",
286 source_p->name, source_p->from->name);
287 return 0;
288 }
289
290 mbuf = modebuf;
291 sendbuf[0] = '\0';
292 pargs = 0;
293
294 *mbuf++ = '+';
295
296 s = parv[args + 4];
297 while (*s == ' ')
298 s++;
299 if ((p = strchr(s, ' ')) != NULL)
300 {
301 *p++ = '\0';
302 while (*p == ' ')
303 p++;
304 have_many_nicks = *p;
305 }
306
307 while (*s)
308 {
309 int valid_mode = 1;
310 fl = 0;
311
312 do
313 {
314 switch (*s)
315 {
316 case '@':
317 fl |= CHFL_CHANOP;
318 s++;
319 break;
320 #ifdef HALFOPS
321 case '%':
322 fl |= CHFL_HALFOP;
323 s++;
324 break;
325 #endif
326 case '+':
327 fl |= CHFL_VOICE;
328 s++;
329 break;
330 default:
331 valid_mode = 0;
332 break;
333 }
334 } while (valid_mode);
335
336 target_p = find_chasing(source_p, s);
337 assert(IsClient(target_p));
338
339 /*
340 * if the client doesnt exist, or if its fake direction/server, skip.
341 * we cannot send ERR_NOSUCHNICK here because if its a UID, we cannot
342 * lookup the nick, and its better to never send the numeric than only
343 * sometimes.
344 */
345 if (target_p == NULL || target_p->from != source_p->from)
346 goto nextnick;
347
348 len_uid = strlen(target_p->id);
349 up = uid_prefix;
350
351 if (keep_new_modes)
352 {
353 if (fl & CHFL_CHANOP)
354 {
355 *up++ = '@';
356 len_uid++;
357 }
358 #ifdef HALFOPS
359 if (fl & CHFL_HALFOP)
360 {
361 *up++ = '%';
362 len_uid++;
363 }
364 #endif
365 if (fl & CHFL_VOICE)
366 {
367 *up++ = '+';
368 len_uid++;
369 }
370 }
371 else
372 {
373 if (fl & (CHFL_CHANOP|CHFL_HALFOP))
374 fl = CHFL_DEOPPED;
375 else
376 fl = 0;
377 }
378 *up = '\0';
379
380 if ((uid_ptr - uid_buf + len_uid) > (IRCD_BUFSIZE - 2))
381 {
382 sendto_server(source_p, NOCAPS, NOCAPS, "%s", uid_buf);
383
384 buflen = snprintf(uid_buf, sizeof(uid_buf), ":%s SJOIN %lu %s %s %s:",
385 source_p->id, (unsigned long)tstosend,
386 chptr->chname, modebuf, parabuf);
387 uid_ptr = uid_buf + buflen;
388 }
389
390 uid_ptr += sprintf(uid_ptr, "%s%s ", uid_prefix, target_p->id);
391
392 if (!IsMember(target_p, chptr))
393 {
394 add_user_to_channel(chptr, target_p, fl, !have_many_nicks);
395 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
396 target_p->name, target_p->username,
397 target_p->host, chptr->chname);
398 if (target_p->away[0])
399 sendto_channel_local_butone(target_p, 0, CAP_AWAY_NOTIFY, chptr,
400 ":%s!%s@%s AWAY :%s",
401 target_p->name, target_p->username,
402 target_p->host, target_p->away);
403 }
404
405 if (fl & CHFL_CHANOP)
406 {
407 *mbuf++ = 'o';
408 para[pargs++] = target_p->name;
409
410 if (pargs >= MAXMODEPARAMS)
411 {
412 /*
413 * Ok, the code is now going to "walk" through
414 * sendbuf, filling in para strings. So, I will use sptr
415 * to point into the sendbuf.
416 * Notice, that ircsprintf() returns the number of chars
417 * successfully inserted into string.
418 * - Dianora
419 */
420
421 sptr = sendbuf;
422 *mbuf = '\0';
423
424 for(lcount = 0; lcount < MAXMODEPARAMS; lcount++)
425 {
426 slen = sprintf(sptr, " %s", para[lcount]); /* see? */
427 sptr += slen; /* ready for next */
428 }
429 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
430 servername, chptr->chname, modebuf, sendbuf);
431 mbuf = modebuf;
432 *mbuf++ = '+';
433
434 sendbuf[0] = '\0';
435 pargs = 0;
436 }
437 }
438 #ifdef HALFOPS
439 if (fl & CHFL_HALFOP)
440 {
441 *mbuf++ = 'h';
442 para[pargs++] = target_p->name;
443
444 if (pargs >= MAXMODEPARAMS)
445 {
446 sptr = sendbuf;
447 *mbuf = '\0';
448 for(lcount = 0; lcount < MAXMODEPARAMS; lcount++)
449 {
450 slen = sprintf(sptr, " %s", para[lcount]);
451 sptr += slen;
452 }
453 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
454 servername, chptr->chname, modebuf, sendbuf);
455
456 mbuf = modebuf;
457 *mbuf++ = '+';
458
459 sendbuf[0] = '\0';
460 pargs = 0;
461 }
462 }
463 #endif
464 if (fl & CHFL_VOICE)
465 {
466 *mbuf++ = 'v';
467 para[pargs++] = target_p->name;
468
469 if (pargs >= MAXMODEPARAMS)
470 {
471 sptr = sendbuf;
472 *mbuf = '\0';
473 for (lcount = 0; lcount < MAXMODEPARAMS; lcount++)
474 {
475 slen = sprintf(sptr, " %s", para[lcount]);
476 sptr += slen;
477 }
478 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
479 servername, chptr->chname, modebuf, sendbuf);
480
481 mbuf = modebuf;
482 *mbuf++ = '+';
483
484 sendbuf[0] = '\0';
485 pargs = 0;
486 }
487 }
488
489 nextnick:
490 if ((s = p) == NULL)
491 break;
492 while (*s == ' ')
493 s++;
494 if ((p = strchr(s, ' ')) != NULL)
495 {
496 *p++ = 0;
497 while (*p == ' ')
498 p++;
499 }
500 }
501
502 *mbuf = '\0';
503 *(uid_ptr - 1) = '\0';
504
505 /*
506 * checking for lcount < MAXMODEPARAMS at this time is wrong
507 * since the code has already verified above that pargs < MAXMODEPARAMS
508 * checking for para[lcount] != '\0' is also wrong, since
509 * there is no place where para[lcount] is set!
510 * - Dianora
511 */
512
513 if (pargs != 0)
514 {
515 sptr = sendbuf;
516
517 for (lcount = 0; lcount < pargs; lcount++)
518 {
519 slen = sprintf(sptr, " %s", para[lcount]);
520 sptr += slen;
521 }
522
523 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
524 servername, chptr->chname, modebuf, sendbuf);
525 }
526
527 /* If this happens, its the result of a malformed SJOIN
528 * a remnant from the old persistent channel code. *sigh*
529 * Or it could be the result of a client just leaving
530 * and leaving us with a channel formed just as the client parts.
531 * - Dianora
532 */
533
534 if ((dlink_list_length(&chptr->members) == 0) && isnew)
535 {
536 destroy_channel(chptr);
537 return 0;
538 }
539
540 if (parv[4 + args][0] == '\0')
541 return 0;
542
543 sendto_server(source_p, NOCAPS, NOCAPS, "%s", uid_buf);
544
545 if (!keep_our_modes)
546 {
547 if (dlink_list_length(&chptr->banlist) > 0)
548 remove_ban_list(chptr, source_p, &chptr->banlist, 'b');
549
550 if (dlink_list_length(&chptr->exceptlist) > 0)
551 remove_ban_list(chptr, source_p, &chptr->exceptlist, 'e');
552
553 if (dlink_list_length(&chptr->invexlist) > 0)
554 remove_ban_list(chptr, source_p, &chptr->invexlist, 'I');
555 clear_ban_cache(chptr);
556 }
557
558 return 0;
559 }
560
561 /* set_final_mode
562 *
563 * inputs - channel mode
564 * - old channel mode
565 * output - NONE
566 * side effects - walk through all the channel modes turning off modes
567 * that were on in oldmode but aren't on in mode.
568 * Then walk through turning on modes that are on in mode
569 * but were not set in oldmode.
570 */
571 static void
572 set_final_mode(struct Mode *mode, struct Mode *oldmode)
573 {
574 const struct mode_letter *tab;
575 char *pbuf = parabuf;
576 int len;
577
578 *mbuf++ = '-';
579
580 for (tab = chan_modes; tab->letter; ++tab)
581 {
582 if ((tab->mode & oldmode->mode) &&
583 !(tab->mode & mode->mode))
584 *mbuf++ = tab->letter;
585 }
586
587 if (oldmode->limit != 0 && mode->limit == 0)
588 *mbuf++ = 'l';
589
590 if (oldmode->key[0] && !mode->key[0])
591 {
592 *mbuf++ = 'k';
593 len = sprintf(pbuf, "%s ", oldmode->key);
594 pbuf += len;
595 pargs++;
596 }
597
598 if (*(mbuf-1) == '-')
599 *(mbuf-1) = '+';
600 else
601 *mbuf++ = '+';
602
603 for (tab = chan_modes; tab->letter; ++tab)
604 {
605 if ((tab->mode & mode->mode) &&
606 !(tab->mode & oldmode->mode))
607 *mbuf++ = tab->letter;
608 }
609
610 if (mode->limit != 0 && oldmode->limit != mode->limit)
611 {
612 *mbuf++ = 'l';
613 len = sprintf(pbuf, "%d ", mode->limit);
614 pbuf += len;
615 pargs++;
616 }
617
618 if (mode->key[0] && strcmp(oldmode->key, mode->key))
619 {
620 *mbuf++ = 'k';
621 len = sprintf(pbuf, "%s ", mode->key);
622 pbuf += len;
623 pargs++;
624 }
625 if (*(mbuf-1) == '+')
626 *(mbuf-1) = '\0';
627 else
628 *mbuf = '\0';
629 }
630
631 /* remove_our_modes()
632 *
633 * inputs - pointer to channel to remove modes from
634 * - client pointer
635 * output - NONE
636 * side effects - Go through the local members, remove all their
637 * chanop modes etc., this side lost the TS.
638 */
639 static void
640 remove_our_modes(struct Channel *chptr, struct Client *source_p)
641 {
642 remove_a_mode(chptr, source_p, CHFL_CHANOP, 'o');
643 #ifdef HALFOPS
644 remove_a_mode(chptr, source_p, CHFL_HALFOP, 'h');
645 #endif
646 remove_a_mode(chptr, source_p, CHFL_VOICE, 'v');
647 }
648
649 /* remove_a_mode()
650 *
651 * inputs - pointer to channel
652 * - server or client removing the mode
653 * - mask o/h/v mask to be removed
654 * - flag o/h/v to be removed
655 * output - NONE
656 * side effects - remove ONE mode from all members of a channel
657 */
658 static void
659 remove_a_mode(struct Channel *chptr, struct Client *source_p,
660 int mask, char flag)
661 {
662 dlink_node *ptr;
663 struct Membership *ms;
664 char lmodebuf[MODEBUFLEN];
665 char *sp=sendbuf;
666 const char *lpara[MAXMODEPARAMS];
667 int count = 0;
668 int i;
669 int l;
670
671 mbuf = lmodebuf;
672 *mbuf++ = '-';
673 *sp = '\0';
674
675 DLINK_FOREACH(ptr, chptr->members.head)
676 {
677 ms = ptr->data;
678
679 if ((ms->flags & mask) == 0)
680 continue;
681
682 ms->flags &= ~mask;
683
684 lpara[count++] = ms->client_p->name;
685
686 *mbuf++ = flag;
687
688 if (count >= MAXMODEPARAMS)
689 {
690 for(i = 0; i < MAXMODEPARAMS; i++)
691 {
692 l = sprintf(sp, " %s", lpara[i]);
693 sp += l;
694 }
695
696 *mbuf = '\0';
697 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
698 (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
699 me.name : source_p->name,
700 chptr->chname, lmodebuf, sendbuf);
701 mbuf = lmodebuf;
702 *mbuf++ = '-';
703 count = 0;
704 sp = sendbuf;
705 *sp = '\0';
706 }
707 }
708
709 if (count != 0)
710 {
711 *mbuf = '\0';
712 for(i = 0; i < count; i++)
713 {
714 l = sprintf(sp, " %s", lpara[i]);
715 sp += l;
716 }
717 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
718 (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
719 me.name : source_p->name,
720 chptr->chname, lmodebuf, sendbuf);
721 }
722 }
723
724 /* remove_ban_list()
725 *
726 * inputs - channel, source, list to remove, char of mode
727 * outputs - none
728 * side effects - given ban list is removed, modes are sent to local clients
729 */
730 static void
731 remove_ban_list(struct Channel *chptr, struct Client *source_p,
732 dlink_list *list, char c)
733 {
734 char lmodebuf[MODEBUFLEN];
735 char lparabuf[IRCD_BUFSIZE];
736 struct Ban *banptr = NULL;
737 dlink_node *ptr = NULL;
738 dlink_node *next_ptr = NULL;
739 char *pbuf = NULL;
740 int count = 0;
741 int cur_len, mlen, plen;
742
743 pbuf = lparabuf;
744 cur_len = mlen = sprintf(lmodebuf, ":%s MODE %s -",
745 source_p->name, chptr->chname);
746 mbuf = lmodebuf + mlen;
747
748 DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
749 {
750 banptr = ptr->data;
751
752 plen = banptr->len + 4; /* another +b and "!@ " */
753 if (count >= MAXMODEPARAMS ||
754 (cur_len + 1 /* space between */ + (plen - 1)) > IRCD_BUFSIZE - 2)
755 {
756 /* NUL-terminate and remove trailing space */
757 *mbuf = *(pbuf - 1) = '\0';
758 sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", lmodebuf, lparabuf);
759 cur_len = mlen;
760 mbuf = lmodebuf + mlen;
761 pbuf = lparabuf;
762 count = 0;
763 }
764
765 *mbuf++ = c;
766 cur_len += plen;
767 pbuf += sprintf(pbuf, "%s!%s@%s ", banptr->name, banptr->user,
768 banptr->host);
769 ++count;
770
771 remove_ban(banptr, list);
772 }
773
774 *mbuf = *(pbuf - 1) = '\0';
775 sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", lmodebuf, lparabuf);
776 }
777
778 static struct Message sjoin_msgtab =
779 {
780 "SJOIN", 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
781 { m_unregistered, m_ignore, ms_sjoin, m_ignore, m_ignore, m_ignore }
782 };
783
784 static void
785 module_init(void)
786 {
787 mod_add_cmd(&sjoin_msgtab);
788 }
789
790 static void
791 module_exit(void)
792 {
793 mod_del_cmd(&sjoin_msgtab);
794 }
795
796 struct module module_entry =
797 {
798 .node = { NULL, NULL, NULL },
799 .name = NULL,
800 .version = "$Revision$",
801 .handle = NULL,
802 .modinit = module_init,
803 .modexit = module_exit,
804 .flags = MODULE_FLAG_CORE
805 };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision