1 #ifdef RCS
2 static char rcsid[]="$Id: servfunc.c,v 1.1.1.1 2000/11/13 02:42:48 holsta Exp $";
3 #endif
4 /******************************************************************************
5 * Internetting Cooperating Programmers
6 * ----------------------------------------------------------------------------
7 *
8 * ____ PROJECT
9 * | _ \ __ _ _ __ ___ ___ _ __
10 * | | | |/ _` | '_ \ / __/ _ \ '__|
11 * | |_| | (_| | | | | (_| __/ |
12 * |____/ \__,_|_| |_|\___\___|_| the IRC bot
13 *
14 * All files in this archive are subject to the GNU General Public License.
15 *
16 * $Source: /cvsroot/dancer/dancer/src/servfunc.c,v $
17 * $Revision: 1.1.1.1 $
18 * $Date: 2000/11/13 02:42:48 $
19 * $Author: holsta $
20 * $State: Exp $
21 * $Locker: $
22 *
23 * ---------------------------------------------------------------------------
24 *****************************************************************************/
25
26 #include "dancer.h"
27 #include "trio.h"
28 #include "strio.h"
29 #include "list.h"
30 #include "function.h"
31 #include "servfunc.h"
32 #include "fplrun.h"
33
34 /* --- Global ----------------------------------------------------- */
35
36 extern time_t now;
37
38 extern char servername[];
39 extern char servfile[];
40 extern char *errfrom;
41 extern itemserv *currentserv;
42
43 itemserv *servHead;
44 static int servid = 1;
45
46
47 /* --- FindServ --------------------------------------------------- */
48
FindServ(char * name,long port)49 itemserv *FindServ(char *name, long port)
50 {
51 int id;
52 itemserv *s;
53
54 snapshot;
55 id = atoi(name);
56 for (s = First(servHead); s; s = Next(s)) {
57 if ((id && (id == s->s.id)) ||
58 (StrEqual(name, s->s.name) && (port == s->s.port))) {
59 return s;
60 }
61 }
62 return NULL;
63 }
64
65 /* --- NextServ --------------------------------------------------- */
66
NextServ(void)67 itemserv *NextServ(void)
68 {
69 itemserv *afterthis;
70 itemserv *s;
71
72 snapshot;
73 afterthis = currentserv;
74 for (s = First(servHead); s; s = Next(s)) {
75 if (s->s.flags & SERV_DISABLED)
76 continue;
77 if (NULL == afterthis)
78 return s;
79 else if (s == afterthis)
80 afterthis = NULL; /* get the next */
81 }
82 return First(servHead); /* if nothing matched, return the first */
83 }
84
AddServ(struct ServerSub * sub)85 int AddServ(struct ServerSub *sub)
86 {
87 int retcode = TRUE;
88 itemserv *s;
89
90 snapshot;
91 s = FindServ(sub->name, sub->port);
92 if (NULL == s) {
93 s = NewEntry(itemserv);
94 if (s) {
95 InsertLast(servHead, s);
96 s->s = *sub;
97 s->s.id = servid++;
98 return FALSE;
99 }
100 }
101 else if (s->s.flags & SERV_DISABLED &&
102 !(sub->flags & SERV_DISABLED) &&
103 !(sub->flags & SERV_INCONFIG)) {
104 /*
105 * The existing one is marked disabled. The new one is not, and it is
106 * not from the .config file.
107 * .config file entries are not allowed to undo disabled ones.
108 */
109
110 /*
111 * The added one already exists, so we should return successful
112 * but we should free the resources of this new struct since we
113 * are reusing an old one.
114 */
115 s->s.flags &= ~SERV_DISABLED;
116 retcode = FALSE;
117 }
118 else if (sub->flags & SERV_INCONFIG) {
119 s->s.flags |= SERV_INCONFIG; /* this exist in .config we know now */
120 }
121
122 /* Free the resources */
123 if (sub->name)
124 StrFree(sub->name);
125 if (sub->passwd)
126 StrFree(sub->passwd);
127 if (sub->adder)
128 StrFree(sub->adder);
129 if (sub->message)
130 StrFree(sub->message);
131
132 return retcode;
133 }
134
ManAddServ(char * name,long port,char * passwd,char * who,long flags)135 int ManAddServ(char *name, long port, char *passwd, char *who, long flags)
136 {
137 struct ServerSub sub;
138
139 snapshot;
140 memset(&sub, 0, sizeof(struct ServerSub));
141 sub.name = StrDuplicate(name);
142 sub.port = port ? port : IRCPORT;
143 sub.passwd = passwd ? StrDuplicate(passwd) : NULL;
144 sub.adder = who ? StrDuplicate(who) : NULL;
145 sub.addtime = now;
146 sub.flags = flags;
147 return AddServ(&sub);
148 }
149
ListServ(char * from,char * line)150 void ListServ(char *from, char *line)
151 {
152 char match[MIDBUFFER] = "*";
153 itemserv *s;
154
155 snapshot;
156 StrScan(line, "%"MIDBUFFERTXT"s", match);
157 for (s = First(servHead); s; s = Next(s)) {
158 if (Match(s->s.name, match)) {
159 Sendf(from, "%d - %s %d%s%s", s->s.id, s->s.name, s->s.port,
160 s->s.passwd ? " <password>" : "",
161 (s->s.flags & SERV_DISABLED) ? " [DISABLED]" : "");
162 }
163 }
164 }
165
166 /* --- SaveServ --------------------------------------------------- */
167
SaveServ(void)168 int SaveServ(void)
169 {
170 char tempfile[BIGBUFFER];
171 bool ok = TRUE;
172 itemserv *s;
173 FILE *f;
174
175 snapshot;
176 if (NIL == servfile[0])
177 return TRUE;
178
179 StrFormatMax(tempfile, sizeof(tempfile), "%s~", servfile);
180
181 f = fopen(tempfile, "w");
182 if (f) {
183 if (0 > fprintf(f, "# Dancer serverlist version: " VERSIONMSG "\n")) {
184 ok = FALSE;
185 }
186 else {
187 for (s = First(servHead); s; s = Next(s)) {
188 if (0 > fprintf(f, "%s:%d:%s\n" ":%s\n" "-%s\n" "!%d %d %d %d %d %d\n",
189 s->s.name, s->s.port, s->s.passwd ? s->s.passwd : "",
190 s->s.message ? s->s.message : "",
191 s->s.adder ? s->s.adder : "",
192 s->s.connect, s->s.disconnect, s->s.average,
193 s->s.numconnects, s->s.flags, s->s.addtime)) {
194 ok = FALSE;
195 break;
196 }
197 }
198 }
199 fclose(f);
200
201 if (ok)
202 rename(tempfile, servfile);
203 }
204 else
205 return TRUE;
206
207 return FALSE;
208 }
209
210 /* --- LoadServ --------------------------------------------------- */
211
LoadServ(void)212 int LoadServ(void)
213 {
214 char buffer[MAXLINE];
215 char name1[BIGBUFFER];
216 char name2[BIGBUFFER];
217 int number[6];
218 struct ServerSub sub;
219 FILE *f;
220
221 snapshot;
222 f = fopen(servfile, "r");
223 if (f) {
224 memset(&sub, 0, sizeof(struct ServerSub));
225 while (fgets(buffer, sizeof(buffer), f)) {
226 switch(buffer[0]) {
227
228 case '#':
229 case '\n':
230 break;
231
232 case ':':
233 if (1 == StrScan(buffer, ":%[^\n]", name1)) {
234 sub.message = StrDuplicate(name1);
235 }
236 break;
237
238 case '-':
239 if (1 == StrScan(buffer, "-%[^\n]", name1)) {
240 sub.adder = StrDuplicate(name1);
241 }
242 break;
243
244 case '!':
245 if (6 == StrScan(buffer, "!%d %d %d %d %d %d",
246 &number[0], &number[1], &number[2],
247 &number[3], &number[4], &number[5])) {
248 sub.connect = number[0];
249 sub.disconnect = number[1];
250 sub.average = number[2];
251 sub.numconnects = number[3];
252 sub.flags = number[4] & ~SERV_INCONFIG;
253 sub.addtime = number[5];
254 }
255 AddServ(&sub);
256 memset(&sub, 0, sizeof(struct ServerSub));
257 break;
258
259 default:
260 name2[0] = (char)0;
261 number[0] = IRCPORT;
262 if (1 <= StrScan(buffer, "%[^:]:%d:%[^\n]",
263 name1, &number[0], name2)) {
264 sub.name = StrDuplicate(name1);
265 sub.port = number[0];
266 if (name2[0])
267 sub.passwd = StrDuplicate(name2);
268 }
269 break;
270 }
271 }
272 fclose(f);
273 }
274 else
275 return TRUE;
276
277 return FALSE;
278 }
279
FreeServ(void * v)280 void FreeServ(void *v)
281 {
282 itemserv *s;
283
284 snapshot;
285 s = (itemserv *)v;
286 if (s) {
287 if (s->s.name)
288 StrFree(s->s.name);
289 if (s->s.passwd)
290 StrFree(s->s.passwd);
291 if (s->s.message)
292 StrFree(s->s.message);
293 if (s->s.adder)
294 StrFree(s->s.adder);
295 }
296 }
297
ServInit(void)298 void ServInit(void)
299 {
300 extern itemlist *serverHead;
301 char servername[BIGBUFFER], serverpasswd[BIGBUFFER];
302 int serverport;
303 itemlist *p;
304
305 snapshot;
306 servHead = NewList(itemserv);
307 if (servHead) {
308 /* First, we get the servers from the .serv file */
309 LoadServ();
310
311 /* Now, we convert the old-style serverlist */
312 for (p = First(serverHead); p; p = Next(p)) {
313 serverpasswd[0] = (char)0;
314 serverport = IRCPORT;
315 StrScan((char *)p->pointer, "%[a-zA-Z0-9.-]%*[ :]%d%*[ :]%[^\n]",
316 servername, &serverport, serverpasswd);
317 ManAddServ(servername, serverport, serverpasswd[0] ? serverpasswd : NULL,
318 NULL, SERV_INCONFIG);
319 }
320 }
321 }
322
ServCleanup(void)323 void ServCleanup(void)
324 {
325 snapshot;
326 SaveServ();
327 DeleteList(servHead, FreeServ);
328 }
329
DelServ(char * name,long port)330 int DelServ(char *name, long port)
331 {
332 itemserv *s;
333
334 snapshot;
335 s = FindServ(name, port);
336 if (s) {
337 if (s->s.flags & SERV_INCONFIG) {
338 /*
339 * This is entered in the .config file and therefore we cannot
340 * remove this for real, just mark it disabled
341 */
342 s->s.flags |= SERV_DISABLED;
343 }
344 else {
345 DeleteEntry(servHead, s, FreeServ); /* remove */
346 }
347 return FALSE;
348 }
349 return TRUE;
350 }
351
ManDelServ(char * from,char * line)352 int ManDelServ(char *from, char *line)
353 {
354 char server[SEMIBUFFER];
355 long port = IRCPORT;
356
357 snapshot;
358 if (StrScan(line, "%"SEMIBUFFERTXT"s %d", server, &port)) {
359 if (currentserv &&
360 StrEqual(server, currentserv->s.name) &&
361 (port == currentserv->s.port)) {
362 Send(errfrom, GetText(msg_cant_delete_current_server));
363 return TRUE;
364 }
365 if (DelServ(server, port)) {
366 Sendf(errfrom, GetText(msg_could_not_find_server), server, port);
367 return TRUE;
368 }
369 Sendf(from, GetText(msg_server_removed), server, port);
370 SaveServ();
371 }
372 else
373 return TRUE;
374
375 return FALSE;
376 }
377
StatServ(char * from,int options,char * server,long port)378 void StatServ(char *from, int options, char *server, long port)
379 {
380 itemserv *s;
381
382 snapshot;
383 if (NIL == server[0]) {
384 s = currentserv;
385 if (NULL == s) {
386 Sendf(errfrom, GetText(msg_server_not_in_list), servername);
387 return;
388 }
389 }
390 else {
391 s = FindServ(server, port);
392 if (NULL == s) {
393 Sendf(errfrom, GetText(msg_could_not_find_server), server, port);
394 return;
395 }
396 }
397
398 /*
399 * The switch makes duplicate flags get ignored, only one of them set
400 * will make a change
401 */
402 switch(options) {
403 case SERV_ENABLED:
404 s->s.flags &= ~SERV_DISABLED;
405 break;
406 case SERV_DISABLED:
407 s->s.flags |= SERV_DISABLED;
408 break;
409 }
410
411 Sendf(from, "%s port %d %s", s->s.name, s->s.port,
412 s->s.passwd ? "<passwd>" : "");
413 Sendf(from, "%s last connect %s ago", (currentserv == s) ? "<current>" : "",
414 s->s.connect ? TimeAgo(s->s.connect) : "ages");
415 Sendf(from, "last disconnect %s ago, average connect time %s",
416 s->s.disconnect ? TimeAgo(s->s.disconnect) : "ages",
417 SecsToString(s->s.average));
418 Sendf(from, "number of connects: %d", s->s.numconnects);
419 Sendf(from, "State:%s",
420 (s->s.flags & SERV_DISABLED) ? " [DISABLED]" : " normal");
421 }
422
ConnectServ(itemserv * serv)423 void ConnectServ(itemserv *serv)
424 {
425 snapshot;
426 currentserv = serv;
427 if (serv) {
428 #ifdef HAVE_LIBFPL
429 if (runfpl(RUN_CONNECT, serv->s.name, FPLRUN_PRE))
430 return;
431 #endif
432 serv->s.connect = now;
433 serv->s.numconnects++;
434 SaveServ();
435 runfpl(RUN_CONNECT, serv->s.name, FPLRUN_POST);
436 }
437 }
438
DisconnectServ(char * fmt,...)439 void DisconnectServ(char *fmt, ...)
440 {
441 char buf[BIGBUFFER];
442 va_list args;
443
444 snapshot;
445 va_start(args, fmt);
446 trio_vsnprintf(buf, sizeof(buf), fmt, args);
447 va_end(args);
448
449 #ifdef HAVE_LIBFPL
450 if (runfpl(RUN_DISCONNECT, buf, FPLRUN_PRE))
451 return;
452 #endif
453
454 if (currentserv) {
455 if (currentserv->s.message)
456 StrFree(currentserv->s.message);
457 currentserv->s.message = StrDuplicate(buf);
458 currentserv->s.disconnect = now;
459
460 /* calculate the new average connect time */
461 currentserv->s.average = ((currentserv->s.average *
462 (currentserv->s.numconnects - 1)) +
463 (currentserv->s.disconnect -
464 currentserv->s.connect)) /
465 currentserv->s.numconnects;
466 }
467
468 runfpl(RUN_DISCONNECT, buf, FPLRUN_POST);
469 }
470