unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

monitor.c (6351B)

      1 /*
      2  *   IRC - Internet Relay Chat, src/modules/monitor.c
      3  *   (C) 2021 The UnrealIRCd Team
      4  *
      5  *   See file AUTHORS in IRC package for additional names of
      6  *   the programmers.
      7  *
      8  *   This program is free software; you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 1, or (at your option)
     11  *   any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *   GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program; if not, write to the Free Software
     20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     21  */
     22 
     23 #include "unrealircd.h"
     24 
     25 #define MSG_MONITOR 	"MONITOR"
     26 
     27 #define STR_HELPER(x) #x
     28 #define STR(x) STR_HELPER(x)
     29 
     30 CMD_FUNC(cmd_monitor);
     31 char *monitor_isupport_param(void);
     32 int monitor_nickchange(Client *client, MessageTag *mtags, const char *newnick);
     33 int monitor_post_nickchange(Client *client, MessageTag *mtags, const char *oldnick);
     34 int monitor_quit(Client *client, MessageTag *mtags, const char *comment);
     35 int monitor_connect(Client *client);
     36 int monitor_notification(Client *client, Watch *watch, Link *lp, int event);
     37 
     38 ModuleHeader MOD_HEADER
     39   = {
     40 	"monitor",
     41 	"5.0",
     42 	"command /monitor", 
     43 	"UnrealIRCd Team",
     44 	"unrealircd-6",
     45     };
     46 
     47 MOD_INIT()
     48 {	
     49 	MARK_AS_OFFICIAL_MODULE(modinfo);
     50 	
     51 	CommandAdd(modinfo->handle, MSG_MONITOR, cmd_monitor, 2, CMD_USER);
     52 	HookAdd(modinfo->handle, HOOKTYPE_LOCAL_NICKCHANGE, 0, monitor_nickchange);
     53 	HookAdd(modinfo->handle, HOOKTYPE_REMOTE_NICKCHANGE, 0, monitor_nickchange);
     54 	HookAdd(modinfo->handle, HOOKTYPE_POST_LOCAL_NICKCHANGE, 0, monitor_post_nickchange);
     55 	HookAdd(modinfo->handle, HOOKTYPE_POST_REMOTE_NICKCHANGE, 0, monitor_post_nickchange);
     56 	HookAdd(modinfo->handle, HOOKTYPE_REMOTE_QUIT, 0, monitor_quit);
     57 	HookAdd(modinfo->handle, HOOKTYPE_LOCAL_QUIT, 0, monitor_quit);
     58 	HookAdd(modinfo->handle, HOOKTYPE_LOCAL_CONNECT, 0, monitor_connect);
     59 	HookAdd(modinfo->handle, HOOKTYPE_REMOTE_CONNECT, 0, monitor_connect);
     60 
     61 	return MOD_SUCCESS;
     62 }
     63 
     64 MOD_LOAD()
     65 {
     66 	ISupportAdd(modinfo->handle, "MONITOR", monitor_isupport_param());
     67 	return MOD_SUCCESS;
     68 }
     69 
     70 MOD_UNLOAD()
     71 {
     72 	return MOD_SUCCESS;
     73 }
     74 
     75 char *monitor_isupport_param(void)
     76 {
     77 	/* i find it unlikely for a client to use WATCH and MONITOR at the same time, so keep a single limit for both */
     78 	return STR(MAXWATCH);
     79 }
     80 
     81 int monitor_nickchange(Client *client, MessageTag *mtags, const char *newnick)
     82 {
     83 	if (!smycmp(client->name, newnick)) // new nick is same as old one, maybe the case changed
     84 		return 0;
     85 
     86 	watch_check(client, WATCH_EVENT_OFFLINE, monitor_notification);
     87 	return 0;
     88 }
     89 
     90 int monitor_post_nickchange(Client *client, MessageTag *mtags, const char *oldnick)
     91 {
     92 	if (!smycmp(client->name, oldnick)) // new nick is same as old one, maybe the case changed
     93 		return 0;
     94 
     95 	watch_check(client, WATCH_EVENT_ONLINE, monitor_notification);
     96 	return 0;
     97 }
     98 
     99 int monitor_quit(Client *client, MessageTag *mtags, const char *comment)
    100 {
    101 	watch_check(client, WATCH_EVENT_OFFLINE, monitor_notification);
    102 	return 0;
    103 }
    104 
    105 int monitor_connect(Client *client)
    106 {
    107 	watch_check(client, WATCH_EVENT_ONLINE, monitor_notification);
    108 	return 0;
    109 }
    110 
    111 int monitor_notification(Client *client, Watch *watch, Link *lp, int event)
    112 {
    113 	if (!(lp->flags & WATCH_FLAG_TYPE_MONITOR))
    114 		return 0;
    115 
    116 	switch (event)
    117 	{
    118 		case WATCH_EVENT_ONLINE:
    119 			sendnumeric(lp->value.client, RPL_MONONLINE, client->name, client->user->username, GetHost(client));
    120 			break;
    121 		case WATCH_EVENT_OFFLINE:
    122 			sendnumeric(lp->value.client, RPL_MONOFFLINE, client->name);
    123 			break;
    124 		default:
    125 			break; /* may be handled by other modules */
    126 	}
    127 	
    128 	return 0;
    129 }
    130 
    131 void send_status(Client *client, MessageTag *recv_mtags, const char *nick)
    132 {
    133 	MessageTag *mtags = NULL;
    134 	Client *user;
    135 	user = find_user(nick, NULL);
    136 	new_message(client, recv_mtags, &mtags);
    137 	if (!user){
    138 		sendnumeric(client, RPL_MONOFFLINE, nick);
    139 	} else {
    140 		sendnumeric(client, RPL_MONONLINE, user->name, user->user->username, GetHost(user));
    141 	}
    142 	free_message_tags(mtags);
    143 }
    144 
    145 #define WATCHES(client) (moddata_local_client(client, watchCounterMD).i)
    146 #define WATCH(client) (moddata_local_client(client, watchListMD).ptr)
    147 
    148 CMD_FUNC(cmd_monitor)
    149 {
    150 	char request[BUFSIZE];
    151 	char cmd;
    152 	char *s, *p = NULL;
    153 	int i;
    154 	int toomany = 0;
    155 	Link *lp;
    156 
    157 	if (!MyUser(client))
    158 		return;
    159 
    160 	if (parc < 2 || BadPtr(parv[1]))
    161 		cmd = 'l';
    162 	else
    163 		cmd = tolower(*parv[1]);
    164 
    165 	ModDataInfo *watchCounterMD = findmoddata_byname("watchCount", MODDATATYPE_LOCAL_CLIENT);
    166 	ModDataInfo *watchListMD = findmoddata_byname("watchList", MODDATATYPE_LOCAL_CLIENT);
    167 	
    168 	if (!watchCounterMD || !watchListMD)
    169 	{
    170 		unreal_log(ULOG_ERROR, "monitor", "WATCH_BACKEND_MISSING", NULL,
    171 		           "[monitor] moddata unavailable. Is the 'watch-backend' module loaded?");
    172 		sendnotice(client, "MONITOR command is not available at this moment. Please try again later.");
    173 		return;
    174 	}
    175 	
    176 	switch(cmd)
    177 	{
    178 		case 'c':
    179 			watch_del_list(client, WATCH_FLAG_TYPE_MONITOR);
    180 			break;
    181 		case 'l':
    182 			lp = WATCH(client);
    183 			while (lp)
    184 			{
    185 				if (!(lp->flags & WATCH_FLAG_TYPE_MONITOR))
    186 				{
    187 					lp = lp->next;
    188 					continue; /* this one is not ours */
    189 				}
    190 				sendnumeric(client, RPL_MONLIST, lp->value.wptr->nick);
    191 				lp = lp->next;
    192 			}
    193 
    194 			sendnumeric(client, RPL_ENDOFMONLIST);
    195 			break;
    196 		case 's':
    197 			lp = WATCH(client);
    198 			while (lp)
    199 			{
    200 				if (!(lp->flags & WATCH_FLAG_TYPE_MONITOR))
    201 				{
    202 					lp = lp->next;
    203 					continue; /* this one is not ours */
    204 				}
    205 				send_status(client, recv_mtags, lp->value.wptr->nick);
    206 				lp = lp->next;
    207 			}
    208 			break;
    209 		case '-':
    210 		case '+':
    211 			if (parc < 3 || BadPtr(parv[2]))
    212 				return;
    213 			strlcpy(request, parv[2], sizeof(request));
    214 			for (s = strtoken(&p, request, ","); s; s = strtoken(&p, NULL, ","))
    215 			{
    216 				if (cmd == '-') {
    217 					watch_del(s, client, WATCH_FLAG_TYPE_MONITOR);
    218 				} else {
    219 					if (WATCHES(client) >= MAXWATCH)
    220 					{
    221 						sendnumeric(client, ERR_MONLISTFULL, MAXWATCH, s);
    222 						continue;
    223 					}
    224 					if (do_nick_name(s))
    225 						watch_add(s, client, WATCH_FLAG_TYPE_MONITOR);
    226 					send_status(client, recv_mtags, s);
    227 				}
    228 			}
    229 			break;
    230 	}
    231 }
    232