]> jfr.im git - irc/quakenet/newserv.git/blame - serverlist/serverlist.c
serverlist: Make hostname column wider.
[irc/quakenet/newserv.git] / serverlist / serverlist.c
CommitLineData
b7eccf5f
P
1/* Some utterly useless dog */
2
3#include "../core/schedule.h"
475b3d9d 4#include "../irc/irc.h"
b7eccf5f
P
5#include "../lib/irc_string.h"
6#include "../localuser/localuserchannel.h"
7#include "../control/control.h"
074a4529 8#include "../usercount/usercount.h"
240bbd21
CP
9#include "../lib/version.h"
10
11MODULE_VERSION("")
b7eccf5f
P
12
13#include <stdlib.h>
14#include <string.h>
15#include <stdarg.h>
41b5727a 16#include <stdio.h>
475b3d9d 17#include <sys/time.h>
b7eccf5f
P
18
19int cmd_serverlist(void *sender, int cargc, char **cargv);
20void serverlist_hook_newserver(int hook, void *arg);
21void serverlist_hook_lostserver(int hook, void *arg);
22int serverlist_versionreply(void *source, int cargc, char **cargv);
475b3d9d
GB
23void serverlist_pingservers(void *arg);
24int serverlist_rpong(void *source, int cargc, char **cargv);
b7eccf5f
P
25
26struct {
27 int used;
28 time_t ts;
475b3d9d 29 int lag;
b7eccf5f
P
30 sstring *version1;
31 sstring *version2;
32} serverinfo[MAXSERVERS];
33
34void serverlist_doversion(void);
35
36
37void _init(void) {
38 registercontrolhelpcmd("serverlist",NO_OPER,1,&cmd_serverlist,"Usage: serverlist [pattern]\nShows all currently connected servers");
39 /* hooks for serverlist */
40 registerhook(HOOK_SERVER_NEWSERVER, &serverlist_hook_newserver);
41 registerhook(HOOK_SERVER_LOSTSERVER, &serverlist_hook_lostserver);
42 int i;
43
44 for (i = 0; i < MAXSERVERS; i++) {
45 if (serverlist[i].linkstate == LS_LINKED)
46 serverinfo[i].used = 1;
47 else
48 serverinfo[i].used = 0;
49
50 serverinfo[i].ts = getnettime();
475b3d9d 51 serverinfo[i].lag = -1;
b7eccf5f
P
52 serverinfo[i].version1 = NULL;
53 serverinfo[i].version2 = NULL;
54 }
55 registernumerichandler(351, &serverlist_versionreply, 2);
475b3d9d 56 registerserverhandler("RO", &serverlist_rpong, 4);
b7eccf5f 57
b2615f8b 58 schedulerecurring(time(NULL)+1, 0, 60, &serverlist_pingservers, NULL);
b7eccf5f
P
59}
60
61void _fini(void) {
62 int i;
63 for (i = 0; i < MAXSERVERS; i++) {
64 if (serverinfo[i].used) {
65 freesstring(serverinfo[i].version1);
66 freesstring(serverinfo[i].version2);
67 }
68 }
69 deregisternumerichandler(351, &serverlist_versionreply);
475b3d9d 70 deregisterserverhandler("RO", &serverlist_rpong);
b7eccf5f
P
71
72 deregisterhook(HOOK_SERVER_NEWSERVER, &serverlist_hook_newserver);
73 deregisterhook(HOOK_SERVER_LOSTSERVER, &serverlist_hook_lostserver);
74
75 deregistercontrolcmd("serverlist",cmd_serverlist);
475b3d9d
GB
76
77 deleteschedule(NULL, &serverlist_pingservers, NULL);
b7eccf5f
P
78}
79
80int cmd_serverlist(void *sender, int cargc, char **cargv) {
81 nick *np = (nick*)sender;
82 int a, i, ucount, acount, scount;
41b5727a 83 char lagstr[20];
b7eccf5f 84
7cb440fd 85 controlreply(np, "%-7s %-35s %5s/%5s/%-5s %-7s %-20s %-8s %-20s", "Numeric", "Hostname", "ECl", "Cl", "MaxCl", "Flags", "Connected for", "Lag", "Version");
b7eccf5f
P
86
87 scount = acount = 0;
88
89 for (i = 0; i < MAXSERVERS; i++) {
90 if (serverlist[i].linkstate == LS_LINKED && (cargc < 1 || match2strings(cargv[0], serverlist[i].name->content))) {
91 ucount = 0;
92
19f8fda5 93 for (a = 0; a <= serverlist[i].maxusernum; a++)
b7eccf5f
P
94 if (servernicks[i][a] != NULL)
95 ucount++;
96
97 acount += ucount;
98 scount++;
99
41b5727a
GB
100 if (serverinfo[i].lag == -1)
101 strcpy(lagstr, "-");
102 else
103 snprintf(lagstr, sizeof(lagstr), "%d", serverinfo[i].lag);
104
7cb440fd 105 controlreply(np, "%-7d %-35s %5d/%5d/%-5d %-7s %-20s %-8s %-20s - %s", i, serverlist[i].name->content,
4f2ceb49
CP
106 servercount[i], ucount, serverlist[i].maxusernum,
107 printflags(serverlist[i].flags, smodeflags),
108 longtoduration(getnettime() - serverinfo[i].ts, 0),
41b5727a 109 lagstr,
b7eccf5f
P
110 serverinfo[i].version1 ? serverinfo[i].version1->content : "Unknown",
111 serverinfo[i].version2 ? serverinfo[i].version2->content : "Unknown");
112 }
113 }
114
115 controlreply(np, "--- End of list. %d users and %d servers on the net.", acount, scount);
116
117 /* update version info for next time */
118 serverlist_doversion();
119
120 return CMD_OK;
121}
122
123int serverlist_versionreply(void *source, int cargc, char **cargv) {
124 int num;
125
126 if (cargc < 6)
127 return CMD_OK;
128
129 num = numerictolong(cargv[0], 2);
130
131 if (serverinfo[num].used) {
132 freesstring(serverinfo[num].version1);
133 freesstring(serverinfo[num].version2);
134
135 serverinfo[num].version1 = getsstring(cargv[3], strlen(cargv[3]));
136 serverinfo[num].version2 = getsstring(cargv[5], strlen(cargv[5]));
137 }
138 return CMD_OK;
139}
140
141void serverlist_doversion(void) {
142 int i;
143 char *num1, *numeric;
144
145 if (mynick == NULL)
146 return;
147
148 for (i = 0; i < MAXSERVERS; i++) {
149 if (serverlist[i].linkstate == LS_LINKED && serverinfo[i].version1 == NULL) {
150 numeric = longtonumeric(mynick->numeric,5);
151 num1 = (char*)malloc(strlen(numeric) + 1); /* bleh.. longtonumeric() is using static variables */
152 strcpy(num1, numeric);
153
154 irc_send("%s V :%s", num1, longtonumeric(i,2));
155 free(num1);
156 }
157 }
158}
159
160void serverlist_hook_newserver(int hook, void *arg) {
161 char *num1, *numeric;
074a4529 162 long num = (long)arg;
b7eccf5f
P
163
164 if (mynick == NULL)
165 return;
166
167 serverinfo[num].used = 1;
168 serverinfo[num].ts = getnettime();
169 serverinfo[num].version1 = NULL;
170 serverinfo[num].version2 = NULL;
171
172 numeric = longtonumeric(mynick->numeric,5);
173 num1 = (char*)malloc(strlen(numeric) + 1); /* bleh.. longtonumeric() is using static variables */
174 strcpy(num1, numeric);
175
176 irc_send("%s V :%s", num1, longtonumeric(num,2));
177
178 free(num1);
179}
180
181void serverlist_hook_lostserver(int hook, void *arg) {
074a4529 182 long num = (long)arg;
b7eccf5f
P
183
184 serverinfo[num].used = 0;
185 freesstring(serverinfo[num].version1);
186 freesstring(serverinfo[num].version2);
187}
188
475b3d9d
GB
189
190void serverlist_pingservers(void *arg) {
191 int i;
192 server *from, *to;
193 char fnum[10], tnum[10];
194 struct timeval tv;
195
196 if (!mynick)
197 return;
198
199 for(i=0;i<MAXSERVERS;i++) {
200 to = &serverlist[i];
201
202 if (to->parent == -1)
203 continue;
204
205 from = &serverlist[to->parent];
206
207 if (to->linkstate != LS_LINKED || from->linkstate != LS_LINKED)
208 continue;
209
210 strcpy(fnum, longtonumeric(to->parent,2));
211 strcpy(tnum, longtonumeric(i, 2));
212
213 if (from->parent == -1) { /* Are we the source? */
214 (void) gettimeofday(&tv, NULL);
215 irc_send("%s RI %s %s %jd %jd :RP", mynumeric->content, tnum, longtonumeric(mynick->numeric,5), (intmax_t)tv.tv_sec, (intmax_t)tv.tv_usec);
216 } else {
217 strcpy(fnum, longtonumeric(to->parent,2));
218 strcpy(tnum, longtonumeric(i, 2));
219 irc_send("%s RI %s %s :RP", longtonumeric(mynick->numeric,5), to->name->content, fnum);
220 }
221 }
222}
223
224int serverlist_rpong(void *source, int cargc, char **cargv) {
225 int to, lag;
226 struct timeval tv;
227
228 if (cargc < 4)
229 return CMD_ERROR;
230
231 if (cargc == 5) { /* From target to source server */
232 if (strcmp(cargv[4], "RP") != 0)
233 return CMD_OK;
234
235 to = numerictolong(source, 2);
236
237 (void) gettimeofday(&tv, NULL);
238 lag = (tv.tv_sec - strtoull(cargv[2], NULL, 10)) * 1000 + (tv.tv_usec - strtoull(cargv[3], NULL, 10)) / 1000;
239 } else { /* From source server to client */
240 if (strcmp(cargv[3], "RP") != 0)
241 return CMD_OK;
242
243 to = findserver(cargv[1]);
244
245 if (to == -1)
246 return CMD_ERROR;
247
248 lag = atoi(cargv[2]);
249 }
250
251 serverinfo[to].lag = lag;
252
253 return CMD_OK;
254}
255