2 * IRC - Internet Relay Chat, ircd/m_join.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
6 * See file AUTHORS in IRC package for additional names of
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 1, or (at your option)
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
27 * m_functions execute protocol messages on this server:
29 * cptr is always NON-NULL, pointing to a *LOCAL* client
30 * structure (with an open socket connected!). This
31 * identifies the physical socket where the message
32 * originated (or which caused the m_function to be
33 * executed--some m_functions may call others...).
35 * sptr is the source of the message, defined by the
36 * prefix part of the message if present. If not
37 * or prefix not found, then sptr==cptr.
39 * (!IsServer(cptr)) => (cptr == sptr), because
40 * prefixes are taken *only* from servers...
43 * (sptr == cptr) => the message didn't
46 * (sptr != cptr && IsServer(sptr) means
47 * the prefix specified servername. (?)
49 * (sptr != cptr && !IsServer(sptr) means
50 * that message originated from a remote
55 * (!IsServer(sptr)) means that, sptr can safely
56 * taken as defining the target structure of the
57 * message in this server.
59 * *Always* true (if 'parse' and others are working correct):
61 * 1) sptr->from == cptr (note: cptr->from == cptr)
63 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64 * *cannot* be a local connection, unless it's
65 * actually cptr!). [MyConnect(x) should probably
66 * be defined as (x == x->from) --msa ]
68 * parc number of variable parameter strings (if zero,
69 * parv is allowed to be NULL)
71 * parv a NULL terminated list of parameter pointers,
73 * parv[0], sender (prefix string), if not present
74 * this points to an empty string.
75 * parv[1]...parv[parc-1]
76 * pointers to additional parameters
77 * parv[parc] == NULL, *always*
79 * note: it is guaranteed that parv[0]..parv[parc-1] are all
84 * No need to include handlers.h here the signatures must match
85 * and we don't need to force a rebuild of all the handlers everytime
86 * we add a new one to the list. --Bleep
95 #include "ircd_chattr.h"
96 #include "ircd_reply.h"
97 #include "ircd_string.h"
100 #include "numnicks.h"
108 #if !defined(XXX_BOGUS_TEMP_HACK)
109 #include "handlers.h" /* m_names */
113 * m_join - generic message handler
115 int m_join(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
117 static char jbuf[BUFSIZE];
118 static char mbuf[BUFSIZE];
119 struct Membership* member;
120 struct Channel* chptr;
122 char* keysOrTS = NULL;
126 unsigned int flags = 0;
134 * Doesn't make sense having a server join a channel, and besides
140 if (parc < 2 || *parv[1] == '\0')
141 return need_more_params(sptr, "JOIN");
143 for (p = parv[1]; *p; p++) /* find the last "JOIN 0" in the line -Kev */
145 && (*(p + 1) == ',' || *(p + 1) == '\0' || !IsChannelChar(*(p + 1))))
147 /* If it's a single "0", remember the place; we will start parsing
148 the channels after the last 0 in the line -Kev */
155 { /* Step through to the next comma or until the
156 end of the line, in an attempt to save CPU
158 while (*p != ',' && *p != '\0')
164 keysOrTS = parv[2]; /* Remember where our keys are or the TS is;
165 parv[2] needs to be NULL for the call to
166 m_names below -Kev */
169 *jbuf = *mbuf = '\0'; /* clear both join and mode buffers -Kev */
171 * Rebuild list of channels joined to be the actual result of the
172 * JOIN. Note that "JOIN 0" is the destructive problem.
174 for (name = ircd_strtok(&p, parv[1], ","); name; name = ircd_strtok(&p, NULL, ","))
178 clean_channelname(name);
179 else if (IsLocalChannel(name))
181 if (*name == '0' && *(name + 1) == '\0')
183 /* Remove the user from all his channels -Kev */
184 while ((member = sptr->user->channel))
186 chptr = member->channel;
187 if (!IsZombie(member))
188 sendto_channel_butserv(chptr, sptr, PartFmt2,
189 parv[0], chptr->chname, "Left all channels");
190 remove_user_from_channel(sptr, chptr);
193 *mbuf = *jbuf = '\0';
197 { /* not a /join 0, so treat it as
198 a /join #channel -Kev */
199 if (!IsChannelName(name))
202 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
209 if (bad_channel(name) && !IsAnOper(sptr))
211 sendto_one(sptr, err_str(ERR_BADCHANNAME), me.name, parv[0], name);
216 * Local client is first to enter previously nonexistant
217 * channel so make them (rightfully) the Channel Operator.
218 * This looks kind of ugly because we try to avoid calling the strlen()
220 if (ChannelExists(name))
222 flags = CHFL_DEOPPED;
225 else if (strlen(name) > CHANNELLEN)
227 *(name + CHANNELLEN) = '\0';
228 if (ChannelExists(name))
230 flags = CHFL_DEOPPED;
235 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
241 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
245 #ifdef OPER_NO_CHAN_LIMIT
247 * Opers are allowed to join any number of channels
249 if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsAnOper(sptr))
251 if (sptr->user->joined >= MAXCHANNELSPERUSER)
254 chptr = get_channel(sptr, name, CGT_NO_CREATE);
255 sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
256 me.name, parv[0], chptr ? chptr->chname : name);
258 * Can't return, else he won't get on ANY channels!
259 * Break out of the for loop instead. -Kev
264 chptr = get_channel(sptr, name, CGT_CREATE);
265 if (chptr && (member = find_member_link(chptr, sptr)))
267 if (IsZombie(member))
270 flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
271 remove_user_from_channel(sptr, chptr);
272 chptr = get_channel(sptr, name, CGT_CREATE);
277 name = chptr->chname;
278 if (!chptr->creationtime) /* A remote JOIN created this channel ? */
279 chptr->creationtime = MAGIC_REMOTE_JOIN_TS;
282 if (chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
283 chptr->creationtime = atoi(keysOrTS);
285 parc = 2; /* Don't pass it on */
289 if (!MyConnect(sptr))
290 flags = CHFL_DEOPPED;
291 if (sptr->flags & FLAGS_TS8)
292 flags |= CHFL_SERVOPOK;
296 int created = chptr->users == 0;
297 if (check_target_limit(sptr, chptr, chptr->chname, created))
299 if (created) /* Did we create the channel? */
300 sub1_from_channel(chptr); /* Remove it again! */
303 if ((i = can_join(sptr, chptr, keysOrTS)))
305 #ifdef OPER_WALK_THROUGH_LMODES
306 if (i > MAGIC_OPER_OVERRIDE)
308 switch(i - MAGIC_OPER_OVERRIDE)
310 case ERR_CHANNELISFULL: i = 'l'; break;
311 case ERR_INVITEONLYCHAN: i = 'i'; break;
312 case ERR_BANNEDFROMCHAN: i = 'b'; break;
313 case ERR_BADCHANNELKEY: i = 'k'; break;
315 sendto_op_mask(SNO_HACK4,"OPER JOIN: %s JOIN %s (overriding +%c)",sptr->name,chptr->chname,i);
319 sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
323 sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
329 * Complete user entry to the new channel (if any)
331 add_user_to_channel(chptr, sptr, flags);
334 * Notify all other users on the new channel
336 sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
340 del_invite(sptr, chptr);
341 if (chptr->topic[0] != '\0')
343 sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
344 parv[0], name, chptr->topic);
345 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0], name,
346 chptr->topic_nick, chptr->topic_time);
349 m_names(cptr, sptr, 2, parv);
353 /* Select proper buffer; mbuf for creation, jbuf otherwise */
356 continue; /* Head off local channels at the pass */
358 bufptr = (sendcreate == 0) ? jbuf : mbuf;
359 buflen = (sendcreate == 0) ? &jlen : &mlen;
361 if (*buflen < BUFSIZE - len - 2)
365 strcat(bufptr, ","); /* Add to join buf */
368 strncat(bufptr, name, BUFSIZE - *buflen - 1);
371 sendcreate = 0; /* Reset sendcreate */
374 if (*jbuf) /* Propgate joins to P10 servers */
375 sendto_serv_butone(cptr,
376 parc > 2 ? "%s%s " TOK_JOIN " %s %s" : "%s%s " TOK_JOIN " %s", NumNick(sptr), jbuf, keysOrTS);
377 if (*mbuf) /* and now creation events */
378 sendto_serv_butone(cptr, "%s%s " TOK_CREATE " %s " TIME_T_FMT,
379 NumNick(sptr), mbuf, TStime());
382 { /* shouldn't ever set TS for remote JOIN's */
384 { /* check for channels that need TS's */
386 for (name = ircd_strtok(&p, jbuf, ","); name; name = ircd_strtok(&p, NULL, ","))
388 chptr = get_channel(sptr, name, CGT_NO_CREATE);
389 if (chptr && chptr->mode.mode & MODE_SENDTS)
391 sendto_serv_butone(cptr, "%s " TOK_MODE " %s + " TIME_T_FMT, NumServ(&me),
392 chptr->chname, chptr->creationtime); /* ok, send TS */
393 chptr->mode.mode &= ~MODE_SENDTS; /* reset flag */
402 * ms_join - server message handler
404 int ms_join(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
406 static char jbuf[BUFSIZE];
407 static char mbuf[BUFSIZE];
408 struct Membership* member;
409 struct Channel* chptr;
411 char* keysOrTS = NULL;
415 unsigned int flags = 0;
423 * Doesn't make sense having a server join a channel, and besides
429 if (parc < 2 || *parv[1] == '\0')
430 return need_more_params(sptr, "JOIN");
432 for (p = parv[1]; *p; p++) /* find the last "JOIN 0" in the line -Kev */
434 && (*(p + 1) == ',' || *(p + 1) == '\0' || !IsChannelChar(*(p + 1))))
436 /* If it's a single "0", remember the place; we will start parsing
437 the channels after the last 0 in the line -Kev */
444 { /* Step through to the next comma or until the
445 end of the line, in an attempt to save CPU
447 while (*p != ',' && *p != '\0')
453 keysOrTS = parv[2]; /* Remember where our keys are or the TS is;
454 parv[2] needs to be NULL for the call to
455 m_names below -Kev */
458 *jbuf = *mbuf = '\0'; /* clear both join and mode buffers -Kev */
460 * Rebuild list of channels joined to be the actual result of the
461 * JOIN. Note that "JOIN 0" is the destructive problem.
463 for (name = ircd_strtok(&p, parv[1], ","); name; name = ircd_strtok(&p, NULL, ","))
467 clean_channelname(name);
468 else if (IsLocalChannel(name))
470 if (*name == '0' && *(name + 1) == '\0')
472 /* Remove the user from all his channels -Kev */
473 while ((member = sptr->user->channel))
475 chptr = member->channel;
476 if (!IsZombie(member))
477 sendto_channel_butserv(chptr, sptr, PartFmt2,
478 parv[0], chptr->chname, "Left all channels");
479 remove_user_from_channel(sptr, chptr);
482 *mbuf = *jbuf = '\0';
486 { /* not a /join 0, so treat it as
487 a /join #channel -Kev */
488 if (!IsChannelName(name))
491 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
498 if (bad_channel(name) && !IsAnOper(sptr))
500 sendto_one(sptr, err_str(ERR_BADCHANNAME), me.name, parv[0], name);
505 * Local client is first to enter previously nonexistant
506 * channel so make them (rightfully) the Channel Operator.
507 * This looks kind of ugly because we try to avoid calling the strlen()
509 if (ChannelExists(name))
511 flags = CHFL_DEOPPED;
514 else if (strlen(name) > CHANNELLEN)
516 *(name + CHANNELLEN) = '\0';
517 if (ChannelExists(name))
519 flags = CHFL_DEOPPED;
524 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
530 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
534 #ifdef OPER_NO_CHAN_LIMIT
536 * Opers are allowed to join any number of channels
538 if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsAnOper(sptr))
540 if (sptr->user->joined >= MAXCHANNELSPERUSER)
543 chptr = get_channel(sptr, name, CGT_NO_CREATE);
544 sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
545 me.name, parv[0], chptr ? chptr->chname : name);
547 * Can't return, else he won't get on ANY channels!
548 * Break out of the for loop instead. -Kev
553 chptr = get_channel(sptr, name, CGT_CREATE);
554 if (chptr && (member = find_member_link(chptr, sptr)))
556 if (IsZombie(member))
559 flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
560 remove_user_from_channel(sptr, chptr);
561 chptr = get_channel(sptr, name, CGT_CREATE);
566 name = chptr->chname;
567 if (!chptr->creationtime) /* A remote JOIN created this channel ? */
568 chptr->creationtime = MAGIC_REMOTE_JOIN_TS;
571 if (chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
572 chptr->creationtime = atoi(keysOrTS);
574 parc = 2; /* Don't pass it on */
578 if (!MyConnect(sptr))
579 flags = CHFL_DEOPPED;
580 if (sptr->flags & FLAGS_TS8)
581 flags |= CHFL_SERVOPOK;
585 int created = chptr->users == 0;
586 if (check_target_limit(sptr, chptr, chptr->chname, created))
588 if (created) /* Did we create the channel? */
589 sub1_from_channel(chptr); /* Remove it again! */
592 if ((i = can_join(sptr, chptr, keysOrTS)))
594 sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
599 * Complete user entry to the new channel (if any)
601 add_user_to_channel(chptr, sptr, flags);
604 * Notify all other users on the new channel
606 sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
610 del_invite(sptr, chptr);
611 if (chptr->topic[0] != '\0')
613 sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
614 parv[0], name, chptr->topic);
615 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0], name,
616 chptr->topic_nick, chptr->topic_time);
619 m_names(cptr, sptr, 2, parv);
623 /* Select proper buffer; mbuf for creation, jbuf otherwise */
626 continue; /* Head off local channels at the pass */
628 bufptr = (sendcreate == 0) ? jbuf : mbuf;
629 buflen = (sendcreate == 0) ? &jlen : &mlen;
631 if (*buflen < BUFSIZE - len - 2)
635 strcat(bufptr, ","); /* Add to join buf */
638 strncat(bufptr, name, BUFSIZE - *buflen - 1);
641 sendcreate = 0; /* Reset sendcreate */
644 if (*jbuf) /* Propgate joins to P10 servers */
645 sendto_serv_butone(cptr,
646 parc > 2 ? "%s%s " TOK_JOIN " %s %s" : "%s%s " TOK_JOIN " %s", NumNick(sptr), jbuf, keysOrTS);
647 if (*mbuf) /* and now creation events */
648 sendto_serv_butone(cptr, "%s%s " TOK_CREATE " %s " TIME_T_FMT,
649 NumNick(sptr), mbuf, TStime());
652 { /* shouldn't ever set TS for remote JOIN's */
654 { /* check for channels that need TS's */
656 for (name = ircd_strtok(&p, jbuf, ","); name; name = ircd_strtok(&p, NULL, ","))
658 chptr = get_channel(sptr, name, CGT_NO_CREATE);
659 if (chptr && chptr->mode.mode & MODE_SENDTS)
661 sendto_serv_butone(cptr, "%s " TOK_MODE " %s + " TIME_T_FMT, NumServ(&me),
662 chptr->chname, chptr->creationtime); /* ok, send TS */
663 chptr->mode.mode &= ~MODE_SENDTS; /* reset flag */
676 * parv[0] = sender prefix
678 * parv[2] = channel keys (client), or channel TS (server)
680 int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
682 static char jbuf[BUFSIZE];
683 static char mbuf[BUFSIZE];
684 struct Membership* member;
685 struct Channel* chptr;
687 char* keysOrTS = NULL;
691 unsigned int flags = 0;
699 * Doesn't make sense having a server join a channel, and besides
705 if (parc < 2 || *parv[1] == '\0')
706 return need_more_params(sptr, "JOIN");
708 for (p = parv[1]; *p; p++) /* find the last "JOIN 0" in the line -Kev */
710 && (*(p + 1) == ',' || *(p + 1) == '\0' || !IsChannelChar(*(p + 1))))
712 /* If it's a single "0", remember the place; we will start parsing
713 the channels after the last 0 in the line -Kev */
720 { /* Step through to the next comma or until the
721 end of the line, in an attempt to save CPU
723 while (*p != ',' && *p != '\0')
729 keysOrTS = parv[2]; /* Remember where our keys are or the TS is;
730 parv[2] needs to be NULL for the call to
731 m_names below -Kev */
734 *jbuf = *mbuf = '\0'; /* clear both join and mode buffers -Kev */
736 * Rebuild list of channels joined to be the actual result of the
737 * JOIN. Note that "JOIN 0" is the destructive problem.
739 for (name = ircd_strtok(&p, parv[1], ","); name; name = ircd_strtok(&p, NULL, ","))
743 clean_channelname(name);
744 else if (IsLocalChannel(name))
746 if (*name == '0' && *(name + 1) == '\0')
748 /* Remove the user from all his channels -Kev */
749 while ((member = sptr->user->channel))
751 chptr = member->channel;
752 if (!IsZombie(member))
753 sendto_channel_butserv(chptr, sptr, PartFmt2,
754 parv[0], chptr->chname, "Left all channels");
755 remove_user_from_channel(sptr, chptr);
758 *mbuf = *jbuf = '\0';
762 { /* not a /join 0, so treat it as
763 a /join #channel -Kev */
764 if (!IsChannelName(name))
767 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
774 if (bad_channel(name) && !IsAnOper(sptr))
776 sendto_one(sptr, err_str(ERR_BADCHANNAME), me.name, parv[0], name);
781 * Local client is first to enter previously nonexistant
782 * channel so make them (rightfully) the Channel Operator.
783 * This looks kind of ugly because we try to avoid calling the strlen()
785 if (ChannelExists(name))
787 flags = CHFL_DEOPPED;
790 else if (strlen(name) > CHANNELLEN)
792 *(name + CHANNELLEN) = '\0';
793 if (ChannelExists(name))
795 flags = CHFL_DEOPPED;
800 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
806 flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
810 #ifdef OPER_NO_CHAN_LIMIT
812 * Opers are allowed to join any number of channels
814 if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsAnOper(sptr))
816 if (sptr->user->joined >= MAXCHANNELSPERUSER)
819 chptr = get_channel(sptr, name, CGT_NO_CREATE);
820 sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
821 me.name, parv[0], chptr ? chptr->chname : name);
823 * Can't return, else he won't get on ANY channels!
824 * Break out of the for loop instead. -Kev
829 chptr = get_channel(sptr, name, CGT_CREATE);
830 if (chptr && (member = find_member_link(chptr, sptr)))
832 if (IsZombie(member))
835 flags = member->status & (CHFL_DEOPPED | CHFL_SERVOPOK);
836 remove_user_from_channel(sptr, chptr);
837 chptr = get_channel(sptr, name, CGT_CREATE);
842 name = chptr->chname;
843 if (!chptr->creationtime) /* A remote JOIN created this channel ? */
844 chptr->creationtime = MAGIC_REMOTE_JOIN_TS;
847 if (chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
848 chptr->creationtime = atoi(keysOrTS);
850 parc = 2; /* Don't pass it on */
854 if (!MyConnect(sptr))
855 flags = CHFL_DEOPPED;
856 if (sptr->flags & FLAGS_TS8)
857 flags |= CHFL_SERVOPOK;
861 int created = chptr->users == 0;
862 if (check_target_limit(sptr, chptr, chptr->chname, created))
864 if (created) /* Did we create the channel? */
865 sub1_from_channel(chptr); /* Remove it again! */
868 if ((i = can_join(sptr, chptr, keysOrTS)))
870 sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
871 #ifdef OPER_WALK_THROUGH_LMODES
872 if (i > MAGIC_OPER_OVERRIDE)
874 switch(i - MAGIC_OPER_OVERRIDE)
876 case ERR_CHANNELISFULL: i = 'l'; break;
877 case ERR_INVITEONLYCHAN: i = 'i'; break;
878 case ERR_BANNEDFROMCHAN: i = 'b'; break;
879 case ERR_BADCHANNELKEY: i = 'k'; break;
881 sendto_op_mask(SNO_HACK4,"OPER JOIN: %s JOIN %s (overriding +%c)",sptr->name,chptr->chname,i);
891 * Complete user entry to the new channel (if any)
893 add_user_to_channel(chptr, sptr, flags);
896 * Notify all other users on the new channel
898 sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
902 del_invite(sptr, chptr);
903 if (chptr->topic[0] != '\0')
905 sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
906 parv[0], name, chptr->topic);
907 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0], name,
908 chptr->topic_nick, chptr->topic_time);
911 m_names(cptr, sptr, 2, parv);
915 /* Select proper buffer; mbuf for creation, jbuf otherwise */
918 continue; /* Head off local channels at the pass */
920 bufptr = (sendcreate == 0) ? jbuf : mbuf;
921 buflen = (sendcreate == 0) ? &jlen : &mlen;
923 if (*buflen < BUFSIZE - len - 2)
927 strcat(bufptr, ","); /* Add to join buf */
930 strncat(bufptr, name, BUFSIZE - *buflen - 1);
933 sendcreate = 0; /* Reset sendcreate */
936 if (*jbuf) /* Propgate joins to P10 servers */
937 sendto_serv_butone(cptr,
938 parc > 2 ? "%s%s " TOK_JOIN " %s %s" : "%s%s " TOK_JOIN " %s", NumNick(sptr), jbuf, keysOrTS);
939 if (*mbuf) /* and now creation events */
940 sendto_serv_butone(cptr, "%s%s " TOK_CREATE " %s " TIME_T_FMT,
941 NumNick(sptr), mbuf, TStime());
944 { /* shouldn't ever set TS for remote JOIN's */
946 { /* check for channels that need TS's */
948 for (name = ircd_strtok(&p, jbuf, ","); name; name = ircd_strtok(&p, NULL, ","))
950 chptr = get_channel(sptr, name, CGT_NO_CREATE);
951 if (chptr && chptr->mode.mode & MODE_SENDTS)
953 sendto_serv_butone(cptr, "%s " TOK_MODE " %s + " TIME_T_FMT, NumServ(&me),
954 chptr->chname, chptr->creationtime); /* ok, send TS */
955 chptr->mode.mode &= ~MODE_SENDTS; /* reset flag */