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

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

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


Revision 1.37 - (hide annotations) (download) (as text)
Thu Jun 22 03:45:05 2000 UTC (19 years, 5 months ago) by guppy
Branch: MAIN
Changes since 1.36: +5 -4 lines
File MIME type: text/x-chdr
put all patches in the queue into 1.4

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