/[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.100 - (hide annotations) (download) (as text)
Fri May 3 07:57:12 2002 UTC (17 years, 7 months ago) by stdarg
Branch: MAIN
Changes since 1.99: +44 -52 lines
File MIME type: text/x-chdr
* Made itraffic_* otraffic_* into a single struct.
* mod-path -> mod_path

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