From: Bleep Date: Tue, 21 Mar 2000 01:08:51 +0000 (+0000) Subject: Author: Kev X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=aaa7ba6e9b842215aff8289b03629a3e9c608f4b;p=ircu2.10.12-pk.git Author: Kev Log message: Add missing jupe files doh!! git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@42 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/doc/readme.jupe b/doc/readme.jupe new file mode 100644 index 0000000..da36f9a --- /dev/null +++ b/doc/readme.jupe @@ -0,0 +1,55 @@ +JUPE documentation, last updated on 18 Mar 2000 + +For an ordinary user, the syntax is: + + JUPE [] + +If is given, and if a jupe for that server exists, all the +information about that jupe is displayed. If is not given, +all un-expired jupes are displayed. + +For an operator, the syntax is: + + JUPE [[+|-] [ :]] + +If is not given, or if it is not prefixed by "+" or "-", the +operation is exactly the same as if it were issued by an ordinary +user. If the "+" or "-" prefixes are used, the arguments , +, and must be given, even if the jupe already +exists. If is "*" and the currently existing jupe is a local +jupe, the local jupe will be erased and recreated with the parameters +given, as described below. Otherwise, if the jupe currently exists, a +prefix of "+" will cause an inactive jupe to be activated, whereas a +prefix of "-" will cause an active jupe to be deactivated. + +If the jupe does not already exist, it is created; is used to +select whether the jupe is only to apply to a single server (which +need not be the local server) or to the whole network. This could be +useful if a single particular link is having problems, for instance. +The parameter is a number of seconds, not to exceed 7 +days, for the jupe to exist. The argument is mandatory and +should describe why this particular jupe was placed. + +For a server, the syntax is: + + JU (+|-) : + +The may be a server numeric or the character "*", for a +globally scoped jupe. The argument is a server name, and +must be prefixed by one of "+" (to indicate an active jupe) or "-" (to +indicate an inactive jupe). The parameter is a total +number of seconds the jupe is to live for, and is used for +versioning. Since JUPEs are propagated during netbursts, there must +be some way of resolving conflicting states, which is the reason for +this argument, and is also the reason jupes cannot be deleted, only +deactivated. The parameter indicates the reason the jupe was +placed. + +If a JUPE is received with a of "*", any jupes with local +scope are deleted, in preference for the globally scoped version. If +the jupe already exists, the values of are compared; if the +received is less than the stored , the existing +jupe is resent to the server from which the JUPE message was received; +otherwise, the jupe is activated or deactivated, depending on the + prefix. If the jupe does not currently exist, it is created +with the parameters given. diff --git a/include/jupe.h b/include/jupe.h new file mode 100644 index 0000000..5c0cf7a --- /dev/null +++ b/include/jupe.h @@ -0,0 +1,71 @@ +#ifndef INCLUDED_jupe_h +#define INCLUDED_jupe_h +/* + * IRC - Internet Relay Chat, include/jupe.h + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * Copyright (C) 2000 Kevin L. Mitchell + * + * 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. + * + * $Id$ + */ +#ifndef INCLUDED_config_h +#include "config.h" +#endif +#ifndef INCLUDED_sys_types_h +#include +#define INCLUDED_sys_types_h +#endif + + +struct Client; + +#define JUPE_MAX_EXPIRE 604800 /* max expire: 7 days */ + +struct Jupe { + struct Jupe* ju_next; + struct Jupe** ju_prev_p; + char* ju_server; + char* ju_reason; + time_t ju_expire; + time_t ju_lastmod; + unsigned int ju_flags; +}; + +#define JUPE_ACTIVE 1 +#define JUPE_LOCAL 2 + +#define JupeIsActive(j) ((j)->ju_flags & JUPE_ACTIVE) +#define JupeIsLocal(j) ((j)->ju_flags & JUPE_LOCAL) + +#define JupeServer(j) ((j)->ju_server) +#define JupeReason(j) ((j)->ju_reason) +#define JupeLastMod(j) ((j)->ju_lastmod) + +extern int jupe_add(struct Client *cptr, struct Client *sptr, char *server, + char *reason, time_t expire, time_t lastmod, int local, + int active); +extern int jupe_activate(struct Client *cptr, struct Client *sptr, + struct Jupe *jupe, time_t lastmod); +extern int jupe_deactivate(struct Client *cptr, struct Client *sptr, + struct Jupe *jupe, time_t lastmod); +extern struct Jupe* jupe_find(char *server); +extern void jupe_free(struct Jupe *jupe); +extern void jupe_burst(struct Client *cptr); +extern int jupe_resend(struct Client *cptr, struct Jupe *jupe); +extern int jupe_list(struct Client *sptr, char *server); + +#endif /* INCLUDED_jupe_h */ diff --git a/ircd/jupe.c b/ircd/jupe.c new file mode 100644 index 0000000..bde16cb --- /dev/null +++ b/ircd/jupe.c @@ -0,0 +1,339 @@ +/* + * IRC - Internet Relay Chat, ircd/jupe.c + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Finland + * Copyright (C) 2000 Kevin L. Mitchell + * + * 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 1, 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. + * + * $Id$ + */ +#include "jupe.h" +#include "client.h" +#include "hash.h" +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_string.h" +#include "match.h" +#include "msg.h" +#include "numeric.h" +#include "numnicks.h" +#include "s_bsd.h" +#include "s_misc.h" +#include "send.h" +#include "struct.h" +#include "support.h" +#include "sys.h" /* FALSE bleah */ + +#include + +static struct Jupe* GlobalJupeList = 0; + +static struct Jupe * +make_jupe(char *server, char *reason, time_t expire, time_t lastmod, + unsigned int flags) +{ + struct Jupe *ajupe; + + ajupe = (struct Jupe*) MyMalloc(sizeof(struct Jupe)); /* alloc memory */ + assert(0 != ajupe); + + DupString(ajupe->ju_server, server); /* copy vital information */ + DupString(ajupe->ju_reason, reason); + ajupe->ju_expire = expire; + ajupe->ju_lastmod = lastmod; + ajupe->ju_flags = flags; /* set jupe flags */ + + ajupe->ju_next = GlobalJupeList; /* link it into the list */ + ajupe->ju_prev_p = &GlobalJupeList; + if (GlobalJupeList) + GlobalJupeList->ju_prev_p = &ajupe->ju_next; + GlobalJupeList = ajupe; + + return ajupe; +} + +static int +do_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe) +{ + struct Client *acptr; + + if (!JupeIsActive(jupe)) /* no action to be taken on inactive jupes */ + return 0; + + acptr = FindServer(jupe->ju_server); + + /* server isn't online or isn't local or is me */ + if (!acptr || !MyConnect(acptr) || IsMe(acptr)) + return 0; + + return exit_client_msg(cptr, acptr, &me, "Juped: %s", jupe->ju_reason); +} + +static void +propagate_jupe(struct Client *cptr, struct Client *sptr, struct Jupe *jupe) +{ + if (JupeIsLocal(jupe)) /* don't propagate local jupes */ + return; + + if (IsUser(sptr)) /* select correct prefix */ + sendto_serv_butone(cptr, "%s%s " TOK_JUPE " * %c%s " TIME_T_FMT " " + TIME_T_FMT " :%s", NumNick(sptr), + JupeIsActive(jupe) ? '+' : '-', jupe->ju_server, + jupe->ju_expire - TStime(), jupe->ju_lastmod, + jupe->ju_reason); + else + sendto_serv_butone(cptr, "%s " TOK_JUPE " * %c%s " TIME_T_FMT " " + TIME_T_FMT " :%s", NumServ(sptr), + JupeIsActive(jupe) ? '+' : '-', jupe->ju_server, + jupe->ju_expire - TStime(), jupe->ju_lastmod, + jupe->ju_reason); +} + +int +jupe_add(struct Client *cptr, struct Client *sptr, char *server, char *reason, + time_t expire, time_t lastmod, int local, int active) +{ + struct Jupe *ajupe; + unsigned int flags = 0; + + assert(0 != server); + assert(0 != reason); + + /* + * You cannot set a negative (or zero) expire time, nor can you set an + * expiration time for greater than JUPE_MAX_EXPIRE. + */ + if (expire <= 0 || expire > JUPE_MAX_EXPIRE) { + if (!IsServer(cptr) && MyConnect(cptr)) + sendto_one(cptr, err_str(ERR_BADEXPIRE), me.name, cptr->name, expire); + return 0; + } + + expire += TStime(); /* convert from lifetime to timestamp */ + + /* Inform ops and log it */ + if (IsServer(sptr)) { + sendto_op_mask(SNO_NETWORK, "%s adding %sJUPE for %s, expiring at " + TIME_T_FMT ": %s", sptr->name, local ? "local " : "", + server, expire, reason); +#ifdef JPATH + write_log(JPATH, TIME_T_FMT " %s adding %sJUPE for %s, expiring at " + TIME_T_FMT ": %s\n", TStime(), sptr->name, + local ? "local " : "", server, expire, reason); +#endif /* JPATH */ + } else { + sendto_op_mask(SNO_NETWORK, "%s adding %sJUPE for %s, expiring at " + TIME_T_FMT ": %s", sptr->user->server->name, + local ? "local " : "", server, expire, + reason); +#ifdef JPATH + write_log(JPATH, TIME_T_FMT, " %s!%s@%s adding %sJUPE for %s, expiring at " + TIME_T_FMT ": %s\n", TStime(), sptr->name, sptr->user->username, + sptr->user->host, local ? "local " : "", server, expire, reason); +#endif /* JPATH */ + } + + if (active) /* compute initial flags */ + flags |= JUPE_ACTIVE; + if (local) + flags |= JUPE_LOCAL; + + /* make the jupe */ + ajupe = make_jupe(server, reason, expire, lastmod, flags); + + propagate_jupe(cptr, sptr, ajupe); + + return do_jupe(cptr, sptr, ajupe); /* remove server if necessary */ +} + +int +jupe_activate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe, + time_t lastmod) +{ + assert(0 != jupe); + + jupe->ju_flags |= JUPE_ACTIVE; + jupe->ju_lastmod = lastmod; + + /* Inform ops and log it */ + if (IsServer(sptr)) { + sendto_op_mask(SNO_NETWORK, "%s activating %sJUPE for %s, expiring at " + TIME_T_FMT ": %s", sptr->name, JupeIsLocal(jupe) ? + "local " : "", jupe->ju_server, jupe->ju_expire, + jupe->ju_reason); +#ifdef JPATH + write_log(JPATH, TIME_T_FMT " %s activating %sJUPE for %s, expiring at " + TIME_T_FMT ": %s\n", TStime(), sptr->name, JupeIsLocal(jupe) ? + "local " : "", jupe->ju_server, jupe->ju_expire, + jupe->ju_reason); +#endif /* JPATH */ + } else { + sendto_op_mask(SNO_NETWORK, "%s activating %sJUPE for %s, expiring at " + TIME_T_FMT ": %s", sptr->user->server->name, + JupeIsLocal(jupe) ? "local " : "", jupe->ju_server, + jupe->ju_expire, jupe->ju_reason); +#ifdef JPATH + write_log(JPATH, TIME_T_FMT, " %s!%s@%s activating %sJUPE for %s, " + "expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name, + sptr->user->username, sptr->user->host, JupeIsLocal(jupe) ? + "local " : "", jupe->ju_server, jupe->ju_expire, + jupe->ju_reason); +#endif /* JPATH */ + } + + propagate_jupe(cptr, sptr, jupe); + + return do_jupe(cptr, sptr, jupe); +} + +int +jupe_deactivate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe, + time_t lastmod) +{ + assert(0 != jupe); + + jupe->ju_flags &= ~JUPE_ACTIVE; + jupe->ju_lastmod = lastmod; + + /* Inform ops and log it */ + if (IsServer(sptr)) { + sendto_op_mask(SNO_NETWORK, "%s deactivating %sJUPE for %s, expiring at " + TIME_T_FMT ": %s", sptr->name, JupeIsLocal(jupe) ? + "local " : "", jupe->ju_server, jupe->ju_expire, + jupe->ju_reason); +#ifdef JPATH + write_log(JPATH, TIME_T_FMT " %s deactivating %sJUPE for %s, expiring at " + TIME_T_FMT ": %s\n", TStime(), sptr->name, JupeIsLocal(jupe) ? + "local " : "", jupe->ju_server, jupe->ju_expire, + jupe->ju_reason); +#endif /* JPATH */ + } else { + sendto_op_mask(SNO_NETWORK, "%s deactivating %sJUPE for %s, expiring at " + TIME_T_FMT ": %s", sptr->user->server->name, + JupeIsLocal(jupe) ? "local " : "", jupe->ju_server, + jupe->ju_expire, jupe->ju_reason); +#ifdef JPATH + write_log(JPATH, TIME_T_FMT, " %s!%s@%s deactivating %sJUPE for %s, " + "expiring at " TIME_T_FMT ": %s\n", TStime(), sptr->name, + sptr->user->username, sptr->user->host, JupeIsLocal(jupe) ? + "local " : "", jupe->ju_server, jupe->ju_expire, + jupe->ju_reason); +#endif /* JPATH */ + } + + propagate_jupe(cptr, sptr, jupe); + + return 0; +} + +struct Jupe * +jupe_find(char *server) +{ + struct Jupe* jupe; + struct Jupe* sjupe; + + for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */ + sjupe = jupe->ju_next; + + if (jupe->ju_expire <= TStime()) /* expire any that need expiring */ + jupe_free(jupe); + else if (0 == ircd_strcmp(server, jupe->ju_server)) /* found it yet? */ + return jupe; + } + + return 0; +} + +void +jupe_free(struct Jupe* jupe) +{ + assert(0 != jupe); + + *jupe->ju_prev_p = jupe->ju_next; /* squeeze this jupe out */ + if (jupe->ju_next) + jupe->ju_next->ju_prev_p = jupe->ju_prev_p; + + MyFree(jupe->ju_server); /* and free up the memory */ + MyFree(jupe->ju_reason); + MyFree(jupe); +} + +void +jupe_burst(struct Client *cptr) +{ + struct Jupe *jupe; + struct Jupe *sjupe; + + for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */ + sjupe = jupe->ju_next; + + if (jupe->ju_expire <= TStime()) /* expire any that need expiring */ + jupe_free(jupe); + else if (!JupeIsLocal(jupe)) /* forward global jupes */ + sendto_one(cptr, "%s " TOK_JUPE " * %c%s "TIME_T_FMT" "TIME_T_FMT" :%s", + NumServ(&me), JupeIsActive(jupe) ? '+' : '-', + jupe->ju_server, jupe->ju_expire - TStime(), + jupe->ju_lastmod, jupe->ju_reason); + } +} + +int +jupe_resend(struct Client *cptr, struct Jupe *jupe) +{ + if (JupeIsLocal(jupe)) /* don't propagate local jupes */ + return 0; + + sendto_one(cptr, "%s " TOK_JUPE " * %c%s " TIME_T_FMT " " TIME_T_FMT " :%s", + NumServ(&me), JupeIsActive(jupe) ? '+' : '-', jupe->ju_server, + jupe->ju_expire - TStime(), jupe->ju_lastmod, jupe->ju_reason); + + return 0; +} + +int +jupe_list(struct Client *sptr, char *server) +{ + struct Jupe *jupe; + struct Jupe *sjupe; + + if (server) { + if (!(jupe = jupe_find(server))) { /* no such jupe */ + sendto_one(sptr, err_str(ERR_NOSUCHJUPE), me.name, sptr->name, server); + return 0; + } + + /* send jupe information along */ + sendto_one(sptr, rpl_str(RPL_JUPELIST), me.name, sptr->name, + jupe->ju_server, jupe->ju_expire, JupeIsLocal(jupe) ? + me.name : "*", JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason); + } else { + for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */ + sjupe = jupe->ju_next; + + if (jupe->ju_expire <= TStime()) /* expire any that need expiring */ + jupe_free(jupe); + else /* send jupe information along */ + sendto_one(sptr, rpl_str(RPL_JUPELIST), me.name, sptr->name, + jupe->ju_server, jupe->ju_expire, JupeIsLocal(jupe) ? + me.name : "*", JupeIsActive(jupe) ? '+' : '-', + jupe->ju_reason); + } + } + + /* end of jupe information */ + sendto_one(sptr, rpl_str(RPL_ENDOFJUPELIST), me.name, sptr->name); + return 0; +} diff --git a/ircd/m_jupe.c b/ircd/m_jupe.c new file mode 100644 index 0000000..ccb7737 --- /dev/null +++ b/ircd/m_jupe.c @@ -0,0 +1,272 @@ +/* + * IRC - Internet Relay Chat, ircd/m_jupe.c + * Copyright (C) 1990 Jarkko Oikarinen and + * University of Oulu, Computing Center + * Copyright (C) 2000 Kevin L. Mitchell + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * 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 1, 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. + * + * $Id$ + */ + +/* + * m_functions execute protocol messages on this server: + * + * cptr is always NON-NULL, pointing to a *LOCAL* client + * structure (with an open socket connected!). This + * identifies the physical socket where the message + * originated (or which caused the m_function to be + * executed--some m_functions may call others...). + * + * sptr is the source of the message, defined by the + * prefix part of the message if present. If not + * or prefix not found, then sptr==cptr. + * + * (!IsServer(cptr)) => (cptr == sptr), because + * prefixes are taken *only* from servers... + * + * (IsServer(cptr)) + * (sptr == cptr) => the message didn't + * have the prefix. + * + * (sptr != cptr && IsServer(sptr) means + * the prefix specified servername. (?) + * + * (sptr != cptr && !IsServer(sptr) means + * that message originated from a remote + * user (not local). + * + * combining + * + * (!IsServer(sptr)) means that, sptr can safely + * taken as defining the target structure of the + * message in this server. + * + * *Always* true (if 'parse' and others are working correct): + * + * 1) sptr->from == cptr (note: cptr->from == cptr) + * + * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr + * *cannot* be a local connection, unless it's + * actually cptr!). [MyConnect(x) should probably + * be defined as (x == x->from) --msa ] + * + * parc number of variable parameter strings (if zero, + * parv is allowed to be NULL) + * + * parv a NULL terminated list of parameter pointers, + * + * parv[0], sender (prefix string), if not present + * this points to an empty string. + * parv[1]...parv[parc-1] + * pointers to additional parameters + * parv[parc] == NULL, *always* + * + * note: it is guaranteed that parv[0]..parv[parc-1] are all + * non-NULL pointers. + */ +#if 0 +/* + * No need to include handlers.h here the signatures must match + * and we don't need to force a rebuild of all the handlers everytime + * we add a new one to the list. --Bleep + */ +#include "handlers.h" +#endif /* 0 */ +#include "client.h" +#include "jupe.h" +#include "hash.h" +#include "ircd.h" +#include "ircd_reply.h" +#include "ircd_string.h" +#include "match.h" +#include "msg.h" +#include "numeric.h" +#include "numnicks.h" +#include "s_conf.h" +#include "s_misc.h" +#include "send.h" +#include "support.h" + +#include +#include +#include + +/* + * ms_jupe - server message handler + * + * parv[0] = Send prefix + * + * From server: + * + * parv[1] = Target: server numeric or * + * parv[2] = (+|-) + * parv[3] = Expiration offset + * parv[4] = Last modification time + * parv[5] = Comment + * + */ +int ms_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + struct Client *acptr = 0; + struct Jupe *ajupe; + int local = 0, active = 1; + time_t expire_off, lastmod; + char *server = parv[2], *target = parv[1], *reason = parv[5]; + + if (parc < 6) + return need_more_params(sptr, "JUPE"); + + if (!(target[0] == '*' && target[1] == '\0')) { + if (!(acptr = FindNServer(target))) + return 0; /* no such server */ + + if (!IsMe(acptr)) { /* manually propagate, since we don't set it */ + sendto_one(acptr, "%s " TOK_JUPE " %s %s %s %s :%s", NumServ(sptr), + target, server, parv[3], parv[4], reason); + + return 0; + } + + local = 1; + } + + if (*server == '-') { + active = 0; + server++; + } else if (*server == '+') { + active = 1; + server++; + } + + expire_off = atoi(parv[3]); + lastmod = atoi(parv[4]); + + ajupe = jupe_find(server); + + if (ajupe) { + if (JupeIsLocal(ajupe) && !local) /* global jupes override local ones */ + jupe_free(ajupe); + else if (JupeLastMod(ajupe) < lastmod) { /* new modification */ + if (active) + return jupe_activate(cptr, sptr, ajupe, lastmod); + else + return jupe_deactivate(cptr, sptr, ajupe, lastmod); + } else if (JupeLastMod(ajupe) == lastmod) /* no changes */ + return 0; + else + return jupe_resend(cptr, ajupe); /* other server desynched WRT jupes */ + } + + return jupe_add(cptr, sptr, server, reason, expire_off, lastmod, local, + active); +} + +/* + * mo_jupe - oper message handler + * + * parv[0] = Send prefix + * + * From oper: + * + * parv[1] = [[+|-]] + * parv[2] = [target] + * parv[3] = [Expiration offset] + * parv[4] = [Comment] + * + */ +int mo_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + struct Client *acptr = 0; + struct Jupe *ajupe; + int local = 0, active = 1; + time_t expire_off; + char *server = parv[1], *target = parv[2], *reason = parv[4]; + + if (parc < 2) + return jupe_list(sptr, 0); + + if (*server == '+') { + active = 1; + server++; + } else if (*server == '-') { + active = 0; + server++; + } else + return jupe_list(sptr, server); + + if (parc < 5) + return need_more_params(sptr, "JUPE"); + + if (!(target[0] == '*' && target[1] == '\0')) { + if (!(acptr = find_match_server(target))) { + sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], target); + return 0; + } + + if (!IsMe(acptr)) { /* manually propagate, since we don't set it */ + if (!IsOper(sptr)) { + sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); + return 0; + } + + sendto_one(acptr, "%s%s " TOK_JUPE " %s %c%s %s " TIME_T_FMT " :%s", + NumNick(sptr), NumServ(acptr), server, active ? '+' : '-', + parv[3], TStime(), reason); + return 0; + } + + local = 1; + } + + expire_off = atoi(parv[3]); + + ajupe = jupe_find(server); + + if (ajupe) { + if (JupeIsLocal(ajupe) && !local) /* global jupes override local ones */ + jupe_free(ajupe); + else { + if (active) + return jupe_activate(cptr, sptr, ajupe, TStime()); + else + return jupe_deactivate(cptr, sptr, ajupe, TStime()); + } + } + + return jupe_add(cptr, sptr, server, reason, expire_off, TStime(), local, + active); +} + +/* + * m_jupe - user message handler + * + * parv[0] = Send prefix + * + * From user: + * + * parv[1] = [] + * + */ +int m_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + if (parc < 2) + return jupe_list(sptr, 0); + + return jupe_list(sptr, parv[1]); +}