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