2 * IRC - Internet Relay Chat, ircd/opercmds.c (formerly ircd/s_serv.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.
51 #include "sprintf_irc.h"
66 * parv[0] = sender prefix
67 * parv[1] = server name
69 * parv[parc-1] = comment
71 int m_squit(aClient *cptr, aClient *sptr, int parc, char *parv[])
73 Reg1 aConfItem *aconf;
76 char *comment = (parc > ((!IsServer(cptr)) ? 2 : 3) &&
77 !BadPtr(parv[parc - 1])) ? parv[parc - 1] : cptr->name;
79 if (!IsPrivileged(sptr))
81 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
85 if (parc > (IsServer(cptr) ? 2 : 1))
89 * To accomodate host masking, a squit for a masked server
90 * name is expanded if the incoming mask is the same as
91 * the server name for that link to the name of link.
93 if ((*server == '*') && IsServer(cptr) && (aconf = cptr->serv->nline) &&
94 !strCasediff(server, my_name_for_link(me.name, aconf)))
102 * The following allows wild cards in SQUIT. Only usefull
103 * when the command is issued by an oper.
105 for (acptr = client; (acptr = next_client(acptr, server));
107 if (IsServer(acptr) || IsMe(acptr))
117 server = cptr->sockhost;
125 * Look for a matching server that is closer,
126 * that way we won't accidently squit two close
127 * servers like davis.* and davis-r.* when typing
131 for (acptr2 = acptr->serv->up; acptr2 != &me;
132 acptr2 = acptr2->serv->up)
133 if (!match(server, acptr2->name))
138 /* If atoi(parv[2]) == 0 we must indeed squit !
139 * It wil be our neighbour.
141 if (acptr && IsServer(cptr) &&
142 atoi(parv[2]) && atoi(parv[2]) != acptr->serv->timestamp)
144 Debug((DEBUG_NOTICE, "Ignoring SQUIT with wrong timestamp"));
150 sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SQUIT");
154 * This is actually protocol error. But, well, closing
155 * the link is very proper answer to that...
157 server = cptr->sockhost;
166 sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], server);
169 if (IsLocOp(sptr) && !MyConnect(acptr))
171 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
175 return exit_client(cptr, acptr, sptr, comment);
181 * Report N/C-configuration lines from this server. This could
182 * report other configuration lines too, but converting the
183 * status back to "char" is a bit akward--not worth the code
186 * Note: The info is reported in the order the server uses
187 * it--not reversed as in ircd.conf!
190 static unsigned int report_array[17][3] = {
191 {CONF_CONNECT_SERVER, RPL_STATSCLINE, 'C'},
192 {CONF_NOCONNECT_SERVER, RPL_STATSNLINE, 'N'},
193 {CONF_CLIENT, RPL_STATSILINE, 'I'},
194 {CONF_KILL, RPL_STATSKLINE, 'K'},
195 {CONF_IPKILL, RPL_STATSKLINE, 'k'},
196 {CONF_LEAF, RPL_STATSLLINE, 'L'},
197 {CONF_OPERATOR, RPL_STATSOLINE, 'O'},
198 {CONF_HUB, RPL_STATSHLINE, 'H'},
199 {CONF_LOCOP, RPL_STATSOLINE, 'o'},
200 {CONF_CRULEALL, RPL_STATSDLINE, 'D'},
201 {CONF_CRULEAUTO, RPL_STATSDLINE, 'd'},
202 {CONF_UWORLD, RPL_STATSULINE, 'U'},
203 {CONF_TLINES, RPL_STATSTLINE, 'T'},
204 {CONF_LISTEN_PORT, RPL_STATSPLINE, 'P'},
208 static void report_configured_links(aClient *sptr, int mask)
210 static char null[] = "<NULL>";
213 unsigned short int port;
214 char c, *host, *pass, *name;
216 for (tmp = conf; tmp; tmp = tmp->next)
217 if ((tmp->status & mask))
219 for (p = &report_array[0][0]; *p; p += 3)
220 if (*p == tmp->status)
225 host = BadPtr(tmp->host) ? null : tmp->host;
226 pass = BadPtr(tmp->passwd) ? null : tmp->passwd;
227 name = BadPtr(tmp->name) ? null : tmp->name;
230 * On K line the passwd contents can be
231 * displayed on STATS reply. -Vesa
233 /* Special-case 'k' or 'K' lines as appropriate... -Kev */
234 if ((tmp->status & CONF_KLINE))
235 sendto_one(sptr, rpl_str(p[1]), me.name,
236 sptr->name, c, host, pass, name, port, get_conf_class(tmp));
237 /* connect rules are classless */
238 else if ((tmp->status & CONF_CRULE))
239 sendto_one(sptr, rpl_str(p[1]), me.name, sptr->name, c, host, name);
240 else if ((tmp->status & CONF_TLINES))
241 sendto_one(sptr, rpl_str(p[1]), me.name, sptr->name, c, host, pass);
242 else if ((tmp->status & CONF_LISTEN_PORT))
243 sendto_one(sptr, rpl_str(p[1]), me.name, sptr->name, c, port,
244 tmp->clients, tmp->status);
245 else if ((tmp->status & CONF_UWORLD))
246 sendto_one(sptr, rpl_str(p[1]),
247 me.name, sptr->name, c, host, pass, name, port,
248 get_conf_class(tmp));
250 sendto_one(sptr, rpl_str(p[1]), me.name, sptr->name, c, host, name,
251 port, get_conf_class(tmp));
259 * parv[0] = sender prefix
260 * parv[1] = statistics selector (defaults to Message frequency)
261 * parv[2] = target server (current server defaulted, if omitted)
262 * And 'stats l' and 'stats' L:
263 * parv[3] = server mask ("*" defaulted, if omitted)
265 * parv[3] = port mask (returns p-lines when its port is matched by this)
266 * Or for stats k,K,i and I:
267 * parv[3] = [user@]host.name (returns which K/I-lines match this)
268 * or [user@]host.mask (returns which K/I-lines are mmatched by this)
269 * (defaults to old reply if ommitted, when local or Oper)
270 * A remote mask (something containing wildcards) is only
271 * allowed for IRC Operators.
273 * parv[3] = time param
274 * parv[4] = time param
275 * (see report_memleak_stats() in runmalloc.c for details)
277 * This function is getting really ugly. -Ghostwolf
279 int m_stats(aClient *cptr, aClient *sptr, int parc, char *parv[])
281 static char Sformat[] = ":%s %d %s Connection SendQ SendM SendKBytes "
282 "RcveM RcveKBytes :Open since";
283 static char Lformat[] = ":%s %d %s %s %u %u %u %u %u :" TIME_T_FMT;
286 aGline *agline, *a2gline;
288 char stat = parc > 1 ? parv[1][0] : '\0';
291 /* m_stats is so obnoxiously full of special cases that the different
292 * hunt_server() possiblites were becoming very messy. It now uses a
293 * switch() so as to be easier to read and update as params change.
298 /* open to all, standard # of params */
302 if (hunt_server(0, cptr, sptr, ":%s STATS %s :%s", 2, parc, parv)
308 /* open to all, varying # of params */
318 if (hunt_server(0, cptr, sptr, ":%s STATS %s %s :%s", 2, parc, parv)
324 if (hunt_server(0, cptr, sptr, ":%s STATS %s :%s", 2, parc, parv)
331 /* oper only, varying # of params */
338 if (hunt_server(1, cptr, sptr, ":%s STATS %s %s :%s", 2, parc, parv)
344 if (hunt_server(1, cptr, sptr, ":%s STATS %s %s %s :%s", 2, parc,
345 parv) != HUNTED_ISME)
348 else if (hunt_server(1, cptr, sptr, ":%s STATS %s :%s", 2, parc, parv)
354 /* oper only, standard # of params */
357 if (hunt_server(1, cptr, sptr, ":%s STATS %s :%s", 2, parc, parv)
369 int doall = 0, wilds = 0;
371 if (parc > 3 && *parv[3])
375 wilds = (*name == '*' || *name == '?');
376 for (p = name + 1; *p; ++p)
377 if ((*p == '*' || *p == '?') && p[-1] != '\\')
386 * Send info about connections which match, or all if the
387 * mask matches me.name. Only restrictions are on those who
388 * are invisible not being visible to 'foreigners' who use
389 * a wild card based search to list it.
391 sendto_one(sptr, Sformat, me.name, RPL_STATSLINKINFO, parv[0]);
392 for (i = 0; i <= highest_fd; i++)
394 if (!(acptr = loc_clients[i]))
396 /* Don't return clients when this is a request for `all' */
397 if (doall && IsUser(acptr))
399 /* Don't show invisible people to unauthorized people when using
400 * wildcards -- Is this still needed now /stats is oper only ? */
401 if (IsInvisible(acptr) && (doall || wilds) &&
402 !(MyConnect(sptr) && IsOper(sptr)) &&
403 !IsAnOper(acptr) && (acptr != sptr))
405 /* Only show the ones that match the given mask - if any */
406 if (!doall && wilds && match(name, acptr->name))
408 /* Skip all that do not match the specific query */
409 if (!(doall || wilds) && strCasediff(name, acptr->name))
411 sendto_one(sptr, Lformat, me.name, RPL_STATSLINKINFO, parv[0],
413 get_client_name(acptr, TRUE) : get_client_name(acptr, FALSE),
414 (int)DBufLength(&acptr->sendQ), (int)acptr->sendM,
415 (int)acptr->sendK, (int)acptr->receiveM, (int)acptr->receiveK,
416 time(NULL) - acptr->firsttime);
422 report_configured_links(sptr,
423 CONF_CONNECT_SERVER | CONF_NOCONNECT_SERVER);
428 for (agline = gline, a2gline = NULL; agline; agline = agline->next)
430 if (agline->expire <= TStime())
431 { /* handle expired glines */
432 free_gline(agline, a2gline);
433 agline = a2gline ? a2gline : gline; /* make sure to splice
436 break; /* last gline; break out of loop */
437 continue; /* continue! */
439 sendto_one(sptr, rpl_str(RPL_STATSGLINE), me.name,
440 sptr->name, 'G', agline->name, agline->host,
441 agline->expire, agline->reason);
447 report_configured_links(sptr, CONF_HUB | CONF_LEAF);
452 case 'k': /* display CONF_IPKILL as well
456 char *user, *host, *p;
457 int conf_status = (stat == 'k' || stat == 'K') ? CONF_KLINE : CONF_CLIENT;
458 if ((MyUser(sptr) || IsOper(sptr)) && parc < 4)
460 report_configured_links(sptr, conf_status);
463 if (parc < 4 || *parv[3] == '\0')
465 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
466 (conf_status & CONF_KLINE) ? "STATS K" : "STATS I");
470 for (p = parv[3]; *p; p++)
478 if (*p == '?' || *p == '*')
484 if (!(MyConnect(sptr) || IsOper(sptr)))
492 if (conf_status == CONF_CLIENT)
494 user = NULL; /* Not used, but to avoid compiler warning. */
500 if ((host = strchr(parv[3], '@')))
511 for (aconf = conf; aconf; aconf = aconf->next)
513 if ((aconf->status & conf_status))
515 if (conf_status == CONF_KLINE)
517 if ((!wilds && ((user || aconf->host[1]) &&
518 !match(aconf->host, host) &&
519 (!user || !match(aconf->name, user)))) ||
520 (wilds && !mmatch(host, aconf->host) &&
521 (!user || !mmatch(user, aconf->name))))
523 sendto_one(sptr, rpl_str(RPL_STATSKLINE), me.name,
524 sptr->name, 'K', aconf->host, aconf->passwd, aconf->name,
525 aconf->port, get_conf_class(aconf));
530 else if (conf_status == CONF_CLIENT)
532 if ((!wilds && (!match(aconf->host, host) ||
533 !match(aconf->name, host))) ||
534 (wilds && (!mmatch(host, aconf->host) ||
535 !mmatch(host, aconf->name))))
537 sendto_one(sptr, rpl_str(RPL_STATSILINE), me.name,
538 sptr->name, 'I', aconf->host, aconf->name,
539 aconf->port, get_conf_class(aconf));
550 sendto_one(sptr, rpl_str(RPL_STATMEMTOT),
551 me.name, parv[0], get_mem_size(), get_alloc_cnt());
554 report_memleak_stats(sptr, parc, parv);
556 #if !defined(MEMSIZESTATS) && !defined(MEMLEAKSTATS)
557 sendto_one(sptr, ":%s NOTICE %s :stats M : Memory allocation monitoring "
558 "is not enabled on this server", me.name, parv[0]);
562 for (mptr = msgtab; mptr->cmd; mptr++)
564 sendto_one(sptr, rpl_str(RPL_STATSCOMMANDS),
565 me.name, parv[0], mptr->cmd, mptr->count, mptr->bytes);
569 report_configured_links(sptr, CONF_OPS);
576 if ((MyUser(sptr) || IsOper(sptr)) && parc < 4)
578 report_configured_links(sptr, CONF_LISTEN_PORT);
581 if (!(MyConnect(sptr) || IsOper(sptr)))
583 for (aconf = conf; aconf; aconf = aconf->next)
584 if (aconf->status == CONF_LISTEN_PORT)
586 if (parc >= 4 && *parv[3] != '\0')
588 sprintf_irc(port, "%u", aconf->port);
589 if (match(parv[3], port))
592 sendto_one(sptr, rpl_str(RPL_STATSPLINE), me.name, sptr->name, 'P',
593 aconf->port, aconf->clients, aconf->status);
602 send_usage(sptr, parv[0]);
606 report_configured_links(sptr, CONF_CRULEALL);
609 report_configured_links(sptr, CONF_CRULE);
612 tstats(sptr, parv[0]);
615 report_configured_links(sptr, CONF_TLINES);
618 report_configured_links(sptr, CONF_UWORLD);
622 register time_t nowr;
624 nowr = now - me.since;
625 sendto_one(sptr, rpl_str(RPL_STATSUPTIME), me.name, parv[0],
626 nowr / 86400, (nowr / 3600) % 24, (nowr / 60) % 60, nowr % 60);
627 sendto_one(sptr, rpl_str(RPL_STATSCONN), me.name, parv[0],
628 max_connection_count, max_client_count);
638 send_listinfo(sptr, parv[0]);
643 report_classes(sptr);
647 count_memory(sptr, parv[0]);
653 sendto_one(sptr, rpl_str(RPL_ENDOFSTATS), me.name, parv[0], stat);
658 * m_connect - Added by Jto 11 Feb 1989
660 * parv[0] = sender prefix
661 * parv[1] = servername
662 * parv[2] = [IP-number:]port number
663 * parv[3] = remote server
665 int m_connect(aClient *cptr, aClient *sptr, int parc, char *parv[])
668 unsigned short int port, tmpport;
669 aConfItem *aconf, *cconf;
673 if (!IsPrivileged(sptr))
675 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
679 if (IsLocOp(sptr) && parc > 3) /* Only allow LocOps to make */
680 return 0; /* local CONNECTS --SRB */
682 if (parc > 3 && MyUser(sptr))
684 aClient *acptr2, *acptr3;
685 if (!(acptr3 = find_match_server(parv[3])))
687 sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], parv[3]);
691 /* Look for closest matching server */
692 for (acptr2 = acptr3; acptr2 != &me; acptr2 = acptr2->serv->up)
693 if (!match(parv[3], acptr2->name))
696 parv[3] = acptr3->name;
699 if (hunt_server(1, cptr, sptr, ":%s CONNECT %s %s :%s", 3, parc, parv) !=
703 if (parc < 2 || *parv[1] == '\0')
705 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "CONNECT");
709 if ((acptr = FindServer(parv[1])))
711 if (MyUser(sptr) || Protocol(cptr) < 10)
712 sendto_one(sptr, ":%s NOTICE %s :Connect: Server %s %s %s.",
713 me.name, parv[0], parv[1], "already exists from", acptr->from->name);
715 sendto_one(sptr, "%s NOTICE %s%s :Connect: Server %s %s %s.",
716 NumServ(&me), NumNick(sptr), parv[1], "already exists from",
721 if (parc > 2 && !BadPtr(parv[2]))
722 p = strchr(parv[2], ':');
727 for (aconf = conf; aconf; aconf = aconf->next)
728 if (aconf->status == CONF_CONNECT_SERVER &&
729 match(parv[1], aconf->name) == 0 &&
730 (!p || match(parv[2], aconf->host) == 0 ||
731 match(parv[2], strchr(aconf->host, '@') + 1) == 0))
733 /* Checked first servernames, then try hostnames. */
735 for (aconf = conf; aconf; aconf = aconf->next)
736 if (aconf->status == CONF_CONNECT_SERVER &&
737 (match(parv[1], aconf->host) == 0 ||
738 match(parv[1], strchr(aconf->host, '@') + 1) == 0))
745 if (MyUser(sptr) || Protocol(cptr) < 10)
747 ":%s NOTICE %s :Connect: Host %s not listed in ircd.conf",
748 me.name, parv[0], parv[1]);
751 "%s NOTICE %s%s :Connect: Host %s not listed in ircd.conf",
752 NumServ(&me), NumNick(sptr), parv[1]);
756 * Get port number from user, if given. If not specified,
757 * use the default from configuration structure. If missing
758 * from there, then use the precompiled default.
760 tmpport = port = aconf->port;
761 if (parc > 2 && !BadPtr(parv[2]))
763 p = strchr(parv[2], ':');
768 if ((port = atoi(p)) == 0)
770 if (MyUser(sptr) || Protocol(cptr) < 10)
772 ":%s NOTICE %s :Connect: Invalid port number", me.name, parv[0]);
774 sendto_one(sptr, "%s NOTICE %s%s :Connect: Invalid port number",
775 NumServ(&me), NumNick(sptr));
779 else if (port == 0 && (port = PORTNUM) == 0)
781 if (MyUser(sptr) || Protocol(cptr) < 10)
782 sendto_one(sptr, ":%s NOTICE %s :Connect: missing port number",
785 sendto_one(sptr, "%s NOTICE %s%s :Connect: missing port number",
786 NumServ(&me), NumNick(sptr));
791 * Evaluate connection rules... If no rules found, allow the
792 * connect. Otherwise stop with the first true rule (ie: rules
793 * are ored together. Oper connects are effected only by D
794 * lines (CRULEALL) not d lines (CRULEAUTO).
796 for (cconf = conf; cconf; cconf = cconf->next)
797 if ((cconf->status == CONF_CRULEALL) &&
798 (match(cconf->host, aconf->name) == 0))
799 if (crule_eval(cconf->passwd))
801 if (MyUser(sptr) || Protocol(cptr) < 10)
802 sendto_one(sptr, ":%s NOTICE %s :Connect: Disallowed by rule: %s",
803 me.name, parv[0], cconf->name);
805 sendto_one(sptr, "%s NOTICE %s%s :Connect: Disallowed by rule: %s",
806 NumServ(&me), NumNick(sptr), cconf->name);
811 * Notify all operators about remote connect requests
815 sendto_ops_butone(NULL, &me, ":%s WALLOPS :Remote CONNECT %s %s from %s",
816 me.name, parv[1], parv[2] ? parv[2] : "", get_client_name(sptr, FALSE));
817 #if defined(USE_SYSLOG) && defined(SYSLOG_CONNECT)
819 "CONNECT From %s : %s %d", parv[0], parv[1], parv[2] ? parv[2] : "");
823 switch (retval = connect_server(aconf, sptr, NULL))
826 if (MyUser(sptr) || Protocol(cptr) < 10)
828 ":%s NOTICE %s :*** Connecting to %s[%s].",
829 me.name, parv[0], aconf->host, aconf->name);
832 "%s NOTICE %s%s :*** Connecting to %s[%s].",
833 NumServ(&me), NumNick(sptr), aconf->host, aconf->name);
836 /* Comments already sent */
839 if (MyUser(sptr) || Protocol(cptr) < 10)
840 sendto_one(sptr, ":%s NOTICE %s :*** Host %s is unknown.",
841 me.name, parv[0], aconf->host);
843 sendto_one(sptr, "%s NOTICE %s%s :*** Host %s is unknown.",
844 NumServ(&me), NumNick(sptr), aconf->host);
847 if (MyUser(sptr) || Protocol(cptr) < 10)
849 ":%s NOTICE %s :*** Connection to %s failed: %s",
850 me.name, parv[0], aconf->host, strerror(retval));
853 "%s NOTICE %s%s :*** Connection to %s failed: %s",
854 NumServ(&me), NumNick(sptr), aconf->host, strerror(retval));
856 aconf->port = tmpport;
863 * Writes to all +w users currently online
865 * parv[0] = sender prefix
866 * parv[1] = message text
868 int m_wallops(aClient *cptr, aClient *sptr, int parc, char *parv[])
872 message = parc > 1 ? parv[1] : NULL;
876 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "WALLOPS");
880 if (!IsServer(sptr) && MyConnect(sptr) && !IsAnOper(sptr))
882 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
885 sendto_ops_butone(IsServer(cptr) ? cptr : NULL, sptr,
886 ":%s WALLOPS :%s", parv[0], message);
893 * parv[0] = sender prefix
894 * parv[1] = servername
896 int m_time(aClient *cptr, aClient *sptr, int parc, char *parv[])
898 if (hunt_server(0, cptr, sptr, ":%s TIME :%s", 1, parc, parv) == HUNTED_ISME)
899 sendto_one(sptr, rpl_str(RPL_TIME), me.name,
900 parv[0], me.name, TStime(), TSoffset, date((long)0));
907 * parv[0] = sender prefix
909 * parv[2] = servername (Only used when sptr is an Oper).
911 int m_settime(aClient *cptr, aClient *sptr, int parc, char *parv[])
915 static char tbuf[11];
918 if (!IsPrivileged(sptr))
923 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SETTIME");
927 if (parc == 2 && MyUser(sptr))
928 parv[parc++] = me.name;
933 if (t < 779557906 || dt < -9000000)
935 sendto_one(sptr, ":%s NOTICE %s :SETTIME: Bad value", me.name, parv[0]);
939 if (IsServer(sptr)) /* send to unlagged servers */
941 #ifdef RELIABLE_CLOCK
942 sprintf_irc(tbuf, TIME_T_FMT, TStime());
945 for (lp = me.serv->down; lp; lp = lp->next)
946 if (cptr != lp->value.cptr && DBufLength(&lp->value.cptr->sendQ) < 8000)
947 sendto_one(lp->value.cptr, ":%s SETTIME %s", parv[0], parv[1]);
951 sprintf_irc(tbuf, TIME_T_FMT, TStime());
953 if (hunt_server(1, cptr, sptr, ":%s SETTIME %s %s", 2, parc, parv) !=
958 #ifdef RELIABLE_CLOCK
959 if ((dt > 600) || (dt < -600))
960 sendto_serv_butone((aClient *)NULL,
961 ":%s WALLOPS :Bad SETTIME from %s: " TIME_T_FMT, me.name, sptr->name,
965 if (MyUser(sptr) || Protocol(cptr) < 10)
966 sendto_one(sptr, ":%s NOTICE %s :clock is not set %ld seconds %s : "
967 "RELIABLE_CLOCK is defined", me.name, parv[0],
968 (dt < 0) ? -dt : dt, (dt < 0) ? "forwards" : "backwards");
970 sendto_one(sptr, "%s NOTICE %s%s :clock is not set %ld seconds %s : "
971 "RELIABLE_CLOCK is defined", NumServ(&me), NumNick(sptr),
972 (dt < 0) ? -dt : dt, (dt < 0) ? "forwards" : "backwards");
975 sendto_ops("SETTIME from %s, clock is set %ld seconds %s",
976 get_client_name(sptr, FALSE), (dt < 0) ? -dt : dt,
977 (dt < 0) ? "forwards" : "backwards");
981 if (MyUser(sptr) || Protocol(cptr) < 10)
982 sendto_one(sptr, ":%s NOTICE %s :clock is set %ld seconds %s", me.name,
983 parv[0], (dt < 0) ? -dt : dt, (dt < 0) ? "forwards" : "backwards");
985 sendto_one(sptr, "%s NOTICE %s%s :clock is set %ld seconds %s",
986 NumServ(&me), NumNick(sptr),
987 (dt < 0) ? -dt : dt, (dt < 0) ? "forwards" : "backwards");
993 static char *militime(char *sec, char *usec)
996 static char timebuf[18];
998 gettimeofday(&tv, NULL);
1000 #if defined(__sun__) || defined(__bsdi__) || (__GLIBC__ >= 2) || defined(__NetBSD__)
1001 sprintf(timebuf, "%ld",
1002 (tv.tv_sec - atoi(sec)) * 1000 + (tv.tv_usec - atoi(usec)) / 1000);
1004 sprintf_irc(timebuf, "%d",
1005 (tv.tv_sec - atoi(sec)) * 1000 + (tv.tv_usec - atoi(usec)) / 1000);
1008 #if defined(__sun__) || defined(__bsdi__) || (__GLIBC__ >= 2) || defined(__NetBSD__)
1009 sprintf(timebuf, "%ld %ld", tv.tv_sec, tv.tv_usec);
1011 sprintf_irc(timebuf, "%d %d", tv.tv_sec, tv.tv_usec);
1019 * parv[0] = sender (sptr->name thus)
1020 * if sender is a person: (traveling towards start server)
1021 * parv[1] = pinged server[mask]
1022 * parv[2] = start server (current target)
1023 * parv[3] = optional remark
1024 * if sender is a server: (traveling towards pinged server)
1025 * parv[1] = pinged server (current target)
1026 * parv[2] = original sender (person)
1027 * parv[3] = start time in s
1028 * parv[4] = start time in us
1029 * parv[5] = the optional remark
1031 int m_rping(aClient *cptr, aClient *sptr, int parc, char *parv[])
1035 if (!IsPrivileged(sptr))
1038 if (parc < (IsAnOper(sptr) ? (MyConnect(sptr) ? 2 : 3) : 6))
1040 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "RPING");
1046 parv[parc++] = me.name;
1047 else if (!(acptr = find_match_server(parv[2])))
1054 parv[2] = acptr->name;
1056 parv[parc++] = "<No client start time>";
1061 if (hunt_server(1, cptr, sptr, ":%s RPING %s %s :%s", 2, parc, parv) !=
1064 if (!(acptr = find_match_server(parv[1])) || !IsServer(acptr))
1066 sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], parv[1]);
1069 if (Protocol(acptr->from) < 10)
1070 sendto_one(acptr, ":%s RPING %s %s %s :%s",
1071 me.name, acptr->name, sptr->name, militime(NULL, NULL), parv[3]);
1073 sendto_one(acptr, ":%s RPING %s %s %s :%s",
1074 me.name, NumServ(acptr), sptr->name, militime(NULL, NULL), parv[3]);
1078 if (hunt_server(1, cptr, sptr, ":%s RPING %s %s %s %s :%s", 1, parc, parv)
1081 sendto_one(cptr, ":%s RPONG %s %s %s %s :%s", me.name, parv[0],
1082 parv[2], parv[3], parv[4], parv[5]);
1088 * m_rpong -- by Run too :)
1090 * parv[0] = sender prefix
1091 * parv[1] = from pinged server: start server; from start server: sender
1092 * parv[2] = from pinged server: sender; from start server: pinged server
1093 * parv[3] = pingtime in ms
1094 * parv[4] = client info (for instance start time)
1096 int m_rpong(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
1100 if (!IsServer(sptr))
1105 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "RPING");
1109 if (!(acptr = FindClient(parv[1])))
1114 if (IsServer(acptr) && parc > 5)
1116 sendto_one(acptr, ":%s RPONG %s %s %s %s :%s",
1117 parv[0], parv[1], parv[2], parv[3], parv[4], parv[5]);
1124 parv[2] = sptr->name;
1126 parv[3] = militime(parv[3], parv[4]);
1128 if (!(acptr = FindUser(parv[1])))
1129 return 0; /* No bouncing between servers ! */
1132 sendto_one(acptr, ":%s RPONG %s %s %s :%s",
1133 parv[0], parv[1], parv[2], parv[3], parv[4]);
1137 #if defined(OPER_REHASH) || defined(LOCOP_REHASH)
1141 int m_rehash(aClient *cptr, aClient *sptr, int parc, char *parv[])
1143 #ifndef LOCOP_REHASH
1144 if (!MyUser(sptr) || !IsOper(sptr))
1147 if (!MyUser(sptr) || !IsAnOper(sptr))
1149 if (!MyUser(sptr) || !IsLocOp(sptr))
1153 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1156 sendto_one(sptr, rpl_str(RPL_REHASHING), me.name, parv[0], configfile);
1157 sendto_ops("%s is rehashing Server config file", parv[0]);
1159 syslog(LOG_INFO, "REHASH From %s\n", get_client_name(sptr, FALSE));
1161 return rehash(cptr, (parc > 1) ? ((*parv[1] == 'q') ? 2 : 0) : 0);
1165 #if defined(OPER_RESTART) || defined(LOCOP_RESTART)
1169 int m_restart(aClient *UNUSED(cptr), aClient *sptr, int UNUSED(parc),
1172 #ifndef LOCOP_RESTART
1173 if (!MyUser(sptr) || !IsOper(sptr))
1176 if (!MyUser(sptr) || !IsAnOper(sptr))
1178 if (!MyUser(sptr) || !IsLocOp(sptr))
1182 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1186 syslog(LOG_WARNING, "Server RESTART by %s\n", get_client_name(sptr, FALSE));
1196 * parv[0] = sender prefix
1197 * parv[1] = nick or servername
1198 * parv[2] = 'target' servername
1200 int m_trace(aClient *cptr, aClient *sptr, int parc, char *parv[])
1203 Reg2 aClient *acptr;
1206 int doall, link_s[MAXCONNECTIONS], link_u[MAXCONNECTIONS];
1207 int cnt = 0, wilds, dow;
1209 if (parc < 2 || BadPtr(parv[1]))
1211 /* just "TRACE" without parameters. Must be from local client */
1217 else if (parc < 3 || BadPtr(parv[2]))
1219 /* No target specified. Make one before propagating. */
1222 if ((acptr = find_match_server(parv[1])) ||
1223 ((acptr = FindClient(parv[1])) && !MyUser(acptr)))
1226 parv[2] = acptr->user->server->name;
1228 parv[2] = acptr->name;
1231 if ((i = hunt_server(IsServer(acptr), cptr, sptr,
1232 ":%s TRACE %s :%s", 2, parc, parv)) == HUNTED_NOSUCH)
1240 /* Got "TRACE <tname> :<target>" */
1242 if (MyUser(sptr) || Protocol(cptr) < 10)
1243 acptr = find_match_server(parv[2]);
1245 acptr = FindNServer(parv[2]);
1246 if ((i = hunt_server(0, cptr, sptr,
1247 ":%s TRACE %s :%s", 2, parc, parv)) == HUNTED_NOSUCH)
1252 if (i == HUNTED_PASS)
1255 acptr = next_client(client, tname);
1257 acptr = acptr->from;
1258 sendto_one(sptr, rpl_str(RPL_TRACELINK), me.name, parv[0],
1260 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>");
1262 version, debugmode, tname, acptr ? acptr->from->name : "<No_match>",
1263 (acptr && acptr->from->serv) ? acptr->from->serv->timestamp : 0);
1264 #endif /* GODMODE */
1268 doall = (parv[1] && (parc > 1)) ? !match(tname, me.name) : TRUE;
1269 wilds = !parv[1] || strchr(tname, '*') || strchr(tname, '?');
1270 dow = wilds || doall;
1272 /* Don't give (long) remote listings to lusers */
1273 if (dow && !MyConnect(sptr) && !IsAnOper(sptr))
1276 for (i = 0; i < MAXCONNECTIONS; i++)
1277 link_s[i] = 0, link_u[i] = 0;
1281 for (acptr = client; acptr; acptr = acptr->next)
1283 link_u[acptr->from->fd]++;
1284 else if (IsServer(acptr))
1285 link_s[acptr->from->fd]++;
1288 /* report all direct connections */
1290 for (i = 0; i <= highest_fd; i++)
1293 unsigned int conClass;
1295 if (!(acptr = loc_clients[i])) /* Local Connection? */
1297 if (IsInvisible(acptr) && dow && !(MyConnect(sptr) && IsOper(sptr)) &&
1298 !IsAnOper(acptr) && (acptr != sptr))
1300 if (!doall && wilds && match(tname, acptr->name))
1302 if (!dow && strCasediff(tname, acptr->name))
1304 name = get_client_name(acptr, FALSE);
1305 conClass = get_client_class(acptr);
1307 switch (acptr->status)
1309 case STAT_CONNECTING:
1310 sendto_one(sptr, rpl_str(RPL_TRACECONNECTING),
1311 me.name, parv[0], conClass, name);
1314 case STAT_HANDSHAKE:
1315 sendto_one(sptr, rpl_str(RPL_TRACEHANDSHAKE),
1316 me.name, parv[0], conClass, name);
1322 case STAT_UNKNOWN_USER:
1323 case STAT_UNKNOWN_SERVER:
1324 sendto_one(sptr, rpl_str(RPL_TRACEUNKNOWN),
1325 me.name, parv[0], conClass, name);
1329 /* Only opers see users if there is a wildcard
1330 but anyone can see all the opers. */
1331 if ((IsAnOper(sptr) && (MyUser(sptr) ||
1332 !(dow && IsInvisible(acptr)))) || !dow || IsAnOper(acptr))
1334 if (IsAnOper(acptr))
1335 sendto_one(sptr, rpl_str(RPL_TRACEOPERATOR),
1336 me.name, parv[0], conClass, name, now - acptr->lasttime);
1338 sendto_one(sptr, rpl_str(RPL_TRACEUSER),
1339 me.name, parv[0], conClass, name, now - acptr->lasttime);
1344 * Connection is a server
1346 * Serv <class> <nS> <nC> <name> <ConnBy> <last> <age>
1348 * class Class the server is in
1349 * nS Number of servers reached via this link
1350 * nC Number of clients reached via this link
1351 * name Name of the server linked
1352 * ConnBy Who established this link
1353 * last Seconds since we got something from this link
1354 * age Seconds this link has been alive
1356 * Additional comments etc...... -Cym-<cym@acrux.net>
1360 if (acptr->serv->user)
1361 sendto_one(sptr, rpl_str(RPL_TRACESERVER),
1362 me.name, parv[0], conClass, link_s[i],
1363 link_u[i], name, acptr->serv->by,
1364 acptr->serv->user->username,
1365 acptr->serv->user->host,
1366 now - acptr->lasttime, now - acptr->serv->timestamp);
1368 sendto_one(sptr, rpl_str(RPL_TRACESERVER),
1369 me.name, parv[0], conClass, link_s[i],
1370 link_u[i], name, *(acptr->serv->by) ?
1371 acptr->serv->by : "*", "*", me.name,
1372 now - acptr->lasttime, now - acptr->serv->timestamp);
1376 sendto_one(sptr, rpl_str(RPL_TRACELOG),
1377 me.name, parv[0], LOGFILE, acptr->port);
1381 sendto_one(sptr, rpl_str(RPL_TRACEPING), me.name,
1382 parv[0], name, (acptr->acpt) ? acptr->acpt->name : "<null>");
1384 default: /* We actually shouldn't come here, -msa */
1385 sendto_one(sptr, rpl_str(RPL_TRACENEWTYPE), me.name, parv[0], name);
1391 * Add these lines to summarize the above which can get rather long
1392 * and messy when done remotely - Avalon
1394 if (!IsAnOper(sptr) || !cnt)
1397 /* let the user have some idea that its at the end of the trace */
1398 sendto_one(sptr, rpl_str(RPL_TRACESERVER),
1399 me.name, parv[0], 0, link_s[me.fd],
1400 link_u[me.fd], "<No_match>", *(me.serv->by) ?
1401 me.serv->by : "*", "*", me.name, 0, 0);
1404 for (cltmp = FirstClass(); doall && cltmp; cltmp = NextClass(cltmp))
1405 if (Links(cltmp) > 0)
1406 sendto_one(sptr, rpl_str(RPL_TRACECLASS), me.name,
1407 parv[0], ConClass(cltmp), Links(cltmp));
1412 * m_close - added by Darren Reed Jul 13 1992.
1414 int m_close(aClient *cptr, aClient *sptr, int UNUSED(parc), char *parv[])
1416 Reg1 aClient *acptr;
1422 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1426 for (i = highest_fd; i; i--)
1428 if (!(acptr = loc_clients[i]))
1430 if (!IsUnknown(acptr) && !IsConnecting(acptr) && !IsHandshake(acptr))
1432 sendto_one(sptr, rpl_str(RPL_CLOSING), me.name, parv[0],
1433 get_client_name(acptr, TRUE), acptr->status);
1434 exit_client(cptr, acptr, &me, "Oper Closing");
1437 sendto_one(sptr, rpl_str(RPL_CLOSEEND), me.name, parv[0], closed);
1441 #if defined(OPER_DIE) || defined(LOCOP_DIE)
1445 int m_die(aClient *UNUSED(cptr), aClient *sptr, int UNUSED(parc), char *parv[])
1447 Reg1 aClient *acptr;
1451 if (!MyUser(sptr) || !IsOper(sptr))
1454 if (!MyUser(sptr) || !IsAnOper(sptr))
1456 if (!MyUser(sptr) || !IsLocOp(sptr))
1460 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
1464 for (i = 0; i <= highest_fd; i++)
1466 if (!(acptr = loc_clients[i]))
1469 sendto_one(acptr, ":%s NOTICE %s :Server Terminating. %s",
1470 me.name, acptr->name, get_client_name(sptr, TRUE));
1471 else if (IsServer(acptr))
1472 sendto_one(acptr, ":%s ERROR :Terminated by %s",
1473 me.name, get_client_name(sptr, TRUE));
1484 static void add_gline(aClient *sptr, int ip_mask, char *host, char *comment,
1485 char *user, time_t expire, int local)
1492 if(*host=='#' || *host == '&' || *host == '+')
1493 gtype=1; /* BAD CHANNEL */
1496 sendto_op_mask(SNO_GLINE,
1497 "%s adding %s%s for %s@%s, expiring at " TIME_T_FMT ": %s", sptr->name,
1498 local ? "local " : "",
1499 gtype ? "BADCHAN":"GLINE", user, host, expire, comment);
1503 "# " TIME_T_FMT " %s adding %s %s for %s@%s, expiring at " TIME_T_FMT
1504 ": %s\n", TStime(), sptr->name, local ? "local" : "global",
1505 gtype ? "BADCHAN" : "GLINE", user, host, expire, comment);
1507 /* this can be inserted into the conf */
1509 write_log(GPATH, "%c:%s:%s:%s\n", ip_mask ? 'k' : 'K', host, comment,
1513 agline = make_gline(ip_mask, host, comment, user, expire);
1515 SetGlineIsLocal(agline);
1521 for (fd = highest_fd; fd >= 0; --fd) /* get the users! */
1522 if ((acptr = loc_clients[fd]) && !IsMe(acptr))
1525 if (!acptr->user || strlen(acptr->sockhost) > (size_t)HOSTLEN ||
1526 (acptr->user->username ? strlen(acptr->user->username) : 0) >
1528 continue; /* these tests right out of
1529 find_kill for safety's sake */
1531 if ((GlineIsIpMask(agline) ?
1532 match(agline->host, inetntoa(acptr->ip)) :
1533 match(agline->host, acptr->sockhost)) == 0 &&
1534 (!acptr->user->username ||
1535 match(agline->name, acptr->user->username) == 0))
1538 /* ok, he was the one that got G-lined */
1539 sendto_one(acptr, ":%s %d %s :*** %s.", me.name,
1540 ERR_YOUREBANNEDCREEP, acptr->name, agline->reason);
1542 /* let the ops know about my first kill */
1543 sendto_op_mask(SNO_GLINE, "G-line active for %s",
1544 get_client_name(acptr, FALSE));
1546 /* and get rid of him */
1548 exit_client(sptr->from, acptr, &me, "G-lined");
1556 * parv[0] = Send prefix
1560 * parv[1] = Target: server numeric
1561 * parv[2] = [+|-]<G-line mask>
1562 * parv[3] = Expiration offset
1567 * parv[1] = [+|-]<G-line mask>
1568 * parv[2] = Expiration offset
1572 int m_gline(aClient *cptr, aClient *sptr, int parc, char *parv[])
1574 aClient *acptr = NULL; /* Init. to avoid compiler warning. */
1576 aGline *agline, *a2gline;
1578 int active, ip_mask,gtype = 0;
1581 /* Remove expired G-lines */
1582 for (agline = gline, a2gline = NULL; agline; agline = agline->next)
1584 if (agline->expire <= TStime())
1586 free_gline(agline, a2gline);
1587 agline = a2gline ? a2gline : gline;
1596 /* Remove expired bad channels */
1597 for (agline = badchan, a2gline = NULL; agline; agline = agline->next)
1599 if (agline->expire <= TStime())
1601 free_gline(agline, a2gline);
1602 agline = a2gline ? a2gline : badchan;
1614 if (find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))
1616 if (parc < 3 || (*parv[2] != '-' && (parc < 5 || *parv[4] == '\0')))
1618 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
1623 if (*parv[2] == '-') /* add mode or delete mode? */
1628 if (*parv[2] == '+' || *parv[2] == '-')
1629 parv[2]++; /* step past mode indicator */
1631 /* forward the message appropriately */
1632 if (!strCasediff(parv[1], "*")) /* global! */
1633 sendto_serv_butone(cptr, active ? ":%s GLINE %s +%s %s :%s" :
1634 ":%s GLINE %s -%s", parv[0], parv[1], parv[2], parv[3], parv[4]);
1638 * REMOVE THIS after all servers upgraded to 2.10.01 and
1639 * Uworld uses a numeric too
1641 (strlen(parv[1]) != 1 && !(acptr = FindClient(parv[1])))) ||
1642 (strlen(parv[1]) == 1 &&
1644 !(acptr = FindNServer(parv[1]))))
1645 return 0; /* no such server/user exists; forget it */
1649 * REMOVE THIS after all servers upgraded to 2.10.01 and
1650 * Uworld uses a numeric too
1652 if (IsServer(acptr) || !MyConnect(acptr))
1655 sendto_one(acptr, active ? ":%s GLINE %s +%s %s :%s" :
1656 ":%s GLINE %s -%s", parv[0], parv[1], parv[2], parv[3], parv[4]); /* single destination */
1657 return 0; /* only the intended destination
1658 should add this gline */
1661 if (!(host = strchr(parv[2], '@')))
1662 { /* convert user@host */
1663 user = "*"; /* no @'s; assume username is '*' */
1669 *(host++) = '\0'; /* break up string at the '@' */
1671 ip_mask = check_if_ipmask(host); /* Store this boolean */
1673 if(*host=='#' || *host == '&' || *host == '+')
1674 gtype=1; /* BAD CHANNEL GLINE */
1677 for (agline = (gtype)?badchan:gline, a2gline = NULL; agline;
1678 agline = agline->next)
1680 if (!strCasediff(agline->name, user)
1681 && !strCasediff(agline->host, host))
1686 if (!active && agline)
1687 { /* removing the gline */
1689 sendto_op_mask(SNO_GLINE, "%s removing %s for %s@%s", parv[0],
1690 gtype?"BADCHAN":"GLINE",agline->name, agline->host);
1693 write_log(GPATH, "# " TIME_T_FMT " %s removing %s for %s@%s\n",
1694 TStime(), parv[0], gtype?"BADCHAN":"GLINE",agline->name,
1698 free_gline(agline, a2gline); /* remove the gline */
1701 { /* must be adding a gline */
1702 expire = atoi(parv[3]) + TStime(); /* expire time? */
1703 if (agline && agline->expire < expire)
1704 { /* new expire time? */
1705 /* yes, notify the opers */
1706 sendto_op_mask(SNO_GLINE,
1707 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
1708 parv[0], gtype?"BADCHAN":"GLINE",agline->name, agline->host,
1712 write_log(GPATH, "# " TIME_T_FMT " %s resetting expiration time "
1713 "on %s for %s@%s to " TIME_T_FMT "\n",
1714 TStime(), parv[0], gtype?"BADCHAN":"GLINE",
1715 agline->name, agline->host, expire);
1718 agline->expire = expire; /* reset the expire time */
1721 { /* create gline */
1722 for (agline = gtype?badchan:gline; agline; agline = agline->next)
1723 if (!mmatch(agline->name, user) &&
1724 (ip_mask ? GlineIsIpMask(agline) : !GlineIsIpMask(agline)) &&
1725 !mmatch(agline->host, host))
1726 return 0; /* found an existing G-line that matches */
1729 add_gline(sptr, ip_mask, host, parv[4], user, expire, 0);
1734 else if (parc < 2 || *parv[1] == '\0')
1736 /* Not enough args and a user; list glines */
1737 for (agline = gline; agline; agline = agline->next)
1738 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0],
1739 agline->name, agline->host, agline->expire, agline->reason,
1740 GlineIsActive(agline) ? (GlineIsLocal(agline) ? " (local)" : "") :
1742 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
1749 priv = IsAnOper(cptr);
1751 priv = IsOper(cptr);
1755 { /* non-oper not permitted to change things */
1756 if (*parv[1] == '-')
1757 { /* oper wants to deactivate the gline */
1761 else if (*parv[1] == '+')
1762 { /* oper wants to activate inactive gline */
1770 expire = atoi(parv[2]) + TStime(); /* oper wants to reset
1776 if (!(host = strchr(parv[1], '@')))
1778 user = "*"; /* no @'s; assume username is '*' */
1784 *(host++) = '\0'; /* break up string at the '@' */
1786 ip_mask = check_if_ipmask(host); /* Store this boolean */
1788 if(*host=='#' || *host == '&' || *host == '+')
1789 #ifndef LOCAL_BADCHAN
1792 gtype=1; /* BAD CHANNEL */
1796 for (agline = gtype?badchan:gline, a2gline = NULL; agline;
1797 agline = agline->next)
1799 if (!mmatch(agline->name, user) &&
1800 (ip_mask ? GlineIsIpMask(agline) : !GlineIsIpMask(agline)) &&
1801 !mmatch(agline->host, host))
1809 if (priv && active && expire > now)
1811 /* Add local G-line */
1812 if (parc < 4 || !strchr(parv[3], ' '))
1814 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
1815 me.name, parv[0], "GLINE");
1818 add_gline(sptr, ip_mask, host, parv[3], user, expire, 1);
1822 sendto_one(cptr, err_str(ERR_NOSUCHGLINE), me.name, parv[0], user,
1828 if (expire <= agline->expire)
1831 if ((active == -1 ||
1832 (active ? GlineIsActive(agline) : !GlineIsActive(agline))) &&
1835 /* oper wants a list of one gline only */
1836 sendto_one(cptr, rpl_str(RPL_GLIST), me.name, parv[0], agline->name,
1837 agline->host, agline->expire, agline->reason,
1838 GlineIsActive(agline) ? "" : " (Inactive)");
1839 sendto_one(cptr, rpl_str(RPL_ENDOFGLIST), me.name, parv[0]);
1844 (active ? !GlineIsActive(agline) : GlineIsActive(agline)))
1846 if (active) /* reset activation on gline */
1849 else if (GlineIsLocal(agline))
1851 /* Remove local G-line */
1852 sendto_op_mask(SNO_GLINE, "%s removed local %s for %s@%s",
1853 parv[0], gtype?"BADCHAN":"GLINE",agline->name, agline->host);
1855 write_log(GPATH, "# " TIME_T_FMT
1856 " %s!%s@%s removed local %s for %s@%s\n",
1857 TStime(), parv[0], cptr->user->username, cptr->user->host,
1858 gtype?"BADCHAN":"GLINE",
1859 agline->name, agline->host);
1861 free_gline(agline, a2gline); /* remove the gline */
1866 ClearActive(agline);
1869 active = -1; /* for later sendto_ops and logging functions */
1872 agline->expire = expire; /* reset expiration time */
1874 /* inform the operators what's up */
1876 { /* changing the activation */
1877 sendto_op_mask(SNO_GLINE, !expire ? "%s %sactivating %s for %s@%s" :
1878 "%s %sactivating %s for %s@%s and "
1879 "resetting expiration time to " TIME_T_FMT,
1880 parv[0], active ? "re" : "de", gtype?"BADCHAN":"GLINE",agline->name,
1881 agline->host, agline->expire);
1883 write_log(GPATH, !expire ? "# " TIME_T_FMT " %s!%s@%s %sactivating "
1884 "%s for %s@%s\n" : "# " TIME_T_FMT " %s!%s@%s %sactivating %s "
1885 "for %s@%s and resetting expiration time to " TIME_T_FMT "\n",
1886 TStime(), parv[0], cptr->user->username, cptr->user->host,
1887 active ? "re" : "de", gtype?"BADCHAN":"GLINE",agline->name,
1888 agline->host, agline->expire);
1893 { /* changing only the expiration */
1894 sendto_op_mask(SNO_GLINE,
1895 "%s resetting expiration time on %s for %s@%s to " TIME_T_FMT,
1896 parv[0], gtype?"BADCHAN":"GLINE",agline->name, agline->host,
1899 write_log(GPATH, "# " TIME_T_FMT " %s!%s@%s resetting expiration "
1900 "time on %s for %s@%s to " TIME_T_FMT "\n", TStime(), parv[0],
1901 cptr->user->username, cptr->user->host,gtype?"BADCHAN":"GLINE",
1902 agline->name, agline->host, agline->expire);