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

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

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


Revision 1.69 - (hide annotations) (download) (as text)
Sun Oct 7 04:02:54 2001 UTC (18 years, 2 months ago) by stdarg
Branch: MAIN
Changes since 1.68: +2 -2 lines
File MIME type: text/x-chdr
Got rid of bind tables in the exported irc function table. They're not used anywhere in the core or other normal modules. Other people should use find_bind_table(), not #define's.
Got rid of H_* bind tables in irc module. All are BT_* now.
Integrated the new bind tables in with the normal bind/unbind command.
Made tcl callbacks work with the normal data types (string, int, user (handle)).
Got rid of old bind tables in server.mod
Made ctcp.mod use the new bind tables.
Wrote down most of the stuff I did so that ITE could see a detailed report :) hehe (although I have a feeling I've left something out)

1 guppy 1.49 /*
2 segfault 1.1 * cmds.c -- handles:
3 fabian 1.15 * commands from a user via dcc
4     * (split in 2, this portion contains no-irc commands)
5 guppy 1.49 *
6 stdarg 1.69 * $Id: cmds.c,v 1.68 2001/10/05 04:28:48 guppy Exp $
7 segfault 1.1 */
8 guppy 1.49 /*
9     * Copyright (C) 1997 Robey Pointer
10     * Copyright (C) 1999, 2000, 2001 Eggheads Development Team
11     *
12 fabian 1.15 * This program is free software; you can redistribute it and/or
13     * modify it under the terms of the GNU General Public License
14     * as published by the Free Software Foundation; either version 2
15     * of the License, or (at your option) any later version.
16 guppy 1.49 *
17 fabian 1.15 * This program is distributed in the hope that it will be useful,
18     * but WITHOUT ANY WARRANTY; without even the implied warranty of
19     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20     * GNU General Public License for more details.
21 guppy 1.49 *
22 fabian 1.15 * You should have received a copy of the GNU General Public License
23     * along with this program; if not, write to the Free Software
24     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 segfault 1.1 */
26    
27     #include "main.h"
28     #include "tandem.h"
29     #include "modules.h"
30     #include <ctype.h>
31    
32 fabian 1.22 extern struct chanset_t *chanset;
33     extern struct dcc_t *dcc;
34     extern struct userrec *userlist;
35     extern tcl_timer_t *timer, *utimer;
36     extern int dcc_total, remote_boots, backgrd, make_userfile,
37 fabian 1.40 do_restart, conmask, require_p, must_be_owner,
38 guppy 1.64 strict_host, term_z, con_chan;
39 fabian 1.25 extern unsigned long otraffic_irc, otraffic_irc_today,
40 fabian 1.22 itraffic_irc, itraffic_irc_today,
41     otraffic_bn, otraffic_bn_today,
42     itraffic_bn, itraffic_bn_today,
43     otraffic_dcc, otraffic_dcc_today,
44     itraffic_dcc, itraffic_dcc_today,
45     otraffic_trans, otraffic_trans_today,
46     itraffic_trans, itraffic_trans_today,
47     otraffic_unknown, otraffic_unknown_today,
48     itraffic_unknown, itraffic_unknown_today;
49     extern Tcl_Interp *interp;
50     extern char botnetnick[], origbotname[], ver[], network[],
51 guppy 1.62 owner[], spaces[], quit_msg[];
52 fabian 1.22 extern time_t now, online_since;
53    
54    
55 guppy 1.46 static char *btos(unsigned long);
56 fabian 1.22
57 segfault 1.1
58 fabian 1.22 /* Add hostmask to a bot's record if possible.
59     */
60 segfault 1.1 static int add_bot_hostmask(int idx, char *nick)
61     {
62     struct chanset_t *chan;
63    
64 fabian 1.36 for (chan = chanset; chan; chan = chan->next)
65 segfault 1.1 if (channel_active(chan)) {
66 fabian 1.36 memberlist *m = ismember(chan, nick);
67    
68 segfault 1.1 if (m) {
69 fabian 1.40 char s[UHOSTLEN];
70 segfault 1.1 struct userrec *u;
71    
72 fabian 1.36 egg_snprintf(s, sizeof s, "%s!%s", m->nick, m->userhost);
73 segfault 1.1 u = get_user_by_host(s);
74     if (u) {
75 ite 1.66 dprintf(idx, _("(Can't add hostmask for %1$s because it matches %2$s)\n"),
76 segfault 1.1 nick, u->handle);
77     return 0;
78     }
79 fabian 1.40 if (strchr("~^+=-", m->userhost[0]))
80     egg_snprintf(s, sizeof s, "*!%s%s", strict_host ? "?" : "", m->userhost+1);
81     else
82     egg_snprintf(s, sizeof s, "*!%s", m->userhost);
83 ite 1.66 dprintf(idx, _("(Added hostmask for %1$s from %2$s)\n"), nick, chan->dname);
84 fabian 1.40 addhost_by_handle(nick, s);
85 segfault 1.1 return 1;
86     }
87     }
88     return 0;
89     }
90    
91     static void tell_who(struct userrec *u, int idx, int chan)
92     {
93     int i, k, ok = 0, atr = u ? u->flags : 0, len;
94     char s[1024]; /* temp fix - 1.4 has a better one */
95    
96 guppy 1.45 if (!chan)
97 segfault 1.1 dprintf(idx, "Party line members: (* = owner, + = master, @ = op)\n");
98     else {
99     simple_sprintf(s, "assoc %d", chan);
100     if ((Tcl_Eval(interp, s) != TCL_OK) || !interp->result[0])
101     dprintf(idx,
102     "People on channel %s%d: (* = owner, + = master, @ = op)\n",
103     (chan < 100000) ? "" : "*", chan % 100000);
104     else
105     dprintf(idx,
106     "People on channel '%s' (%s%d): (* = owner, + = master, @ = op)\n",
107     interp->result, (chan < 100000) ? "" : "*", chan % 100000);
108     }
109     for (i = 0; i < dcc_total; i++)
110     if (dcc[i].type == &DCC_CHAT)
111     if (dcc[i].u.chat->channel == chan) {
112     spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
113     if (atr & USER_OWNER) {
114     sprintf(s, " [%.2lu] %c%s%s %s",
115     dcc[i].sock, (geticon(i) == '-' ? ' ' : geticon(i)),
116     dcc[i].nick, spaces, dcc[i].host);
117     } else {
118     sprintf(s, " %c%s%s %s",
119     (geticon(i) == '-' ? ' ' : geticon(i)),
120     dcc[i].nick, spaces, dcc[i].host);
121     }
122     spaces[len] = ' ';
123     if (atr & USER_MASTER) {
124     if (dcc[i].u.chat->con_flags)
125     sprintf(&s[strlen(s)], " (con:%s)",
126     masktype(dcc[i].u.chat->con_flags));
127     }
128     if (now - dcc[i].timeval > 300) {
129     unsigned long days, hrs, mins;
130    
131     days = (now - dcc[i].timeval) / 86400;
132     hrs = ((now - dcc[i].timeval) - (days * 86400)) / 3600;
133     mins = ((now - dcc[i].timeval) - (hrs * 3600)) / 60;
134     if (days > 0)
135     sprintf(&s[strlen(s)], " (idle %lud%luh)", days, hrs);
136     else if (hrs > 0)
137     sprintf(&s[strlen(s)], " (idle %luh%lum)", hrs, mins);
138     else
139     sprintf(&s[strlen(s)], " (idle %lum)", mins);
140     }
141     dprintf(idx, "%s\n", s);
142     if (dcc[i].u.chat->away != NULL)
143     dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
144     }
145     for (i = 0; i < dcc_total; i++)
146     if (dcc[i].type == &DCC_BOT) {
147     if (!ok) {
148     ok = 1;
149     dprintf(idx, "Bots connected:\n");
150     }
151 fabian 1.41 egg_strftime(s, 14, "%d %b %H:%M", localtime(&dcc[i].timeval));
152 segfault 1.1 spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
153     if (atr & USER_OWNER) {
154     dprintf(idx, " [%.2lu] %s%c%s%s (%s) %s\n",
155     dcc[i].sock, dcc[i].status & STAT_CALLED ? "<-" : "->",
156     dcc[i].status & STAT_SHARE ? '+' : ' ',
157     dcc[i].nick, spaces, s, dcc[i].u.bot->version);
158     } else {
159     dprintf(idx, " %s%c%s%s (%s) %s\n",
160     dcc[i].status & STAT_CALLED ? "<-" : "->",
161     dcc[i].status & STAT_SHARE ? '+' : ' ',
162     dcc[i].nick, spaces, s, dcc[i].u.bot->version);
163     }
164     spaces[len] = ' ';
165     }
166     ok = 0;
167     for (i = 0; i < dcc_total; i++) {
168     if ((dcc[i].type == &DCC_CHAT) && (dcc[i].u.chat->channel != chan)) {
169     if (!ok) {
170     ok = 1;
171     dprintf(idx, "Other people on the bot:\n");
172     }
173     spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
174     if (atr & USER_OWNER) {
175     sprintf(s, " [%.2lu] %c%s%s ",
176     dcc[i].sock,
177     (geticon(i) == '-' ? ' ' : geticon(i)), dcc[i].nick,
178     spaces);
179     } else {
180     sprintf(s, " %c%s%s ",
181     (geticon(i) == '-' ? ' ' : geticon(i)), dcc[i].nick,
182     spaces);
183     }
184     spaces[len] = ' ';
185     if (atr & USER_MASTER) {
186     if (dcc[i].u.chat->channel < 0)
187     strcat(s, "(-OFF-) ");
188 guppy 1.45 else if (!dcc[i].u.chat->channel)
189 segfault 1.1 strcat(s, "(party) ");
190     else
191     sprintf(&s[strlen(s)], "(%5d) ", dcc[i].u.chat->channel);
192     }
193     strcat(s, dcc[i].host);
194     if (atr & USER_MASTER) {
195     if (dcc[i].u.chat->con_flags)
196     sprintf(&s[strlen(s)], " (con:%s)",
197     masktype(dcc[i].u.chat->con_flags));
198     }
199     if (now - dcc[i].timeval > 300) {
200     k = (now - dcc[i].timeval) / 60;
201     if (k < 60)
202     sprintf(&s[strlen(s)], " (idle %dm)", k);
203     else
204     sprintf(&s[strlen(s)], " (idle %dh%dm)", k / 60, k % 60);
205     }
206     dprintf(idx, "%s\n", s);
207     if (dcc[i].u.chat->away != NULL)
208     dprintf(idx, " AWAY: %s\n", dcc[i].u.chat->away);
209     }
210     if ((atr & USER_MASTER) && (dcc[i].type->flags & DCT_SHOWWHO) &&
211     (dcc[i].type != &DCC_CHAT)) {
212     if (!ok) {
213     ok = 1;
214     dprintf(idx, "Other people on the bot:\n");
215     }
216     spaces[len = HANDLEN - strlen(dcc[i].nick)] = 0;
217     if (atr & USER_OWNER) {
218     sprintf(s, " [%.2lu] %c%s%s (files) %s",
219     dcc[i].sock, dcc[i].status & STAT_CHAT ? '+' : ' ',
220     dcc[i].nick, spaces, dcc[i].host);
221     } else {
222     sprintf(s, " %c%s%s (files) %s",
223     dcc[i].status & STAT_CHAT ? '+' : ' ',
224     dcc[i].nick, spaces, dcc[i].host);
225     }
226     spaces[len] = ' ';
227     dprintf(idx, "%s\n", s);
228     }
229     }
230     }
231    
232     static void cmd_botinfo(struct userrec *u, int idx, char *par)
233     {
234     char s[512], s2[32];
235     struct chanset_t *chan;
236 guppy 1.64 unsigned long uptime, tmp, hr, min;
237 segfault 1.1
238 guppy 1.64 putlog(LOG_CMDS, "*", "#%s# botinfo", dcc[idx].nick);
239    
240     uptime = now - online_since;
241 segfault 1.1 s2[0] = 0;
242 guppy 1.64 if (uptime > 86400) {
243     tmp = (uptime / 86400);
244     sprintf(s2, "%lu day%s, ", tmp, (tmp == 1) ? "" : "s");
245     uptime -= (tmp * 86400);
246     }
247     hr = (uptime / 3600);
248     uptime -= (hr * 3600);
249     min = (uptime / 60);
250     sprintf(&s2[strlen(s2)], "%02lu:%02lu", hr, min);
251 segfault 1.1
252     simple_sprintf(s, "%d:%s@%s", dcc[idx].sock, dcc[idx].nick, botnetnick);
253     botnet_send_infoq(-1, s);
254     s[0] = 0;
255     if (module_find("server", 0, 0)) {
256 guppy 1.56 for (chan = chanset; chan; chan = chan->next) {
257 segfault 1.1 if (!channel_secret(chan)) {
258 guppy 1.49 if ((strlen(s) + strlen(chan->dname) + strlen(network)
259 segfault 1.1 + strlen(botnetnick) + strlen(ver) + 1) >= 490) {
260     strcat(s,"++ ");
261     break; /* yeesh! */
262     }
263 fabian 1.8 strcat(s, chan->dname);
264 segfault 1.1 strcat(s, ", ");
265     }
266     }
267    
268     if (s[0]) {
269     s[strlen(s) - 2] = 0;
270     dprintf(idx, "*** [%s] %s <%s> (%s) [UP %s]\n", botnetnick,
271 guppy 1.49 ver, network, s, s2);
272 segfault 1.1 } else
273     dprintf(idx, "*** [%s] %s <%s> (%s) [UP %s]\n", botnetnick,
274 ite 1.63 ver, network, _("no channels"), s2);
275 segfault 1.1 } else
276     dprintf(idx, "*** [%s] %s <NO_IRC> [UP %s]\n", botnetnick, ver, s2);
277     }
278    
279     static void cmd_whom(struct userrec *u, int idx, char *par)
280     {
281     if (par[0] == '*') {
282     putlog(LOG_CMDS, "*", "#%s# whom %s", dcc[idx].nick, par);
283     answer_local_whom(idx, -1);
284     return;
285     } else if (dcc[idx].u.chat->channel < 0) {
286     dprintf(idx, "You have chat turned off.\n");
287     return;
288     }
289     putlog(LOG_CMDS, "*", "#%s# whom %s", dcc[idx].nick, par);
290     if (!par[0]) {
291     answer_local_whom(idx, dcc[idx].u.chat->channel);
292     } else {
293     int chan = -1;
294    
295     if ((par[0] < '0') || (par[0] > '9')) {
296     Tcl_SetVar(interp, "chan", par, 0);
297     if ((Tcl_VarEval(interp, "assoc ", "$chan", NULL) == TCL_OK) &&
298     interp->result[0]) {
299     chan = atoi(interp->result);
300     }
301     if (chan <= 0) {
302     dprintf(idx, "No such channel.\n");
303     return;
304     }
305     } else
306     chan = atoi(par);
307     if ((chan < 0) || (chan > 99999)) {
308     dprintf(idx, "Channel # out of range: must be 0-99999\n");
309     return;
310     }
311     answer_local_whom(idx, chan);
312     }
313     }
314    
315     static void cmd_me(struct userrec *u, int idx, char *par)
316     {
317     int i;
318    
319     if (dcc[idx].u.chat->channel < 0) {
320     dprintf(idx, "You have chat turned off.\n");
321     return;
322     }
323     if (!par[0]) {
324     dprintf(idx, "Usage: me <action>\n");
325     return;
326     }
327     if (dcc[idx].u.chat->away != NULL)
328     not_away(idx);
329     for (i = 0; i < dcc_total; i++)
330     if ((dcc[i].type->flags & DCT_CHAT) &&
331     (dcc[i].u.chat->channel == dcc[idx].u.chat->channel) &&
332     ((i != idx) || (dcc[i].status & STAT_ECHO)))
333     dprintf(i, "* %s %s\n", dcc[idx].nick, par);
334     botnet_send_act(idx, botnetnick, dcc[idx].nick,
335     dcc[idx].u.chat->channel, par);
336     check_tcl_act(dcc[idx].nick, dcc[idx].u.chat->channel, par);
337     }
338    
339     static void cmd_motd(struct userrec *u, int idx, char *par)
340     {
341     int i;
342    
343     if (par[0]) {
344     putlog(LOG_CMDS, "*", "#%s# motd %s", dcc[idx].nick, par);
345 fabian 1.26 if (!egg_strcasecmp(par, botnetnick))
346 segfault 1.1 show_motd(idx);
347     else {
348     i = nextbot(par);
349     if (i < 0)
350     dprintf(idx, "That bot isn't connected.\n");
351     else {
352     char x[40];
353    
354     simple_sprintf(x, "%s%d:%s@%s",
355     (u->flags & USER_HIGHLITE) ?
356     ((dcc[idx].status & STAT_TELNET) ? "#" : "!") : "",
357     dcc[idx].sock, dcc[idx].nick, botnetnick);
358     botnet_send_motd(i, x, par);
359     }
360     }
361     } else {
362     putlog(LOG_CMDS, "*", "#%s# motd", dcc[idx].nick);
363     show_motd(idx);
364     }
365     }
366    
367     static void cmd_away(struct userrec *u, int idx, char *par)
368     {
369     if (strlen(par) > 60)
370     par[60] = 0;
371     set_away(idx, par);
372     }
373    
374     static void cmd_back(struct userrec *u, int idx, char *par)
375     {
376     not_away(idx);
377     }
378    
379     static void cmd_newpass(struct userrec *u, int idx, char *par)
380     {
381     char *new;
382    
383     if (!par[0]) {
384     dprintf(idx, "Usage: newpass <newpassword>\n");
385     return;
386     }
387     new = newsplit(&par);
388     if (strlen(new) > 16)
389     new[16] = 0;
390     if (strlen(new) < 6) {
391     dprintf(idx, "Please use at least 6 characters.\n");
392     return;
393     }
394     set_user(&USERENTRY_PASS, u, new);
395     putlog(LOG_CMDS, "*", "#%s# newpass...", dcc[idx].nick);
396     dprintf(idx, "Changed password to '%s'\n", new);
397     }
398    
399     static void cmd_bots(struct userrec *u, int idx, char *par)
400     {
401     putlog(LOG_CMDS, "*", "#%s# bots", dcc[idx].nick);
402     tell_bots(idx);
403     }
404    
405     static void cmd_bottree(struct userrec *u, int idx, char *par)
406     {
407     putlog(LOG_CMDS, "*", "#%s# bottree", dcc[idx].nick);
408     tell_bottree(idx, 0);
409     }
410    
411     static void cmd_vbottree(struct userrec *u, int idx, char *par)
412     {
413     putlog(LOG_CMDS, "*", "#%s# vbottree", dcc[idx].nick);
414     tell_bottree(idx, 1);
415     }
416    
417     static void cmd_rehelp(struct userrec *u, int idx, char *par)
418     {
419     putlog(LOG_CMDS, "*", "#%s# rehelp", dcc[idx].nick);
420     dprintf(idx, "Reload help cache...\n");
421     reload_help_data();
422     }
423    
424     static void cmd_help(struct userrec *u, int idx, char *par)
425     {
426 fabian 1.4 struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
427 segfault 1.1
428     get_user_flagrec(u, &fr, dcc[idx].u.chat->con_chan);
429     if (par[0]) {
430     putlog(LOG_CMDS, "*", "#%s# help %s", dcc[idx].nick, par);
431     if (!strcmp(par, "all"))
432     tellallhelp(idx, "all", &fr);
433 fabian 1.4 else if (strchr(par, '*') || strchr(par, '?')) {
434     char *p = par;
435    
436     /* Check if the search pattern only consists of '*' and/or '?'
437     * If it does, show help for "all" instead of listing all help
438 fabian 1.22 * entries.
439     */
440 fabian 1.4 for (p = par; *p && ((*p == '*') || (*p == '?')); p++);
441     if (*p)
442     tellwildhelp(idx, par, &fr);
443     else
444     tellallhelp(idx, "all", &fr);
445     } else
446 segfault 1.1 tellhelp(idx, par, &fr, 0);
447     } else {
448     putlog(LOG_CMDS, "*", "#%s# help", dcc[idx].nick);
449     if (glob_op(fr) || glob_botmast(fr) || chan_op(fr))
450     tellhelp(idx, "help", &fr, 0);
451     else
452     tellhelp(idx, "helpparty", &fr, 0);
453     }
454     }
455    
456     static void cmd_addlog(struct userrec *u, int idx, char *par)
457     {
458     if (!par[0]) {
459     dprintf(idx, "Usage: addlog <message>\n");
460     return;
461     }
462     dprintf(idx, "Placed entry in the log file.\n");
463     putlog(LOG_MISC, "*", "%s: %s", dcc[idx].nick, par);
464     }
465    
466     static void cmd_who(struct userrec *u, int idx, char *par)
467     {
468     int i;
469    
470     if (par[0]) {
471     if (dcc[idx].u.chat->channel < 0) {
472     dprintf(idx, "You have chat turned off.\n");
473     return;
474     }
475     putlog(LOG_CMDS, "*", "#%s# who %s", dcc[idx].nick, par);
476 fabian 1.26 if (!egg_strcasecmp(par, botnetnick))
477 segfault 1.1 tell_who(u, idx, dcc[idx].u.chat->channel);
478     else {
479     i = nextbot(par);
480     if (i < 0) {
481     dprintf(idx, "That bot isn't connected.\n");
482     } else if (dcc[idx].u.chat->channel > 99999)
483     dprintf(idx, "You are on a local channel\n");
484     else {
485     char s[40];
486    
487     simple_sprintf(s, "%d:%s@%s", dcc[idx].sock,
488     dcc[idx].nick, botnetnick);
489     botnet_send_who(i, s, par, dcc[idx].u.chat->channel);
490     }
491     }
492     } else {
493     putlog(LOG_CMDS, "*", "#%s# who", dcc[idx].nick);
494     if (dcc[idx].u.chat->channel < 0)
495     tell_who(u, idx, 0);
496     else
497     tell_who(u, idx, dcc[idx].u.chat->channel);
498     }
499     }
500    
501     static void cmd_whois(struct userrec *u, int idx, char *par)
502     {
503     if (!par[0]) {
504     dprintf(idx, "Usage: whois <handle>\n");
505     return;
506     }
507     putlog(LOG_CMDS, "*", "#%s# whois %s", dcc[idx].nick, par);
508     tell_user_ident(idx, par, u ? (u->flags & USER_MASTER) : 0);
509     }
510    
511     static void cmd_match(struct userrec *u, int idx, char *par)
512     {
513     int start = 1, limit = 20;
514     char *s, *s1, *chname;
515    
516     if (!par[0]) {
517     dprintf(idx, "Usage: match <nick/host> [[skip] count]\n");
518     return;
519     }
520     putlog(LOG_CMDS, "*", "#%s# match %s", dcc[idx].nick, par);
521     s = newsplit(&par);
522     if (strchr(CHANMETA, par[0]) != NULL)
523     chname = newsplit(&par);
524     else
525     chname = "";
526     if (atoi(par) > 0) {
527     s1 = newsplit(&par);
528     if (atoi(par) > 0) {
529     start = atoi(s1);
530     limit = atoi(par);
531     } else
532     limit = atoi(s1);
533     }
534     tell_users_match(idx, s, start, limit, u ? (u->flags & USER_MASTER) : 0,
535     chname);
536     }
537    
538     static void cmd_uptime(struct userrec *u, int idx, char *par)
539     {
540 guppy 1.64 char s[256];
541     unsigned long uptime, tmp, hr, min;
542    
543 segfault 1.1 putlog(LOG_CMDS, "*", "#%s# uptime", dcc[idx].nick);
544 guppy 1.64
545     uptime = now - online_since;
546     s[0] = 0;
547     if (uptime > 86400) {
548     tmp = (uptime / 86400);
549     sprintf(s, "%lu day%s, ", tmp, (tmp == 1) ? "" : "s");
550     uptime -= (tmp * 86400);
551     }
552     hr = (uptime / 3600);
553     uptime -= (hr * 3600);
554     min = (uptime / 60);
555     sprintf(&s[strlen(s)], "%02lu:%02lu", hr, min);
556    
557     dprintf(idx, "%s %s (%s)\n", _("Online for"), s, backgrd ?
558     _("background") : term_z ? _("terminal mode") : con_chan ?
559     _("status mode") : _("log dump mode"));
560 segfault 1.1 }
561    
562     static void cmd_status(struct userrec *u, int idx, char *par)
563     {
564     int atr = u ? u->flags : 0;
565    
566 fabian 1.26 if (!egg_strcasecmp(par, "all")) {
567 segfault 1.1 if (!(atr & USER_MASTER)) {
568     dprintf(idx, "You do not have Bot Master privileges.\n");
569     return;
570     }
571     putlog(LOG_CMDS, "*", "#%s# status all", dcc[idx].nick);
572     tell_verbose_status(idx);
573     tell_mem_status_dcc(idx);
574     dprintf(idx, "\n");
575     tell_settings(idx);
576     do_module_report(idx, 1, NULL);
577     } else {
578     putlog(LOG_CMDS, "*", "#%s# status", dcc[idx].nick);
579     tell_verbose_status(idx);
580     tell_mem_status_dcc(idx);
581     do_module_report(idx, 0, NULL);
582     }
583     }
584    
585     static void cmd_dccstat(struct userrec *u, int idx, char *par)
586     {
587     putlog(LOG_CMDS, "*", "#%s# dccstat", dcc[idx].nick);
588     tell_dcc(idx);
589     }
590    
591     static void cmd_boot(struct userrec *u, int idx, char *par)
592     {
593     int i, files = 0, ok = 0;
594     char *who;
595     struct userrec *u2;
596    
597     if (!par[0]) {
598     dprintf(idx, "Usage: boot nick[@bot]\n");
599     return;
600     }
601     who = newsplit(&par);
602     if (strchr(who, '@') != NULL) {
603 fabian 1.39 char whonick[HANDLEN + 1];
604 segfault 1.1
605 poptix 1.65 splitcn(whonick, who, '@', HANDLEN + 1);
606 fabian 1.26 if (!egg_strcasecmp(who, botnetnick)) {
607 segfault 1.1 cmd_boot(u, idx, whonick);
608     return;
609     }
610     if (remote_boots > 0) {
611     i = nextbot(who);
612     if (i < 0) {
613 fabian 1.39 dprintf(idx, "No such bot connected.\n");
614     return;
615 segfault 1.1 }
616     botnet_send_reject(i, dcc[idx].nick, botnetnick, whonick,
617     who, par[0] ? par : dcc[idx].nick);
618 fabian 1.7 putlog(LOG_BOTS, "*", "#%s# boot %s@%s (%s)", dcc[idx].nick, whonick,
619 segfault 1.1 who, par[0] ? par : dcc[idx].nick);
620     } else
621     dprintf(idx, "Remote boots are disabled here.\n");
622     return;
623     }
624     for (i = 0; i < dcc_total; i++)
625 fabian 1.39 if (!egg_strcasecmp(dcc[i].nick, who)
626     && !ok && (dcc[i].type->flags & DCT_CANBOOT)) {
627 segfault 1.1 u2 = get_user_by_handle(userlist, dcc[i].nick);
628 fabian 1.39 if (u2 && (u2->flags & USER_OWNER)
629     && egg_strcasecmp(dcc[idx].nick, who)) {
630     dprintf(idx, "Can't boot the bot owner.\n");
631     return;
632     }
633     if (u2 && (u2->flags & USER_MASTER) && !(u && (u->flags & USER_MASTER))) {
634     dprintf(idx, "Can't boot a bot master.\n");
635     return;
636 segfault 1.1 }
637     files = (dcc[i].type->flags & DCT_FILES);
638     if (files)
639 fabian 1.39 dprintf(idx, "Booted %s from the file section.\n", dcc[i].nick);
640 segfault 1.1 else
641 fabian 1.39 dprintf(idx, "Booted %s from the bot.\n", dcc[i].nick);
642 segfault 1.1 putlog(LOG_CMDS, "*", "#%s# boot %s %s", dcc[idx].nick, who, par);
643     do_boot(i, dcc[idx].nick, par);
644     ok = 1;
645     }
646     if (!ok)
647     dprintf(idx, "Who? No such person on the party line.\n");
648     }
649    
650     static void cmd_console(struct userrec *u, int idx, char *par)
651     {
652     char *nick, s[2], s1[512];
653     int dest = 0, i, ok = 0, pls, md;
654 fabian 1.8 struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
655 segfault 1.1 module_entry *me;
656    
657     if (!par[0]) {
658     dprintf(idx, "Your console is %s: %s (%s)\n",
659     dcc[idx].u.chat->con_chan,
660     masktype(dcc[idx].u.chat->con_flags),
661     maskname(dcc[idx].u.chat->con_flags));
662     return;
663     }
664     get_user_flagrec(u, &fr, dcc[idx].u.chat->con_chan);
665     strcpy(s1, par);
666     nick = newsplit(&par);
667 guppy 1.49 /* Don't remove '+' as someone couldn't have '+' in CHANMETA cause
668 fabian 1.22 * he doesn't use IRCnet ++rtc.
669     */
670 fabian 1.6 if (nick[0] && !strchr(CHANMETA "+-*", nick[0]) && glob_master(fr)) {
671 segfault 1.1 for (i = 0; i < dcc_total; i++)
672 fabian 1.26 if (!egg_strcasecmp(nick, dcc[i].nick) &&
673 segfault 1.1 (dcc[i].type == &DCC_CHAT) && (!ok)) {
674     ok = 1;
675     dest = i;
676     }
677     if (!ok) {
678     dprintf(idx, "No such user on the party line!\n");
679     return;
680     }
681     nick[0] = 0;
682     } else
683     dest = idx;
684     if (!nick[0])
685     nick = newsplit(&par);
686 fabian 1.22 /* Consider modeless channels, starting with '+' */
687 guppy 1.49 if ((nick [0] == '+' && findchan_by_dname(nick)) ||
688 fabian 1.6 (nick [0] != '+' && strchr(CHANMETA "*", nick[0]))) {
689 fabian 1.8 if (strcmp(nick, "*") && !findchan_by_dname(nick)) {
690 segfault 1.1 dprintf(idx, "Invalid console channel: %s\n", nick);
691     return;
692     }
693     get_user_flagrec(u, &fr, nick);
694     if (!chan_op(fr) && !(glob_op(fr) && !chan_deop(fr))) {
695     dprintf(idx, "You don't have op or master access to channel %s\n",
696     nick);
697     return;
698     }
699 guppy 1.45 strncpyz(dcc[dest].u.chat->con_chan, nick, 81);
700 segfault 1.1 nick[0] = 0;
701     if ((dest == idx) && !glob_master(fr) && !chan_master(fr))
702 fabian 1.22 /* Consoling to another channel for self */
703 segfault 1.1 dcc[dest].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS | LOG_WALL);
704     }
705     if (!nick[0])
706     nick = newsplit(&par);
707     pls = 1;
708     if (nick[0]) {
709     if ((nick[0] != '+') && (nick[0] != '-'))
710     dcc[dest].u.chat->con_flags = 0;
711     for (; *nick; nick++) {
712     if (*nick == '+')
713     pls = 1;
714     else if (*nick == '-')
715     pls = 0;
716     else {
717     s[0] = *nick;
718     s[1] = 0;
719     md = logmodes(s);
720     if ((dest == idx) && !glob_master(fr) && pls) {
721     if (chan_master(fr))
722     md &= ~(LOG_FILES | LOG_LEV1 | LOG_LEV2 | LOG_LEV3 |
723     LOG_LEV4 | LOG_LEV5 | LOG_LEV6 | LOG_LEV7 |
724     LOG_LEV8 | LOG_DEBUG);
725     else
726     md &= ~(LOG_MISC | LOG_CMDS | LOG_FILES | LOG_LEV1 |
727     LOG_LEV2 | LOG_LEV3 | LOG_LEV4 | LOG_LEV5 |
728     LOG_LEV6 | LOG_LEV7 | LOG_LEV8 | LOG_WALL |
729     LOG_DEBUG);
730     }
731     if (!glob_owner(fr) && pls)
732     md &= ~(LOG_RAW | LOG_SRVOUT | LOG_BOTNET | LOG_BOTSHARE);
733     if (!glob_botmast(fr) && pls)
734     md &= ~LOG_BOTS;
735     if (pls)
736     dcc[dest].u.chat->con_flags |= md;
737     else
738     dcc[dest].u.chat->con_flags &= ~md;
739     }
740     }
741     }
742     putlog(LOG_CMDS, "*", "#%s# console %s", dcc[idx].nick, s1);
743     if (dest == idx) {
744     dprintf(idx, "Set your console to %s: %s (%s)\n",
745     dcc[idx].u.chat->con_chan,
746     masktype(dcc[idx].u.chat->con_flags),
747     maskname(dcc[idx].u.chat->con_flags));
748     } else {
749     dprintf(idx, "Set console of %s to %s: %s (%s)\n", dcc[dest].nick,
750     dcc[dest].u.chat->con_chan,
751     masktype(dcc[dest].u.chat->con_flags),
752     maskname(dcc[dest].u.chat->con_flags));
753     dprintf(dest, "%s set your console to %s: %s (%s)\n", dcc[idx].nick,
754     dcc[dest].u.chat->con_chan,
755     masktype(dcc[dest].u.chat->con_flags),
756     maskname(dcc[dest].u.chat->con_flags));
757     }
758 fabian 1.22 /* New style autosave -- drummer,07/25/1999*/
759 fabian 1.2 if ((me = module_find("console", 1, 1))) {
760 segfault 1.1 Function *func = me->funcs;
761 fabian 1.3 (func[CONSOLE_DOSTORE]) (dest);
762 segfault 1.1 }
763     }
764    
765     static void cmd_pls_bot(struct userrec *u, int idx, char *par)
766     {
767     char *handle, *addr, *p, *q, *host;
768     struct userrec *u1;
769     struct bot_addr *bi;
770 drummer 1.61 int addrlen;
771 segfault 1.1
772     if (!par[0])
773     dprintf(idx, "Usage: +bot <handle> <address[:telnet-port[/relay-port]]> [host]\n");
774     else {
775     handle = newsplit(&par);
776     addr = newsplit(&par);
777     if (strlen(handle) > HANDLEN)
778     handle[HANDLEN] = 0; /* max len = XX .. for the moment :) */
779     if (get_user_by_handle(userlist, handle))
780     dprintf(idx, "Someone already exists by that name.\n");
781 fabian 1.6 else if (strchr(BADHANDCHARS, handle[0]) != NULL)
782 segfault 1.1 dprintf(idx, "You can't start a botnick with '%c'.\n", handle[0]);
783     else {
784     if (strlen(addr) > 60)
785     addr[60] = 0;
786     putlog(LOG_CMDS, "*", "#%s# +bot %s %s", dcc[idx].nick, handle, addr);
787     userlist = adduser(userlist, handle, "none", "-", USER_BOT);
788     u1 = get_user_by_handle(userlist, handle);
789     bi = user_malloc(sizeof(struct bot_addr));
790    
791 drummer 1.61 if (*addr == '[') {
792     addr++;
793     if ((q = strchr(addr, ']'))) {
794     addrlen = q - addr;
795     q++;
796     if (*q != ':')
797     q = 0;
798     } else
799     addrlen = strlen(addr);
800     } else {
801     if ((q = strchr(addr, ':')))
802     addrlen = q - addr;
803     else
804     addrlen = strlen(addr);
805     }
806 segfault 1.1 if (!q) {
807 drummer 1.61 bi->address = user_malloc(addrlen + 1);
808 segfault 1.1 strcpy(bi->address, addr);
809     bi->telnet_port = 3333;
810     bi->relay_port = 3333;
811     } else {
812 drummer 1.61 bi->address = user_malloc(addrlen + 1);
813     strncpyz(bi->address, addr, addrlen + 1);
814 segfault 1.1 p = q + 1;
815     bi->telnet_port = atoi(p);
816     q = strchr(p, '/');
817     if (!q) {
818     bi->relay_port = bi->telnet_port;
819     } else {
820     bi->relay_port = atoi(q + 1);
821     }
822     }
823     set_user(&USERENTRY_BOTADDR, u1, bi);
824     dprintf(idx, "Added bot '%s' with address '%s' and no password.\n",
825     handle, addr);
826     host = newsplit(&par);
827     if (host[0]) {
828     addhost_by_handle(handle, host);
829     } else if (!add_bot_hostmask(idx, handle))
830     dprintf(idx, "You'll want to add a hostmask if this bot will ever %s",
831     "be on any channels that I'm on.\n");
832     }
833     }
834     }
835    
836 fabian 1.27 static void cmd_chhandle(struct userrec *u, int idx, char *par)
837 segfault 1.1 {
838 fabian 1.2 char hand[HANDLEN + 1], newhand[HANDLEN + 1];
839 segfault 1.1 int i, atr = u ? u->flags : 0, atr2;
840     struct userrec *u2;
841    
842 guppy 1.45 strncpyz(hand, newsplit(&par), sizeof hand);
843     strncpyz(newhand, newsplit(&par), sizeof newhand);
844 fabian 1.2
845     if (!hand[0] || !newhand[0]) {
846 fabian 1.27 dprintf(idx, "Usage: chhandle <oldhandle> <newhandle>\n");
847 fabian 1.2 return;
848     }
849     for (i = 0; i < strlen(newhand); i++)
850     if ((newhand[i] <= 32) || (newhand[i] >= 127) || (newhand[i] == '@'))
851     newhand[i] = '?';
852 fabian 1.6 if (strchr(BADHANDCHARS, newhand[0]) != NULL)
853 fabian 1.2 dprintf(idx, "Bizarre quantum forces prevent nicknames from starting with %c\n",
854     newhand[0]);
855     else if (get_user_by_handle(userlist, newhand) &&
856 fabian 1.26 egg_strcasecmp(hand, newhand))
857 fabian 1.2 dprintf(idx, "Somebody is already using %s.\n", newhand);
858 segfault 1.1 else {
859 fabian 1.2 u2 = get_user_by_handle(userlist, hand);
860     atr2 = u2 ? u2->flags : 0;
861     if ((atr & USER_BOTMAST) && !(atr & USER_MASTER) &&
862     !(atr2 & USER_BOT))
863     dprintf(idx, "You can't change nick for non-bots.\n");
864     else if ((bot_flags(u2) & BOT_SHARE) && !(atr & USER_OWNER))
865     dprintf(idx, "You can't change shared bot's nick.\n");
866     else if ((atr2 & USER_OWNER) && !(atr & USER_OWNER) &&
867 fabian 1.26 egg_strcasecmp(dcc[idx].nick, hand))
868 fabian 1.2 dprintf(idx, "Can't change the bot owner's handle.\n");
869 fabian 1.26 else if (isowner(hand) && egg_strcasecmp(dcc[idx].nick, hand))
870 fabian 1.2 dprintf(idx, "Can't change the permanent bot owner's handle.\n");
871 fabian 1.26 else if (!egg_strcasecmp(newhand, botnetnick) && (!(atr2 & USER_BOT) ||
872 fabian 1.6 nextbot(hand) != -1))
873     dprintf(idx, "Hey! That's MY name!\n");
874 fabian 1.2 else if (change_handle(u2, newhand)) {
875 fabian 1.27 putlog(LOG_CMDS, "*", "#%s# chhandle %s %s", dcc[idx].nick,
876 fabian 1.2 hand, newhand);
877     dprintf(idx, "Changed.\n");
878     } else
879     dprintf(idx, "Failed.\n");
880 segfault 1.1 }
881     }
882    
883 fabian 1.27 static void cmd_handle(struct userrec *u, int idx, char *par)
884 segfault 1.1 {
885 fabian 1.27 char oldhandle[HANDLEN + 1], newhandle[HANDLEN + 1];
886 fabian 1.2 int i;
887    
888 guppy 1.45 strncpyz(newhandle, newsplit(&par), sizeof newhandle);
889 segfault 1.1
890 fabian 1.27 if (!newhandle[0]) {
891     dprintf(idx, "Usage: handle <new-handle>\n");
892 segfault 1.1 return;
893     }
894 fabian 1.27 for (i = 0; i < strlen(newhandle); i++)
895     if ((newhandle[i] <= 32) || (newhandle[i] >= 127) || (newhandle[i] == '@'))
896     newhandle[i] = '?';
897     if (strchr(BADHANDCHARS, newhandle[0]) != NULL) {
898     dprintf(idx, "Bizarre quantum forces prevent handle from starting with '%c'\n",
899     newhandle[0]);
900     } else if (get_user_by_handle(userlist, newhandle) &&
901     egg_strcasecmp(dcc[idx].nick, newhandle)) {
902     dprintf(idx, "Somebody is already using %s.\n", newhandle);
903     } else if (!egg_strcasecmp(newhandle, botnetnick)) {
904 fabian 1.2 dprintf(idx, "Hey! That's MY name!\n");
905 segfault 1.1 } else {
906 guppy 1.45 strncpyz(oldhandle, dcc[idx].nick, sizeof oldhandle);
907 fabian 1.27 if (change_handle(u, newhandle)) {
908     putlog(LOG_CMDS, "*", "#%s# handle %s", oldhandle, newhandle);
909 segfault 1.1 dprintf(idx, "Okay, changed.\n");
910     } else
911     dprintf(idx, "Failed.\n");
912     }
913     }
914    
915     static void cmd_chpass(struct userrec *u, int idx, char *par)
916     {
917     char *handle, *new;
918     int atr = u ? u->flags : 0, l;
919    
920     if (!par[0])
921     dprintf(idx, "Usage: chpass <handle> [password]\n");
922     else {
923     handle = newsplit(&par);
924     u = get_user_by_handle(userlist, handle);
925     if (!u)
926     dprintf(idx, "No such user.\n");
927     else if ((atr & USER_BOTMAST) && !(atr & USER_MASTER) &&
928     !(u->flags & USER_BOT))
929     dprintf(idx, "You can't change password for non-bots.\n");
930     else if ((bot_flags(u) & BOT_SHARE) && !(atr & USER_OWNER))
931     dprintf(idx, "You can't change shared bot's password.\n");
932     else if ((u->flags & USER_OWNER) && !(atr & USER_OWNER) &&
933 fabian 1.26 egg_strcasecmp(handle, dcc[idx].nick))
934 segfault 1.1 dprintf(idx, "Can't change the bot owner's password.\n");
935 fabian 1.26 else if (isowner(handle) && egg_strcasecmp(dcc[idx].nick, handle))
936 fabian 1.19 dprintf(idx, "Can't change the permanent bot owner's password.\n");
937 segfault 1.1 else if (!par[0]) {
938     putlog(LOG_CMDS, "*", "#%s# chpass %s [nothing]", dcc[idx].nick,
939     handle);
940     set_user(&USERENTRY_PASS, u, NULL);
941     dprintf(idx, "Removed password.\n");
942     } else {
943     l = strlen(new = newsplit(&par));
944     if (l > 16)
945     new[16] = 0;
946     if (l < 6)
947     dprintf(idx, "Please use at least 6 characters.\n");
948     else {
949     set_user(&USERENTRY_PASS, u, new);
950     putlog(LOG_CMDS, "*", "#%s# chpass %s [something]", dcc[idx].nick,
951     handle);
952     dprintf(idx, "Changed password.\n");
953     }
954     }
955     }
956     }
957    
958     static void cmd_chaddr(struct userrec *u, int idx, char *par)
959     {
960 guppy 1.51 int telnet_port = 3333, relay_port = 3333;
961 segfault 1.1 char *handle, *addr, *p, *q;
962     struct bot_addr *bi;
963     struct userrec *u1;
964 drummer 1.61 int addrlen;
965 segfault 1.1
966     if (!par[0]) {
967 guppy 1.51 dprintf(idx, "Usage: chaddr <botname> <address[:telnet-port[/relay-port]]>\n");
968 segfault 1.1 return;
969     }
970     handle = newsplit(&par);
971     addr = newsplit(&par);
972 fabian 1.6 if (strlen(addr) > UHOSTMAX)
973     addr[UHOSTMAX] = 0;
974 segfault 1.1 u1 = get_user_by_handle(userlist, handle);
975     if (!u1 || !(u1->flags & USER_BOT)) {
976     dprintf(idx, "Useful only for tandem bots.\n");
977     return;
978     }
979     if ((bot_flags(u1) & BOT_SHARE) && (!u || !u->flags & USER_OWNER)) {
980     dprintf(idx, "You can't change shared bot's address.\n");
981     return;
982     }
983     putlog(LOG_CMDS, "*", "#%s# chaddr %s %s", dcc[idx].nick, handle, addr);
984     dprintf(idx, "Changed bot's address.\n");
985 guppy 1.51
986     bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, u1);
987     if (bi) {
988     telnet_port = bi->telnet_port;
989     relay_port = bi->relay_port;
990     }
991    
992 segfault 1.1 bi = user_malloc(sizeof(struct bot_addr));
993    
994 drummer 1.61 if (*addr == '[') {
995     addr++;
996     if ((q = strchr(addr, ']'))) {
997     addrlen = q - addr;
998     q++;
999     if (*q != ':')
1000     q = 0;
1001     } else
1002     addrlen = strlen(addr);
1003     } else {
1004     if ((q = strchr(addr, ':')))
1005     addrlen = q - addr;
1006     else
1007     addrlen = strlen(addr);
1008     }
1009 segfault 1.1 if (!q) {
1010 drummer 1.61 bi->address = user_malloc(addrlen + 1);
1011 segfault 1.1 strcpy(bi->address, addr);
1012 guppy 1.51 bi->telnet_port = telnet_port;
1013     bi->relay_port = relay_port;
1014 segfault 1.1 } else {
1015 drummer 1.61 bi->address = user_malloc(addrlen + 1);
1016     strncpyz(bi->address, addr, addrlen + 1);
1017 segfault 1.1 p = q + 1;
1018     bi->telnet_port = atoi(p);
1019     q = strchr(p, '/');
1020     if (!q) {
1021     bi->relay_port = bi->telnet_port;
1022     } else {
1023     bi->relay_port = atoi(q + 1);
1024     }
1025     }
1026     set_user(&USERENTRY_BOTADDR, u1, bi);
1027     }
1028    
1029     static void cmd_comment(struct userrec *u, int idx, char *par)
1030     {
1031     char *handle;
1032     struct userrec *u1;
1033    
1034     if (!par[0]) {
1035     dprintf(idx, "Usage: comment <handle> <newcomment>\n");
1036     return;
1037     }
1038     handle = newsplit(&par);
1039     u1 = get_user_by_handle(userlist, handle);
1040     if (!u1) {
1041     dprintf(idx, "No such user!\n");
1042     return;
1043     }
1044     if ((u1->flags & USER_OWNER) && !(u && (u->flags & USER_OWNER)) &&
1045 fabian 1.26 egg_strcasecmp(handle, dcc[idx].nick)) {
1046 segfault 1.1 dprintf(idx, "Can't change comment on the bot owner.\n");
1047     return;
1048     }
1049     putlog(LOG_CMDS, "*", "#%s# comment %s %s", dcc[idx].nick, handle, par);
1050 fabian 1.26 if (!egg_strcasecmp(par, "none")) {
1051 segfault 1.1 dprintf(idx, "Okay, comment blanked.\n");
1052     set_user(&USERENTRY_COMMENT, u1, NULL);
1053     return;
1054     }
1055     dprintf(idx, "Changed comment.\n");
1056     set_user(&USERENTRY_COMMENT, u1, par);
1057     }
1058    
1059     static void cmd_restart(struct userrec *u, int idx, char *par)
1060     {
1061     putlog(LOG_CMDS, "*", "#%s# restart", dcc[idx].nick);
1062     if (!backgrd) {
1063 guppy 1.64 dprintf(idx, "%s\n", _("You can not .restart a bot when running -n (due to tcl)"));
1064 segfault 1.1 return;
1065     }
1066     dprintf(idx, "Restarting.\n");
1067 guppy 1.64 if (make_userfile)
1068 segfault 1.1 make_userfile = 0;
1069     write_userfile(-1);
1070 guppy 1.64 putlog(LOG_MISC, "*", "%s", _("Restarting ..."));
1071 segfault 1.1 wipe_timers(interp, &utimer);
1072     wipe_timers(interp, &timer);
1073     do_restart = idx;
1074     }
1075    
1076     static void cmd_rehash(struct userrec *u, int idx, char *par)
1077     {
1078     putlog(LOG_CMDS, "*", "#%s# rehash", dcc[idx].nick);
1079 guppy 1.64 dprintf(idx, "%s\n", _("Rehashing."));
1080     if (make_userfile)
1081 segfault 1.1 make_userfile = 0;
1082     write_userfile(-1);
1083 guppy 1.64 putlog(LOG_MISC, "*", "%s", _("Rehashing..."));
1084 segfault 1.1 do_restart = -2;
1085     }
1086    
1087     static void cmd_reload(struct userrec *u, int idx, char *par)
1088     {
1089     putlog(LOG_CMDS, "*", "#%s# reload", dcc[idx].nick);
1090 guppy 1.64 dprintf(idx, "%s\n", _("Reloading user file..."));
1091 segfault 1.1 reload();
1092     }
1093    
1094     void cmd_die(struct userrec *u, int idx, char *par)
1095     {
1096 guppy 1.62 char s1[1024], s2[1024];
1097 segfault 1.1
1098     putlog(LOG_CMDS, "*", "#%s# die %s", dcc[idx].nick, par);
1099     if (par[0]) {
1100 guppy 1.64 egg_snprintf(s1, sizeof s1, "%s (%s: %s)", _("BOT SHUTDOWN"), dcc[idx].nick,
1101     par);
1102     egg_snprintf(s2, sizeof s2, "%s %s!%s (%s)", _("DIE BY"), dcc[idx].nick,
1103     dcc[idx].host, par);
1104 guppy 1.62 strncpyz(quit_msg, par, 1024);
1105 segfault 1.1 } else {
1106 guppy 1.64 egg_snprintf(s1, sizeof s1, "%s (%s %s)", _("BOT SHUTDOWN"), _("Authorized by"),
1107     dcc[idx].nick);
1108     egg_snprintf(s2, sizeof s2, "%s %s!%s (%s)", _("DIE BY"), dcc[idx].nick,
1109     dcc[idx].host, _("requested"));
1110 guppy 1.62 strncpyz(quit_msg, dcc[idx].nick, 1024);
1111 segfault 1.1 }
1112 guppy 1.62 kill_bot(s1, s2);
1113 segfault 1.1 }
1114    
1115     static void cmd_debug(struct userrec *u, int idx, char *par)
1116     {
1117 fabian 1.26 if (!egg_strcasecmp(par, "help")) {
1118 segfault 1.1 putlog(LOG_CMDS, "*", "#%s# debug help", dcc[idx].nick);
1119     debug_help(idx);
1120     } else {
1121     putlog(LOG_CMDS, "*", "#%s# debug", dcc[idx].nick);
1122     debug_mem_to_dcc(idx);
1123     }
1124     }
1125    
1126     static void cmd_simul(struct userrec *u, int idx, char *par)
1127     {
1128     char *nick;
1129     int i, ok = 0;
1130    
1131     nick = newsplit(&par);
1132     if (!par[0]) {
1133 johoho 1.32 dprintf(idx, "Usage: simul <hand> <text>\n");
1134 segfault 1.1 return;
1135     }
1136     if (isowner(nick)) {
1137     dprintf(idx, "Unable to '.simul' permanent owners.\n");
1138     return;
1139     }
1140     for (i = 0; i < dcc_total; i++)
1141 fabian 1.26 if (!egg_strcasecmp(nick, dcc[i].nick) && !ok &&
1142 segfault 1.1 (dcc[i].type->flags & DCT_SIMUL)) {
1143     putlog(LOG_CMDS, "*", "#%s# simul %s %s", dcc[idx].nick, nick, par);
1144     if (dcc[i].type && dcc[i].type->activity) {
1145     dcc[i].type->activity(i, par, strlen(par));
1146     ok = 1;
1147     }
1148     }
1149     if (!ok)
1150     dprintf(idx, "No such user on the party line.\n");
1151     }
1152    
1153     static void cmd_link(struct userrec *u, int idx, char *par)
1154     {
1155     char *s;
1156     int i;
1157    
1158     if (!par[0]) {
1159     dprintf(idx, "Usage: link [some-bot] <new-bot>\n");
1160     return;
1161     }
1162     putlog(LOG_CMDS, "*", "#%s# link %s", dcc[idx].nick, par);
1163     s = newsplit(&par);
1164 fabian 1.26 if (!par[0] || !egg_strcasecmp(par, botnetnick))
1165 segfault 1.1 botlink(dcc[idx].nick, idx, s);
1166     else {
1167     char x[40];
1168    
1169     i = nextbot(s);
1170     if (i < 0) {
1171     dprintf(idx, "No such bot online.\n");
1172     return;
1173     }
1174     simple_sprintf(x, "%d:%s@%s", dcc[idx].sock, dcc[idx].nick, botnetnick);
1175     botnet_send_link(i, x, s, par);
1176     }
1177     }
1178    
1179     static void cmd_unlink(struct userrec *u, int idx, char *par)
1180     {
1181     int i;
1182     char *bot;
1183    
1184     if (!par[0]) {
1185     dprintf(idx, "Usage: unlink <bot> [reason]\n");
1186     return;
1187     }
1188     putlog(LOG_CMDS, "*", "#%s# unlink %s", dcc[idx].nick, par);
1189     bot = newsplit(&par);
1190     i = nextbot(bot);
1191     if (i < 0) {
1192     botunlink(idx, bot, par);
1193     return;
1194     }
1195 guppy 1.49 /* If we're directly connected to that bot, just do it
1196 fabian 1.22 * (is nike gunna sue?)
1197     */
1198 fabian 1.26 if (!egg_strcasecmp(dcc[i].nick, bot))
1199 segfault 1.1 botunlink(idx, bot, par);
1200     else {
1201     char x[40];
1202    
1203     simple_sprintf(x, "%d:%s@%s", dcc[idx].sock, dcc[idx].nick, botnetnick);
1204     botnet_send_unlink(i, x, lastbot(bot), bot, par);
1205     }
1206     }
1207    
1208     static void cmd_relay(struct userrec *u, int idx, char *par)
1209     {
1210     if (!par[0]) {
1211     dprintf(idx, "Usage: relay <bot>\n");
1212     return;
1213     }
1214     putlog(LOG_CMDS, "*", "#%s# relay %s", dcc[idx].nick, par);
1215     tandem_relay(idx, par, 0);
1216     }
1217    
1218     static void cmd_save(struct userrec *u, int idx, char *par)
1219     {
1220     putlog(LOG_CMDS, "*", "#%s# save", dcc[idx].nick);
1221     dprintf(idx, "Saving user file...\n");
1222     write_userfile(-1);
1223     }
1224    
1225     static void cmd_backup(struct userrec *u, int idx, char *par)
1226     {
1227     putlog(LOG_CMDS, "*", "#%s# backup", dcc[idx].nick);
1228 guppy 1.60 dprintf(idx, "Backing up the channel & user file...\n");
1229     call_hook(HOOK_BACKUP);
1230 segfault 1.1 }
1231    
1232     static void cmd_trace(struct userrec *u, int idx, char *par)
1233     {
1234     int i;
1235     char x[NOTENAMELEN + 11], y[11];
1236    
1237     if (!par[0]) {
1238     dprintf(idx, "Usage: trace <botname>\n");
1239     return;
1240     }
1241 fabian 1.26 if (!egg_strcasecmp(par, botnetnick)) {
1242 segfault 1.1 dprintf(idx, "That's me! Hiya! :)\n");
1243     return;
1244     }
1245     i = nextbot(par);
1246     if (i < 0) {
1247     dprintf(idx, "Unreachable bot.\n");
1248     return;
1249     }
1250     putlog(LOG_CMDS, "*", "#%s# trace %s", dcc[idx].nick, par);
1251     simple_sprintf(x, "%d:%s@%s", dcc[idx].sock, dcc[idx].nick, botnetnick);
1252     simple_sprintf(y, ":%d", now);
1253     botnet_send_trace(i, x, par, y);
1254     }
1255    
1256     static void cmd_binds(struct userrec *u, int idx, char *par)
1257     {
1258     putlog(LOG_CMDS, "*", "#%s# binds %s", dcc[idx].nick, par);
1259     tell_binds(idx, par);
1260     }
1261    
1262     static void cmd_banner(struct userrec *u, int idx, char *par)
1263     {
1264     char s[1024];
1265     int i;
1266    
1267     if (!par[0]) {
1268     dprintf(idx, "Usage: banner <message>\n");
1269     return;
1270     }
1271 guppy 1.50 simple_sprintf(s, "\007### Botwide: [%s] %s\n", dcc[idx].nick, par);
1272 segfault 1.1 for (i = 0; i < dcc_total; i++)
1273     if (dcc[i].type->flags & DCT_MASTER)
1274     dprintf(i, "%s", s);
1275     }
1276    
1277 fabian 1.22 /* After messing with someone's user flags, make sure the dcc-chat flags
1278     * are set correctly.
1279     */
1280 segfault 1.1 int check_dcc_attrs(struct userrec *u, int oatr)
1281     {
1282     int i, stat;
1283    
1284     if (!u)
1285     return 0;
1286 fabian 1.22 /* Make sure default owners are +n */
1287 poptix 1.57 if (isowner(u->handle)) {
1288     u->flags = sanity_check(u->flags | USER_OWNER);
1289 segfault 1.1 }
1290     for (i = 0; i < dcc_total; i++) {
1291     if ((dcc[i].type->flags & DCT_MASTER) &&
1292 fabian 1.26 (!egg_strcasecmp(u->handle, dcc[i].nick))) {
1293 segfault 1.1 stat = dcc[i].status;
1294     if ((dcc[i].type == &DCC_CHAT) &&
1295     ((u->flags & (USER_OP | USER_MASTER | USER_OWNER |
1296     USER_BOTMAST))
1297     != (oatr & (USER_OP | USER_MASTER | USER_OWNER |
1298     USER_BOTMAST)))) {
1299     botnet_send_join_idx(i, -1);
1300     }
1301     if ((oatr & USER_MASTER) && !(u->flags & USER_MASTER)) {
1302 fabian 1.22 struct flag_record fr = {FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
1303 segfault 1.1
1304     dcc[i].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS | LOG_RAW |
1305     LOG_FILES | LOG_LEV1 | LOG_LEV2 |
1306     LOG_LEV3 | LOG_LEV4 | LOG_LEV5 |
1307     LOG_LEV6 | LOG_LEV7 | LOG_LEV8 |
1308     LOG_WALL | LOG_DEBUG);
1309     get_user_flagrec(u, &fr, NULL);
1310     if (!chan_master(fr))
1311     dcc[i].u.chat->con_flags |= (LOG_MISC | LOG_CMDS);
1312     dprintf(i, "*** POOF! ***\n");
1313     dprintf(i, "You are no longer a master on this bot.\n");
1314     }
1315     if (!(oatr & USER_MASTER) && (u->flags & USER_MASTER)) {
1316     dcc[i].u.chat->con_flags |= conmask;
1317     dprintf(i, "*** POOF! ***\n");
1318     dprintf(i, "You are now a master on this bot.\n");
1319     }
1320     if (!(oatr & USER_BOTMAST) && (u->flags & USER_BOTMAST)) {
1321     dprintf(i, "### POOF! ###\n");
1322     dprintf(i, "You are now a botnet master on this bot.\n");
1323     }
1324     if ((oatr & USER_BOTMAST) && !(u->flags & USER_BOTMAST)) {
1325     dprintf(i, "### POOF! ###\n");
1326     dprintf(i, "You are no longer a botnet master on this bot.\n");
1327     }
1328     if (!(oatr & USER_OWNER) && (u->flags & USER_OWNER)) {
1329     dprintf(i, "@@@ POOF! @@@\n");
1330     dprintf(i, "You are now an OWNER of this bot.\n");
1331     }
1332     if ((oatr & USER_OWNER) && !(u->flags & USER_OWNER)) {
1333     dprintf(i, "@@@ POOF! @@@\n");
1334     dprintf(i, "You are no longer an owner of this bot.\n");
1335     }
1336     if ((stat & STAT_PARTY) && (u->flags & USER_OP))
1337     stat &= ~STAT_PARTY;
1338     if (!(stat & STAT_PARTY) && !(u->flags & USER_OP) &&
1339     !(u->flags & USER_MASTER))
1340     stat |= STAT_PARTY;
1341     if ((stat & STAT_CHAT) && !(u->flags & USER_PARTY) &&
1342     !(u->flags & USER_MASTER) &&
1343     (!(u->flags & USER_OP) || require_p))
1344     stat &= ~STAT_CHAT;
1345     if ((dcc[i].type->flags & DCT_FILES) && !(stat & STAT_CHAT) &&
1346     ((u->flags & USER_MASTER) || (u->flags & USER_PARTY) ||
1347     ((u->flags & USER_OP) && !require_p)))
1348     stat |= STAT_CHAT;
1349     dcc[i].status = stat;
1350 fabian 1.22 /* Check if they no longer have access to wherever they are.
1351 guppy 1.49 *
1352 fabian 1.22 * NOTE: DON'T kick someone off the party line just cuz they lost +p
1353     * (pinvite script removes +p after 5 mins automatically)
1354     */
1355 segfault 1.1 if ((dcc[i].type->flags & DCT_FILES) && !(u->flags & USER_XFER) &&
1356     !(u->flags & USER_MASTER)) {
1357     dprintf(i, "-+- POOF! -+-\n");
1358     dprintf(i, "You no longer have file area access.\n\n");
1359     putlog(LOG_MISC, "*", "DCC user [%s]%s removed from file system",
1360     dcc[i].nick, dcc[i].host);
1361     if (dcc[i].status & STAT_CHAT) {
1362     struct chat_info *ci;
1363    
1364     ci = dcc[i].u.file->chat;
1365     nfree(dcc[i].u.file);
1366     dcc[i].u.chat = ci;
1367     dcc[i].status &= (~STAT_CHAT);
1368     dcc[i].type = &DCC_CHAT;
1369     if (dcc[i].u.chat->channel >= 0) {
1370     chanout_but(-1, dcc[i].u.chat->channel,
1371     "*** %s has returned.\n", dcc[i].nick);
1372     if (dcc[i].u.chat->channel < 100000)
1373     botnet_send_join_idx(i, -1);
1374     }
1375     } else {
1376     killsock(dcc[i].sock);
1377 fabian 1.16 lostdcc(i);
1378 segfault 1.1 }
1379     }
1380     }
1381 fabian 1.26 if (dcc[i].type == &DCC_BOT && !egg_strcasecmp(u->handle, dcc[i].nick)) {
1382 segfault 1.1 if ((dcc[i].status & STAT_LEAF) && !(u->flags & BOT_LEAF))
1383     dcc[i].status &= ~(STAT_LEAF | STAT_WARNED);
1384     if (!(dcc[i].status & STAT_LEAF) && (u->flags & BOT_LEAF))
1385     dcc[i].status |= STAT_LEAF;
1386     }
1387     }
1388     return u->flags;
1389     }
1390    
1391     int check_dcc_chanattrs(struct userrec *u, char *chname, int chflags,
1392     int ochatr)
1393     {
1394     int i, found = 0, atr = u ? u->flags : 0;
1395     struct chanset_t *chan;
1396    
1397     if (!u)
1398     return 0;
1399     for (i = 0; i < dcc_total; i++) {
1400     if ((dcc[i].type->flags & DCT_MASTER) &&
1401 fabian 1.26 !egg_strcasecmp(u->handle, dcc[i].nick)) {
1402 segfault 1.1 if ((dcc[i].type == &DCC_CHAT) &&
1403     ((chflags & (USER_OP | USER_MASTER | USER_OWNER))
1404     != (ochatr & (USER_OP | USER_MASTER | USER_OWNER))))
1405     botnet_send_join_idx(i, -1);
1406     if ((ochatr & USER_MASTER) && !(chflags & USER_MASTER)) {
1407     if (!(atr & USER_MASTER))
1408     dcc[i].u.chat->con_flags &= ~(LOG_MISC | LOG_CMDS);
1409     dprintf(i, "*** POOF! ***\n");
1410     dprintf(i, "You are no longer a master on %s.\n", chname);
1411     }
1412     if (!(ochatr & USER_MASTER) && (chflags & USER_MASTER)) {
1413     dcc[i].u.chat->con_flags |= conmask;
1414     if (!(atr & USER_MASTER))
1415     dcc[i].u.chat->con_flags &=
1416     ~(LOG_LEV1 | LOG_LEV2 | LOG_LEV3 | LOG_LEV4 |
1417     LOG_LEV5 | LOG_LEV6 | LOG_LEV7 | LOG_LEV8 |
1418     LOG_RAW | LOG_DEBUG | LOG_WALL | LOG_FILES | LOG_SRVOUT);
1419     dprintf(i, "*** POOF! ***\n");
1420     dprintf(i, "You are now a master on %s.\n", chname);
1421     }
1422     if (!(ochatr & USER_OWNER) && (chflags & USER_OWNER)) {
1423     dprintf(i, "@@@ POOF! @@@\n");
1424     dprintf(i, "You are now an OWNER of %s.\n", chname);
1425     }
1426     if ((ochatr & USER_OWNER) && !(chflags & USER_OWNER)) {
1427     dprintf(i, "@@@ POOF! @@@\n");
1428     dprintf(i, "You are no longer an owner of %s.\n", chname);
1429     }
1430     if (((ochatr & (USER_OP | USER_MASTER | USER_OWNER)) &&
1431     (!(chflags & (USER_OP | USER_MASTER | USER_OWNER)))) ||
1432     ((chflags & (USER_OP | USER_MASTER | USER_OWNER)) &&
1433     (!(ochatr & (USER_OP | USER_MASTER | USER_OWNER))))) {
1434 fabian 1.11 struct flag_record fr = {FR_CHAN, 0, 0, 0, 0, 0};
1435 segfault 1.1
1436 guppy 1.56 for (chan = chanset; chan && !found; chan = chan->next) {
1437 fabian 1.8 get_user_flagrec(u, &fr, chan->dname);
1438 segfault 1.1 if (fr.chan & (USER_OP | USER_MASTER | USER_OWNER))
1439     found = 1;
1440     }
1441     if (!chan)
1442     chan = chanset;
1443     if (chan)
1444 fabian 1.8 strcpy(dcc[i].u.chat->con_chan, chan->dname);
1445 segfault 1.1 else
1446     strcpy(dcc[i].u.chat->con_chan, "*");
1447     }
1448     }
1449     }
1450     return chflags;
1451     }
1452    
1453     static void cmd_chattr(struct userrec *u, int idx, char *par)
1454     {
1455 fabian 1.6 char *hand, *arg = NULL, *tmpchg = NULL, *chg = NULL, work[1024];
1456 segfault 1.1 struct chanset_t *chan = NULL;
1457     struct userrec *u2;
1458 fabian 1.2 struct flag_record pls = {0, 0, 0, 0, 0, 0},
1459     mns = {0, 0, 0, 0, 0, 0},
1460     user = {0, 0, 0, 0, 0, 0};
1461 segfault 1.1 module_entry *me;
1462     int fl = -1, of = 0, ocf = 0;
1463    
1464     if (!par[0]) {
1465     dprintf(idx, "Usage: chattr <handle> [changes] [channel]\n");
1466     return;
1467     }
1468     hand = newsplit(&par);
1469     u2 = get_user_by_handle(userlist, hand);
1470 fabian 1.6 if (!u2) {
1471 segfault 1.1 dprintf(idx, "No such user!\n");
1472     return;
1473     }
1474 fabian 1.6
1475     /* Parse args */
1476     if (par[0]) {
1477 fabian 1.8 arg = newsplit(&par);
1478 fabian 1.6 if (par[0]) {
1479     /* .chattr <handle> <changes> <channel> */
1480     chg = arg;
1481 fabian 1.8 arg = newsplit(&par);
1482     chan = findchan_by_dname(arg);
1483 fabian 1.6 } else {
1484 fabian 1.8 chan = findchan_by_dname(arg);
1485 fabian 1.22 /* Consider modeless channels, starting with '+' */
1486 fabian 1.6 if (!(arg[0] == '+' && chan) &&
1487     !(arg[0] != '+' && strchr (CHANMETA, arg[0]))) {
1488     /* .chattr <handle> <changes> */
1489     chg = arg;
1490     chan = NULL; /* uh, !strchr (CHANMETA, channel[0]) && channel found?? */
1491     arg = NULL;
1492     }
1493     /* .chattr <handle> <channel>: nothing to do... */
1494     }
1495     }
1496     /* arg: pointer to channel name, NULL if none specified
1497     * chan: pointer to channel structure, NULL if none found or none specified
1498     * chg: pointer to changes, NULL if none specified
1499     */
1500 fabian 1.13 Assert(!(!arg && chan));
1501 fabian 1.6 if (arg && !chan) {
1502     dprintf(idx, "No channel record for %s.\n", arg);
1503     return;
1504 segfault 1.1 }
1505 fabian 1.6 if (chg) {
1506     if (!arg && strpbrk(chg, "&|")) {
1507     /* .chattr <handle> *[&|]*: use console channel if found... */
1508     if (!strcmp ((arg = dcc[idx].u.chat->con_chan), "*"))
1509     arg = NULL;
1510     else
1511 fabian 1.8 chan = findchan_by_dname(arg);
1512 fabian 1.6 if (arg && !chan) {
1513     dprintf (idx, "Invalid console channel %s.\n", arg);
1514     return;
1515     }
1516     } else if (arg && !strpbrk(chg, "&|")) {
1517     tmpchg = nmalloc(strlen(chg) + 2);
1518 fabian 1.11 strcpy(tmpchg, "|");
1519     strcat(tmpchg, chg);
1520 fabian 1.6 chg = tmpchg;
1521 segfault 1.1 }
1522     }
1523 fabian 1.6 par = arg;
1524 segfault 1.1 user.match = FR_GLOBAL;
1525     if (chan)
1526     user.match |= FR_CHAN;
1527 fabian 1.8 get_user_flagrec(u, &user, chan ? chan->dname : 0);
1528 segfault 1.1 if (!chan && !glob_botmast(user)) {
1529     dprintf(idx, "You do not have Bot Master privileges.\n");
1530 fabian 1.6 if (tmpchg)
1531     nfree(tmpchg);
1532 segfault 1.1 return;
1533     }
1534     if (chan && !glob_master(user) && !chan_master(user)) {
1535     dprintf(idx, "You do not have channel master privileges for channel %s\n",
1536     par);
1537 fabian 1.6 if (tmpchg)
1538     nfree(tmpchg);
1539 segfault 1.1 return;
1540     }
1541     user.match &= fl;
1542     if (chg) {
1543     pls.match = user.match;
1544     break_down_flags(chg, &pls, &mns);
1545 fabian 1.22 /* No-one can change these flags on-the-fly */
1546 fabian 1.6 pls.global &= ~(USER_BOT);
1547     mns.global &= ~(USER_BOT);
1548 segfault 1.1
1549     if (chan) {
1550     pls.chan &= ~(BOT_SHARE);
1551     mns.chan &= ~(BOT_SHARE);
1552     }
1553     if (!glob_owner(user)) {
1554 fabian 1.6 pls.global &= ~(USER_OWNER | USER_MASTER | USER_BOTMAST | USER_UNSHARED);
1555     mns.global &= ~(USER_OWNER | USER_MASTER | USER_BOTMAST | USER_UNSHARED);
1556 segfault 1.1
1557     if (chan) {
1558     pls.chan &= ~USER_OWNER;
1559     mns.chan &= ~USER_OWNER;
1560     }
1561     if (!glob_master(user)) {
1562 fabian 1.6 pls.global &= USER_PARTY | USER_XFER;
1563     mns.global &= USER_PARTY | USER_XFER;
1564 segfault 1.1
1565     if (!glob_botmast(user)) {
1566     pls.global = 0;
1567     mns.global = 0;
1568     }
1569     }
1570     }
1571     if (chan && !chan_owner(user) && !glob_owner(user)) {
1572     pls.chan &= ~USER_MASTER;
1573     mns.chan &= ~USER_MASTER;
1574     if (!chan_master(user) && !glob_master(user)) {
1575     pls.chan = 0;
1576     mns.chan = 0;
1577     }
1578     }
1579     get_user_flagrec(u2, &user, par);
1580     if (user.match & FR_GLOBAL) {
1581     of = user.global;
1582     user.global = sanity_check((user.global |pls.global) &~mns.global);
1583    
1584     user.udef_global = (user.udef_global | pls.udef_global)
1585     & ~mns.udef_global;
1586     }
1587     if (chan) {
1588     ocf = user.chan;
1589     user.chan = chan_sanity_check((user.chan | pls.chan) & ~mns.chan,
1590     user.global);
1591    
1592     user.udef_chan = (user.udef_chan | pls.udef_chan) & ~mns.udef_chan;
1593     }
1594     set_user_flagrec(u2, &user, par);
1595     }
1596     if (chan)
1597     putlog(LOG_CMDS, "*", "#%s# (%s) chattr %s %s",
1598 fabian 1.8 dcc[idx].nick, chan ? chan->dname : "*", hand, chg ? chg : "");
1599 segfault 1.1 else
1600     putlog(LOG_CMDS, "*", "#%s# chattr %s %s", dcc[idx].nick, hand,
1601     chg ? chg : "");
1602 fabian 1.22 /* Get current flags and display them */
1603 segfault 1.1 if (user.match & FR_GLOBAL) {
1604     user.match = FR_GLOBAL;
1605     if (chg)
1606     check_dcc_attrs(u2, of);
1607     get_user_flagrec(u2, &user, NULL);
1608     build_flags(work, &user, NULL);
1609     if (work[0] != '-')
1610     dprintf(idx, "Global flags for %s are now +%s\n", hand, work);
1611     else
1612     dprintf(idx, "No global flags for %s.\n", hand);
1613     }
1614     if (chan) {
1615     user.match = FR_CHAN;
1616     get_user_flagrec(u2, &user, par);
1617     user.chan &= ~BOT_SHARE;
1618     if (chg)
1619 fabian 1.8 check_dcc_chanattrs(u2, chan->dname, user.chan, ocf);
1620 segfault 1.1 build_flags(work, &user, NULL);
1621     if (work[0] != '-')
1622     dprintf(idx, "Channel flags for %s on %s are now +%s\n", hand,
1623 fabian 1.8 chan->dname, work);
1624 segfault 1.1 else
1625 fabian 1.8 dprintf(idx, "No flags for %s on %s.\n", hand, chan->dname);
1626 fabian 1.6 if (chg && (me = module_find("irc", 0, 0))) {
1627 segfault 1.1 Function *func = me->funcs;
1628    
1629     if (chan)
1630 fabian 1.2 (func[IRC_RECHECK_CHANNEL]) (chan, 0);
1631 segfault 1.1 }
1632     }
1633 fabian 1.6 if (tmpchg)
1634     nfree(tmpchg);
1635 segfault 1.1 }
1636    
1637     static void cmd_botattr(struct userrec *u, int idx, char *par)
1638     {
1639 fabian 1.6 char *hand, *chg = NULL, *arg = NULL, *tmpchg = NULL, work[1024];
1640 segfault 1.1 struct chanset_t *chan = NULL;
1641     struct userrec *u2;
1642 fabian 1.8 struct flag_record pls = {0, 0, 0, 0, 0, 0},
1643     mns = {0, 0, 0, 0, 0, 0},
1644     user = {0, 0, 0, 0, 0, 0};
1645 segfault 1.1 int idx2;
1646    
1647     if (!par[0]) {
1648     dprintf(idx, "Usage: botattr <handle> [changes] [channel]\n");
1649     return;
1650     }
1651     hand = newsplit(&par);
1652     u2 = get_user_by_handle(userlist, hand);
1653 fabian 1.6 if (!u2 || !(u2->flags & USER_BOT)) {
1654 segfault 1.1 dprintf(idx, "No such bot!\n");
1655     return;
1656     }
1657     for (idx2 = 0; idx2 < dcc_total; idx2++)
1658 fabian 1.33 if (dcc[idx2].type != &DCC_RELAY && dcc[idx2].type != &DCC_FORK_BOT &&
1659     !egg_strcasecmp(dcc[idx2].nick, hand))
1660 segfault 1.1 break;
1661     if (idx2 != dcc_total) {
1662 fabian 1.6 dprintf(idx, "You may not change the attributes of a directly linked bot.\n");
1663 segfault 1.1 return;
1664     }
1665 fabian 1.6 /* Parse args */
1666     if (par[0]) {
1667 fabian 1.10 arg = newsplit(&par);
1668 fabian 1.6 if (par[0]) {
1669     /* .botattr <handle> <changes> <channel> */
1670     chg = arg;
1671 fabian 1.10 arg = newsplit(&par);
1672 fabian 1.8 chan = findchan_by_dname(arg);
1673 fabian 1.6 } else {
1674 fabian