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

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

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


Revision 1.111 - (show annotations) (download) (as text)
Mon Feb 3 10:43:36 2003 UTC (16 years, 10 months ago) by wcc
Branch: MAIN
Changes since 1.110: +2 -9 lines
File MIME type: text/x-chdr
* Removed protection stuff, will be added back in a module later.
* Removed klined, ques5, sentinel, and notes2 as they won't be compatable and
  are not maintained by us.

1 /*
2 * cmds.c --
3 *
4 * commands from a user via dcc
5 * (split in 2, this portion contains no-irc commands)
6 */
7 /*
8 * Copyright (C) 1997 Robey Pointer
9 * Copyright (C) 1999, 2000, 2001, 2002, 2003 Eggheads Development Team
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 */
25
26 #ifndef lint
27 static const char rcsid[] = "$Id: cmds.c,v 1.110 2003/01/02 21:33:15 wcc Exp $";
28 #endif
29
30 #include "main.h"
31 #include "modules.h"
32 #include "logfile.h"
33 #include "misc.h"
34 #include "cmdt.h" /* cmd_t */
35 #include "core_binds.h" /* check_bind_act, check_bind_chpt,
36 check_bind_chjn, check_bind_chof */
37 #include "users.h" /* get_user_by_host, set_user,
38 USERENTRY_PASS */
39 #include "chanprog.h" /* masktype, tell_verbose_status,
40 tell_settings, maskname, logmodes
41 isowner, reload */
42 #include "dccutil.h" /* dprintf_eggdrop, not_away, set_away
43 tell_dcc, do_boot, chanout_but,
44 dcc_chatter, flush_lines */
45 #include "net.h" /* tell_netdebug, killsock */
46 #include "cmds.h" /* prototypes */
47
48 #include <ctype.h>
49 #include "traffic.h" /* egg_traffic_t */
50
51 extern struct chanset_t *chanset;
52 extern struct dcc_t *dcc;
53 extern user_t *userlist;
54 extern int dcc_total, remote_boots, backgrd, make_userfile,
55 do_restart, conmask, strict_host,
56 term_z, con_chan;
57 extern egg_traffic_t traffic;
58 extern char botnetnick[], ver[], network[],
59 owner[], spaces[], quit_msg[];
60 extern time_t now, online_since;
61 extern module_entry *module_list;
62
63 #ifndef MAKING_MODS
64 extern struct dcc_table DCC_CHAT, DCC_BOT, DCC_RELAY, DCC_FORK_BOT,
65 DCC_CHAT_PASS;
66 #endif /* MAKING_MODS */
67
68 static char *btos(unsigned long);
69
70
71 static void tell_who(user_t *u, int idx, int chan)
72 {
73 int i, k, ok = 0, atr = u ? u->flags : 0, len;
74 char s[1024]; /* temp fix - 1.4 has a better one */
75
76 if (!chan)
77 dprintf(idx, "Party line members: (* = owner, + = master, @ = op)\n");
78 else {
79 dprintf(idx,
80 "People on channel %s%d: (* = owner, + = master, @ = op)\n",
81 (chan < 100000) ? "" : "*", chan % 100000);
82 }
83 for (i = 0; i < dcc_total; i++)
84 if (dcc[i].type == &DCC_CHAT)
85 if (dcc[i].u.chat->channel == chan) {
86 spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
87 if (atr & USER_OWNER) {
88 sprintf(s, " [%.2lu] %c%s%s %s", dcc[i].sock,
89 (geticon(dcc[i].user) == '-' ? ' ' : geticon(dcc[i].user)),
90 dcc[i].nick, spaces, dcc[i].host);
91 } else {
92 sprintf(s, " %c%s%s %s",
93 (geticon(dcc[i].user) == '-' ? ' ' : geticon(dcc[i].user)),
94 dcc[i].nick, spaces, dcc[i].host);
95 }
96 spaces[len] = ' ';
97 if (atr & USER_MASTER) {
98 if (dcc[i].u.chat->con_flags)
99 sprintf(&s[strlen(s)], " (con:%s)",
100 masktype(dcc[i].u.chat->con_flags));
101 }
102 if (now - dcc[i].timeval > 300) {
103 unsigned long days, hrs, mins;
104
105 days = (now - dcc[i].timeval) / 86400;
106 hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
107 mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
108 if (days > 0)
109 sprintf(&s[strlen(s)], " (idle %lud%luh)", days, hrs);
110 else if (hrs > 0)
111 sprintf(&s[strlen(s)], " (idle %luh%lum)", hrs, mins);
112 else
113 sprintf(&s[strlen(s)], " (idle %lum)", mins);
114 }
115 dprintf(idx, "%s\n", s);
116 if (dcc[i].u.chat->away != NULL)
117 dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
118 }
119 ok = 0;
120 for (i = 0; i < dcc_total; i++) {
121 if ((dcc[i].type == &DCC_CHAT) && (dcc[i].u.chat->channel != chan)) {
122 if (!ok) {
123 ok = 1;
124 dprintf(idx, _("Other people on the bot:\n"));
125 }
126 spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
127 if (atr & USER_OWNER) {
128 sprintf(s, " [%.2lu] %c%s%s ",
129 dcc[i].sock,
130 (geticon(dcc[i].user) == '-' ? ' ' : geticon(dcc[i].user)),
131 dcc[i].nick, spaces);
132 } else {
133 sprintf(s, " %c%s%s ",
134 (geticon(dcc[i].user) == '-' ? ' ' : geticon(dcc[i].user)),
135 dcc[i].nick, spaces);
136 }
137 spaces[len] = ' ';
138 if (atr & USER_MASTER) {
139 if (dcc[i].u.chat->channel < 0)
140 strcat(s, "(-OFF-) ");
141 else if (!dcc[i].u.chat->channel)
142 strcat(s, "(party) ");
143 else
144 sprintf(&s[strlen(s)], "(%5d) ", dcc[i].u.chat->channel);
145 }
146 strcat(s, dcc[i].host);
147 if (atr & USER_MASTER) {
148 if (dcc[i].u.chat->con_flags)
149 sprintf(&s[strlen(s)], " (con:%s)",
150 masktype(dcc[i].u.chat->con_flags));
151 }
152 if (now - dcc[i].timeval > 300) {
153 k = (now - dcc[i].timeval) / 60;
154 if (k < 60)
155 sprintf(&s[strlen(s)], " (idle %dm)", k);
156 else
157 sprintf(&s[strlen(s)], " (idle %dh%dm)", k / 60, k % 60);
158 }
159 dprintf(idx, "%s\n", s);
160 if (dcc[i].u.chat->away != NULL)
161 dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
162 }
163 if ((atr & USER_MASTER) && dcc[i].type && (dcc[i].type->flags & DCT_SHOWWHO) &&
164 (dcc[i].type != &DCC_CHAT)) {
165 if (!ok) {
166 ok = 1;
167 dprintf(idx, _("Other people on the bot:\n"));
168 }
169 spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
170 if (atr & USER_OWNER) {
171 sprintf(s, " [%.2lu] %c%s%s (files) %s",
172 dcc[i].sock, dcc[i].status & STAT_CHAT ? '+' : ' ',
173 dcc[i].nick, spaces, dcc[i].host);
174 } else {
175 sprintf(s, " %c%s%s (files) %s",
176 dcc[i].status & STAT_CHAT ? '+' : ' ',
177 dcc[i].nick, spaces, dcc[i].host);
178 }
179 spaces[len] = ' ';
180 dprintf(idx, "%s\n", s);
181 }
182 }
183 }
184
185 static int cmd_me(user_t *u, int idx, char *par)
186 {
187 int i;
188
189 if (dcc[idx].u.chat->channel < 0) {
190 dprintf(idx, _("You have chat turned off.\n"));
191 return(0);
192 }
193 if (!par[0]) {
194 dprintf(idx, "Usage: me <action>\n");
195 return(0);
196 }
197 if (dcc[idx].u.chat->away != NULL)
198 not_away(idx);
199 for (i = 0; i < dcc_total; i++)
200 check_bind_act(dcc[idx].nick, dcc[idx].u.chat->channel, par);
201 return(0);
202 }
203
204 static int cmd_motd(user_t *u, int idx, char *par)
205 {
206 show_motd(idx);
207 return(1);
208 }
209
210 static int cmd_away(user_t *u, int idx, char *par)
211 {
212 if (strlen(par) > 60)
213 par[60] = 0;
214 set_away(idx, par);
215 return(1);
216 }
217
218 static int cmd_back(user_t *u, int idx, char *par)
219 {
220 not_away(idx);
221 return(1);
222 }
223
224 static int cmd_newpass(user_t *u, int idx, char *par)
225 {
226 char *new;
227
228 if (!par[0]) {
229 dprintf(idx, "Usage: newpass <newpassword>\n");
230 return(0);
231 }
232 new = newsplit(&par);
233 if (strlen(new) > 16)
234 new[16] = 0;
235 if (strlen(new) < 6) {
236 dprintf(idx, _("Please use at least 6 characters.\n"));
237 return(0);
238 }
239 set_user(&USERENTRY_PASS, u, new);
240 putlog(LOG_CMDS, "*", "#%s# newpass ...", dcc[idx].nick);
241 dprintf(idx, _("Changed password to '%s'\n"), new);
242 return(0);
243 }
244
245 static int cmd_rehelp(user_t *u, int idx, char *par)
246 {
247 dprintf(idx, _("Reload help cache...\n"));
248 reload_help_data();
249 return(1);
250 }
251
252 static int cmd_help(user_t *u, int idx, char *par)
253 {
254 struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
255
256 get_user_flagrec(u, &fr, dcc[idx].u.chat->con_chan);
257 if (par[0]) {
258 if (!strcmp(par, "all"))
259 tellallhelp(idx, "all", &fr);
260 else if (strchr(par, '*') || strchr(par, '?')) {
261 char *p = par;
262
263 /* Check if the search pattern only consists of '*' and/or '?'
264 * If it does, show help for "all" instead of listing all help
265 * entries.
266 */
267 for (p = par; *p && ((*p == '*') || (*p == '?')); p++);
268 if (*p)
269 tellwildhelp(idx, par, &fr);
270 else
271 tellallhelp(idx, "all", &fr);
272 } else
273 tellhelp(idx, par, &fr, 0);
274 } else {
275 if (glob_op(fr) || glob_botmast(fr) || chan_op(fr))
276 tellhelp(idx, "help", &fr, 0);
277 else
278 tellhelp(idx, "helpparty", &fr, 0);
279 }
280 return(1);
281 }
282
283 static int cmd_who(user_t *u, int idx, char *par)
284 {
285 putlog(LOG_CMDS, "*", "#%s# who", dcc[idx].nick);
286 if (dcc[idx].u.chat->channel < 0)
287 tell_who(u, idx, 0);
288 else
289 tell_who(u, idx, dcc[idx].u.chat->channel);
290
291 return(1);
292 }
293
294 static int cmd_whois(user_t *u, int idx, char *par)
295 {
296 if (!par[0]) {
297 dprintf(idx, "Usage: whois <handle>\n");
298 return(0);
299 }
300 tell_user_ident(idx, par, u ? (u->flags & USER_MASTER) : 0);
301 return(1);
302 }
303
304 static int cmd_match(user_t *u, int idx, char *par)
305 {
306 int start = 1, limit = 20;
307 char *s, *s1, *chname;
308
309 if (!par[0]) {
310 dprintf(idx, "Usage: match <nick/host> [[skip] count]\n");
311 return(0);
312 }
313 s = newsplit(&par);
314 if (strchr(CHANMETA, par[0]) != NULL)
315 chname = newsplit(&par);
316 else
317 chname = "";
318 if (atoi(par) > 0) {
319 s1 = newsplit(&par);
320 if (atoi(par) > 0) {
321 start = atoi(s1);
322 limit = atoi(par);
323 } else
324 limit = atoi(s1);
325 }
326 tell_users_match(idx, s, start, limit, u ? (u->flags & USER_MASTER) : 0,
327 chname);
328 return(1);
329 }
330
331 static int cmd_uptime(user_t *u, int idx, char *par)
332 {
333 char s[256];
334 unsigned long uptime, tmp, hr, min;
335
336 uptime = now - online_since;
337 s[0] = 0;
338 if (uptime > 86400) {
339 tmp = (uptime / 86400);
340 sprintf(s, "%lu day%s, ", tmp, (tmp == 1) ? "" : "s");
341 uptime -= (tmp * 86400);
342 }
343 hr = (uptime / 3600);
344 uptime -= (hr * 3600);
345 min = (uptime / 60);
346 sprintf(&s[strlen(s)], "%02lu:%02lu", hr, min);
347
348 dprintf(idx, "%s %s (%s)\n", _("Online for"), s, backgrd ?
349 _("background") : term_z ? _("terminal mode") : con_chan ?
350 _("status mode") : _("log dump mode"));
351 return(1);
352 }
353
354 static int cmd_status(user_t *u, int idx, char *par)
355 {
356 int atr = u ? u->flags : 0;
357
358 if (!strcasecmp(par, "all")) {
359 if (!(atr & USER_MASTER)) {
360 dprintf(idx, _("You do not have Bot Master privileges.\n"));
361 return(0);
362 }
363 tell_verbose_status(idx);
364 dprintf(idx, "\n");
365 tell_settings(idx);
366 do_module_report(idx, 1, NULL);
367 } else {
368 tell_verbose_status(idx);
369 do_module_report(idx, 0, NULL);
370 }
371 return(1);
372 }
373
374 static int cmd_dccstat(user_t *u, int idx, char *par)
375 {
376 tell_dcc(idx);
377 return(1);
378 }
379
380 static int cmd_boot(user_t *u, int idx, char *par)
381 {
382 int i, files = 0, ok = 0;
383 char *who;
384 user_t *u2;
385
386 if (!par[0]) {
387 dprintf(idx, "Usage: boot nick[@bot]\n");
388 return(0);
389 }
390 who = newsplit(&par);
391 for (i = 0; i < dcc_total; i++)
392 if (dcc[i].type && !strcasecmp(dcc[i].nick, who)
393 && !ok && (dcc[i].type->flags & DCT_CANBOOT)) {
394 u2 = get_user_by_handle(userlist, dcc[i].nick);
395 if (u2 && (u2->flags & USER_OWNER)
396 && strcasecmp(dcc[idx].nick, who)) {
397 dprintf(idx, _("You can't boot a bot owner.\n"));
398 return(0);
399 }
400 if (u2 && (u2->flags & USER_MASTER) && !(u && (u->flags & USER_MASTER))) {
401 dprintf(idx, _("You can't boot a bot master.\n"));
402 return(0);
403 }
404 files = (dcc[i].type->flags & DCT_FILES);
405 if (files)
406 dprintf(idx, _("Booted %s from the file area.\n"), dcc[i].nick);
407 else
408 dprintf(idx, _("Booted %s from the party line.\n"), dcc[i].nick);
409 do_boot(i, dcc[idx].nick, par);
410 ok = 1;
411 }
412 if (!ok) {
413 dprintf(idx, _("Who? No such person on the party line.\n"));
414 return(0);
415 }
416 return(1);
417 }
418
419 static int cmd_console(user_t *u, int idx, char *par)
420 {
421 char *nick, s[2], s1[512];
422 int dest = 0, i, ok = 0, pls, md;
423 struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
424 module_entry *me;
425
426 if (!par[0]) {
427 dprintf(idx, "Your console is %s: %s (%s).\n",
428 dcc[idx].u.chat->con_chan,
429 masktype(dcc[idx].u.chat->con_flags),
430 maskname(dcc[idx].u.chat->con_flags));
431 return(1);
432 }
433 get_user_flagrec(u, &fr, dcc[idx].u.chat->con_chan);
434 strcpy(s1, par);
435 nick = newsplit(&par);
436 /* Don't remove '+' as someone couldn't have '+' in CHANMETA cause
437 * he doesn't use IRCnet ++rtc.
438 */
439 if (nick[0] && !strchr(CHANMETA "+-*", nick[0]) && glob_master(fr)) {
440 for (i = 0; i < dcc_total; i++)
441 if (dcc[i].type && !strcasecmp(nick, dcc[i].nick) &&
442 (dcc[i].type == &DCC_CHAT) && (!ok)) {
443 ok = 1;
444 dest = i;
445 }
446 if (!ok) {
447 dprintf(idx, "No such user on the party line!\n");
448 return(0);
449 }
450 nick[0] = 0;
451 } else
452 dest = idx;
453 if (!nick[0])
454 nick = newsplit(&par);
455 /* Consider modeless channels, starting with '+' */
456 if ((nick [0] == '+' && findchan_by_dname(nick)) ||
457 (nick [0] != '+' && strchr(CHANMETA "*", nick[0]))) {
458 if (strcmp(nick, "*") && !findchan_by_dname(nick)) {
459 dprintf(idx, "Invalid console channel: %s.\n", nick);
460 return(0);
461 }
462 get_user_flagrec(u, &fr, nick);
463 if (!chan_op(fr) && !glob_op(fr)) {
464 dprintf(idx, "You don't have op or master access to channel %s.\n",
465 nick);
466 return(0);
467 }
468 strlcpy(dcc[dest].u.chat->con_chan, nick, 81);
469 nick[0] = 0;
470 if ((dest == idx) && !glob_master(fr) && !chan_master(fr))
471 /* Consoling to another channel for self */
472 dcc[dest].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS | LOG_WALL);
473 }
474 if (!nick[0])
475 nick = newsplit(&par);
476 pls = 1;
477 if (nick[0]) {
478 if ((nick[0] != '+') && (nick[0] != '-'))
479 dcc[dest].u.chat->con_flags = 0;
480 for (; *nick; nick++) {
481 if (*nick == '+')
482 pls = 1;
483 else if (*nick == '-')
484 pls = 0;
485 else {
486 s[0] = *nick;
487 s[1] = 0;
488 md = logmodes(s);
489 if ((dest == idx) && !glob_master(fr) && pls) {
490 if (chan_master(fr))
491 md &= ~(LOG_FILES | LOG_LEV1 | LOG_LEV2 | LOG_LEV3 |
492 LOG_LEV4 | LOG_LEV5 | LOG_LEV6 | LOG_LEV7 |
493 LOG_LEV8 | LOG_DEBUG);
494 else
495 md &= ~(LOG_MISC | LOG_CMDS | LOG_FILES | LOG_LEV1 |
496 LOG_LEV2 | LOG_LEV3 | LOG_LEV4 | LOG_LEV5 |
497 LOG_LEV6 | LOG_LEV7 | LOG_LEV8 | LOG_WALL |
498 LOG_DEBUG);
499 }
500 if (!glob_owner(fr) && pls)
501 md &= ~(LOG_RAW | LOG_SRVOUT | LOG_BOTNET | LOG_BOTSHARE);
502 if (!glob_botmast(fr) && pls)
503 md &= ~LOG_BOTS;
504 if (pls)
505 dcc[dest].u.chat->con_flags |= md;
506 else
507 dcc[dest].u.chat->con_flags &= ~md;
508 }
509 }
510 }
511 if (dest == idx) {
512 dprintf(idx, "Set your console to %s: %s (%s).\n",
513 dcc[idx].u.chat->con_chan,
514 masktype(dcc[idx].u.chat->con_flags),
515 maskname(dcc[idx].u.chat->con_flags));
516 } else {
517 dprintf(idx, "Set console of %s to %s: %s (%s).\n", dcc[dest].nick,
518 dcc[dest].u.chat->con_chan,
519 masktype(dcc[dest].u.chat->con_flags),
520 maskname(dcc[dest].u.chat->con_flags));
521 dprintf(dest, "%s set your console to %s: %s (%s).\n", dcc[idx].nick,
522 dcc[dest].u.chat->con_chan,
523 masktype(dcc[dest].u.chat->con_flags),
524 maskname(dcc[dest].u.chat->con_flags));
525 }
526 /* New style autosave -- drummer,07/25/1999*/
527 if ((me = module_find("console", 1, 1))) {
528 Function *func = me->funcs;
529 (func[CONSOLE_DOSTORE]) (dest);
530 }
531 return(1);
532 }
533
534 static int cmd_pls_bot(user_t *u, int idx, char *par)
535 {
536 char *handle, *addr, *p, *q, *host;
537 user_t *u1;
538 struct bot_addr *bi;
539 int addrlen;
540
541 if (!par[0])
542 dprintf(idx, "Usage: +bot <handle> <address[:telnet-port[/relay-port]]> [host]\n");
543 else {
544 handle = newsplit(&par);
545 addr = newsplit(&par);
546 if (strlen(handle) > HANDLEN)
547 handle[HANDLEN] = 0; /* max len = XX .. for the moment :) */
548 if (get_user_by_handle(userlist, handle))
549 dprintf(idx, _("Someone already exists by that name.\n"));
550 else if (strchr(BADHANDCHARS, handle[0]) != NULL)
551 dprintf(idx, _("You can't start a botnick with '%c'.\n"), handle[0]);
552 else {
553 if (strlen(addr) > 60)
554 addr[60] = 0;
555 userlist = adduser(userlist, handle, "none", "-", USER_BOT);
556 u1 = get_user_by_handle(userlist, handle);
557 bi = malloc(sizeof(struct bot_addr));
558
559 if (*addr == '[') {
560 addr++;
561 if ((q = strchr(addr, ']'))) {
562 addrlen = q - addr;
563 q++;
564 if (*q != ':')
565 q = 0;
566 } else
567 addrlen = strlen(addr);
568 } else {
569 if ((q = strchr(addr, ':')))
570 addrlen = q - addr;
571 else
572 addrlen = strlen(addr);
573 }
574 if (!q) {
575 bi->address = strdup(addr);
576 bi->telnet_port = 3333;
577 bi->relay_port = 3333;
578 } else {
579 bi->address = malloc(addrlen + 1);
580 strlcpy(bi->address, addr, addrlen + 1);
581 p = q + 1;
582 bi->telnet_port = atoi(p);
583 q = strchr(p, '/');
584 if (!q) {
585 bi->relay_port = bi->telnet_port;
586 } else {
587 bi->relay_port = atoi(q + 1);
588 }
589 }
590 set_user(&USERENTRY_BOTADDR, u1, bi);
591 dprintf(idx, _("Added bot '%s' with address '%s' and no password.\n"),
592 handle, addr);
593 host = newsplit(&par);
594 if (host[0]) {
595 addhost_by_handle(handle, host);
596 } else if (!add_bot_hostmask(idx, handle))
597 dprintf(idx, _("You'll want to add a hostmask if this bot will ever be on any channels that I'm on.\n"));
598 }
599 }
600 return(1);
601 }
602
603 static int cmd_chhandle(user_t *u, int idx, char *par)
604 {
605 char hand[HANDLEN + 1], newhand[HANDLEN + 1];
606 int i, atr = u ? u->flags : 0, atr2;
607 user_t *u2;
608
609 strlcpy(hand, newsplit(&par), sizeof hand);
610 strlcpy(newhand, newsplit(&par), sizeof newhand);
611
612 if (!hand[0] || !newhand[0]) {
613 dprintf(idx, "Usage: chhandle <oldhandle> <newhandle>\n");
614 return(0);
615 }
616 for (i = 0; i < strlen(newhand); i++)
617 if ((newhand[i] <= 32) || (newhand[i] >= 127) || (newhand[i] == '@'))
618 newhand[i] = '?';
619 if (strchr(BADHANDCHARS, newhand[0]) != NULL)
620 dprintf(idx, _("Bizarre quantum forces prevent nicknames from starting with %c.\n"),
621 newhand[0]);
622 else if (get_user_by_handle(userlist, newhand) &&
623 strcasecmp(hand, newhand))
624 dprintf(idx, _("Somebody is already using %s.\n"), newhand);
625 else {
626 u2 = get_user_by_handle(userlist, hand);
627 atr2 = u2 ? u2->flags : 0;
628 if ((atr & USER_BOTMAST) && !(atr & USER_MASTER) &&
629 !(atr2 & USER_BOT))
630 dprintf(idx, _("You can't change handles for non-bots.\n"));
631 else if ((bot_flags(u2) & BOT_SHARE) && !(atr & USER_OWNER))
632 dprintf(idx, _("You can't change a share bot's handle.\n"));
633 else if ((atr2 & USER_OWNER) && !(atr & USER_OWNER) &&
634 strcasecmp(dcc[idx].nick, hand))
635 dprintf(idx, _("You can't change a bot owner's handle.\n"));
636 else if (isowner(hand) && strcasecmp(dcc[idx].nick, hand))
637 dprintf(idx, _("You can't change a permanent bot owner's handle.\n"));
638 else if (!strcasecmp(newhand, botnetnick) && !(atr2 & USER_BOT))
639 dprintf(idx, _("Hey! That's MY name!\n"));
640 else if (change_handle(u2, newhand)) {
641 dprintf(idx, _("Changed.\n"));
642 } else
643 dprintf(idx, _("Failed.\n"));
644 }
645 return(1);
646 }
647
648 static int cmd_handle(user_t *u, int idx, char *par)
649 {
650 char oldhandle[HANDLEN + 1], newhandle[HANDLEN + 1];
651 int i;
652
653 strlcpy(newhandle, newsplit(&par), sizeof newhandle);
654
655 if (!newhandle[0]) {
656 dprintf(idx, "Usage: handle <new-handle>\n");
657 return(0);
658 }
659 for (i = 0; i < strlen(newhandle); i++)
660 if ((newhandle[i] <= 32) || (newhandle[i] >= 127) || (newhandle[i] == '@'))
661 newhandle[i] = '?';
662 if (strchr(BADHANDCHARS, newhandle[0]) != NULL) {
663 dprintf(idx, _("Bizarre quantum forces prevent handle from starting with '%c'\n"),
664 newhandle[0]);
665 } else if (get_user_by_handle(userlist, newhandle) &&
666 strcasecmp(dcc[idx].nick, newhandle)) {
667 dprintf(idx, _("Somebody is already using %s.\n"), newhandle);
668 } else if (!strcasecmp(newhandle, botnetnick)) {
669 dprintf(idx, _("Hey! That's MY name!\n"));
670 } else {
671 strlcpy(oldhandle, dcc[idx].nick, sizeof oldhandle);
672 if (change_handle(u, newhandle)) {
673 dprintf(idx, _("Okay, changed.\n"));
674 } else
675 dprintf(idx, _("Failed.\n"));
676 }
677 return(1);
678 }
679
680 static int cmd_chpass(user_t *u, int idx, char *par)
681 {
682 char *handle, *new;
683 int atr = u ? u->flags : 0, l;
684
685 if (!par[0])
686 dprintf(idx, "Usage: chpass <handle> [password]\n");
687 else {
688 handle = newsplit(&par);
689 u = get_user_by_handle(userlist, handle);
690 if (!u)
691 dprintf(idx, _("No such user.\n"));
692 else if ((atr & USER_BOTMAST) && !(atr & USER_MASTER) &&
693 !(u->flags & USER_BOT))
694 dprintf(idx, _("You can't change passwords for non-bots.\n"));
695 else if ((bot_flags(u) & BOT_SHARE) && !(atr & USER_OWNER))
696 dprintf(idx, _("You can't change a share bot's password.\n"));
697 else if ((u->flags & USER_OWNER) && !(atr & USER_OWNER) &&
698 strcasecmp(handle, dcc[idx].nick))
699 dprintf(idx, _("You can't change a bot owner's password.\n"));
700 else if (isowner(handle) && strcasecmp(dcc[idx].nick, handle))
701 dprintf(idx, _("You can't change a permanent bot owner's password.\n"));
702 else if (!par[0]) {
703 set_user(&USERENTRY_PASS, u, NULL);
704 dprintf(idx, _("Removed password.\n"));
705 } else {
706 l = strlen(new = newsplit(&par));
707 if (l > 16)
708 new[16] = 0;
709 if (l < 6)
710 dprintf(idx, _("Please use at least 6 characters.\n"));
711 else {
712 set_user(&USERENTRY_PASS, u, new);
713 dprintf(idx, _("Changed password.\n"));
714 }
715 }
716 }
717 return(0);
718 }
719
720 static int cmd_chaddr(user_t *u, int idx, char *par)
721 {
722 int telnet_port = 3333, relay_port = 3333;
723 char *handle, *addr, *p, *q;
724 struct bot_addr *bi;
725 user_t *u1;
726 int addrlen;
727
728 if (!par[0]) {
729 dprintf(idx, "Usage: chaddr <botname> <address[:telnet-port[/relay-port]]>\n");
730 return(0);
731 }
732 handle = newsplit(&par);
733 addr = newsplit(&par);
734 if (strlen(addr) > UHOSTMAX)
735 addr[UHOSTMAX] = 0;
736 u1 = get_user_by_handle(userlist, handle);
737 if (!u1 || !(u1->flags & USER_BOT)) {
738 dprintf(idx, _("This command is only useful for tandem bots.\n"));
739 return(0);
740 }
741 if ((bot_flags(u1) & BOT_SHARE) && (!u || !u->flags & USER_OWNER)) {
742 dprintf(idx, _("You can't change a share bot's address.\n"));
743 return(0);
744 }
745 dprintf(idx, _("Changed bot's address.\n"));
746
747 bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u1);
748 if (bi) {
749 telnet_port = bi->telnet_port;
750 relay_port = bi->relay_port;
751 }
752
753 bi = malloc(sizeof(struct bot_addr));
754
755 if (*addr == '[') {
756 addr++;
757 if ((q = strchr(addr, ']'))) {
758 addrlen = q - addr;
759 q++;
760 if (*q != ':')
761 q = 0;
762 } else
763 addrlen = strlen(addr);
764 } else {
765 if ((q = strchr(addr, ':')))
766 addrlen = q - addr;
767 else
768 addrlen = strlen(addr);
769 }
770 if (!q) {
771 bi->address = strdup(addr);
772 bi->telnet_port = telnet_port;
773 bi->relay_port = relay_port;
774 } else {
775 bi->address = malloc(addrlen + 1);
776 strlcpy(bi->address, addr, addrlen + 1);
777 p = q + 1;
778 bi->telnet_port = atoi(p);
779 q = strchr(p, '/');
780 if (!q) {
781 bi->relay_port = bi->telnet_port;
782 } else {
783 bi->relay_port = atoi(q + 1);
784 }
785 }
786 set_user(&USERENTRY_BOTADDR, u1, bi);
787 return(1);
788 }
789
790 static int cmd_comment(user_t *u, int idx, char *par)
791 {
792 char *handle;
793 user_t *u1;
794
795 if (!par[0]) {
796 dprintf(idx, "Usage: comment <handle> <newcomment>\n");
797 return(0);
798 }
799 handle = newsplit(&par);
800 u1 = get_user_by_handle(userlist, handle);
801 if (!u1) {
802 dprintf(idx, _("No such user!\n"));
803 return(0);
804 }
805 if ((u1->flags & USER_OWNER) && !(u && (u->flags & USER_OWNER)) &&
806 strcasecmp(handle, dcc[idx].nick)) {
807 dprintf(idx, _("Can't change comment on the bot owner.\n"));
808 return(0);
809 }
810 if (!strcasecmp(par, "none")) {
811 dprintf(idx, _("Okay, comment blanked.\n"));
812 set_user(&USERENTRY_COMMENT, u1, NULL);
813 return(0);
814 }
815 dprintf(idx, _("Changed comment.\n"));
816 set_user(&USERENTRY_COMMENT, u1, par);
817 return(1);
818 }
819
820 static int cmd_restart(user_t *u, int idx, char *par)
821 {
822 if (!backgrd) {
823 dprintf(idx, "%s\n", _("You cannot .restart a bot when running -n (due to tcl)."));
824 return(0);
825 }
826 dprintf(idx, _("Restarting.\n"));
827 if (make_userfile)
828 make_userfile = 0;
829 write_userfile(-1);
830 putlog(LOG_MISC, "*", "%s", _("Restarting ..."));
831 do_restart = idx;
832 return(1);
833 }
834
835 static int cmd_rehash(user_t *u, int idx, char *par)
836 {
837 dprintf(idx, "%s\n", _("Rehashing."));
838 if (make_userfile)
839 make_userfile = 0;
840 write_userfile(-1);
841 putlog(LOG_MISC, "*", "%s", _("Rehashing..."));
842 do_restart = -2;
843 return(1);
844 }
845
846 static int cmd_reload(user_t *u, int idx, char *par)
847 {
848 dprintf(idx, "%s\n", _("Reloading user file..."));
849 reload();
850 return(1);
851 }
852
853 void cmd_die(user_t *u, int idx, char *par)
854 {
855 char s1[1024], s2[1024];
856
857 if (par[0]) {
858 snprintf(s1, sizeof s1, "%s (%s: %s)", _("BOT SHUTDOWN"), dcc[idx].nick,
859 par);
860 snprintf(s2, sizeof s2, "%s %s!%s (%s)", _("DIE BY"), dcc[idx].nick,
861 dcc[idx].host, par);
862 strlcpy(quit_msg, par, 1024);
863 } else {
864 snprintf(s1, sizeof s1, "%s (%s %s)", _("BOT SHUTDOWN"), _("Authorized by"),
865 dcc[idx].nick);
866 snprintf(s2, sizeof s2, "%s %s!%s (%s)", _("DIE BY"), dcc[idx].nick,
867 dcc[idx].host, _("requested"));
868 strlcpy(quit_msg, dcc[idx].nick, 1024);
869 }
870 kill_bot(s1, s2);
871 }
872
873 static int cmd_simul(user_t *u, int idx, char *par)
874 {
875 char *nick;
876 int i, ok = 0;
877
878 nick = newsplit(&par);
879 if (!par[0]) {
880 dprintf(idx, "Usage: simul <hand> <text>\n");
881 return(0);
882 }
883 if (isowner(nick)) {
884 dprintf(idx, _("Unable to '.simul' permanent owners.\n"));
885 return(0);
886 }
887 for (i = 0; i < dcc_total; i++)
888 if (dcc[i].type && !strcasecmp(nick, dcc[i].nick) && !ok &&
889 (dcc[i].type->flags & DCT_SIMUL)) {
890 if (dcc[i].type && dcc[i].type->activity) {
891 dcc[i].type->activity(i, par, strlen(par));
892 ok = 1;
893 }
894 }
895 if (!ok)
896 dprintf(idx, _("No such user on the party line.\n"));
897 return(1);
898 }
899
900 static int cmd_save(user_t *u, int idx, char *par)
901 {
902 dprintf(idx, _("Saving user file...\n"));
903 write_userfile(-1);
904 return(1);
905 }
906
907 static int cmd_backup(user_t *u, int idx, char *par)
908 {
909 dprintf(idx, _("Backing up the channel & user files...\n"));
910 call_hook(HOOK_BACKUP);
911 return(1);
912 }
913
914 /* After messing with someone's user flags, make sure the dcc-chat flags
915 * are set correctly.
916 */
917 int check_dcc_attrs(user_t *u, int oatr)
918 {
919 int i, stat;
920
921 if (!u)
922 return 0;
923 /* Make sure default owners are +n */
924 if (isowner(u->handle)) {
925 u->flags = sanity_check(u->flags | USER_OWNER);
926 }
927 for (i = 0; i < dcc_total; i++) {
928 if (dcc[i].type && (dcc[i].type->flags & DCT_MASTER) &&
929 (!strcasecmp(u->handle, dcc[i].nick))) {
930 stat = dcc[i].status;
931 if ((oatr & USER_MASTER) && !(u->flags & USER_MASTER)) {
932 struct flag_record fr = {FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
933
934 dcc[i].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS | LOG_RAW |
935 LOG_FILES | LOG_LEV1 | LOG_LEV2 |
936 LOG_LEV3 | LOG_LEV4 | LOG_LEV5 |
937 LOG_LEV6 | LOG_LEV7 | LOG_LEV8 |
938 LOG_WALL | LOG_DEBUG);
939 get_user_flagrec(u, &fr, NULL);
940 if (!chan_master(fr))
941 dcc[i].u.chat->con_flags |= (LOG_MISC | LOG_CMDS);
942 dprintf(i, "*** POOF! ***\n");
943 dprintf(i, _("You are no longer a master on this bot.\n"));
944 }
945 if (!(oatr & USER_MASTER) && (u->flags & USER_MASTER)) {
946 dcc[i].u.chat->con_flags |= conmask;
947 dprintf(i, "*** POOF! ***\n");
948 dprintf(i, _("You are now a master on this bot.\n"));
949 }
950 if (!(oatr & USER_BOTMAST) && (u->flags & USER_BOTMAST)) {
951 dprintf(i, "### POOF! ###\n");
952 dprintf(i, _("You are now a botnet master on this bot.\n"));
953 }
954 if ((oatr & USER_BOTMAST) && !(u->flags & USER_BOTMAST)) {
955 dprintf(i, "### POOF! ###\n");
956 dprintf(i, _("You are no longer a botnet master on this bot.\n"));
957 }
958 if (!(oatr & USER_OWNER) && (u->flags & USER_OWNER)) {
959 dprintf(i, "@@@ POOF! @@@\n");
960 dprintf(i, _("You are now an OWNER of this bot.\n"));
961 }
962 if ((oatr & USER_OWNER) && !(u->flags & USER_OWNER)) {
963 dprintf(i, "@@@ POOF! @@@\n");
964 dprintf(i, _("You are no longer an owner of this bot.\n"));
965 }
966 if ((stat & STAT_PARTY) && (u->flags & USER_OP))
967 stat &= ~STAT_PARTY;
968 if (!(stat & STAT_PARTY) && !(u->flags & USER_OP) &&
969 !(u->flags & USER_MASTER))
970 stat |= STAT_PARTY;
971 if ((stat & STAT_CHAT) && !(u->flags & USER_PARTY) &&
972 !(u->flags & USER_MASTER))
973 stat &= ~STAT_CHAT;
974 if ((dcc[i].type->flags & DCT_FILES) && !(stat & STAT_CHAT) &&
975 ((u->flags & USER_MASTER) || (u->flags & USER_PARTY)))
976 stat |= STAT_CHAT;
977 dcc[i].status = stat;
978 /* Check if they no longer have access to wherever they are.
979 *
980 * NOTE: DON'T kick someone off the party line just cuz they lost +p
981 * (pinvite script removes +p after 5 mins automatically)
982 */
983 if ((dcc[i].type->flags & DCT_FILES) && !(u->flags & USER_XFER) &&
984 !(u->flags & USER_MASTER)) {
985 dprintf(i, "-+- POOF! -+-\n");
986 dprintf(i, _("You no longer have file area access.\n\n"));
987 putlog(LOG_MISC, "*", _("DCC user [%s]%s removed from file system"),
988 dcc[i].nick, dcc[i].host);
989 if (dcc[i].status & STAT_CHAT) {
990 struct chat_info *ci;
991
992 ci = dcc[i].u.file->chat;
993 free(dcc[i].u.file);
994 dcc[i].u.chat = ci;
995 dcc[i].status &= (~STAT_CHAT);
996 dcc[i].type = &DCC_CHAT;
997 if (dcc[i].u.chat->channel >= 0) {
998 chanout_but(-1, dcc[i].u.chat->channel,
999 "*** %s has returned.\n", dcc[i].nick);
1000 }
1001 } else {
1002 killsock(dcc[i].sock);
1003 lostdcc(i);
1004 }
1005 }
1006 }
1007 }
1008 return u->flags;
1009 }
1010
1011 int check_dcc_chanattrs(user_t *u, char *chname, int chflags,
1012 int ochatr)
1013 {
1014 int i, found = 0, atr = u ? u->flags : 0;
1015 struct chanset_t *chan;
1016
1017 if (!u)
1018 return 0;
1019 for (i = 0; i < dcc_total; i++) {
1020 if (dcc[i].type && (dcc[i].type->flags & DCT_MASTER) &&
1021 !strcasecmp(u->handle, dcc[i].nick)) {
1022 if ((ochatr & USER_MASTER) && !(chflags & USER_MASTER)) {
1023 if (!(atr & USER_MASTER))
1024 dcc[i].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS);
1025 dprintf(i, "*** POOF! ***\n");
1026 dprintf(i, _("You are no longer a master on %s.\n"), chname);
1027 }
1028 if (!(ochatr & USER_MASTER) && (chflags & USER_MASTER)) {
1029 dcc[i].u.chat->con_flags |= conmask;
1030 if (!(atr & USER_MASTER))
1031 dcc[i].u.chat->con_flags &=
1032 ~(LOG_LEV1 | LOG_LEV2 | LOG_LEV3 | LOG_LEV4 |
1033 LOG_LEV5 | LOG_LEV6 | LOG_LEV7 | LOG_LEV8 |
1034 LOG_RAW | LOG_DEBUG | LOG_WALL | LOG_FILES | LOG_SRVOUT);
1035 dprintf(i, "*** POOF! ***\n");
1036 dprintf(i, _("You are now a master on %s.\n"), chname);
1037 }
1038 if (!(ochatr & USER_OWNER) && (chflags & USER_OWNER)) {
1039 dprintf(i, "@@@ POOF! @@@\n");
1040 dprintf(i, _("You are now an OWNER of %s.\n"), chname);
1041 }
1042 if ((ochatr & USER_OWNER) && !(chflags & USER_OWNER)) {
1043 dprintf(i, "@@@ POOF! @@@\n");
1044 dprintf(i, _("You are no longer an owner of %s.\n"), chname);
1045 }
1046 if (((ochatr & (USER_OP | USER_MASTER | USER_OWNER)) &&
1047 (!(chflags & (USER_OP | USER_MASTER | USER_OWNER)))) ||
1048 ((chflags & (USER_OP | USER_MASTER | USER_OWNER)) &&
1049 (!(ochatr & (USER_OP | USER_MASTER | USER_OWNER))))) {
1050 struct flag_record fr = {FR_CHAN, 0, 0, 0, 0, 0};
1051
1052 for (chan = chanset; chan && !found; chan = chan->next) {
1053 get_user_flagrec(u, &fr, chan->dname);
1054 if (fr.chan & (USER_OP | USER_MASTER | USER_OWNER))
1055 found = 1;
1056 }
1057 if (!chan)
1058 chan = chanset;
1059 if (chan)
1060 strcpy(dcc[i].u.chat->con_chan, chan->dname);
1061 else
1062 strcpy(dcc[i].u.chat->con_chan, "*");
1063 }
1064 }
1065 }
1066 return chflags;
1067 }
1068
1069 static int cmd_chattr(user_t *u, int idx, char *par)
1070 {
1071 char *hand, *arg = NULL, *tmpchg = NULL, *chg = NULL, work[1024];
1072 struct chanset_t *chan = NULL;
1073 user_t *u2;
1074 struct flag_record pls = {0, 0, 0, 0, 0, 0},
1075 mns = {0, 0, 0, 0, 0, 0},
1076 user = {0, 0, 0, 0, 0, 0};
1077 module_entry *me;
1078 int fl = -1, of = 0, ocf = 0;
1079
1080 if (!par[0]) {
1081 dprintf(idx, "Usage: chattr <handle> [changes] [channel]\n");
1082 return(0);
1083 }
1084 hand = newsplit(&par);
1085 u2 = get_user_by_handle(userlist, hand);
1086 if (!u2) {
1087 dprintf(idx, _("No such user!\n"));
1088 return(0);
1089 }
1090
1091 /* Parse args */
1092 if (par[0]) {
1093 arg = newsplit(&par);
1094 if (par[0]) {
1095 /* .chattr <handle> <changes> <channel> */
1096 chg = arg;
1097 arg = newsplit(&par);
1098 chan = findchan_by_dname(arg);
1099 } else {
1100 chan = findchan_by_dname(arg);
1101 /* Consider modeless channels, starting with '+' */
1102 if (!(arg[0] == '+' && chan) &&
1103 !(arg[0] != '+' && strchr (CHANMETA, arg[0]))) {
1104 /* .chattr <handle> <changes> */
1105 chg = arg;
1106 chan = NULL; /* uh, !strchr (CHANMETA, channel[0]) && channel found?? */
1107 arg = NULL;
1108 }
1109 /* .chattr <handle> <channel>: nothing to do... */
1110 }
1111 }
1112 /* arg: pointer to channel name, NULL if none specified
1113 * chan: pointer to channel structure, NULL if none found or none specified
1114 * chg: pointer to changes, NULL if none specified
1115 */
1116 assert(!(!arg && chan));
1117 if (arg && !chan) {
1118 dprintf(idx, _("No channel record for %s.\n"), arg);
1119 return(0);
1120 }
1121 if (chg) {
1122 if (!arg && strpbrk(chg, "&|")) {
1123 /* .chattr <handle> *[&|]*: use console channel if found... */
1124 if (!strcmp ((arg = dcc[idx].u.chat->con_chan), "*"))
1125 arg = NULL;
1126 else
1127 chan = findchan_by_dname(arg);
1128 if (arg && !chan) {
1129 dprintf (idx, _("Invalid console channel %s.\n"), arg);
1130 return(0);
1131 }
1132 } else if (arg && !strpbrk(chg, "&|")) {
1133 tmpchg = malloc(strlen(chg) + 2);
1134 strcpy(tmpchg, "|");
1135 strcat(tmpchg, chg);
1136 chg = tmpchg;
1137 }
1138 }
1139 par = arg;
1140 user.match = FR_GLOBAL;
1141 if (chan)
1142 user.match |= FR_CHAN;
1143 get_user_flagrec(u, &user, chan ? chan->dname : 0);
1144 if (!chan && !glob_botmast(user)) {
1145 dprintf(idx, _("You do not have Bot Master privileges.\n"));
1146 if (tmpchg)
1147 free(tmpchg);
1148 return(0);
1149 }
1150 if (chan && !glob_master(user) && !chan_master(user)) {
1151 dprintf(idx,
1152 _("You do not have channel master privileges for channel %s.\n"),
1153 par);
1154 if (tmpchg)
1155 free(tmpchg);
1156 return(0);
1157 }
1158 user.match &= fl;
1159 if (chg) {
1160 pls.match = user.match;
1161 break_down_flags(chg, &pls, &mns);
1162 /* No-one can change these flags on-the-fly */
1163 pls.global &= ~(USER_BOT);
1164 mns.global &= ~(USER_BOT);
1165
1166 if (chan) {
1167 pls.chan &= ~(BOT_SHARE);
1168 mns.chan &= ~(BOT_SHARE);
1169 }
1170 if (!glob_owner(user)) {
1171 pls.global &= ~(USER_OWNER | USER_MASTER | USER_BOTMAST | USER_UNSHARED);
1172 mns.global &= ~(USER_OWNER | USER_MASTER | USER_BOTMAST | USER_UNSHARED);
1173
1174 if (chan) {
1175 pls.chan &= ~USER_OWNER;
1176 mns.chan &= ~USER_OWNER;
1177 }
1178 if (!glob_master(user)) {
1179 pls.global &= USER_PARTY | USER_XFER;
1180 mns.global &= USER_PARTY | USER_XFER;
1181
1182 if (!glob_botmast(user)) {
1183 pls.global = 0;
1184 mns.global = 0;
1185 }
1186 }
1187 }
1188 if (chan && !chan_owner(user) && !glob_owner(user)) {
1189 pls.chan &= ~USER_MASTER;
1190 mns.chan &= ~USER_MASTER;
1191 if (!chan_master(user) && !glob_master(user)) {
1192 pls.chan = 0;
1193 mns.chan = 0;
1194 }
1195 }
1196 get_user_flagrec(u2, &user, par);
1197 if (user.match & FR_GLOBAL) {
1198 of = user.global;
1199 user.global = sanity_check((user.global |pls.global) &~mns.global);
1200
1201 user.udef_global = (user.udef_global | pls.udef_global)
1202 & ~mns.udef_global;
1203 }
1204 if (chan) {
1205 ocf = user.chan;
1206 user.chan = chan_sanity_check((user.chan | pls.chan) & ~mns.chan,
1207 user.global);
1208
1209 user.udef_chan = (user.udef_chan | pls.udef_chan) & ~mns.udef_chan;
1210 }
1211 set_user_flagrec(u2, &user, par);
1212 }
1213 /* Get current flags and display them */
1214 if (user.match & FR_GLOBAL) {
1215 user.match = FR_GLOBAL;
1216 if (chg)
1217 check_dcc_attrs(u2, of);
1218 get_user_flagrec(u2, &user, NULL);
1219 build_flags(work, &user, NULL);
1220 if (work[0] != '-')
1221 dprintf(idx, _("Global flags for %1$s are now +%2$s.\n"), hand, work);
1222 else
1223 dprintf(idx, _("No global flags for %s.\n"), hand);
1224 }
1225 if (chan) {
1226 user.match = FR_CHAN;
1227 get_user_flagrec(u2, &user, par);
1228 user.chan &= ~BOT_SHARE;
1229 if (chg)
1230 check_dcc_chanattrs(u2, chan->dname, user.chan, ocf);
1231 build_flags(work, &user, NULL);
1232 if (work[0] != '-')
1233 dprintf(idx, _("Channel flags for %1$s on %2$s are now +%3$s.\n"), hand,
1234 chan->dname, work);
1235 else
1236 dprintf(idx, _("No flags for %1$s on %2$s.\n"), hand, chan->dname);
1237 }
1238 if (chg && (me = module_find("irc", 0, 0))) {
1239 Function *func = me->funcs;
1240
1241 (func[IRC_CHECK_THIS_USER]) (hand, 0, NULL);
1242 }
1243 if (tmpchg)
1244 free(tmpchg);
1245 return(1);
1246 }
1247
1248 static int cmd_botattr(user_t *u, int idx, char *par)
1249 {
1250 char *hand, *chg = NULL, *arg = NULL, *tmpchg = NULL, work[1024];
1251 struct chanset_t *chan = NULL;
1252 user_t *u2;
1253 struct flag_record pls = {0, 0, 0, 0, 0, 0},
1254 mns = {0, 0, 0, 0, 0, 0},
1255 user = {0, 0, 0, 0, 0, 0};
1256 int idx2;
1257
1258 if (!par[0]) {
1259 dprintf(idx, "Usage: botattr <handle> [changes] [channel]\n");
1260 return(0);
1261 }
1262 hand = newsplit(&par);
1263 u2 = get_user_by_handle(userlist, hand);
1264 if (!u2 || !(u2->flags & USER_BOT)) {
1265 dprintf(idx, _("No such bot!\n"));
1266 return(0);
1267 }
1268 for (idx2 = 0; idx2 < dcc_total; idx2++)
1269 if (dcc[idx2].type && !strcasecmp(dcc[idx2].nick, hand))
1270 break;
1271 if (idx2 != dcc_total) {
1272 dprintf(idx,
1273 _("You may not change the attributes of a directly linked bot.\n"));
1274 return(0);
1275 }
1276 /* Parse args */
1277 if (par[0]) {
1278 arg = newsplit(&par);
1279 if (par[0]) {
1280 /* .botattr <handle> <changes> <channel> */
1281 chg = arg;
1282 arg = newsplit(&par);
1283 chan = findchan_by_dname(arg);
1284 } else {
1285 chan = findchan_by_dname(arg);
1286 /* Consider modeless channels, starting with '+' */
1287 if (!(arg[0] == '+' && chan) &&
1288 !(arg[0] != '+' && strchr (CHANMETA, arg[0]))) {
1289 /* .botattr <handle> <changes> */
1290 chg = arg;
1291 chan = NULL; /* uh, !strchr (CHANMETA, channel[0]) && channel found?? */
1292 arg = NULL;
1293 }
1294 /* .botattr <handle> <channel>: nothing to do... */
1295 }
1296 }
1297 /* arg: pointer to channel name, NULL if none specified
1298 * chan: pointer to channel structure, NULL if none found or none specified
1299 * chg: pointer to changes, NULL if none specified
1300 */
1301 assert(!(!arg && chan));
1302 if (arg && !chan) {
1303 dprintf(idx, _("No channel record for %s.\n"), arg);
1304 return(0);
1305 }
1306 if (chg) {
1307 if (!arg && strpbrk(chg, "&|")) {
1308 /* botattr <handle> *[&|]*: use console channel if found... */
1309 if (!strcmp ((arg = dcc[idx].u.chat->con_chan), "*"))
1310 arg = NULL;
1311 else
1312 chan = findchan_by_dname(arg);
1313 if (arg && !chan) {
1314 dprintf (idx, _("Invalid console channel %s.\n"), arg);
1315 return(0);
1316 }
1317 } else if (arg && !strpbrk(chg, "&|")) {
1318 tmpchg = malloc(strlen(chg) + 2);
1319 strcpy(tmpchg, "|");
1320 strcat(tmpchg, chg);
1321 chg = tmpchg;
1322 }
1323 }
1324 par = arg;
1325
1326 user.match = FR_GLOBAL;
1327 get_user_flagrec(u, &user, chan ? chan->dname : 0);
1328 if (!glob_botmast(user)) {
1329 dprintf(idx, _("You do not have Bot Master privileges.\n"));
1330 if (tmpchg)
1331 free(tmpchg);
1332 return(0);
1333 }
1334 if (chg) {
1335 user.match = FR_BOT | (chan ? FR_CHAN : 0);
1336 pls.match = user.match;
1337 break_down_flags(chg, &pls, &mns);
1338 /* No-one can change these flags on-the-fly */
1339 pls.global &=~BOT_BOT;
1340 mns.global &=~BOT_BOT;
1341
1342 if (chan && glob_owner(user)) {
1343 pls.chan &= BOT_SHARE;
1344 mns.chan &= BOT_SHARE;
1345 } else {
1346 pls.chan = 0;
1347 mns.chan = 0;
1348 }
1349 if (!glob_owner(user)) {
1350 pls.bot &= ~(BOT_SHARE | BOT_GLOBAL);
1351 mns.bot &= ~(BOT_SHARE | BOT_GLOBAL);
1352 }
1353 user.match = FR_BOT | (chan ? FR_CHAN : 0);
1354 get_user_flagrec(u2, &user, par);
1355 user.bot = (user.bot | pls.bot) & ~mns.bot;
1356 if ((user.bot & BOT_SHARE) == BOT_SHARE)
1357 user.bot &= ~BOT_SHARE;
1358 if (chan)
1359 user.chan = (user.chan | pls.chan) & ~mns.chan;
1360 set_user_flagrec(u2, &user, par);
1361 }
1362 /* get current flags and display them */
1363 if (!chan || pls.bot || mns.bot) {
1364 user.match = FR_BOT;
1365 get_user_flagrec(u2, &user, NULL);
1366 build_flags(work, &user, NULL);
1367 if (work[0] != '-')
1368 dprintf(idx, _("Bot flags for %1$s are now +%2$s.\n"), hand, work);
1369 else
1370 dprintf(idx, _("No bot flags for %s.\n"), hand);
1371 }
1372 if (chan) {
1373 user.match = FR_CHAN;
1374 get_user_flagrec(u2, &user, par);
1375 user.chan &= BOT_SHARE;
1376 build_flags(work, &user, NULL);
1377 if (work[0] != '-')
1378 dprintf(idx, _("Bot flags for %1$s on %2$s are now +%3$s.\n"), hand,
1379 chan->dname, work);
1380 else
1381 dprintf(idx, _("No bot flags for %1$s on %2$s.\n"), hand, chan->dname);
1382 }
1383 if (tmpchg)
1384 free(tmpchg);
1385 return(1);
1386 }
1387
1388 static int cmd_su(user_t *u, int idx, char *par)
1389 {
1390 int atr = u ? u->flags : 0;
1391 struct flag_record fr = {FR_ANYWH | FR_CHAN | FR_GLOBAL, 0, 0, 0, 0, 0};
1392
1393 u = get_user_by_handle(userlist, par);
1394
1395 if (!par[0])
1396 dprintf(idx, "Usage: su <user>\n");
1397 else if (!u)
1398 dprintf(idx, _("No such user.\n"));
1399 else if (u->flags & USER_BOT)
1400 dprintf(idx, _("Can't su to a bot... then again, why would you wanna?\n"));
1401 else if (dcc[idx].u.chat->su_nick)
1402 dprintf(idx, _("You cannot currently double .su, try .su'ing directly\n"));
1403 else {
1404 get_user_flagrec(u, &fr, NULL);
1405 if (!glob_party(fr) && !(atr & USER_BOTMAST))
1406 dprintf(idx, _("No party line access permitted for %s.\n"), par);
1407 else {
1408 correct_handle(par);
1409 if (!(atr & USER_OWNER) ||
1410 ((u->flags & USER_OWNER) && (isowner(par)) &&
1411 !(isowner(dcc[idx].nick)))) {
1412 /* This check is only important for non-owners */
1413 if (u_pass_match(u, "-")) {
1414 dprintf(idx,
1415 _("No password set for user. You may not .su to them.\n"));
1416 return(0);
1417 }
1418 chanout_but(-1, dcc[idx].u.chat->channel,
1419 "*** %s left the party line.\n", dcc[idx].nick);
1420 /* Store the old nick in the away section, for weenies who can't get
1421 * their password right ;)
1422 */
1423 if (dcc[idx].u.chat->away != NULL)
1424 free(dcc[idx].u.chat->away);
1425 dcc[idx].u.chat->away = calloc(1, strlen(dcc[idx].nick) + 1);
1426 strcpy(dcc[idx].u.chat->away, dcc[idx].nick);
1427 dcc[idx].u.chat->su_nick = calloc(1, strlen(dcc[idx].nick) + 1);
1428 strcpy(dcc[idx].u.chat->su_nick, dcc[idx].nick);
1429 dcc[idx].user = u;
1430 strcpy(dcc[idx].nick, par);
1431 /* Display password prompt and turn off echo (send IAC WILL ECHO). */
1432 dprintf(idx, "Enter password for %s%s\n", par,
1433 (dcc[idx].status & STAT_TELNET) ? TLN_IAC_C TLN_WILL_C
1434 TLN_ECHO_C : "");
1435 dcc[idx].type = &DCC_CHAT_PASS;
1436 } else if (atr & USER_OWNER) {
1437 chanout_but(-1, dcc[idx].u.chat->channel,
1438 "*** %s left the party line.\n", dcc[idx].nick);
1439 dprintf(idx, _("Setting your username to %s.\n"), par);
1440 if (atr & USER_MASTER)
1441 dcc[idx].u.chat->con_flags = conmask;
1442 dcc[idx].u.chat->su_nick = calloc(1, strlen(dcc[idx].nick) + 1);
1443 strcpy(dcc[idx].u.chat->su_nick, dcc[idx].nick);
1444 dcc[idx].user = u;
1445 strcpy(dcc[idx].nick, par);
1446 dcc_chatter(idx);
1447 }
1448 }
1449 }
1450 return(1);
1451 }
1452
1453 static int cmd_fixcodes(user_t *u, int idx, char *par)
1454 {
1455 if (dcc[idx].status & STAT_ECHO) {
1456 dcc[idx].status |= STAT_TELNET;
1457 dcc[idx].status &= ~STAT_ECHO;
1458 dprintf(idx, _("Turned on telnet codes\n"));
1459 putlog(LOG_CMDS, "*", "#%s# fixcodes (telnet on)", dcc[idx].nick);
1460 return(0);
1461 }
1462 if (dcc[idx].status & STAT_TELNET) {
1463 dcc[idx].status |= STAT_ECHO;
1464 dcc[idx].status &= ~STAT_TELNET;
1465 dprintf(idx, _("Turned off telnet codes\n"));
1466 putlog(LOG_CMDS, "*", "#%s# fixcodes (telnet off)", dcc[idx].nick);
1467 return(0);
1468 }
1469 return(1);
1470 }
1471
1472 static int cmd_page(user_t *u, int idx, char *par)
1473 {
1474 int a;
1475 module_entry *me;
1476
1477 if (!par[0]) {
1478 if (dcc[idx].status & STAT_PAGE) {
1479 dprintf(idx, _("Currently paging outputs to %d lines.\n"),
1480 dcc[idx].u.chat->max_line);
1481 } else
1482 dprintf(idx, _("You don't have paging on.\n"));
1483 return(0);
1484 }
1485 a = atoi(par);
1486 if ((!a && !par[0]) || !strcasecmp(par, "off")) {
1487 dcc[idx].status &= ~STAT_PAGE;
1488 dcc[idx].u.chat->max_line = 0x7ffffff; /* flush_lines needs this */
1489 while (dcc[idx].u.chat->buffer)
1490 flush_lines(idx, dcc[idx].u.chat);
1491 dprintf(idx, _("Paging turned off.\n"));
1492 putlog(LOG_CMDS, "*", "#%s# page off", dcc[idx].nick);
1493 } else if (a > 0) {
1494 dprintf(idx, P_("Paging turned on, stopping every %d line.\n",
1495 "Paging turned on, stopping every %d lines.\n", a), a);
1496 dcc[idx].status |= STAT_PAGE;
1497 dcc[idx].u.chat->max_line = a;
1498 dcc[idx].u.chat->line_count = 0;
1499 dcc[idx].u.chat->current_lines = 0;
1500 putlog(LOG_CMDS, "*", "#%s# page %d", dcc[idx].nick, a);
1501 } else {
1502 dprintf(idx, "Usage: page <off or #>\n");
1503 return(0);
1504 }
1505 /* New style autosave here too -- rtc, 09/28/1999*/
1506 if ((me = module_find("console", 1, 1))) {
1507 Function *func = me->funcs;
1508 (func[CONSOLE_DOSTORE]) (idx);
1509 }
1510 return(1);
1511 }
1512
1513 static int cmd_module(user_t *u, int idx, char *par)
1514 {
1515 do_module_report(idx, 2, par[0] ? par : NULL);
1516 return(1);
1517 }
1518
1519 static int cmd_loadmod(user_t *u, int idx, char *par)
1520 {
1521 const char *p;
1522
1523 if (!isowner(dcc[idx].nick)) {
1524 dprintf(idx, _("What? You need .help\n"));
1525 return(0);
1526 }
1527 if (!par[0]) {
1528 dprintf(idx, "%s: loadmod <module>\n", _("Usage"));
1529 } else {
1530 p = module_load(par);
1531 if (p)
1532 dprintf(idx, "%s: %s %s\n", par, _("Error loading module:"), p);
1533 else {
1534 dprintf(idx, _("Module loaded: %-16s"), par);
1535 dprintf(idx, "\n");
1536 }
1537 }
1538 return(1);
1539 }
1540
1541 static int cmd_unloadmod(user_t *u, int idx, char *par)
1542 {
1543 char *p;
1544
1545 if (!isowner(dcc[idx].nick)) {
1546 dprintf(idx, _("What? You need .help\n"));
1547 return(0);
1548 }
1549 if (!par[0]) {
1550 dprintf(idx, "%s: unloadmod <module>\n", _("Usage"));
1551 } else {
1552 p = module_unload(par, dcc[idx].nick);
1553 if (p)
1554 dprintf(idx, "%s %s: %s\n", _("Error unloading module:"), par, p);
1555 else {
1556 dprintf(idx, "%s %s\n", _("Module unloaded:"), par);
1557 }
1558 }
1559 return(1);
1560 }
1561
1562 static int cmd_pls_ignore(user_t *u, int idx, char *par)
1563 {
1564 char *who;
1565 char s[UHOSTLEN];
1566 unsigned long int expire_time = 0;
1567
1568 if (!par[0]) {
1569 dprintf(idx,
1570 "Usage: +ignore <hostmask> [%%<XdXhXm>] [comment]\n");
1571 return(0);
1572 }
1573
1574 who = newsplit(&par);
1575 if (par[0] == '%') {
1576 char *p, *p_expire;
1577 unsigned long int expire_foo;
1578
1579 p = newsplit(&par);
1580 p_expire = p + 1;
1581 while (*(++p) != 0) {
1582 switch (tolower(*p)) {
1583 case 'd':
1584 *p = 0;
1585 expire_foo = strtol(p_expire, NULL, 10);
1586 if (expire_foo > 365)
1587 expire_foo = 365;
1588 expire_time += 86400 * expire_foo;
1589 p_expire = p + 1;
1590 break;
1591 case 'h':
1592 *p = 0;
1593 expire_foo = strtol(p_expire, NULL, 10);
1594 if (expire_foo > 8760)
1595 expire_foo = 8760;
1596 expire_time += 3600 * expire_foo;
1597 p_expire = p + 1;
1598 break;
1599 case 'm':
1600 *p = 0;
1601 expire_foo = strtol(p_expire, NULL, 10);
1602 if (expire_foo > 525600)
1603 expire_foo = 525600;
1604 expire_time += 60 * expire_foo;
1605 p_expire = p + 1;
1606 }
1607 }
1608 }
1609 if (!par[0])
1610 par = "requested";
1611 else if (strlen(par) > 65)
1612 par[65] = 0;
1613 if (strlen(who) > UHOSTMAX - 4)
1614 who[UHOSTMAX - 4] = 0;
1615
1616 /* Fix missing ! or @ BEFORE continuing */
1617 if (!strchr(who, '!')) {
1618 if (!strchr(who, '@'))
1619 simple_sprintf(s, "%s!*@*", who);
1620 else
1621 simple_sprintf(s, "*!%s", who);
1622 } else if (!strchr(who, '@'))
1623 simple_sprintf(s, "%s@*", who);
1624 else
1625 strcpy(s, who);
1626
1627 if (match_ignore(s))
1628 dprintf(idx, _("That already matches an existing ignore.\n"));
1629 else {
1630 dprintf(idx, "Now ignoring: %s (%s)\n", s, par);
1631 addignore(s, dcc[idx].nick, par, expire_time ? now + expire_time : 0L);
1632 }
1633 return(1);
1634 }
1635
1636 static int cmd_mns_ignore(user_t *u, int idx, char *par)
1637 {
1638 char buf[UHOSTLEN];
1639
1640 if (!par[0]) {
1641 dprintf(idx, "Usage: -ignore <hostmask | ignore #>\n");
1642 return(0);
1643 }
1644 strlcpy(buf, par, sizeof buf);
1645 if (delignore(buf)) {
1646 dprintf(idx, _("No longer ignoring: %s\n"), buf);
1647 } else
1648 dprintf(idx, _("That ignore cannot be found.\n"));
1649 return(1);
1650 }
1651
1652 static int cmd_ignores(user_t *u, int idx, char *par)
1653 {
1654 tell_ignores(idx, par);
1655 return(1);
1656 }
1657
1658 static int cmd_pls_user(user_t *u, int idx, char *par)
1659 {
1660 char *handle, *host;
1661
1662 if (!par[0]) {
1663 dprintf(idx, "Usage: +user <handle> [hostmask]\n");
1664 return(0);
1665 }
1666 handle = newsplit(&par);
1667 host = newsplit(&par);
1668 if (strlen(handle) > HANDLEN)
1669 handle[HANDLEN] = 0;
1670 if (get_user_by_handle(userlist, handle))
1671 dprintf(idx, _("Someone already exists by that name.\n"));
1672 else if (strchr(BADNICKCHARS, handle[0]) != NULL)
1673 dprintf(idx, _("You can't start a nick with '%c'.\n"), handle[0]);
1674 else if (!strcasecmp(handle, botnetnick))
1675 dprintf(idx, _("Hey! That's MY name!\n"));
1676 else {
1677 userlist = adduser(userlist, handle, host, "-", 0);
1678 dprintf(idx, _("Added %1$s (%2$s) with no password and no flags.\n"),
1679 handle, host[0] ? host : _("no host"));
1680 }
1681 return(1);
1682 }
1683
1684 static int cmd_mns_user(user_t *u, int idx, char *par)
1685 {
1686 int idx2;
1687 char *handle;
1688 user_t *u2;
1689 module_entry *me;
1690
1691 if (!par[0]) {
1692 dprintf(idx, "Usage: -user <hand>\n");
1693 return(0);
1694 }
1695 handle = newsplit(&par);
1696 u2 = get_user_by_handle(userlist, handle);
1697 if (!u2 || !u) {
1698 dprintf(idx, _("No such user!\n"));
1699 return(0);
1700 }
1701 if (isowner(u2->handle)) {
1702 dprintf(idx, _("You can't remove the permanent bot owner!\n"));
1703 return(0);
1704 }
1705 if ((u2->flags & USER_OWNER) && !(u->flags & USER_OWNER)) {
1706 dprintf(idx, _("You can't remove a bot owner!\n"));
1707 return(0);
1708 }
1709 if (u2->flags & USER_BOT) {
1710 if ((bot_flags(u2) & BOT_SHARE) && !(u->flags & USER_OWNER)) {
1711 dprintf(idx, _("You can't remove share bots.\n"));
1712 return(0);
1713 }
1714 for (idx2 = 0; idx2 < dcc_total; idx2++)
1715 if (dcc[idx2].type && !strcasecmp(dcc[idx2].nick, handle))
1716 break;
1717 if (idx2 != dcc_total) {
1718 dprintf(idx, _("You can't remove a directly linked bot.\n"));
1719 return(0);
1720 }
1721 }
1722 if ((u->flags & USER_BOTMAST) && !(u->flags & USER_MASTER) &&
1723 !(u2->flags & USER_BOT)) {
1724 dprintf(idx, _("You can't remove users who aren't bots!\n"));
1725 return(0);
1726 }
1727 if ((me = module_find("irc", 0, 0))) {
1728 Function *func = me->funcs;
1729
1730 (func[IRC_CHECK_THIS_USER]) (handle, 1, NULL);
1731 }
1732 if (deluser(handle)) {
1733 dprintf(idx, _("Deleted %s.\n"), handle);
1734 } else
1735 dprintf(idx, _("Failed.\n"));
1736 return(1);
1737 }
1738
1739 static int cmd_pls_host(user_t *u, int idx, char *par)
1740 {
1741 char *handle, *host;
1742 user_t *u2;
1743 struct list_type *q;
1744 struct flag_record fr = {FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
1745 struct flag_record fr2 = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0},
1746 fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
1747
1748 if (!par[0]) {
1749 dprintf(idx, "Usage: +host [handle] <newhostmask>\n");
1750 return(0);
1751 }
1752
1753 handle = newsplit(&par);
1754
1755 if (par[0]) {
1756 host = newsplit(&par);
1757 u2 = get_user_by_handle(userlist, handle);
1758 } else {
1759 host = handle;
1760 handle = dcc[idx].nick;
1761 u2 = u;
1762 }
1763 if (!u2 || !u) {
1764 dprintf(idx, _("No such user.\n"));
1765 return(0);
1766 }
1767 get_user_flagrec(u, &fr, NULL);
1768 if (strcasecmp(handle, dcc[idx].nick)) {
1769 get_user_flagrec(u2, &fr2, NULL);
1770 if (!glob_master(fr) && !glob_bot(fr2) && !chan_master(fr)) {
1771 dprintf(idx, _("You can't add hostmasks to non-bots.\n"));
1772 return(0);
1773 }
1774 if (!glob_owner(fr) && glob_bot(fr2) && (bot_flags(u2) & BOT_SHARE)) {
1775 dprintf(idx, _("You can't add hostmasks to share bots.\n"));
1776 return(0);
1777 }
1778 if ((glob_owner(fr2) || glob_master(fr2)) && !glob_owner(fr)) {
1779 dprintf(idx, _("You can't add hostmasks to the bot owner/master.\n"));
1780 return(0);
1781 }
1782 if ((chan_owner(fr2) || chan_master(fr2)) && !glob_master(fr) &&
1783 !glob_owner(fr) && !chan_owner(fr)) {
1784 dprintf(idx, "You can't add hostmasks to a channel owner/master.\n");
1785 return(0);
1786 }
1787 if (!glob_botmast(fr) && !glob_master(fr) && !chan_master(fr)) {
1788 dprintf(idx, "Permission denied.\n");
1789 return(0);
1790 }
1791 }
1792 if (!glob_botmast(fr) && !chan_master(fr) && get_user_by_host(host)) {
1793 dprintf(idx, "You cannot add a host matching another user!\n");
1794 return(0);
1795 }
1796 for (q = get_user(&USERENTRY_HOSTS, u); q; q = q->next)
1797 if (!strcasecmp(q->extra, host)) {
1798 dprintf(idx, _("That hostmask is already there.\n"));
1799 return(0);
1800 }
1801 addhost_by_handle(handle, host);
1802 dprintf(idx, "Added '%s' to %s.\n", host, handle);
1803 if ((me = module_find("irc", 0, 0))) {
1804 Function *func = me->funcs;
1805
1806 (func[IRC_CHECK_THIS_USER]) (handle, 0, NULL);
1807 }
1808 return(1);
1809 }
1810
1811 static int cmd_mns_host(user_t *u, int idx, char *par)
1812 {
1813 char *handle, *host;
1814 user_t *u2;
1815 struct flag_record fr2 = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0},
1816 fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
1817 module_entry *me;
1818
1819 if (!par[0]) {
1820 dprintf(idx, "%s: -host [%s] <%s>\n", _("Usage"), _("handle"),
1821 _("hostmask"));
1822 return(0);
1823 }
1824 handle = newsplit(&par);
1825 if (par[0]) {
1826 host = newsplit(&par);
1827 u2 = get_user_by_handle(userlist, handle);
1828 } else {
1829 host = handle;
1830 handle = dcc[idx].nick;
1831 u2 = u;
1832 }
1833 if (!u2 || !u) {
1834 dprintf(idx, "%s\n", _("No such user."));
1835 return(0);
1836 }
1837
1838 get_user_flagrec(u, &fr, NULL);
1839 get_user_flagrec(u2, &fr2, NULL);
1840 if (strcasecmp(handle, dcc[idx].nick)) {
1841 if (!glob_master(fr) && !glob_bot(fr2) && !chan_master(fr)) {
1842 dprintf(idx, _("You can't remove hostmasks from non-bots.\n"));
1843 return(0);
1844 }
1845 if (glob_bot(fr2) && (bot_flags(u2) & BOT_SHARE) && !glob_owner(fr)) {
1846 dprintf(idx, _("You can't remove hostmasks from a share bot.\n"));
1847 return(0);
1848 }
1849 if ((glob_owner(fr2) || glob_master(fr2)) && !glob_owner(fr)) {
1850 dprintf(idx, _("You can't remove hostmasks from a bot owner/master.\n"));
1851 return(0);
1852 }
1853 if ((chan_owner(fr2) || chan_master(fr2)) && !glob_master(fr) &&
1854 !glob_owner(fr) && !chan_owner(fr)) {
1855 dprintf(idx, "You can't remove hostmasks from a channel owner/master.\n");
1856 return(0);
1857 }
1858 if (!glob_botmast(fr) && !glob_master(fr) && !chan_master(fr)) {
1859 dprintf(idx, _("Permission denied.\n"));
1860 return(0);
1861 }
1862 }
1863 if (delhost_by_handle(handle, host)) {
1864 dprintf(idx, _("Removed '%1$s' from %2$s.\n"), host, handle);
1865 if ((me = module_find("irc", 0, 0))) {
1866 Function *func = me->funcs;
1867
1868 (func[IRC_CHECK_THIS_USER]) (handle, 2, host);
1869 }
1870 } else
1871 dprintf(idx, _("Failed.\n"));
1872 return(1);
1873 }
1874
1875 static int cmd_modules(user_t *u, int idx, char *par)
1876 {
1877 module_entry *me;
1878
1879 dprintf(idx, _("Modules loaded:\n"));
1880 for (me = module_list; me; me = me->next)
1881 dprintf(idx, " Module: %s (v%d.%d)\n", me->name, me->major, me->minor);
1882 dprintf(idx, _("End of modules list.\n"));
1883 return(1);
1884 }
1885
1886 static int cmd_traffic(user_t *u, int idx, char *par)
1887 {
1888 unsigned long itmp, itmp2;
1889
1890 dprintf(idx, "Traffic since last restart\n");
1891 dprintf(idx, "==========================\n");
1892 if (traffic.out_total.irc > 0 || traffic.in_total.irc > 0 || traffic.out_today.irc > 0 ||
1893 traffic.in_today.irc > 0) {
1894 dprintf(idx, "IRC:\n");
1895 dprintf(idx, " out: %s", btos(traffic.out_total.irc + traffic.out_today.irc));
1896 dprintf(idx, " (%s today)\n", btos(traffic.out_today.irc));
1897 dprintf(idx, " in: %s", btos(traffic.in_total.irc + traffic.in_today.irc));
1898 dprintf(idx, " (%s today)\n", btos(traffic.in_today.irc));
1899 }
1900 if (traffic.out_total.dcc > 0 || traffic.in_total.dcc > 0 || traffic.out_today.dcc > 0 ||
1901 traffic.in_today.dcc > 0) {
1902 dprintf(idx, "Partyline:\n");
1903 itmp = traffic.out_total.dcc + traffic.out_today.dcc;
1904 itmp2 = traffic.out_today.dcc;
1905 dprintf(idx, " out: %s", btos(itmp));
1906 dprintf(idx, " (%s today)\n", btos(itmp2));
1907 dprintf(idx, " in: %s", btos(traffic.in_total.dcc + traffic.in_today.dcc));
1908 dprintf(idx, " (%s today)\n", btos(traffic.in_today.dcc));
1909 }
1910 if (traffic.out_total.trans > 0 || traffic.in_total.trans > 0 || traffic.out_today.trans > 0 ||
1911 traffic.in_today.trans > 0) {
1912 dprintf(idx, "Transfer.mod:\n");
1913 dprintf(idx, " out: %s", btos(traffic.out_total.trans + traffic.out_today.trans));
1914 dprintf(idx, " (%s today)\n", btos(traffic.out_today.trans));
1915 dprintf(idx, " in: %s", btos(traffic.in_total.trans + traffic.in_today.trans));
1916 dprintf(idx, " (%s today)\n", btos(traffic.in_today.trans));
1917 }
1918 if (traffic.out_total.unknown > 0 || traffic.out_today.unknown > 0) {
1919 dprintf(idx, "Misc:\n");
1920 dprintf(idx, " out: %s", btos(traffic.out_total.unknown + traffic.out_today.unknown));
1921 dprintf(idx, " (%s today)\n", btos(traffic.out_today.unknown));
1922 dprintf(idx, " in: %s", btos(traffic.in_total.unknown + traffic.in_today.unknown));
1923 dprintf(idx, " (%s today)\n", btos(traffic.in_today.unknown));
1924 }
1925 dprintf(idx, "---\n");
1926 dprintf(idx, "Total:\n");
1927 itmp = traffic.out_total.irc + traffic.out_total.bn + traffic.out_total.dcc + traffic.out_total.trans
1928 + traffic.out_total.unknown + traffic.out_today.irc
1929 + traffic.out_today.dcc + traffic.out_today.trans + traffic.out_today.unknown;
1930 itmp2 = traffic.out_today.irc + traffic.out_today.dcc
1931 + traffic.out_today.trans + traffic.out_today.unknown;
1932 dprintf(idx, " out: %s", btos(itmp));
1933 dprintf(idx, " (%s today)\n", btos(itmp2));
1934 dprintf(idx, " in: %s", btos(traffic.in_total.irc + traffic.in_total.dcc
1935 + traffic.in_total.trans + traffic.in_total.unknown + traffic.in_today.irc
1936 + traffic.in_today.dcc + traffic.in_today.trans
1937 + traffic.in_today.unknown));
1938 dprintf(idx, " (%s today)\n", btos(traffic.in_today.irc
1939 + traffic.in_today.dcc + traffic.in_today.trans
1940 + traffic.in_today.unknown));
1941 return(1);
1942 }
1943
1944 static char traffictxt[20];
1945 static char *btos(unsigned long bytes)
1946 {
1947 char unit[10];
1948 float xbytes;
1949
1950 sprintf(unit, "Bytes");
1951 xbytes = bytes;
1952 if (xbytes > 1024.0) {
1953 sprintf(unit, "KBytes");
1954 xbytes = xbytes / 1024.0;
1955 }
1956 if (xbytes > 1024.0) {
1957 sprintf(unit, "MBytes");
1958 xbytes = xbytes / 1024.0;
1959 }
1960 if (xbytes > 1024.0) {
1961 sprintf(unit, "GBytes");
1962 xbytes = xbytes / 1024.0;
1963 }
1964 if (xbytes > 1024.0) {
1965 sprintf(unit, "TBytes");
1966 xbytes = xbytes / 1024.0;
1967 }
1968 if (bytes > 1024)
1969 sprintf(traffictxt, "%.2f %s", xbytes, unit);
1970 else
1971 sprintf(traffictxt, "%lu Bytes", bytes);
1972 return traffictxt;
1973 }
1974
1975 static int cmd_whoami(user_t *u, int idx, char *par)
1976 {
1977 dprintf(idx, _("You are %s@%s.\n"), dcc[idx].nick, botnetnick);
1978 return(1);
1979 }
1980
1981 static int cmd_quit(user_t *u, int idx, char *text)
1982 {
1983 dprintf(idx, _("*** Ja mata!\n"));
1984 flush_lines(idx, dcc[idx].u.chat);
1985 putlog(LOG_MISC, "*", _("DCC connection closed (%s!%s)"), dcc[idx].nick,
1986 dcc[idx].host);
1987 if (dcc[idx].u.chat->channel >= 0) {
1988 chanout_but(-1, dcc[idx].u.chat->channel, "*** %s left the party line%s%s\n", dcc[idx].nick, text[0] ? ": " : ".", text);
1989 }
1990
1991 if (dcc[idx].u.chat->su_nick) {
1992 dcc[idx].user = get_user_by_handle(userlist, dcc[idx].u.chat->su_nick);
1993 dcc[idx].type = &DCC_CHAT;
1994 dprintf(idx, _("Returning to real nick %s!\n"), dcc[idx].u.chat->su_nick);
1995 free_null(dcc[idx].u.chat->su_nick);
1996 dcc_chatter(idx);
1997 } else if ((dcc[idx].sock != STDOUT) || backgrd) {
1998 killsock(dcc[idx].sock);
1999 lostdcc(idx);
2000 } else {
2001 dprintf(DP_STDOUT, "\n### SIMULATION RESET\n\n");
2002 dcc_chatter(idx);
2003 }
2004 return(1);
2005 }
2006
2007
2008
2009 /* DCC CHAT COMMANDS
2010 */
2011 /* Function call should be:
2012 * int cmd_whatever(idx,"parameters");
2013 * As with msg commands, function is responsible for any logging.
2014 */
2015 cmd_t C_dcc[] =
2016 {
2017 {"+bot", "t", (Function) cmd_pls_bot, NULL},
2018 {"+host", "tm|m", (Function) cmd_pls_host, NULL},
2019 {"+ignore", "m", (Function) cmd_pls_ignore, NULL},
2020 {"+user", "m", (Function) cmd_pls_user, NULL},
2021 {"-bot", "t", (Function) cmd_mns_user, NULL},
2022 {"-host", "", (Function) cmd_mns_host, NULL},
2023 {"-ignore", "m", (Function) cmd_mns_ignore, NULL},
2024 {"-user", "m", (Function) cmd_mns_user, NULL},
2025 {"away", "", (Function) cmd_away