Author: Isomer <perry@coders.net>
[ircu2.10.12-pk.git] / ircd / m_motd.c
1 /*
2  * IRC - Internet Relay Chat, ircd/m_motd.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  *
6  * See file AUTHORS in IRC package for additional names of
7  * the programmers.
8  *
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)
12  * any later version.
13  *
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.
18  *
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.
22  *
23  * $Id$
24  */
25
26 /*
27  * m_functions execute protocol messages on this server:
28  *
29  *    cptr    is always NON-NULL, pointing to a *LOCAL* client
30  *            structure (with an open socket connected!). This
31  *            identifies the physical socket where the message
32  *            originated (or which caused the m_function to be
33  *            executed--some m_functions may call others...).
34  *
35  *    sptr    is the source of the message, defined by the
36  *            prefix part of the message if present. If not
37  *            or prefix not found, then sptr==cptr.
38  *
39  *            (!IsServer(cptr)) => (cptr == sptr), because
40  *            prefixes are taken *only* from servers...
41  *
42  *            (IsServer(cptr))
43  *                    (sptr == cptr) => the message didn't
44  *                    have the prefix.
45  *
46  *                    (sptr != cptr && IsServer(sptr) means
47  *                    the prefix specified servername. (?)
48  *
49  *                    (sptr != cptr && !IsServer(sptr) means
50  *                    that message originated from a remote
51  *                    user (not local).
52  *
53  *            combining
54  *
55  *            (!IsServer(sptr)) means that, sptr can safely
56  *            taken as defining the target structure of the
57  *            message in this server.
58  *
59  *    *Always* true (if 'parse' and others are working correct):
60  *
61  *    1)      sptr->from == cptr  (note: cptr->from == cptr)
62  *
63  *    2)      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64  *            *cannot* be a local connection, unless it's
65  *            actually cptr!). [MyConnect(x) should probably
66  *            be defined as (x == x->from) --msa ]
67  *
68  *    parc    number of variable parameter strings (if zero,
69  *            parv is allowed to be NULL)
70  *
71  *    parv    a NULL terminated list of parameter pointers,
72  *
73  *                    parv[0], sender (prefix string), if not present
74  *                            this points to an empty string.
75  *                    parv[1]...parv[parc-1]
76  *                            pointers to additional parameters
77  *                    parv[parc] == NULL, *always*
78  *
79  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
80  *                    non-NULL pointers.
81  */
82 #if 0
83 /*
84  * No need to include handlers.h here the signatures must match
85  * and we don't need to force a rebuild of all the handlers everytime
86  * we add a new one to the list. --Bleep
87  */
88 #include "handlers.h"
89 #endif /* 0 */
90 #include "client.h"
91 #include "ircd.h"
92 #include "ircd_reply.h"
93 #include "ircd_string.h"
94 #include "match.h"
95 #include "msg.h"
96 #include "numeric.h"
97 #include "numnicks.h"
98 #include "s_conf.h"
99 #include "class.h"
100 #include "s_user.h"
101 #include "send.h"
102
103 #include <stdlib.h>
104 #include <assert.h>
105
106 /*
107  * m_motd - generic message handler
108  *
109  * parv[0] - sender prefix
110  * parv[1] - servername
111  *
112  * modified 30 mar 1995 by flux (cmlambertus@ucdavis.edu)
113  * T line patch - display motd based on hostmask
114  * modified again 7 sep 97 by Ghostwolf with code and ideas 
115  * stolen from comstud & Xorath.  All motd files are read into
116  * memory in read_motd() in s_conf.c
117  *
118  * When NODEFAULTMOTD is defined, then it is possible that
119  * sptr == NULL, which means that this function is called from
120  * register_user.
121  */
122 int m_motd(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
123 {
124   struct tm *tm = &motd_tm;     /* Default: Most general case */
125   struct TRecord *ptr;
126   int count;
127   struct MotdItem *temp;
128   int class = get_client_class(sptr);
129
130 #ifdef NODEFAULTMOTD
131   int no_motd;
132
133   if (sptr)
134   {
135     no_motd = 0;
136 #endif
137     if (hunt_server_cmd(sptr, CMD_MOTD, cptr, 0, "%C", 1, parc, parv) !=
138         HUNTED_ISME)
139       return 0;
140 #ifdef NODEFAULTMOTD
141   }
142   else
143   {
144     sptr = cptr;
145     no_motd = 1;
146   }
147 #endif
148   /* 2.10.11: Allow per Class T:'s
149    *    -- Isomer 2000-11-19
150    */
151   for (ptr = tdata; ptr; ptr = ptr->next)
152   {
153     if (IsDigit(*ptr->hostmask)) {
154       if (atoi(ptr->hostmask)==class)
155         break;
156     }
157     else if (!match(ptr->hostmask, cptr->sockhost))
158       break;
159   }
160   if (ptr)
161   {
162     temp = ptr->tmotd;
163     tm = &ptr->tmotd_tm;
164   }
165   else
166     temp = motd;
167   if (temp == 0)
168   {
169     send_reply(sptr, ERR_NOMOTD);
170     return 0;
171   }
172 #ifdef NODEFAULTMOTD
173   if (!no_motd)
174   {
175 #endif
176     if (tm)                     /* Not remote? */
177     {
178       send_reply(sptr, RPL_MOTDSTART, me.name);
179       send_reply(sptr, SND_EXPLICIT | RPL_MOTD, ":- %d/%d/%d %d:%02d",
180                  tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year, tm->tm_hour,
181                  tm->tm_min);
182       count = 100;
183     }
184     else
185       count = 3;
186     for (; temp; temp = temp->next)
187     {
188       send_reply(sptr, RPL_MOTD, temp->line);
189       if (--count == 0)
190         break;
191     }
192 #ifdef NODEFAULTMOTD
193   }
194   else
195   {
196     send_reply(sptr, RPL_MOTDSTART, me.name);
197     send_reply(sptr, SND_EXPLICIT | RPL_MOTD, ":\ 2Type /MOTD to read the "
198                "AUP before continuing using this service.\ 2");
199     send_reply(sptr, SND_EXPLICIT | RPL_MOTD, ":The message of the day was "
200                "last changed: %d/%d/%d", tm->tm_mday, tm->tm_mon + 1,
201                1900 + tm->tm_year);
202   }
203 #endif
204   send_reply(sptr, RPL_ENDOFMOTD);
205   return 0;
206 }
207
208 /*
209  * ms_motd - server message handler
210  *
211  * parv[0] - sender prefix
212  * parv[1] - servername
213  *
214  * modified 30 mar 1995 by flux (cmlambertus@ucdavis.edu)
215  * T line patch - display motd based on hostmask
216  * modified again 7 sep 97 by Ghostwolf with code and ideas 
217  * stolen from comstud & Xorath.  All motd files are read into
218  * memory in read_motd() in s_conf.c
219  *
220  * When NODEFAULTMOTD is defined, then it is possible that
221  * sptr == NULL, which means that this function is called from
222  * register_user.
223  */
224 int ms_motd(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
225 {
226   struct tm *tm = &motd_tm;     /* Default: Most general case */
227   struct TRecord *ptr;
228   int count;
229   struct MotdItem *temp;
230
231 #ifdef NODEFAULTMOTD
232   int no_motd;
233
234   if (sptr)
235   {
236     no_motd = 0;
237 #endif
238     if (hunt_server_cmd(sptr, CMD_MOTD, cptr, 0, "%C", 1, parc, parv) !=
239         HUNTED_ISME)
240       return 0;
241 #ifdef NODEFAULTMOTD
242   }
243   else
244   {
245     sptr = cptr;
246     no_motd = 1;
247   }
248 #endif
249
250   /*
251    * Find out if this is a remote query or if we have a T line for our hostname
252    */
253   if (IsServer(cptr))
254   {
255     tm = 0;                  /* Remote MOTD */
256     temp = rmotd;
257   }
258   else
259   {
260     for (ptr = tdata; ptr; ptr = ptr->next)
261     {
262       if (!match(ptr->hostmask, cptr->sockhost))
263         break;
264     }
265     if (ptr)
266     {
267       temp = ptr->tmotd;
268       tm = &ptr->tmotd_tm;
269     }
270     else
271       temp = motd;
272   }
273   if (temp == 0)
274   {
275     send_reply(sptr, ERR_NOMOTD);
276     return 0;
277   }
278 #ifdef NODEFAULTMOTD
279   if (!no_motd)
280   {
281 #endif
282     if (tm)                     /* Not remote? */
283     {
284       send_reply(sptr, RPL_MOTDSTART, me.name);
285       send_reply(sptr, SND_EXPLICIT | RPL_MOTD, ":- %d/%d/%d %d:%02d",
286                  tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year, tm->tm_hour,
287                  tm->tm_min);
288       count = 100;
289     }
290     else
291       count = 3;
292     for (; temp; temp = temp->next)
293     {
294       send_reply(sptr, RPL_MOTD, temp->line);
295       if (--count == 0)
296         break;
297     }
298 #ifdef NODEFAULTMOTD
299   }
300   else
301   {
302     send_reply(sptr, RPL_MOTDSTART, me.name);
303     send_reply(sptr, SND_EXPLICIT | RPL_MOTD, ":\ 2Type /MOTD to read the "
304                "AUP before continuing using this service.\ 2");
305     send_reply(sptr, SND_EXPLICIT | RPL_MOTD, ":The message of the day was "
306                "last changed: %d/%d/%d", tm->tm_mday, tm->tm_mon + 1,
307                1900 + tm->tm_year);
308   }
309 #endif
310   send_reply(sptr, RPL_ENDOFMOTD);
311   return 0;
312 }
313
314 #if 0
315 /*
316  * m_motd
317  *
318  * parv[0] - sender prefix
319  * parv[1] - servername
320  *
321  * modified 30 mar 1995 by flux (cmlambertus@ucdavis.edu)
322  * T line patch - display motd based on hostmask
323  * modified again 7 sep 97 by Ghostwolf with code and ideas 
324  * stolen from comstud & Xorath.  All motd files are read into
325  * memory in read_motd() in s_conf.c
326  *
327  * When NODEFAULTMOTD is defined, then it is possible that
328  * sptr == NULL, which means that this function is called from
329  * register_user.
330  */
331 int m_motd(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
332 {
333   struct tm *tm = &motd_tm;     /* Default: Most general case */
334   struct TRecord *ptr;
335   int count;
336   struct MotdItem *temp;
337
338 #ifdef NODEFAULTMOTD
339   int no_motd;
340
341   if (sptr)
342   {
343     no_motd = 0;
344 #endif
345     if (hunt_server(0, cptr, sptr, "%s%s " TOK_MOTD " %s", 1, parc, /* XXX DEAD */
346         parv) != HUNTED_ISME)
347       return 0;
348 #ifdef NODEFAULTMOTD
349   }
350   else
351   {
352     sptr = cptr;
353     no_motd = 1;
354   }
355 #endif
356
357   /*
358    * Find out if this is a remote query or if we have a T line for our hostname
359    */
360   if (IsServer(cptr))
361   {
362     tm = 0;                  /* Remote MOTD */
363     temp = rmotd;
364   }
365   else
366   {
367     for (ptr = tdata; ptr; ptr = ptr->next)
368     {
369       if (!match(ptr->hostmask, cptr->sockhost))
370         break;
371     }
372     if (ptr)
373     {
374       temp = ptr->tmotd;
375       tm = &ptr->tmotd_tm;
376     }
377     else
378       temp = motd;
379   }
380   if (temp == 0)
381   {
382     sendto_one(sptr, err_str(ERR_NOMOTD), me.name, parv[0]); /* XXX DEAD */
383     return 0;
384   }
385 #ifdef NODEFAULTMOTD
386   if (!no_motd)
387   {
388 #endif
389     if (tm)                     /* Not remote? */
390     {
391       sendto_one(sptr, rpl_str(RPL_MOTDSTART), me.name, parv[0], me.name); /* XXX DEAD */
392       sendto_one(sptr, ":%s %d %s :- %d/%d/%d %d:%02d", me.name, RPL_MOTD, /* XXX DEAD */
393           parv[0], tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year,
394           tm->tm_hour, tm->tm_min);
395       count = 100;
396     }
397     else
398       count = 3;
399     for (; temp; temp = temp->next)
400     {
401       sendto_one(sptr, rpl_str(RPL_MOTD), me.name, parv[0], temp->line); /* XXX DEAD */
402       if (--count == 0)
403         break;
404     }
405 #ifdef NODEFAULTMOTD
406   }
407   else
408   {
409     sendto_one(sptr, rpl_str(RPL_MOTDSTART), me.name, parv[0], me.name); /* XXX DEAD */
410     sendto_one(sptr, ":%s %d %s :%s", me.name, RPL_MOTD, parv[0], /* XXX DEAD */
411         "\ 2Type /MOTD to read the AUP before continuing using this service.\ 2");
412     sendto_one(sptr, /* XXX DEAD */
413         ":%s %d %s :The message of the day was last changed: %d/%d/%d", me.name,
414         RPL_MOTD, parv[0], tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year);
415   }
416 #endif
417   sendto_one(sptr, rpl_str(RPL_ENDOFMOTD), me.name, parv[0]); /* XXX DEAD */
418   return 0;
419 }
420 #endif /* 0 */
421