/[cvs]/eggdrop1.9/src/core_party.c
ViewVC logotype

Contents of /eggdrop1.9/src/core_party.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.52 - (show annotations) (download) (as text)
Tue Nov 14 14:51:24 2006 UTC (12 years, 7 months ago) by sven
Branch: MAIN
Changes since 1.51: +71 -13 lines
File MIME type: text/x-chdr

Misc:
 * Bind table flag BIND_BREAKABLE now includes BIND_STACKABLE, doesn't make
   sense otherwise.
 * If the line buffer contains more than one line of text do a check if the
   index is still valid after every callback (the sockbuf might have been
   deleted).
 * Added a "Doxygen" file in the root dir. It will generate html output in
   doc/developer/html. (The dir will be created by doxygen.)

Partyline stuff:
 * Partychan join and quit functions have an extra parameter indicating if
   the event is triggered because of someone joining/quitting or botnet
   restructuring.
 * Renamed partychan_msg() to chan_msg and made it static. It can now either
   msg the whole channel or just everyone on the local bot on the channel.
 * New functions partychan_msg() (works like before) and localchan_msg() to
   send it to every local user of the chan.
 * Added stuff to the partymember struct: A pointer to the bot the user is
   on, a malloc'd string containing the full unique name in the form
   "id:nick@bot", a pointer into this string to the full name "nick@bot"
   and a pointer to the common name of the user, "nick" for local users and
   "nick@bot" for users on other bots.
 * The id of a partymember is no longer unique, only unique to the bot the
   user is on. The nick was never unique. TODO: Change the script modules
   to take care of that!
 * A partymember is now part of two double linked lists: A list of all
   partymembers and a list of all partymembers on the bot.
 * Removed the partymember_lookup_* functions. partymember_lookup() takes
   cares of all the stuff.
 * Added functions to count all users on a bot and delete all users on a bot.

Ircpartyline:
 * IRC requires nicks to be unique for everyone and useing the usual "@" in
   the "nick@bot" form doesn't work at all on IRC. Therefor the nick format
   is now: "nick*bot:id" for remote users and "nick:id" for local users.

Script stuff:
 * Added a new script parameter: 'B': A bot.
 * TODO: Change the script modules to use it!

Botnet stuff:
 * Added botnet.[ch]. Fully documented!
 * Changed the oldbotnet module to use the new botnet API. Only very basic
   stuff works atm: Bot links, unlinks, partymember joins, quits and chatter.
   But at least it doesn't matter any more if the bot is a leaf or a hub.

1 /* core_party.c: core partyline commands
2 *
3 * Copyright (C) 2003, 2004 Eggheads Development Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifndef lint
21 static const char rcsid[] = "$Id: core_party.c,v 1.51 2006-10-01 00:48:59 sven Exp $";
22 #endif
23
24 #include <eggdrop/eggdrop.h>
25 #include <unistd.h>
26
27 #ifdef HAVE_UNAME
28 # include <sys/utsname.h>
29 #endif
30
31 #include "core_config.h"
32 #include "core_binds.h"
33 #include "logfile.h"
34 #include "terminal.h" /* TERMINAL_NICK */
35 #include "main.h" /* SHUTDOWN_*, core_shutdown, core_restart */
36
37 static int party_help(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
38 {
39 help_summary_t *entry;
40 help_search_t *search;
41 int hits = 0;
42 xml_node_t *node, *arg, *desc, *see;
43 char *argname, *argdesc;
44 int optional;
45
46
47 if (!text || !*text) {
48 partymember_printf(p, "Syntax: help <command|variable|*search*>");
49 return(0);
50 }
51 /* First try to look up an exact match. */
52 entry = help_lookup_summary(text);
53 if (entry) {
54 node = help_lookup_entry(entry);
55 partymember_printf(p, "Syntax:");
56 partymember_printf(p, " %s", entry->syntax);
57 partymember_printf(p, "");
58 partymember_printf(p, "Summary:");
59 partymember_printf(p, " %s", entry->summary);
60 partymember_printf(p, "");
61 xml_node_get_vars(node, "nnn", "desc.line", &desc, "args.arg", &arg, "seealso.see", &see);
62 if (arg) {
63 partymember_printf(p, "Arguments:");
64 for (; arg; arg = arg->next_sibling) {
65 xml_node_get_vars(arg, "sis", "name", &argname, "optional", &optional, "desc", &argdesc);
66 partymember_printf(p, " %s%s - %s", argname, optional ? " (optional)" : "", argdesc);
67 }
68 partymember_printf(p, "");
69 }
70 partymember_printf(p, "Description:");
71 for (; desc; desc = desc->next_sibling) {
72 partymember_printf(p, " %s", xml_node_str(desc, ""));
73 }
74 partymember_printf(p, "");
75 if (see) {
76 partymember_printf(p, "See also:");
77 for (; see; see = see->next_sibling) {
78 partymember_printf(p, " %s", xml_node_str(see, ""));
79 }
80 }
81 xml_node_delete(node);
82 return(0);
83 }
84
85 /* No, do a search. */
86 if (!strchr(text, '*') && !strchr(text, '?')) {
87 partymember_printf(p, "No help was found! Try searching with wildcards, e.g. *%s*", text);
88 return(0);
89 }
90
91 search = help_search_new(text);
92 while ((entry = help_search_result(search))) {
93 partymember_printf(p, "%s - %s", entry->syntax, entry->summary);
94 hits++;
95 }
96 if (hits == 0) {
97 partymember_printf(p, "No help was found! Try more wildcards...");
98 }
99 help_search_end(search);
100 return(0);
101 }
102
103 static int party_join(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
104 {
105 if (!text || !*text) {
106 partymember_printf(p, _("Syntax: join <channel>"));
107 return(0);
108 }
109 partychan_join_name(text, p, 0);
110 return(0);
111 }
112
113 static int party_part(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
114 {
115 partychan_t *chan;
116
117 if (!text || !*text) chan = partychan_get_default(p);
118 else chan = partychan_lookup_name(text);
119 partychan_part(chan, p, "parting");
120 return(0);
121 }
122
123 static int party_quit(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
124 {
125 if (0 == strcmp (p->nick, TERMINAL_NICK)) {
126 partymember_printf (p, "You can't leave the partyline in terminal mode.");
127 return -1;
128 }
129
130 partymember_printf(p, "Goodbye!");
131 if (!text || !*text) partymember_delete(p, NULL, "Quit");
132 else partymember_delete(p, NULL, text);
133 return(0);
134 }
135
136 static int party_whisper(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
137 {
138 char *who;
139 const char *next;
140 partymember_t *dest;
141
142 egg_get_arg(text, &next, &who);
143 if (!who || !next || !*who || !*next) {
144 partymember_printf(p, _("Syntax: whisper <partylineuser> <msg>"));
145 goto done;
146 }
147
148 dest = partymember_lookup(who, NULL, -1);
149 if (!dest) {
150 partymember_printf(p, _("No such user '%s'."), who);
151 goto done;
152 }
153
154 partymember_msg(dest, p, next, -1);
155 done:
156 if (who) free(who);
157 return(0);
158 }
159
160 static void *lookup_setting(partymember_t *p, const char *path)
161 {
162 void *root;
163
164 root = config_get_root("eggdrop");
165 root = config_exists(root, path, 0, NULL);
166 if (!root) partymember_printf(p, _("That setting does not exist."));
167 return(root);
168 }
169
170 static int party_get(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
171 {
172 void *root;
173 char *str = NULL;
174
175 if (!text || !*text) {
176 partymember_printf(p, _("Syntax: get <path>"));
177 return(0);
178 }
179
180 root = lookup_setting(p, text);
181 if (!root) return(0);
182
183 config_get_str(&str, root, NULL);
184 if (str) partymember_printf(p, "Current value: '%s'", str);
185 else partymember_printf(p, _("Current value: null (unset)"));
186 return(0);
187 }
188
189 static int party_set(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
190 {
191 void *root;
192 char *path, *str;
193 const char *next;
194
195 egg_get_arg(text, &next, &path);
196 if (!path) {
197 partymember_printf(p, _("Syntax: set <path> [new value]"));
198 return(0);
199 }
200 if (!next) {
201 free(path);
202 return party_get(p, nick, u, cmd, text);
203 }
204
205 root = lookup_setting(p, path);
206 free(path);
207 if (!root) return(0);
208
209 config_get_str(&str, root, NULL);
210 partymember_printf(p, _("Old value: '%s'"), str);
211 config_set_str(next, root, NULL);
212 config_get_str(&str, root, NULL);
213 if (str) partymember_printf(p, _("New value: '%s'"), str);
214 else partymember_printf(p, _("New value: null (unset)"));
215 return(0);
216 }
217
218 static int party_unset(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
219 {
220 void *root;
221 char *str;
222
223 if (!text || !*text) {
224 partymember_printf(p, _("Syntax: unset <path>"));
225 return(0);
226 }
227
228 root = lookup_setting(p, text);
229 if (!root) return(0);
230
231 config_get_str(&str, root, NULL);
232 if (str) partymember_printf(p, _("Old value: '%s'"), str);
233 else partymember_printf(p, _("Old value: null (unset)"));
234 config_set_str(NULL, root, NULL);
235 config_get_str(&str, root, NULL);
236 if (str) partymember_printf(p, _("New value: '%s'"), str);
237 else partymember_printf(p, _("New value: null (unset)"));
238 return(0);
239 }
240
241 static int party_status(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
242 {
243 #ifdef HAVE_UNAME
244 struct utsname un;
245 #endif
246
247 partymember_printf(p, _("I am %1$s, running Eggdrop %2$s."), core_config.botname, VERSION);
248 partymember_printf(p, _("Owner: %s"), core_config.owner);
249 if (core_config.admin) partymember_printf(p, _("Admin: %s"), core_config.admin);
250 #ifdef HAVE_UNAME
251 if (!uname(&un)) partymember_printf(p, _("OS: %1$s %2$s"), un.sysname, un.release);
252 #endif
253 partymember_printf(p, _("Help path: %s (%d entries, %d sections)"),
254 core_config.help_path, 0, 0);
255 partymember_printf(p, "");
256 check_bind_status(p, text);
257 return(0);
258 }
259
260 static int party_bots(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
261 {
262 int len, bots = 1;
263 char obuf[201] = "";
264 const char *botname;
265 const botnet_bot_t *bot;
266
267 botname = botnet_get_name();
268 if (strlen(botname) < 100) strcpy(obuf, botname);
269 else sprintf(obuf, "%.96s...", botname);
270
271 for (bot = botnet_get_head(); bot; bot = bot->next) {
272 ++bots;
273 len = strlen(bot->name);
274 if (strlen(obuf) + (len < 100 ? len : 99) + 2 > 200) {
275 partymember_printf(p, _("Bots: %s"), obuf);
276 if (strlen(botname) < 100) strcpy(obuf, bot->name);
277 else sprintf(obuf, "%.96s...", bot->name);
278 } else {
279 if (strlen(botname) < 100) sprintf(obuf + strlen(obuf), ", %s", bot->name);
280 else sprintf(obuf + strlen(obuf), ", %.96s...", bot->name);
281 }
282 }
283 partymember_printf(p, _("Bots: %s"), obuf);
284 partymember_printf(p, _("Total: %d"), bots);
285 return 0;
286 }
287
288 static int party_save(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
289 {
290 putlog(LOG_MISC, "*", _("Saving user file..."));
291 user_save(core_config.userfile);
292 putlog(LOG_MISC, "*", _("Saving config file..."));
293 core_config_save();
294 return(1);
295 }
296
297 static int party_newpass(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
298 {
299 if (!text || strlen(text) < 6) {
300 partymember_printf(p, _("Please use at least 6 characters."));
301 return(0);
302 }
303 user_set_pass(p->user, text);
304 partymember_printf(p, _("Changed password to '%s'."), text);
305 return(0);
306 }
307
308 static int intsorter(const void *left, const void *right)
309 {
310 return(*(int *)left - *(int *)right);
311 }
312
313 static int party_who(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
314 {
315 partymember_t *who;
316 int *ids, len, i, width = 0;
317
318 partymember_printf(p, _("Partyline members:"));
319 partymember_who(&ids, &len);
320 qsort(ids, len, sizeof(int), intsorter);
321 if (len > 0) {
322 i = ids[len-1];
323 if (!i) i++;
324 while (i != 0) {
325 i /= 10;
326 width++;
327 }
328 }
329 for (i = 0; i < len; i++) {
330 who = partymember_lookup(NULL, NULL, ids[i]);
331 partymember_printf(p, " [%*d] %s (%s@%s)", width, who->id, who->nick, who->ident, who->host);
332 }
333 free(ids);
334 return(0);
335 }
336
337 static int party_whois(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
338 {
339 user_t *who;
340 flags_t flags;
341 char *item, *chan, *setting, *value, flagstr[64];
342 const char *next;
343 int i;
344
345 if (text && *text) who = user_lookup_by_handle(text);
346 else who = u;
347
348 if (!who) {
349 partymember_printf(p, "No such user.");
350 return(0);
351 }
352
353 next = core_config.whois_items;
354 while (next && *next) {
355 egg_get_arg(next, &next, &item);
356 if (!strcasecmp(item, "handle")) {
357 partymember_printf(p, "%s: '%s'", item, who->handle);
358 }
359 else if (!strcasecmp(item, "uid")) {
360 partymember_printf(p, "%s: '%d'", item, who->uid);
361 }
362 else if (!strcasecmp(item, "ircmasks")) {
363 partymember_printf(p, "%s:", item);
364 for (i = 0; i < who->nircmasks; i++) {
365 partymember_printf(p, " %d. '%s'", i+1, who->ircmasks[i]);
366 }
367 }
368 else {
369 if ((setting = strchr(item, '.'))) {
370 chan = item;
371 *setting = 0;
372 setting++;
373 }
374 else {
375 chan = NULL;
376 setting = item;
377 }
378 if (!strcasecmp(setting, "flags")) {
379 user_get_flags(who, chan, &flags);
380 flag_to_str(&flags, flagstr);
381 value = flagstr;
382 }
383 else {
384 user_get_setting(who, chan, setting, &value);
385 }
386
387 if (chan) partymember_printf(p, "%s.%s: %s", chan, setting, value);
388 else partymember_printf(p, "%s: %s", setting, value);
389 }
390 free(item);
391 }
392 return(0);
393 }
394
395 static int party_die(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
396 {
397 /* XXX: should we really enable hard shutdowns?
398 if (*text && 0 == strcmp(text, "force")) {
399 return core_shutdown(SHUTDOWN_HARD, nick, text);
400 } else
401 */
402 return core_shutdown(SHUTDOWN_GRACEFULL, nick, text);
403 }
404
405 static int party_plus_user(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
406 {
407 const char *error;
408 user_t *newuser;
409
410 if (!text || !*text) {
411 partymember_printf(p, _("Syntax: +user <handle>"));
412 return(0);
413 }
414
415 error = user_invalid_handle(text);
416 if (error) {
417 partymember_printf(p, _("Error: %s"), error);
418 return(0);
419 }
420 newuser = user_new(text);
421 if (newuser) partymember_printf(p, _("User '%s' created."), text);
422 else partymember_printf(p, _("Could not create user '%s'."), text);
423 return(0);
424 }
425
426 static int party_minus_user(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
427 {
428 user_t *who;
429
430 if (!text || !*text) {
431 partymember_printf(p, _("Syntax: -user <handle>"));
432 return(0);
433 }
434 who = user_lookup_by_handle(text);
435 if (!who) partymember_printf(p, _("User '%s' not found."), text);
436 else {
437 partymember_printf(p, _("Deleting user '%s'."), who->handle);
438 user_delete(who);
439 }
440 return(0);
441 }
442
443 static int party_link(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
444 {
445 int error;
446 user_t *who;
447
448 if (!text || !*text) {
449 partymember_printf(p, _("Syntax: link <handle>"));
450 return 0;
451 }
452 who = user_lookup_by_handle(text);
453 if (!who) {
454 partymember_printf(p, _("User '%s' not found."), text);
455 return 0;
456 }
457 error = botnet_link(who);
458 if (!error) return 0;
459
460 if (error == -1) {
461 partymember_printf(p, _("Error linking to '%s': User is not a bot."), who->handle);
462 } else if (error == -2) {
463 partymember_printf(p, _("Error linking to '%s': Bot type not set."), who->handle);
464 } else if (error == -3) {
465 partymember_printf(p, _("Error linking to '%s': No module loaded to link to that bot type."), who->handle);
466 }
467
468 return 0;
469 }
470
471 static int party_plus_host(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
472 {
473 user_t *who;
474 char *target, *newhost;
475
476 egg_get_args(text, NULL, &target, &newhost, NULL);
477 if (!target) {
478 partymember_printf(p, _("Syntax: +host [handle] <host>"));
479 return(0);
480 }
481 if (!newhost) {
482 newhost = target;
483 target = NULL;
484 }
485 if (target) {
486 who = user_lookup_by_handle(target);
487 if (!who) {
488 partymember_printf(p, _("User '%s' not found."), target);
489 goto done;
490 }
491 }
492 else {
493 who = u;
494 if (!who) {
495 partymember_printf(p, _("Only valid users can add hosts."));
496 goto done;
497 }
498 }
499 user_add_ircmask(who, newhost);
500 partymember_printf(p, _("Added '%1$s' to user '%2$s'."), newhost, who->handle);
501
502 done:
503 if (target) free(target);
504 free(newhost);
505
506 return(0);
507 }
508
509 static int party_minus_host(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
510 {
511 user_t *who;
512 char *target, *host;
513
514 egg_get_args(text, NULL, &target, &host, NULL);
515 if (!target) {
516 partymember_printf(p, _("Syntax: -host [handle] <host>"));
517 return(0);
518 }
519 if (!host) {
520 host = target;
521 target = NULL;
522 }
523 if (target) {
524 who = user_lookup_by_handle(target);
525 if (!who) {
526 partymember_printf(p, _("User '%s' not found."), target);
527 goto done;
528 }
529 }
530 else {
531 who = u;
532 if (!who) {
533 partymember_printf(p, _("Only valid users can remove hosts."));
534 goto done;
535 }
536 }
537 if (user_del_ircmask(who, host)) {
538 partymember_printf(p, _("Mask '%1$s' not found for user '%2$s'."), host, who->handle);
539 }
540 else {
541 partymember_printf(p, _("Removed '%1$s' from user '%2$s'."), host, who->handle);
542 }
543
544 done:
545 if (target) free(target);
546 free(host);
547
548 return(0);
549 }
550
551 /* Syntax: chattr <user> [chan] <flags> */
552 static int party_chattr(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
553 {
554 const char *next;
555 char *who, *flags, *chan;
556 user_t *dest;
557 flags_t flagstruct;
558 char flagstr[64];
559 int n;
560
561 n = egg_get_args(text, &next, &who, &chan, &flags, NULL);
562 if (!chan || !*chan) {
563 if (who) free(who);
564 partymember_printf(p, _("Syntax: chattr <handle> [channel] <+/-flags>"));
565 return(0);
566 }
567 if (!flags || !*flags) {
568 flags = chan;
569 chan = NULL;
570 }
571 dest = user_lookup_by_handle(who);
572 if (dest) {
573 user_set_flags_str(dest, chan, flags);
574 user_get_flags(dest, chan, &flagstruct);
575 flag_to_str(&flagstruct, flagstr);
576 partymember_printf(p, _("Flags for %s are now '%s'."), who, flagstr);
577 }
578 else partymember_printf(p, _("'%s' is not a valid user."), who);
579 free(who);
580 free(flags);
581 if (chan) free(chan);
582 return(0);
583 }
584
585 static int party_addlog(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
586 {
587 putlog(LOG_MISC, "*", "%s: %s", nick, text);
588
589 return(BIND_RET_LOG);
590 }
591
592 static int party_modules(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
593 {
594 const char **modules;
595 int nummods, ctr;
596
597 nummods = module_list(&modules);
598 partymember_printf(p, _("Loaded modules:"));
599 for (ctr = 0; ctr < nummods; ctr++) partymember_printf(p, " %s", modules[ctr]);
600 free(modules);
601
602 return(BIND_RET_LOG);
603 }
604
605 static int party_loadmod(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
606 {
607 if (!text || !*text) {
608 partymember_printf(p, _("Syntax: loadmod <module name>"));
609 return BIND_RET_BREAK;
610 }
611 switch (module_load(text)) {
612 case 0:
613 partymember_printf(p, _("Module '%s' loaded successfully."), text);
614 break;
615 case -1:
616 partymember_printf(p, _("Module '%s' is already loaded."), text);
617 break;
618 case -2:
619 partymember_printf(p, _("Module '%s' could not be loaded."), text);
620 break;
621 case -3:
622 partymember_printf(p, _("Module '%s' does not have a valid initialization function. Perhaps it is not an eggdrop module?"), text);
623 break;
624 }
625 return(BIND_RET_LOG);
626 }
627
628 static int party_unloadmod(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
629 {
630 if (!text || !*text) {
631 partymember_printf(p, _("Syntax: unloadmod <module name>"));
632 return BIND_RET_BREAK;
633 }
634 switch (module_unload(text, MODULE_USER)) {
635 case 0:
636 partymember_printf(p, _("Module '%s' unloaded successfully."), text);
637 break;
638 case -1:
639 partymember_printf(p, _("Module '%s' is not loaded."), text);
640 break;
641 case -2:
642 partymember_printf(p, _("Module '%s' has dependencies that are still loaded. You must unload them first."), text);
643 break;
644 case -3:
645 partymember_printf(p, _("Module '%s' refuses to be unloaded by you!"), text);
646 break;
647 }
648 return(BIND_RET_LOG);
649 }
650
651 static int party_binds(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
652 {
653 bind_table_t *table;
654 bind_entry_t *entry;
655 char flags[64];
656
657 partymember_printf(p, "%-16s %-16s %-16s %-10s %-5s %s", _("TABLE"), _("SYNTAX"),
658 _("FUNCTION"), _("MASK"), _("FLAGS"), _("HITS"));
659 for (table = bind_table_list(); table; table = table->next) {
660 for (entry = table->entries; entry; entry = entry->next) {
661 flag_to_str(&entry->user_flags, flags);
662 partymember_printf(p, "%-16s %-16s %-16s %-10s %-5s %d", table->name, table->syntax,
663 entry->function_name, entry->mask, flags, entry->nhits);
664 }
665 }
666
667 return(BIND_RET_LOG);
668 }
669
670 static int party_timers(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
671 {
672 egg_timer_t *timer;
673 int remain, now;
674
675 now = timer_get_now_sec(NULL);
676 partymember_printf(p, "ID SEC LEFT NAME");
677 for (timer = timer_list(); timer; timer = timer->next) {
678 remain = timer->trigger_time.sec - now;
679 partymember_printf(p, "%-5d %-8d %s", timer->id, remain, timer->name);
680 }
681 return(BIND_RET_LOG);
682 }
683
684 static int print_net(partymember_t *p, const char *header, int flags)
685 {
686 int *idx, len;
687 int i, port, peer_port;
688 const char *host, *peer_host;
689 char *self_addr, *peer_addr;
690 sockbuf_handler_t *handler;
691
692 sockbuf_list(&idx, &len, flags);
693 partymember_printf(p, "%s", header);
694 partymember_printf(p, " %3s %20s %20s %s", _("Idx"), _("Local Address"), _("Foreign Address"), _("Description"));
695 for (i = 0; i < len; i++) {
696 sockbuf_get_self(idx[i], &host, &port);
697 sockbuf_get_peer(idx[i], &peer_host, &peer_port);
698 if (!host) host = "*";
699 if (!peer_host) peer_host = "*";
700 sockbuf_get_handler(idx[i], &handler, NULL);
701 if (port) self_addr = egg_mprintf("%s/%d", host, port);
702 else self_addr = egg_mprintf("%s/*", host);
703 if (peer_port) peer_addr = egg_mprintf("%s/%d", peer_host, peer_port);
704 else peer_addr = egg_mprintf("%s/*", peer_host);
705 partymember_printf(p, " %3d %20s %20s %s", idx[i], self_addr, peer_addr, handler->name);
706 free(self_addr);
707 free(peer_addr);
708 }
709 free(idx);
710 return(0);
711 }
712
713 static int party_netstats(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
714 {
715 print_net(p, "Server Sockets", SOCKBUF_SERVER);
716 print_net(p, "Incoming Connections", SOCKBUF_INBOUND);
717 print_net(p, "Outgoing Connections", SOCKBUF_CLIENT);
718 return(0);
719 }
720
721 static int party_restart(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
722 {
723 core_restart (nick);
724
725 return(BIND_RET_LOG);
726 }
727
728 /* Syntax: chhandle <old_handle> <new_handle> */
729 static int party_chhandle(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
730 {
731 const char *error;
732 char *old = NULL, *newh = NULL;
733 user_t *dest;
734
735 egg_get_args(text, NULL, &old, &newh, NULL);
736 if (!old || !newh || !*old || !*newh) {
737 if (old) free(old);
738 if (newh) free(newh);
739 partymember_printf(p, _("Syntax: chhandle <old_handle> <new_handle>"));
740 return 0;
741 }
742
743 dest = user_lookup_by_handle(old);
744 if (!dest) {
745 partymember_printf(p, _("Error: User '%s' does not exist."), old);
746 free(old);
747 free(newh);
748 return 0;
749 }
750
751 error = user_invalid_handle(newh);
752 if (error) {
753 partymember_printf(p, _("Error: %s"), error);
754 free(old);
755 free(newh);
756 return 0;
757 }
758
759 if (!user_change_handle(dest, newh))
760 partymember_printf(p, _("Ok, changed."));
761
762 free(newh);
763 free(old);
764
765 return(BIND_RET_LOG);
766 }
767
768 /* Syntax: chpass <handle> [new_pass] */
769 static int party_chpass(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
770 {
771 char *user = NULL, *pass = NULL;
772 user_t *dest;
773
774 egg_get_args(text, NULL, &user, &pass, NULL);
775
776 if (!user || !*user) {
777 partymember_printf(p, _("Syntax: chpass <handle> [pass]"));
778 goto chpassend;
779 }
780
781 dest = user_lookup_by_handle(user);
782 if (!dest) {
783 partymember_printf(p, _("Error: User '%s' does not exist."), user);
784 goto chpassend;
785 }
786
787 if (pass && *pass && strlen(pass) < 6) {
788 partymember_printf(p, _("Error: Please use at least 6 characters."));
789 goto chpassend;
790 }
791
792 if (user_set_pass(dest, pass))
793 partymember_printf(p, _("Removed password for %s."), user);
794 else
795 partymember_printf(p, _("Password for %s is now '%s'."), user, pass);
796
797 chpassend:
798 free(user);
799 free(pass);
800
801 return(BIND_RET_LOG_COMMAND);
802 }
803
804 /* Makes sure 'start' and 'limit' arguments for .match are reasonable, or else sets them -1 */
805 static int party_match_getbounds(const char *strstart, const char *strlimit, long *start, long *limit)
806 {
807 char *tmpptr;
808
809 if (strstart) {
810 *start = strtol(strstart, &tmpptr, 10);
811 if (!*strstart || *tmpptr || *start < 1) { /* Invalid input*/
812 *start = -1;
813 return 0;
814 }
815
816 if (strlimit) { /* 'start' was really a start and this is now 'limit' */
817 *limit = strtol(strlimit, &tmpptr, 10);
818 if (!*strlimit || *tmpptr || *limit < 1) { /* Invalid input*/
819 *limit = -1;
820 return 0;
821 }
822 }
823 else { /* Ah, no, the only argument specified was the 'limit' */
824 *limit = *start;
825 *start = 0;
826 }
827 }
828 else {
829 *limit = 20;
830 *start = 0;
831 }
832
833 return 0;
834 }
835
836 /* Handles case where .match was given mask to match against */
837 static int party_matchwild(partymember_t *p, const char *mask, const char *rest)
838 {
839 char *strstart = NULL, *strlimit = NULL;
840 long start, limit;
841
842 egg_get_args(rest, NULL, &strstart, &strlimit, NULL);
843
844 party_match_getbounds(strstart, strlimit, &start, &limit);
845 if (start == -1 || limit == -1)
846 partymember_printf(p, _("Error: 'start' and 'limit' must be positive integers"));
847 else
848 partyline_cmd_match_ircmask(p, mask, start, limit);
849
850 free(strstart);
851 free(strlimit);
852
853 return 0;
854 }
855
856 /* Handles case where .match was given attributes to match against */
857 static int party_matchattr(partymember_t *p, const char *mask, const char *rest)
858 {
859 char *channel = NULL, *strstart = NULL, *strlimit = NULL;
860 long start, limit;
861 int ischan = 0;
862
863 egg_get_args(rest, NULL, &channel, &strstart, &strlimit, NULL);
864
865 /* This is probably the easiest way to conclude if content of 'channel'
866 is *NOT* a number, and thus it is a candidate for a valid channel name */
867 if (channel && (*channel < '0' || *channel > '9'))
868 ischan = 1;
869
870
871 if (strlimit) /* .match <flags> <channel> <start> <limit> */
872 party_match_getbounds(strstart, strlimit, &start, &limit);
873 else if (strstart) /* .match <flags> <channel|start> <limit> */
874 party_match_getbounds(ischan?strstart:channel, ischan?NULL:strstart, &start, &limit);
875 else if (ischan) { /* .match <flags> <channel> */
876 start = 0;
877 limit = 20;
878 }
879 else /* .match <flags> [limit] */
880 party_match_getbounds(channel, NULL, &start, &limit);
881
882 free(strstart);
883 free(strlimit);
884
885 if (start == -1 || limit == -1)
886 partymember_printf(p, _("Error: 'start' and 'limit' must be positive integers"));
887 else
888 partyline_cmd_match_attr(p, mask, ischan?channel:NULL, start, limit);
889
890 free(channel);
891
892 return 0;
893 }
894
895 /* match <attr> [channel] [[start] limit] */
896 /* match <mask> [[start] limit] */
897 static int party_match(partymember_t *p, const char *nick, user_t *u, const char *cmd, const char *text)
898 {
899
900 char *attr = NULL;
901 const char *rest = NULL;
902
903 /* FIXME - Check if user is allowed to see results.. if !chan && !glob_master && -> error
904 I have left it available to everyone because 'whois' was that way too.
905 We should update both or neither */
906
907 egg_get_args(text, &rest, &attr, NULL);
908
909 if (!attr) {
910 partymember_printf(p, _("Syntax: match <attr> [channel] [[start] limit]"));
911 partymember_printf(p, _(" or: match <mask> [[start] limit]"));
912 free(attr);
913 return 0;
914 }
915
916 if (*attr == '+' || *attr == '-' || *attr == '|')
917 party_matchattr(p, attr, rest);
918 else if (*attr != '&')
919 party_matchwild(p, attr, rest);
920
921 free(attr);
922
923 return(BIND_RET_LOG);
924 }
925
926 static bind_list_t core_party_binds[] = { /* Old flags requirement */
927 {NULL, "help", party_help},
928 {NULL, "join", party_join}, /* DDD */
929 {NULL, "whisper", party_whisper}, /* DDD */
930 {NULL, "newpass", party_newpass}, /* DDC */ /* -|- */
931 {NULL, "help", party_help}, /* DDC */ /* -|- */
932 {NULL, "part", party_part}, /* DDD */
933 {NULL, "quit", party_quit}, /* DDD */ /* -|- */
934 {NULL, "who", party_who}, /* DDD */
935 {NULL, "whois", party_whois}, /* DDC */ /* ot|o */
936 {NULL, "match", party_match}, /* DDC */ /* ot|o */
937 {NULL, "bots", party_bots}, /* DDD */ /* -|- */
938 {"n", "addlog", party_addlog}, /* DDD */ /* ot|o */
939 {"n", "get", party_get}, /* DDC */
940 {"n", "set", party_set}, /* DDC */
941 {"n", "unset", party_unset}, /* DDC */
942 {"n", "status", party_status}, /* DDC */ /* m|m */
943 {"n", "save", party_save}, /* DDD */ /* m|m */
944 {"n", "die", party_die}, /* DDD */ /* n|- */
945 {"n", "restart", party_restart}, /* DDD */ /* m|- */
946 {"n", "+user", party_plus_user}, /* DDC */ /* m|- */
947 {"n", "-user", party_minus_user}, /* DDC */ /* m|- */
948 {"n", "link", party_link}, /* DDD */ /* t|- */
949 {"n", "chattr", party_chattr}, /* DDC */ /* m|m */
950 {"n", "modules", party_modules}, /* DDD */ /* n|- */
951 {"n", "loadmod", party_loadmod}, /* DDD */ /* n|- */
952 {"n", "unloadmod", party_unloadmod}, /* DDD */ /* n|- */
953 {"n", "binds", party_binds}, /* DDD */ /* m|- */
954 {"n", "timers", party_timers},
955 {"n", "netstats", party_netstats},
956 {"m", "+host", party_plus_host}, /* DDC */ /* t|m */
957 {"m", "-host", party_minus_host}, /* DDC */ /* -|- */
958 {"t", "chhandle", party_chhandle}, /* DDC */ /* t|- */
959 {"t", "chpass", party_chpass}, /* DDC */ /* t|- */
960 {0}
961 };
962
963 void core_party_init(void)
964 {
965 bind_add_list("party", core_party_binds);
966 }
967

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23