/* * IRC - Internet Relay Chat, modules/m_kill.c * * Copyright (C) 2000-2003 TR-IRCD Development * * Copyright (C) 1990 Jarkko Oikarinen and * University of Oulu, Co Center * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "struct.h" #include "common.h" #include "sys.h" #include "numeric.h" #include "msg.h" #include "channel.h" #include "s_conf.h" #include "h.h" static char buf2[BUFSIZE]; static char *token = TOK1_KILL; static struct Message _msgtab[] = { {MSG_KILL, 0, MAXPARA, M_SLOW, 0L, m_unregistered, m_permission, m_kill, s_kill, m_ignore} }; #ifndef STATIC_MODULES char *_version = "$Revision: 1.6 $"; void _modinit(void) { mod_add_cmd(_msgtab); tok1_msgtab[(u_char) *token].msg = _msgtab; } void _moddeinit(void) { mod_del_cmd(_msgtab); tok1_msgtab[(u_char) *token].msg = NULL; } #else void m_kill_init(void) { mod_add_cmd(_msgtab); tok1_msgtab[(u_char) *token].msg = _msgtab; } #endif /* * * m_kill * parv[0] = sender prefix * parv[1] = kill victim * * parv[2] = kill path */ int m_kill(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; char *user, *path, *killer, *p, *nick; char mypath[KILLLEN + 1]; int chasing = 0, kcount = 0; if (!OPIsOpKill(sptr) && MyConnect(sptr)) { return m_permission(cptr, sptr, parc, parv); } if (parc < 2 || *parv[1] == '\0') { send_me_numeric(sptr, ERR_NEEDMOREPARAMS, MSG_KILL); return 0; } user = parv[1]; path = parv[2]; /* * Either defined or NULL (parc >= 2!!) */ if (path == NULL) path = ")"; if (IsAnOper(cptr)) { if (!BadPtr(path)) if (strlen(path) > (size_t) KILLLEN) path[KILLLEN] = '\0'; } if (MyClient(sptr)) user = canonize(user); for (p = NULL, nick = strtoken(&p, user, ","); nick; nick = strtoken(&p, NULL, ",")) { chasing = 0; if (!(acptr = find_client(nick))) { /* * * If the user has recently changed nick, we automaticly * * rewrite the KILL for this new nickname--this keeps * * servers in synch when nick change and kill collide */ if (!(acptr = get_history(nick, (long) KILLCHASETIMELIMIT))) { send_me_numeric(sptr, ERR_NOSUCHNICK, nick); return 0; } send_me_notice(sptr, ":KILL changed from %s to %s", nick, acptr->name); chasing = 1; } if (IsServer(acptr) || IsMe(acptr)) { send_me_numeric(sptr, ERR_CANTKILLSERVER); continue; } kcount++; if (!IsServer(sptr) && (kcount > MAXKILLS)) { send_me_notice(sptr, ":Too many targets, kill list was truncated. Maximum is %d.", MAXKILLS); break; } if (MyClient(sptr)) { char myname[HOSTLEN + 1], *s; int slen; strlcpy_irc(myname, me.name, 80); if ((s = index(myname, '.'))) *s = 0; /* * "!user->host>!name> (path)" */ slen = KILLLEN - (strlen(sptr->name) + 6 + strlen(myname) + 8); if (slen < 0) slen = 0; if (strlen(path) > slen) path[slen] = '\0'; ircsprintf(mypath, "%s!ircops!%s (%s)", myname, sptr->name, path); mypath[KILLLEN] = '\0'; } else strlcpy_irc(mypath, path, KILLLEN); /* * * Notify all *local* opers about the KILL, this includes the * one * originating the kill, if from this server--the special * numeric * reply message is not generated anymore. * * * Note: "acptr->name" is used instead of "user" because we may * have changed the target because of the nickname change. */ if (IsAnOper(sptr)) sendto_lev(0, "Received KILL message for %C. From %C Path: %s", acptr, sptr, mypath); else sendto_lev(SKILL_LEV, "Received KILL message for %^C. From %C Path: %s", acptr, sptr, mypath); /* * * And pass on the message to other servers. Note, that if KILL * * was changed, the message has to be sent to all links, also * * back. * Suicide kills are NOT passed on --SRB */ if (!MyConnect(acptr) || !MyConnect(sptr) || !IsAnOper(sptr)) { sendto_serv_butone(cptr, sptr, TOK1_KILL, "%~C :%s", acptr, mypath); if (chasing && IsServer(cptr)) sendto_one_server(cptr, &me, TOK1_KILL, "%~C :%s", acptr, mypath); acptr->flags |= FLAGS_KILLED; sendto_service(SERVICE_SEE_KILLS, 0, sptr, NULL, TOK1_KILL, "%s :%s", acptr->name, mypath); } /* * * Tell the victim she/he has been zapped, but *only* if * the * victim is on current server--no sense in sending the * * notification chasing the above kill, it won't get far * anyway * (as this user don't exist there any more either) */ if (MyConnect(acptr)) { sendto_one(acptr, ":%C %s %s :%s", sptr, MSG_KILL, acptr->name, mypath); sendto_service(SERVICE_SEE_KILLS, 0, sptr, NULL, TOK1_KILL, "%s :%s", acptr->name, mypath); } /* * * Set FLAGS_KILLED. This prevents exit_one_client from sending * * the unnecessary QUIT for this. ,This flag should never be * * set in any other place... */ logevent_call(LogSys.operevent, MSG_KILL, sptr, &parv, parc); if (MyConnect(acptr) && MyConnect(sptr) && IsAnOper(sptr)) ircsprintf(buf2, "Local kill by %s (%s)", sptr->name, BadPtr(parv[2]) ? sptr->name : parv[2]); else { killer = strchr(mypath, '('); if (killer == NULL) killer = "()"; ircsprintf(buf2, "Killed (%s %s)", sptr->name, killer); } exit_client(acptr, sptr, buf2); } return 0; } /* * * m_kill * parv[0] = sender prefix * parv[1] = kill victim * * parv[2] = kill path */ int s_kill(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; char *user, *path, *killer, *p, *nick; char mypath[KILLLEN + 1]; int chasing = 0, kcount = 0; if (parc < 2 || *parv[1] == '\0') return 0; user = parv[1]; path = parv[2]; /* * Either defined or NULL (parc >= 2!!) */ if (path == NULL) path = ")"; if (MyClient(sptr)) user = canonize(user); for (p = NULL, nick = strtoken(&p, user, ","); nick; nick = strtoken(&p, NULL, ",")) { chasing = 0; if (!(acptr = find_client(nick))) { /* * * If the user has recently changed nick, we automaticly * * rewrite the KILL for this new nickname--this keeps * * servers in synch when nick change and kill collide */ if (!(acptr = get_history(nick, (long) KILLCHASETIMELIMIT))) { return 0; } chasing = 1; } if (IsServer(acptr) || IsMe(acptr)) continue; kcount++; if (!IsServer(sptr) && (kcount > MAXKILLS)) break; if (MyClient(sptr)) { char myname[HOSTLEN + 1], *s; int slen; strlcpy_irc(myname, me.name, 80); if ((s = index(myname, '.'))) *s = 0; slen = KILLLEN - (strlen(sptr->name) + 6 + strlen(myname) + 8); if (slen < 0) slen = 0; if (strlen(path) > slen) path[slen] = '\0'; ircsprintf(mypath, "%s!ircops!%s (%s)", myname, sptr->name, path); mypath[KILLLEN] = '\0'; } else strlcpy_irc(mypath, path, KILLLEN); /* * * Notify all *local* opers about the KILL, this includes the * one * originating the kill, if from this server--the special * numeric * reply message is not generated anymore. * * * Note: "acptr->name" is used instead of "user" because we may * have changed the target because of the nickname change. */ sendto_lev(SKILL_LEV, "Received KILL message for %^C. From %C Path: %s", acptr, sptr, mypath); /* * * And pass on the message to other servers. Note, that if KILL * * was changed, the message has to be sent to all links, also * * back. * Suicide kills are NOT passed on --SRB */ if (!MyConnect(acptr) || !MyConnect(sptr) || !IsAnOper(sptr)) { sendto_serv_butone(cptr, sptr, TOK1_KILL, "%~C :%s", acptr, mypath); if (chasing && IsServer(cptr)) sendto_one_server(cptr, &me, TOK1_KILL, "%~C :%s", acptr, mypath); acptr->flags |= FLAGS_KILLED; sendto_service(SERVICE_SEE_KILLS, 0, sptr, NULL, TOK1_KILL, "%s :%s", acptr->name, mypath); } /* * * Tell the victim she/he has been zapped, but *only* if * the * victim is on current server--no sense in sending the * * notification chasing the above kill, it won't get far * anyway * (as this user don't exist there any more either) */ if (MyConnect(acptr)) { sendto_one(acptr, ":%C %s %s :%s", sptr, MSG_KILL, acptr->name, mypath); sendto_service(SERVICE_SEE_KILLS, 0, sptr, NULL, TOK1_KILL, "%s :%s", acptr->name, mypath); } /* * * Set FLAGS_KILLED. This prevents exit_one_client from sending * * the unnecessary QUIT for this. ,This flag should never be * * set in any other place... */ killer = strchr(mypath, '('); if (killer == NULL) killer = "()"; ircsprintf(buf2, "Killed (%s %s)", sptr->name, killer); exit_client(acptr, sptr, buf2); } return 0; }