2 * IRC - Internet Relay Chat, ircd/querycmds.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.
52 #include "querycmds.h"
57 * m_functions execute protocol messages on this server:
59 * cptr is always NON-NULL, pointing to a *LOCAL* client
60 * structure (with an open socket connected!). This
61 * identifies the physical socket where the message
62 * originated (or which caused the m_function to be
63 * executed--some m_functions may call others...).
65 * sptr is the source of the message, defined by the
66 * prefix part of the message if present. If not
67 * or prefix not found, then sptr==cptr.
69 * (!IsServer(cptr)) => (cptr == sptr), because
70 * prefixes are taken *only* from servers...
73 * (sptr == cptr) => the message didn't
76 * (sptr != cptr && IsServer(sptr) means
77 * the prefix specified servername. (?)
79 * (sptr != cptr && !IsServer(sptr) means
80 * that message originated from a remote
85 * (!IsServer(sptr)) means that, sptr can safely
86 * taken as defining the target structure of the
87 * message in this server.
89 * *Always* true (if 'parse' and others are working correct):
91 * 1) sptr->from == cptr (note: cptr->from == cptr)
93 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
94 * *cannot* be a local connection, unless it's
95 * actually cptr!). [MyConnect(x) should probably
96 * be defined as (x == x->from) --msa ]
98 * parc number of variable parameter strings (if zero,
99 * parv is allowed to be NULL)
101 * parv a NULL terminated list of parameter pointers,
103 * parv[0], sender (prefix string), if not present
104 * this points to an empty string.
105 * parv[1]...parv[parc-1]
106 * pointers to additional parameters
107 * parv[parc] == NULL, *always*
109 * note: it is guaranteed that parv[0]..parv[parc-1] are all
116 * parv[0] = sender prefix
117 * parv[1] = remote server
119 int m_version(aClient *cptr, aClient *sptr, int parc, char *parv[])
123 if (MyConnect(sptr) && parc > 1)
125 if (!(acptr = find_match_server(parv[1])))
127 sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], parv[1]);
130 parv[1] = acptr->name;
133 if (hunt_server(0, cptr, sptr, ":%s VERSION :%s", 1, parc, parv) ==
135 sendto_one(sptr, rpl_str(RPL_VERSION),
136 me.name, parv[0], version, debugmode, me.name, serveropts);
144 * parv[0] = sender prefix
145 * parv[1] = servername
147 int m_info(aClient *cptr, aClient *sptr, int parc, char *parv[])
149 const char **text = infotext;
151 if (hunt_server(1, cptr, sptr, ":%s INFO :%s", 1, parc, parv) == HUNTED_ISME)
156 sendto_one(sptr, rpl_str(RPL_INFO), me.name, parv[0], *text);
162 sendto_one(sptr, rpl_str(RPL_INFO), me.name, parv[0], *text++);
163 sendto_one(sptr, rpl_str(RPL_INFO), me.name, parv[0], "");
165 sendto_one(sptr, ":%s %d %s :Birth Date: %s, compile # %s",
166 me.name, RPL_INFO, parv[0], creation, generation);
167 sendto_one(sptr, ":%s %d %s :On-line since %s",
168 me.name, RPL_INFO, parv[0], myctime(me.firsttime));
169 sendto_one(sptr, rpl_str(RPL_ENDOFINFO), me.name, parv[0]);
177 * parv[0] = sender prefix
178 * parv[1] = servername mask
182 * parv[0] = sender prefix
183 * parv[1] = server to query
184 * parv[2] = servername mask
186 int m_links(aClient *cptr, aClient *sptr, int parc, char *parv[])
193 if (hunt_server(1, cptr, sptr, ":%s LINKS %s :%s", 1, parc, parv) !=
199 mask = parc < 2 ? NULL : parv[1];
201 for (acptr = client, collapse(mask); acptr; acptr = acptr->next)
203 if (!IsServer(acptr) && !IsMe(acptr))
205 if (!BadPtr(mask) && match(mask, acptr->name))
207 sendto_one(sptr, rpl_str(RPL_LINKS),
208 me.name, parv[0], acptr->name, acptr->serv->up->name,
210 acptr->hopcount, acptr->serv->prot,
212 acptr->hopcount, acptr->serv->prot, acptr->serv->timestamp,
215 (acptr->info[0] ? acptr->info : "(Unknown Location)"));
218 sendto_one(sptr, rpl_str(RPL_ENDOFLINKS), me.name, parv[0],
219 BadPtr(mask) ? "*" : mask);
226 * parv[0] = sender prefix
228 int m_help(aClient *UNUSED(cptr), aClient *sptr, int UNUSED(parc), char *parv[])
232 for (i = 0; msgtab[i].cmd; i++)
233 sendto_one(sptr, ":%s NOTICE %s :%s", me.name, parv[0], msgtab[i].cmd);
237 /* Counters of client/servers etc. */
238 struct lusers_st nrof;
240 void init_counters(void)
242 memset(&nrof, 0, sizeof(nrof));
251 * parv[2] = server to query
253 int m_lusers(aClient *cptr, aClient *sptr, int parc, char *parv[])
256 if (hunt_server(1, cptr, sptr, ":%s LUSERS %s :%s", 2, parc, parv) !=
260 sendto_one(sptr, rpl_str(RPL_LUSERCLIENT), me.name, parv[0],
261 nrof.clients - nrof.inv_clients, nrof.inv_clients, nrof.servers);
263 sendto_one(sptr, rpl_str(RPL_LUSEROP), me.name, parv[0], nrof.opers);
264 if (nrof.unknowns > 0)
265 sendto_one(sptr, rpl_str(RPL_LUSERUNKNOWN), me.name, parv[0],
267 if (nrof.channels > 0)
268 sendto_one(sptr, rpl_str(RPL_LUSERCHANNELS), me.name, parv[0],
270 sendto_one(sptr, rpl_str(RPL_LUSERME), me.name, parv[0], nrof.local_clients,
273 if (MyUser(sptr) || Protocol(cptr) < 10)
275 ":%s NOTICE %s :Highest connection count: %d (%d clients)",
276 me.name, parv[0], max_connection_count, max_client_count);
279 "%s NOTICE %s%s :Highest connection count: %d (%d clients)",
280 NumServ(&me), NumNick(sptr), max_connection_count, max_client_count);
288 * parv[0] = sender prefix
289 * parv[1] = servername
291 int m_admin(aClient *cptr, aClient *sptr, int parc, char *parv[])
295 if (MyConnect(sptr) && parc > 1)
298 if (!(acptr = find_match_server(parv[1])))
300 sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], parv[1]);
303 parv[1] = acptr->name;
305 if (hunt_server(0, cptr, sptr, ":%s ADMIN :%s", 1, parc, parv) != HUNTED_ISME)
307 if ((aconf = find_admin()))
309 sendto_one(sptr, rpl_str(RPL_ADMINME), me.name, parv[0], me.name);
310 sendto_one(sptr, rpl_str(RPL_ADMINLOC1), me.name, parv[0], aconf->host);
311 sendto_one(sptr, rpl_str(RPL_ADMINLOC2), me.name, parv[0], aconf->passwd);
312 sendto_one(sptr, rpl_str(RPL_ADMINEMAIL), me.name, parv[0], aconf->name);
315 sendto_one(sptr, err_str(ERR_NOADMININFO), me.name, parv[0], me.name);
322 * parv[0] - sender prefix
323 * parv[1] - servername
325 * modified 30 mar 1995 by flux (cmlambertus@ucdavis.edu)
326 * T line patch - display motd based on hostmask
327 * modified again 7 sep 97 by Ghostwolf with code and ideas
328 * stolen from comstud & Xorath. All motd files are read into
329 * memory in read_motd() in s_conf.c
331 * When NODEFAULTMOTD is defined, then it is possible that
332 * sptr == NULL, which means that this function is called from
335 int m_motd(aClient *cptr, aClient *sptr, int parc, char *parv[])
337 struct tm *tm = &motd_tm; /* Default: Most general case */
340 register aMotdItem *temp;
349 if (hunt_server(0, cptr, sptr, ":%s MOTD :%s", 1, parc,
350 parv) != HUNTED_ISME)
362 * Find out if this is a remote query or if we have a T line for our hostname
366 tm = NULL; /* Remote MOTD */
371 for (ptr = tdata; ptr; ptr = ptr->next)
373 if (!match(ptr->hostmask, cptr->sockhost))
386 sendto_one(sptr, err_str(ERR_NOMOTD), me.name, parv[0]);
393 if (tm) /* Not remote? */
395 sendto_one(sptr, rpl_str(RPL_MOTDSTART), me.name, parv[0], me.name);
396 sendto_one(sptr, ":%s %d %s :- %d/%d/%d %d:%02d", me.name, RPL_MOTD,
397 parv[0], tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year,
398 tm->tm_hour, tm->tm_min);
403 for (; temp; temp = temp->next)
405 sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv[0], temp->line);
413 sendto_one(sptr, rpl_str(RPL_MOTDSTART), me.name, parv[0], me.name);
414 sendto_one(sptr, ":%s %d %s :%s", me.name, RPL_MOTD, parv[0],
415 "
\ 2Type /MOTD to read the AUP before continuing using this service.
\ 2");
417 ":%s %d %s :The message of the day was last changed: %d/%d/%d", me.name,
418 RPL_MOTD, parv[0], tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year);
421 sendto_one(sptr, rpl_str(RPL_ENDOFMOTD), me.name, parv[0]);