Author: Ghostwolf <foxxe@wtfs.net>
[ircu2.10.12-pk.git] / ircd / map.c
1 /*
2  * IRC - Internet Relay Chat, ircd/map.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  * Copyright (C) 2002 Joseph Bongaarts <foxxe@wtfs.net>
6  *
7  * See file AUTHORS in IRC package for additional names of
8  * the programmers.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 1, or (at your option)
13  * any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  * $Id$
25  */
26
27 #include "config.h"
28
29 #include "client.h"
30 #include "ircd.h"
31 #include "ircd_defs.h"
32 #include "ircd_policy.h"
33 #include "ircd_reply.h"
34 #include "ircd_snprintf.h"
35 #include "ircd_string.h"
36 #include "list.h"
37 #include "match.h"
38 #include "msg.h"
39 #include "numeric.h"
40 #include "s_user.h"
41 #include "s_serv.h"
42 #include "send.h"
43 #include "querycmds.h"
44 #include "map.h"
45
46 #include <assert.h>
47 #include <stdio.h>
48 #include <string.h>
49
50 #ifdef HEAD_IN_SAND_MAP
51
52 static struct Map *MapList = 0;
53
54 /* Add a server to the map list. */
55 static void map_add(struct Client *server)
56 {
57   assert(server != 0);
58   assert(!IsHub(server));
59   assert(!IsService(server));
60
61   struct Map *new = (struct Map *)MyAlloc(sizeof(struct Map));
62
63   new->lasttime = TStime();
64   ircd_strcpy(new->name, cli_name(server));
65   new->maxclients = cli_serv(server)->clients;
66
67   new->prev = 0;
68   new->next = MapList;
69
70   if(MapList)
71     MapList->prev = new;
72   
73   MapList = new;
74 }
75
76 /* Remove a server from the map list */
77 static void map_remove(struct Map *cptr)
78 {
79   assert(cptr != 0);
80   
81   if(cptr->next)
82     cptr->next->prev = cptr->prev;
83   
84   if(cptr->prev)
85     cptr->prev->next = cptr->next;
86   
87   if(MapList == cptr)
88     MapList = cptr->next;
89
90   MyFree(cptr);
91
92 }
93
94 /* Update a server in the list. Called when a server connects
95  * splits, or we haven't checked in more than a week. */
96 void map_update(struct Client *cptr)
97 {
98   assert(IsServer(cptr));
99
100   struct Map *map = 0;
101   
102   /* Find the server in the list and update it */ 
103   for(map = MapList.list; map; map = map->next)
104   {
105     /* Show max clients not current, otherwise a split can be detected. */
106     if(!ircd_strcmp(cli_name(cptr), map->name)) 
107     { 
108       map->lasttime = TStime();
109       if(map->maxclients < cli_serv(cptr)->clients) 
110         map->maxclients = cli_serv(cptr)->clients;  
111       break;
112     }
113   }
114
115   /* We do this check after finding a matching map because
116    * a client server can become a hub or service (such as 
117    * santaclara)
118    */
119   if(IsHub(cptr) || IsService(cptr))
120   {
121     if(map)
122       map_remove(map);
123     return;
124   }
125
126   /* If we haven't seen it before, add it to the list. */
127   if(!map)
128     map_add(cli_name(cptr));
129 }
130
131 void dump_map_head_in_sand(struct Client *cptr)
132 {
133   struct Map *map = 0;
134   struct Map *smap = 0;
135   struct Client *acptr = 0;
136
137   /* Send me first */
138   send_reply(cptr, RPL_MAP, "", "", cli_name(&me), "", UserStats.local_clients);
139
140   for(map = MapList; map; map = smap)
141   {
142     smap = map->next;
143
144     /* Don't show servers we haven't seen in more than a week */
145     if(map->lasttime < TStime() - 604800)
146     {
147       acptr = find_match_server(map->name);
148       if(!acptr)
149       {
150         map_remove(map);
151         continue;
152       }
153       else
154         map_update(acptr);
155     }
156     send_reply(cptr, RPL_MAP, "", "|-", map->name, "", map->maxclients);
157   }
158 }
159
160 #endif /* HEAD_IN_SAND_MAP */ 
161   
162 (void map_dump(struct Client *cptr, struct Client *server, char *mask, int prompt_length)
163 {
164   static char prompt[64];
165   struct DLink *lp;
166   char *p = &prompt[prompt_length];
167   int cnt = 0;
168
169   *p = '\0';
170   if (prompt_length > 60)
171     send_reply(cptr, RPL_MAPMORE, prompt, cli_name(server));
172   else {
173     char lag[512];
174     if (cli_serv(server)->lag>10000)
175         lag[0]=0;
176     else if (cli_serv(server)->lag<0)
177         strcpy(lag,"(0s)");
178     else
179         sprintf(lag,"(%is)",cli_serv(server)->lag);
180     send_reply(cptr, RPL_MAP, prompt, (
181                 (IsBurst(server)) ? "*" : (IsBurstAck(server) ? "!" : "")),
182                cli_name(server), lag, (server == &me) ? UserStats.local_clients :
183                cli_serv(server)->clients);
184   }
185   if (prompt_length > 0)
186   {
187     p[-1] = ' ';
188     if (p[-2] == '`')
189       p[-2] = ' ';
190   }
191   if (prompt_length > 60)
192     return;
193   strcpy(p, "|-");
194   for (lp = cli_serv(server)->down; lp; lp = lp->next)
195     if (match(mask, cli_name(lp->value.cptr)))
196       cli_flags(lp->value.cptr) &= ~FLAGS_MAP;
197     else
198     {
199       cli_flags(lp->value.cptr) |= FLAGS_MAP;
200       cnt++;
201     }
202   for (lp = cli_serv(server)->down; lp; lp = lp->next)
203   {
204     if ((cli_flags(lp->value.cptr) & FLAGS_MAP) == 0)
205       continue;
206     if (--cnt == 0)
207       *p = '`';
208     map_dump(cptr, lp->value.cptr, mask, prompt_length + 2);
209   }
210   if (prompt_length > 0)
211     p[-1] = '-';
212 }
213
214