358 lines
7.7 KiB
C
358 lines
7.7 KiB
C
/*
|
|
* IRC - Internet Relay Chat, ircd/watch.c
|
|
* Copyright (C) 1990 Jarkko Oikarinen and
|
|
* University of Oulu, Computing Center
|
|
* Copyright (C) 2002-2007 IRC-Dev Development Team <devel@irc-dev.net>
|
|
* Copyright (C) 2002 Toni Garcia (zoltan) <zoltan@irc-dev.net>
|
|
*
|
|
* 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 3, 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.
|
|
*/
|
|
/** @file
|
|
* @brief Implementation of watches.
|
|
* @version $Id$
|
|
*/
|
|
#include "config.h"
|
|
|
|
#include "watch.h"
|
|
#include "client.h"
|
|
#include "hash.h"
|
|
#include "ircd.h"
|
|
#include "ircd_alloc.h"
|
|
#include "ircd_log.h"
|
|
#include "ircd_reply.h"
|
|
#include "ircd_string.h"
|
|
#include "list.h"
|
|
#include "numeric.h"
|
|
#include "s_user.h"
|
|
#include "send.h"
|
|
#include "struct.h"
|
|
|
|
/* #include <assert.h> -- Now using assert in ircd_log.h */
|
|
#include <string.h>
|
|
|
|
/** @page watch watches.
|
|
*
|
|
* WATCH FUNCTIONS
|
|
*
|
|
* WATCH_LIST
|
|
* |
|
|
* |-wptr1-|- cptr1
|
|
* | |- cptr2
|
|
* | |- cptr3
|
|
* |
|
|
* |-wptr2-|- cptr2
|
|
* |- cptr1
|
|
*
|
|
* LINKS in the Client lists.
|
|
*
|
|
* cptr1 cptr2 cptr3
|
|
* |- wptr1(nickA) |-wptr1(nickA) |-wptr1(nickA)
|
|
* |- wptr2(nickB) |-wptr2(nickB)
|
|
*
|
|
* The operation is based on the WATCH of Bahamut and UnrealIRCD.
|
|
*
|
|
* 2002/05/20 zoltan <zoltan@irc-dev.net>
|
|
*/
|
|
|
|
/** Count of allocated Watch structures. */
|
|
static int watchCount = 0;
|
|
|
|
/** Reserve an entrance in the Watch list.
|
|
* @param[in] nick Nickname that needs to be reserved.
|
|
* @return wptr clean watch pointer.
|
|
*/
|
|
struct Watch *make_watch(const char *nick)
|
|
{
|
|
struct Watch *wptr;
|
|
|
|
wptr = (struct Watch *)MyMalloc(sizeof(struct Watch));
|
|
assert(0 != wptr);
|
|
|
|
/*
|
|
* NOTE: Do not remove this, a lot of code depends on the entire
|
|
* structure being zeroed out
|
|
*/
|
|
memset(wptr, 0, sizeof(struct Watch)); /* All variables are 0 by default */
|
|
|
|
DupString(wt_nick(wptr), nick);
|
|
|
|
hAddWatch(wptr);
|
|
watchCount++;
|
|
|
|
return (wptr);
|
|
|
|
}
|
|
|
|
/** Release an entrace of the Watch list.
|
|
* @param[in] wptr Valid watch pointer.
|
|
*/
|
|
void free_watch(struct Watch *wptr)
|
|
{
|
|
|
|
hRemWatch(wptr);
|
|
MyFree(wt_nick(wptr));
|
|
MyFree(wptr);
|
|
|
|
watchCount--;
|
|
}
|
|
|
|
/** Find number of Watch structs allocated and memory used by them.
|
|
* @param[in,out] count_out Receives number of Watch structs allocated.
|
|
* @param[in,out] bytes_out Receives number of bytes used by Watch structs.
|
|
*/
|
|
void watch_count_memory(size_t* count_out, size_t* bytes_out)
|
|
{
|
|
assert(0 != count_out);
|
|
assert(0 != bytes_out);
|
|
*count_out = watchCount;
|
|
*bytes_out = watchCount * sizeof(struct Watch);
|
|
}
|
|
|
|
/** Notify the users the input/output of nick.
|
|
* @param[in] cptr Client pointer.
|
|
* @param[in] raw Raw reply code.
|
|
*/
|
|
void check_status_watch(struct Client *cptr, int raw)
|
|
{
|
|
struct Watch *wptr;
|
|
struct SLink *lp;
|
|
|
|
wptr = FindWatch(cli_name(cptr));
|
|
|
|
if (!wptr)
|
|
return; /* Not this in some notify */
|
|
|
|
wt_lasttime(wptr) = TStime();
|
|
|
|
/*
|
|
* Sent the warning to all the users who
|
|
* have it in notify.
|
|
*/
|
|
for (lp = wt_watch(wptr); lp; lp = lp->next)
|
|
{
|
|
send_reply(lp->value.cptr, raw, cli_name(cptr),
|
|
IsUser(cptr) ? cli_user(cptr)->username : "<N/A>",
|
|
IsUser(cptr) ?
|
|
(!IsAnOper(lp->value.cptr) ?
|
|
cli_user(cptr)->host : cli_user(cptr)->realhost)
|
|
: "<N/A>",
|
|
wt_lasttime(wptr));
|
|
}
|
|
|
|
}
|
|
|
|
/** Show the state of an user.
|
|
* @param[in] cptr Client pointer of who is doing the watch.
|
|
* @param[in] nick The nickname that the watch is being done on.
|
|
* @param[in] raw1 Raw code for the reply.
|
|
* @param[in] raw2 Raw code for the reply.
|
|
*/
|
|
void show_status_watch(struct Client *cptr, char *nick, int raw1, int raw2)
|
|
{
|
|
struct Client *acptr;
|
|
|
|
if ((acptr = FindUser(nick)))
|
|
{
|
|
send_reply(cptr, raw1, cli_name(acptr), cli_user(acptr)->username,
|
|
!IsAnOper(cptr) ?
|
|
cli_user(acptr)->host : cli_user(acptr)->realhost,
|
|
cli_lastnick(acptr));
|
|
}
|
|
else
|
|
send_reply(cptr, raw2, nick, "*", "*", 0);
|
|
}
|
|
|
|
|
|
/** Add nick to the user watch list.
|
|
* @param[in] cptr Client pointer of who is doing the watch.
|
|
* @param[in] nick The nickname that the watch is being done on.
|
|
* @return 0
|
|
*/
|
|
int add_nick_watch(struct Client *cptr, char *nick)
|
|
{
|
|
struct Watch *wptr;
|
|
struct SLink *lp;
|
|
|
|
/*
|
|
* If not exist, create the registry.
|
|
*/
|
|
if (!(wptr = FindWatch(nick)))
|
|
{
|
|
wptr = make_watch(nick);
|
|
if (!wptr)
|
|
return 0;
|
|
wt_lasttime(wptr) = TStime();
|
|
}
|
|
|
|
/*
|
|
* Find if it already has it in watch.
|
|
*/
|
|
if ((lp = wt_watch(wptr)))
|
|
{
|
|
while (lp && (lp->value.cptr != cptr))
|
|
lp = lp->next;
|
|
}
|
|
|
|
/*
|
|
* Not this, then add it.
|
|
*/
|
|
if (!lp)
|
|
{
|
|
/*
|
|
* Link watch to cptr
|
|
*/
|
|
lp = wt_watch(wptr);
|
|
wt_watch(wptr) = make_link();
|
|
memset(wt_watch(wptr), 0, sizeof(struct SLink));
|
|
wt_watch(wptr)->value.cptr = cptr;
|
|
wt_watch(wptr)->next = lp;
|
|
|
|
/*
|
|
* Link client->user to watch
|
|
*/
|
|
lp = make_link();
|
|
memset(lp, 0, sizeof(struct SLink));
|
|
lp->next = cli_user(cptr)->watch;
|
|
lp->value.wptr = wptr;
|
|
cli_user(cptr)->watch = lp;
|
|
cli_user(cptr)->watches++;
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/** Delete a nick of the user watch list.
|
|
* @param[in] cptr Client pointer of who is doing the watch removal.
|
|
* @param[in] nick The nickname that the watch that needs to be removed.
|
|
* @return 0
|
|
*/
|
|
int del_nick_watch(struct Client *cptr, char *nick)
|
|
{
|
|
struct Watch *wptr;
|
|
struct SLink *lp, *lptmp = 0;
|
|
|
|
wptr = FindWatch(nick);
|
|
if (!wptr)
|
|
return 0; /* Not this in any list */
|
|
|
|
/*
|
|
* Find for in the link cptr->user to watch
|
|
*/
|
|
if ((lp = wt_watch(wptr)))
|
|
{
|
|
while (lp && (lp->value.cptr != cptr))
|
|
{
|
|
lptmp = lp;
|
|
lp = lp->next;
|
|
}
|
|
}
|
|
|
|
if (!lp)
|
|
return 0;
|
|
|
|
if (!lptmp)
|
|
wt_watch(wptr) = lp->next;
|
|
else
|
|
lptmp->next = lp->next;
|
|
|
|
free_link(lp);
|
|
|
|
/*
|
|
* For in the link watch to cptr->user
|
|
*/
|
|
lptmp = lp = 0;
|
|
if ((lp = cli_user(cptr)->watch))
|
|
{
|
|
while (lp && (lp->value.wptr != wptr))
|
|
{
|
|
lptmp = lp;
|
|
lp = lp->next;
|
|
}
|
|
}
|
|
|
|
assert(0 != lp);
|
|
|
|
if (!lptmp)
|
|
cli_user(cptr)->watch = lp->next;
|
|
else
|
|
lptmp->next = lp->next;
|
|
|
|
free_link(lp);
|
|
|
|
/*
|
|
* If it were the onlu associate to nick
|
|
* delete registry in the watch table.
|
|
*/
|
|
if (!wt_watch(wptr))
|
|
free_watch(wptr);
|
|
|
|
/* Update count */
|
|
cli_user(cptr)->watches--;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/** Delete all the watch list when the client execute's /WATCH C or they leave IRC.
|
|
* @param[in] cptr Client that needs to have their watch list cleared.
|
|
* @return 0
|
|
*/
|
|
int del_list_watch(struct Client *cptr)
|
|
{
|
|
struct SLink *lp, *lp2, *lptmp;
|
|
struct Watch *wptr;
|
|
|
|
if (!(lp = cli_user(cptr)->watch))
|
|
return 0; /* Id had the empty list */
|
|
|
|
/*
|
|
* Loop of links cptr->user to watch.
|
|
*/
|
|
while (lp)
|
|
{
|
|
wptr = lp->value.wptr;
|
|
lptmp = 0;
|
|
for (lp2 = wt_watch(wptr); lp2 && (lp2->value.cptr != cptr); lp2 = lp2->next)
|
|
lptmp = lp2;
|
|
|
|
|
|
assert(0 != lp2);
|
|
|
|
if (!lptmp)
|
|
wt_watch(wptr) = lp2->next;
|
|
else
|
|
lptmp->next = lp2->next;
|
|
free_link(lp2);
|
|
|
|
/*
|
|
* If it were the onlu associate to nick
|
|
* delete registry in the watch table.
|
|
*/
|
|
if (!wt_watch(wptr))
|
|
free_watch(wptr);
|
|
|
|
lp2 = lp;
|
|
lp = lp->next;
|
|
free_link(lp2);
|
|
}
|
|
|
|
/* Update count */
|
|
cli_user(cptr)->watch = 0;
|
|
cli_user(cptr)->watches = 0;
|
|
|
|
return 0;
|
|
}
|
|
|