/[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.113 - (show annotations) (download) (as text)
Mon Feb 10 00:09:08 2003 UTC (16 years, 9 months ago) by wcc
Branch: MAIN
Changes since 1.112: +70 -59 lines
File MIME type: text/x-chdr
* Synch 1.6: transfer-cleanups, filesys-move, delbancrash, plsbot_cosmetic,
             stricthostfix, opreverselogic, dontdelfile

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