1 /*
2 * ninjacmd.c:
3 *
4 * this file contains code dealing with /commands for ninja irc
5 *
6 * written by Kraig Amador and Joshua J. Drake
7 *
8 */
9
10 #include "irc.h"
11 #include "dma.h"
12 #include "ircterm.h"
13 #include "vars.h"
14 #include "ircaux.h"
15 #include "server.h"
16 #include "hook.h"
17 #include "window.h"
18 #include "screen.h"
19 #include "output.h"
20 #include "whois.h"
21 #include "parse.h"
22 #include "log.h"
23 #include "notify.h"
24
25 #include "channels.h"
26 #include "bans.h"
27 #include "info.h"
28 #include "friends.h"
29 #include "enemies.h"
30 #include "hosts.h"
31 #include "how_many.h"
32 #include "grep.h"
33 #include "orignick.h"
34 #include "ninja.h"
35 #include "ckey.h"
36 #include "mileston.h"
37 #include "irc_comm.h"
38 #include "ninjacmd.h"
39
40 /* little thingy to help /mdop out */
41 static int nodeop _((u_char **, u_char *));
42
43 /* stuff in edit.c */
44 extern void send_action _((u_char *, u_char *));
45
46 /* nasty global var!! */
47 int in_update_cmd = 0;
48
49 /*
50 * does /whois but with the nickname twice
51 */
52 void
whois2(command,args,subargs)53 whois2(command, args, subargs)
54 u_char *command, *args, *subargs;
55 {
56 u_char *nick;
57
58 if (args && *args)
59 nick = args;
60 else
61 nick = get_server_nickname(from_server);
62 send_to_server("%s %s %s", command, nick, nick);
63 }
64
65 /*
66 * chhost() changes the source host name and tells the user
67 * to reconnect to the server..
68 */
69 void
chhost(command,args,subargs)70 chhost(command, args, subargs)
71 u_char *command, *args, *subargs;
72 {
73 u_char *nhn;
74
75 if ((nhn = next_arg(args, &args)) == NULL)
76 {
77 usage("chhost", "<new host name>");
78 return;
79 }
80 set_var_value(IRCHOST_VAR, nhn);
81 put_info("Use /reconnect to make changes effective.");
82 }
83
84 /*
85 * chuname() changes the username (optionally the hostname and realname field)
86 */
87 void
chuname(command,args,subargs)88 chuname(command, args, subargs)
89 u_char *command, *args, *subargs;
90 {
91 u_char *nun, *nhn = UNULL;
92 u_char *identfn;
93
94 nun = next_arg(args, &args);
95 if (nun)
96 {
97 nhn = my_rindex(nun, '@');
98 if (nhn)
99 *nhn++ = '\0';
100 }
101
102 /* check for a username */
103 if (!nun || my_strlen(nun) < 1)
104 {
105 usage(command, "<new user name>[@<host>] [<real name field>]");
106 return;
107 }
108
109 /* is there a hostname too? */
110 if (nhn)
111 {
112 if (my_strlen(nhn) > 0)
113 set_var_value(IRCHOST_VAR, nhn);
114 else
115 {
116 /* zero length host? */
117 put_error("Please specify a hostname after the @.");
118 return;
119 }
120 }
121
122 /* make the username active */
123 my_strmcpy(username, nun, NAME_LEN - 1);
124
125 /* if we have an ident file name, update it */
126 if ((identfn = get_string_var(HACKED_IDENTD_VAR)) != NULL)
127 {
128 FILE *identf;
129 u_char *ex_idfn = NULL;
130
131 if (*identfn == '~')
132 ex_idfn = expand_twiddle(identfn);
133 if (!ex_idfn)
134 ex_idfn = identfn;
135
136 /* update it */
137 identf = fopen(ex_idfn, "w");
138 if (identf == NULL)
139 put_error("Unable to write to your HACKED_IDENTD file: %s", strerror(errno));
140 else
141 {
142 fprintf(identf, "%s\n", nun);
143 fflush(identf);
144 fclose(identf);
145 put_info("Identity file, \"%s\", updated.", identfn);
146 }
147 if (ex_idfn != identfn)
148 dma_Free(&ex_idfn);
149 }
150 /* just a username change? */
151 if (nhn == NULL)
152 put_info("Changed your user name to: %s", nun);
153 else /* both user and host */
154 put_info("Changed your user@host to: %s@%s", nun, nhn);
155
156 /* do we have a realname too?! */
157 if (args && *args)
158 {
159 set_string_var(REALNAME_VAR, realname);
160 put_info("Changed real name field to: %s", realname);
161 }
162
163 put_info("Use /reconnect to make changes effective.");
164 }
165
166 /*
167 * /about command
168 */
169 void
ninja_about(command,args,subargs)170 ninja_about(command, args, subargs)
171 u_char *command, *args, *subargs;
172 {
173 put_info("Ninja IRC v%s, build #%s by %s@%s on %s [%s]",
174 irc_version,
175 compile_num, compile_user, compile_host, compile_time,
176 ninja_release);
177 put_info("");
178 put_info(" started in 1997 with ircII 2.8.2 to");
179 put_info(" pass some time. i wanted to make");
180 put_info(" ircII look better and have extra features");
181 put_info(" without the slowness of the scripts...");
182 put_info("");
183 put_info("ninja contributors");
184 put_info("");
185 put_info(" Joshua J. Drake Kraig Amador");
186 put_info("");
187 put_info("bug reports and feedback should be aimed at");
188 put_info("IRC: jduck@EFNet or EMAIL: ninja@qoop.org");
189 }
190
191 /*
192 * /uptime command
193 */
194 void
uptime(command,args,subargs)195 uptime(command, args, subargs)
196 u_char *command, *args, *subargs;
197 {
198 time_t uptime_val = time(NULL) - start_time;
199
200 put_info("Your client has been running %s.", ninja_etime(uptime_val));
201 return;
202 }
203
204 /*
205 * /update command
206 */
207 void
update_cmd(command,args,subargs)208 update_cmd(command, args, subargs)
209 u_char *command, *args, *subargs;
210 {
211 extern int checked_for_update;
212
213 checked_for_update = 1;
214 in_update_cmd = 1;
215 ninja_check_update(0);
216 #ifndef NON_BLOCKING_CONNECTS
217 in_update_cmd = 0;
218 #endif
219 }
220
221 #ifdef ALLOW_CHAN_RESYNC
222 /*
223 * re-sync a channel
224 *
225 * this is mostly just a debug command..
226 * if you thing its usefull enough, compile it in...
227 */
228 void
resync(command,args,subargs)229 resync(command, args, subargs)
230 u_char *command, *args, *subargs;
231 {
232 u_char *chan;
233 Channel *tmp;
234
235 if ((chan = next_arg(args, &args)) == NULL)
236 {
237 usage(command, "<channel>");
238 return;
239 }
240 if ((tmp = lookup_channel(make_chan(chan), from_server, 0)) == (Channel *) NULL)
241 {
242 put_error("You're not on %s", chan);
243 return;
244 }
245 tmp->status = 0;
246 send_to_server("NAMES %s", tmp->channel);
247 send_to_server("WHO %s", tmp->channel);
248 send_to_server("MODE %s", tmp->channel);
249 send_to_server("MODE %s b", tmp->channel);
250 /*
251 if (my_index(server_list[from_server].cmodes, 'e'))
252 send_to_server("MODE %s e", tmp->channel);
253 if (my_index(server_list[from_server].cmodes, 'd'))
254 send_to_server("MODE %s d", tmp->channel);
255 */
256 }
257 #endif
258
259 /*
260 * /sc command..
261 */
262 void
ninja_scan(command,args,subargs)263 ninja_scan(command, args, subargs)
264 u_char *command, *args, *subargs;
265 {
266 Channel *chan;
267 Nick *nick;
268 u_char *channel = NULL, ltb[64], tmpbuf1[1024];
269 int count = 0, vcount = 0, ocount = 0;
270 float op_pc, voi_pc;
271
272 if (args && *args)
273 channel = make_chan(next_arg(args, &args));
274 else if (!get_channel_by_refnum(0))
275 {
276 put_info("You are not on a channel!");
277 return;
278 }
279 else
280 channel = get_channel_by_refnum(0);
281 if ((chan = lookup_channel(channel, from_server, 0)))
282 {
283 u_char *nickstr = NULL, *space = " ", *at = "@", *plus = "+";
284
285 if (!(chan->status & CHAN_WHO))
286 {
287 put_info("Sorry, %s is not totally synched yet, please wait...", chan->channel);
288 return;
289 }
290 for (nick = chan->nicks; nick; nick = nick->next)
291 {
292 if ((nick->status & NICK_CHOP))
293 dma_strcat(&nickstr, at);
294 else if ((nick->status & NICK_VOICE))
295 dma_strcat(&nickstr, plus);
296 dma_strcat(&nickstr, nick->nick);
297 if (nick->next)
298 dma_strcat(&nickstr, space);
299 }
300 if (do_hook(NAMES_LIST, "%s %s", chan->channel, nickstr))
301 {
302 for (nick = chan->nicks; nick; nick = nick->next)
303 {
304 if ((nick->status & NICK_VOICE) && !(nick->status & NICK_CHOP))
305 vcount++;
306 if (nick->status & NICK_CHOP)
307 ocount++;
308 count++;
309 }
310 op_pc = ((float) ocount * 100.0) / (float) count;
311 voi_pc = ((float) vcount * 100.0) / (float) count;
312
313 snprintf(tmpbuf1, sizeof(tmpbuf1) - 1,
314 "--[ Users(%d) on %s ]-[ %.1f%% ops(%d), %.1f%% voiced(%d) ]--",
315 count, chan->channel, op_pc, ocount, voi_pc, vcount);
316 tmpbuf1[sizeof(tmpbuf1)-1] = '\0';
317 put_raw("%s%s", tmpbuf1, strfill('-', current_screen->co - my_strlen(tmpbuf1) - 2));
318
319 tmpbuf1[0] = '\0';
320 if (count)
321 {
322 count = 0;
323 for (nick = chan->nicks; nick; nick = nick->next)
324 {
325 if ((nick->status & NICK_CHOP))
326 snprintf(ltb, sizeof(ltb) - 1, "@%-9.9s ", nick->nick);
327 else if ((nick->status & NICK_VOICE))
328 snprintf(ltb, sizeof(ltb) - 1, "+%-9.9s ", nick->nick);
329 else
330 snprintf(ltb, sizeof(ltb) - 1, " %-9.9s ", nick->nick);
331 ltb[sizeof(ltb)-1] = '\0';
332 strmcat(tmpbuf1, ltb, sizeof(tmpbuf1) - 1);
333 if (count++ == (((current_screen->co - 2) / 11) - 1))
334 {
335 put_raw("%s", tmpbuf1);
336 *tmpbuf1 = '\0';
337 count = 0;
338 }
339 }
340 if (count && tmpbuf1[0])
341 put_raw("%s", tmpbuf1);
342 }
343 }
344 dma_Free(&nickstr);
345 }
346 else
347 {
348 put_info("You're not on %s!", channel);
349 return;
350 }
351 }
352
353 /*
354 * /users command
355 *
356 * this command attempts to mimic /who but with cached information
357 */
358 void
users(command,args,subargs)359 users(command, args, subargs)
360 u_char *command, *args, *subargs;
361 {
362 Channel *chan;
363 Ban *banptr;
364 Nick *nicks;
365 Enemy *e;
366 EChan *ec;
367 Friend *f;
368 FChan *fc;
369 u_char *channel = NULL, *foo, *foo2;
370 u_char feb[16], format[128], tmpbuf1[384];
371 u_int cwidth, showhops;
372 /* this stuff is for /who comapatability.. */
373 u_char *arg, *nam, *hst, *srv, *file, *nick, *real, *no_open = UNULL;
374 int noargs = 1, len, mask = 0, ok = 1;
375 u_char buf_data[BUFSIZ];
376 FILE *fip;
377
378 hst = srv = nam = file = nick = real = UNULL;
379 /* parse for [<flags>] */
380 while ((arg = next_arg(args, &args)))
381 {
382 noargs = 0;
383 if (*arg == '-' && !isdigit(*(arg + 1)))
384 {
385 u_char *cmd = UNULL;
386
387 arg++;
388 if ((len = my_strlen(arg)) == 0)
389 {
390 usage(command, "[<flags>] [<channel>]");
391 goto out;
392 }
393 dma_strcpy(&cmd, arg);
394 lower(cmd);
395 if (my_strncmp(cmd, "operators", len) == 0)
396 mask |= WHO_OPS;
397 else if (my_strncmp(cmd, "lusers", len) == 0)
398 mask |= WHO_LUSERS;
399 else if (my_strncmp(cmd, "chops", len) == 0)
400 mask |= WHO_CHOPS;
401 else if (my_strncmp(cmd, "hosts", len) == 0)
402 {
403 if ((arg = next_arg(args, &args)) != NULL)
404 {
405 mask |= WHO_HOST;
406 malloc_strcpy(&hst, arg);
407 channel = hst;
408 }
409 else
410 {
411 usage(command, "-host <hostmask> [<channel>]");
412 new_free(&cmd);
413 goto out;
414 }
415 }
416 else if (my_strncmp(cmd, "here", len) == 0)
417 mask |= WHO_HERE;
418 else if (my_strncmp(cmd, "away", len) == 0)
419 mask |= WHO_AWAY;
420 else if (my_strncmp(cmd, "servers", len) == 0)
421 {
422 if ((arg = next_arg(args, &args)) != NULL)
423 {
424 mask |= WHO_SERVER;
425 malloc_strcpy(&srv, arg);
426 channel = srv;
427 }
428 else
429 {
430 usage(command, "-server <server mask> [<channel>]");
431 new_free(&cmd);
432 goto out;
433 }
434 }
435 else if (my_strncmp(cmd, "name", len) == 0 || my_strncmp(cmd, "user", len) == 0)
436 {
437 if ((arg = next_arg(args, &args)) != NULL)
438 {
439 mask |= WHO_NAME;
440 malloc_strcpy(&nam, arg);
441 channel = nam;
442 }
443 else
444 {
445 usage(command, "-name <username mask> [<channel>]");
446 new_free(&cmd);
447 goto out;
448 }
449 }
450 else if (my_strncmp(cmd, "realname", len) == 0)
451 {
452 if ((arg = next_arg(args, &args)) != NULL)
453 {
454 mask |= WHO_REAL;
455 malloc_strcpy(&real, arg);
456 channel = real;
457 }
458 else
459 {
460 usage(command, "-realname <real mask> [<channel>]");
461 new_free(&cmd);
462 goto out;
463 }
464 }
465 else if (my_strncmp(cmd, "nick", len) == 0)
466 {
467 if ((arg = next_arg(args, &args)) != NULL)
468 {
469 mask |= WHO_NICK;
470 malloc_strcpy(&nick, arg);
471 channel = who_nick;
472 }
473 else
474 {
475 usage(command, "-nick <nick name mask> [<channel>]");
476 new_free(&cmd);
477 goto out;
478 }
479 /* WHO -FILE by Martin 'Efchen' Friedrich */
480 }
481 else if (my_strncmp(cmd, "file", len) == 0)
482 {
483 mask |= WHO_FILE;
484 if ((arg = next_arg(args, &args)) != NULL)
485 malloc_strcpy(&file, arg);
486 else
487 {
488 usage(command, "-file <mask file> [<channel>]");
489 new_free(&cmd);
490 goto out;
491 }
492 }
493 else
494 {
495 usage(command, "[<flags>] [<channel>]");
496 new_free(&cmd);
497 goto out;
498 }
499 new_free(&cmd);
500 }
501 else if (my_strcmp(arg, "*") == 0)
502 {
503 channel = get_channel_by_refnum(0);
504 if (!channel || *channel == '0')
505 {
506 say("I wouldn't do that if I were you");
507 goto out;
508 }
509 }
510 else
511 channel = arg;
512 }
513 /* get the channel to list */
514 if (noargs)
515 channel = get_channel_by_refnum(0);
516 if (channel && !is_channel(channel))
517 channel = make_chan(channel);
518 if (!channel)
519 {
520 usage(command, "[<flags>] [<channel>]");
521 goto out;;
522 }
523
524 /* are we on the channel? */
525 if ((chan = lookup_channel(channel, from_server, 0)) == NULL)
526 {
527 put_info("You're not on %s!", channel);
528 goto out;
529 }
530
531 /* is the channel fully cached? */
532 if (!(chan->status & CHAN_WHO))
533 {
534 #ifdef SHOW_JOIN_TIME
535 put_info("Sorry, %s is not cached yet, please wait for the cache message.", chan->channel);
536 #else
537 put_info("Sorry, %s is not cached yet, please wait..", chan->channel);
538 #endif
539 goto out;
540 }
541
542 /* create the format */
543 showhops = get_int_var(SHOW_WHO_HOPCOUNT_VAR);
544 if ((cwidth = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0)
545 {
546 snprintf(format, sizeof(format) - 1, "%%-%u.%us %%-9s |%%-3s", (u_char) cwidth, (u_char) cwidth);
547 format[sizeof(format)-1] = '\0';
548 }
549 else
550 my_strmcpy(format, "%s\t%-9s |%-3s", sizeof(format) - 1);
551 if (showhops)
552 my_strmcat(format, " %2d", sizeof(format) - 1);
553 my_strmcat(format, "|", sizeof(format) - 1);
554 my_strmcat(format, " %s@%s (%s)", sizeof(format) - 1);
555
556 /* show them.. */
557 for (nicks = chan->nicks; nicks; nicks = nicks->next)
558 {
559 ok = 1;
560
561 memset(feb, 0, sizeof(feb));
562 foo = feb;
563 /* here or away? */
564 if (nicks->status & NICK_HERE)
565 *foo++ = 'H';
566 if (nicks->status & NICK_AWAY)
567 *foo++ = 'G';
568 /* operator? */
569 if (nicks->status & NICK_OPER)
570 *foo++ = '*';
571 /* opped? */
572 if (nicks->status & NICK_CHOP)
573 *foo++ = '@';
574 /* voiced? */
575 if (nicks->status & NICK_VOICE)
576 *foo++ = '+';
577
578 /* enemy? *//* XXX: NEED TO CREATE GET_ENEMY_BY_NUH() */
579 foo2 = nicks->user;
580 if (foo2 && *foo2 == '~')
581 foo2++;
582 snprintf(tmpbuf1, sizeof(tmpbuf1) - 1, "%s!%s@%s", nicks->nick, foo2 ? foo2 : empty_string, nicks->host);
583 tmpbuf1[sizeof(tmpbuf1)-1] = '\0';
584
585 if ((e = get_enemy(tmpbuf1)) != NULL && (ec = get_enemy_chan(e, chan->channel, 0)) != NULL)
586 *foo++ = 'E';
587
588 /* banned? */
589 for (banptr = chan->bans; banptr; banptr = banptr->next)
590 {
591 if (wild_match(banptr->ban, tmpbuf1))
592 {
593 *foo++ = 'B';
594 break;
595 }
596 }
597
598 /* friend? */
599 f = get_friend_by_mask(tmpbuf1);
600 if (f)
601 {
602 *foo++ = 'F';
603 if ((fc = get_fchan(f, chan->channel, 0)))
604 *foo++ = 'C';
605 }
606
607 /* realname cached? */
608 if (nicks->realname)
609 foo = nicks->realname;
610 else
611 foo = empty_string;
612
613 /* check for mask flags */
614 if (mask)
615 {
616 if (mask & WHO_HERE)
617 ok = ok && (nicks->status & NICK_HERE);
618 if (mask & WHO_AWAY)
619 ok = ok && (nicks->status & NICK_AWAY);
620 if (mask & WHO_OPS)
621 ok = ok && (nicks->status & NICK_OPER);
622 if (mask & WHO_LUSERS)
623 ok = ok && !(nicks->status & NICK_OPER);
624 if (mask & WHO_CHOPS)
625 ok = ok && (nicks->status & NICK_CHOP);
626 if (mask & WHO_NAME)
627 ok = ok && wild_match(nam, nicks->user);
628 if (mask & WHO_NICK)
629 ok = ok && wild_match(nick, nicks->nick);
630 if (mask & WHO_HOST)
631 ok = ok && wild_match(hst, nicks->host);
632 if (mask & WHO_REAL)
633 ok = ok && wild_match(real, nicks->realname);
634 if (mask & WHO_SERVER)
635 ok = ok && wild_match(srv, nicks->server);
636 if (mask & WHO_FILE)
637 {
638 ok = 0;
639 if ((fip = fopen(CP(file), "r")) != (FILE *) 0)
640 {
641 while (fgets((char *) buf_data, BUFSIZ, fip) != (char *) 0)
642 {
643 buf_data[my_strlen(buf_data) - 1] = '\0';
644 ok = ok || wild_match(buf_data, nicks->nick);
645 }
646 fclose(fip);
647 }
648 else
649 no_open = file;
650 }
651 }
652
653 /* show the line! */
654 if (ok && do_hook(WHO_LIST, "%s %s %s %s %s %s", chan->channel, nicks->nick, feb, nicks->user, nicks->host, foo))
655 {
656 if (showhops)
657 put_raw(format, chan->channel, nicks->nick, feb, nicks->hops, nicks->user, nicks->host, foo);
658 else
659 put_raw(format, chan->channel, nicks->nick, feb, nicks->user, nicks->host, foo);
660 }
661 }
662 if (no_open)
663 put_error("Cannot open: %s", no_open);
664 out:
665 dma_Free(&hst);
666 dma_Free(&srv);
667 dma_Free(&nam);
668 dma_Free(&real);
669 dma_Free(&nick);
670 dma_Free(&file);
671 }
672
673 /*
674 * just leave a channel and join it
675 */
676 void
cycle(command,args,subargs)677 cycle(command, args, subargs)
678 u_char *command, *args, *subargs;
679 {
680 u_char *tmpchannel = UNULL, tmpbuf[1024];
681 Channel *chan;
682
683 if (args && *args)
684 tmpchannel = make_chan(next_arg(args, &args));
685 else if (!get_channel_by_refnum(0))
686 {
687 put_info("You are not on a channel!");
688 return;
689 }
690 else
691 tmpchannel = get_channel_by_refnum(0);
692
693 if ((chan = lookup_channel(tmpchannel, from_server, 0)) == NULL)
694 {
695 put_info("You are not on %s!", tmpchannel);
696 return;
697 }
698
699 my_strmcpy(tmpbuf, chan->channel, sizeof(tmpbuf) - 1);
700 if (chan->key)
701 {
702 my_strmcat(tmpbuf, " ", sizeof(tmpbuf) - 1);
703 my_strmcat(tmpbuf, chan->key, sizeof(tmpbuf) - 1);
704 }
705 send_to_server("PART %s", tmpchannel);
706 send_to_server("JOIN %s", tmpbuf);
707 }
708
709 /*
710 * send a message to all ops on a channel
711 *
712 * note, this is currently broken due to the nick,nick,nick support
713 * in most servers being broken.
714 */
715 void
do_wall(command,args,subargs)716 do_wall(command, args, subargs)
717 u_char *command, *args, *subargs;
718 {
719 u_char *channel;
720 Nick *nickl;
721 Channel *chanl;
722
723 if (!args || !*args)
724 {
725 usage(command, "[<channel>] <message>");
726 return;
727 }
728
729 if (is_channel(args))
730 channel = next_arg(args, &args);
731 else if ((channel = get_channel_by_refnum(0)) == NULL)
732 {
733 put_info("You're not on a channel.");
734 return;
735 }
736
737 /* am i on the channel? */
738 chanl = lookup_channel(channel, from_server, 0);
739 if (!chanl)
740 {
741 put_error("You're not on %s.", channel);
742 return;
743 }
744 else
745 {
746 u_char wallline[1024], ops[1024];
747 int count = 0, opcount = 0;
748 int first = 1;
749
750 /* what are we going to send everyone? */
751 snprintf(wallline, sizeof(wallline) - 1, "(%s WallOp) %s", channel, args);
752 wallline[sizeof(wallline)-1] = '\0';
753
754 /* who are we going to send it to? */
755 ops[0] = '\0';
756 for (nickl = chanl->nicks; nickl; nickl = nickl->next)
757 if ((nickl->status & NICK_CHOP) && (strcmp(nickl->nick, nickname) != 0))
758 {
759 if (first)
760 {
761 snprintf(ops, sizeof(ops) - 1, "%s,", nickl->nick);
762 ops[sizeof(ops)-1] = '\0';
763 first = 0;
764 }
765 else
766 {
767 strmcat(ops, nickl->nick, sizeof(ops) - 1);
768 strmcat(ops, ",", sizeof(ops) - 1);
769 }
770 count++;
771 opcount++;
772 if (count == 10)
773 {
774 count = 0;
775 first = 1;
776 send_to_server("NOTICE %s :%s", ops, wallline);
777 ops[0] = '\0';
778 }
779 }
780 send_to_server("NOTICE %s :%s", ops, wallline);
781 put_raw("-> (sent %d) %s", opcount, wallline);
782 }
783 }
784
785 /*
786 * this handles kick and bankick
787 *
788 * 09/27/01 cleaned up/optimized by jjd
789 */
790 void
do_special_k(command,args,subargs)791 do_special_k(command, args, subargs)
792 u_char *command, *args, *subargs;
793 {
794 u_char *person, *channel, *reason = NULL;
795 Channel *chanl;
796
797 if (!args || !*args)
798 {
799 usage(command, "[<channel>] <nick> [<reason>]");
800 return;
801 }
802
803 if (is_channel(args))
804 channel = next_arg(args, &args);
805 else if ((channel = get_channel_by_refnum(0)) == NULL)
806 {
807 put_info("You're not on a channel.");
808 return;
809 }
810
811 /* am i on the channel? */
812 chanl = lookup_channel(channel, from_server, 0);
813 if (!chanl)
814 {
815 put_error("You're not on %s.", channel);
816 return;
817 }
818
819 if (!(chanl->status & CHAN_CHOP))
820 {
821 put_error("You're not opped on %s.", channel);
822 return;
823 }
824 else
825 {
826 person = next_arg(args, &args);
827 if (!is_on_channel(channel, from_server, person))
828 {
829 put_error("Hey! %s is not on %s!", person, channel);
830 return;
831 }
832 /* do i have a reason? */
833 if (args && *args)
834 reason = args;
835 else
836 reason = UP("out!");
837 /* should we ban them too? */
838 if (*command == 'B' || my_strcmp(command, "KICKBAN") == 0 || my_strcmp(command, "KB") == 0)
839 do_ban_stuff("BAN", person, channel);
840 /* kick them */
841 send_to_server("KICK %s %s :%s", chanl->channel, person, reason);
842 }
843 }
844
845 /*
846 * this handles /fk and /fbk
847 *
848 * 09/27/01 cleaned up/optimized by jjd
849 */
850 void
filter_kick(command,args,subargs)851 filter_kick(command, args, subargs)
852 u_char *command, *args, *subargs;
853 {
854 u_char *channel, *nuhmask, reason[128];
855 int ban = 0, old_limit, count = 0;
856 Channel *chanl;
857 Nick *nickl;
858
859 if (my_strcmp(command, "FBK") == 0)
860 ban = 1;
861
862 /* check for a mask */
863 nuhmask = next_arg(args, &args);
864 if (!nuhmask)
865 {
866 usage(command, "<filter mask> [<channel> [<reason>]]");
867 return;
868 }
869 if (!my_index(nuhmask, '!') || !my_index(nuhmask, '@'))
870 {
871 put_error("You must specify a valid nick!user@host mask.");
872 return;
873 }
874
875 /* check out the channel situation */
876 if (args && is_channel(args))
877 channel = next_arg(args, &args);
878 else
879 channel = get_channel_by_refnum(0);
880 if (!channel)
881 {
882 put_info("You're not on a channel.");
883 return;
884 }
885
886 /* see if i'm on the channel */
887 chanl = lookup_channel(channel, from_server, 0);
888 if (!chanl)
889 {
890 put_error("You're not on %s.", channel);
891 return;
892 }
893 if (!(chanl->status & CHAN_CHOP))
894 {
895 put_error("You're not opped on %s.", channel);
896 return;
897 }
898
899 /* do we have a reason? */
900 if (args && *args)
901 my_strmcpy(reason, args, sizeof(reason) - 1);
902 else
903 {
904 my_strmcpy(reason, "You match ", sizeof(reason) - 1);
905 my_strmcat(reason, nuhmask, sizeof(reason) - 1);
906 }
907
908 /* initial pass to see if anyone matches.. */
909 for (nickl = chanl->nicks; nickl; nickl = nickl->next)
910 {
911 u_char nuh[384], *foo;
912
913 /* don't kick myself!! */
914 if (my_stricmp(nickl->nick, get_server_nickname(chanl->server)) == 0)
915 continue;
916 foo = nickl->user;
917 if (*foo == '~')
918 foo++;
919 snprintf(nuh, sizeof(nuh) - 1, "%s!*%s@%s", nickl->nick, foo, nickl->host);
920 nuh[sizeof(nuh)-1] = '\0';
921 if (wild_match(nuhmask, nuh))
922 count++;
923 }
924
925 if (count < 1)
926 {
927 put_error("Nobody on %s matches %s!", channel, nuhmask);
928 return;
929 }
930
931 /* if we are supposed to ban them, do it last, but for now, +l 1 */
932 old_limit = chanl->limit;
933 if (ban)
934 send_to_server("MODE %s +l 1", channel);
935
936 /* kick those foolz */
937 for (nickl = chanl->nicks; nickl; nickl = nickl->next)
938 {
939 u_char nuh[384], *foo;
940
941 /* don't kick myself!! */
942 if (my_stricmp(nickl->nick, get_server_nickname(chanl->server)) == 0)
943 continue;
944 foo = nickl->user;
945 if (*foo == '~')
946 foo++;
947 snprintf(nuh, sizeof(nuh) - 1, "%s!*%s@%s", nickl->nick, foo, nickl->host);
948 nuh[sizeof(nuh)-1] = '\0';
949 if (wild_match(nuhmask, nuh))
950 send_to_server("KICK %s %s :%s", chanl->channel, nickl->nick, reason);
951 }
952
953 /* add the ban and restore the limit if necessary */
954 if (ban)
955 send_to_server("MODE %s +b %s", channel, nuhmask);
956 if (old_limit > 0)
957 send_to_server("MODE %s +l %u", channel, old_limit);
958 else
959 send_to_server("MODE %s -l", channel);
960 }
961
962 /*
963 * kick all non-ops out of a channel
964 */
965 void
lamer_kick(command,args,subargs)966 lamer_kick(command, args, subargs)
967 u_char *command, *args, *subargs;
968 {
969 u_char *chan, reason[128];
970 Nick *nickl;
971 Channel *chanl;
972
973 chan = next_arg(args, &args);
974 if (!chan)
975 {
976 usage(command, "<channel> [<reason>]");
977 return;
978 }
979 chan = make_chan(chan);
980
981 /* make sure i'm on the channel */
982 chanl = lookup_channel(chan, from_server, 0);
983 if (!chanl)
984 {
985 put_error("You're not on %s.", chan);
986 return;
987 }
988
989 /* make sure i can kick */
990 if (!(chanl->status & CHAN_CHOP))
991 {
992 put_error("You're not opped on %s.", chan);
993 return;
994 }
995
996 /* setup the reason */
997 if (args && *args)
998 {
999 my_strmcpy(reason, args, sizeof(reason) - 1);
1000 my_strmcat(reason, " (", sizeof(reason) - 1);
1001 my_strmcat(reason, "non-op", sizeof(reason) - 1);
1002 my_strmcat(reason, ")", sizeof(reason) - 1);
1003 }
1004 else
1005 my_strmcpy(reason, "non-op", sizeof(reason) - 1);
1006
1007 /* kick those lamers! */
1008 for (nickl = chanl->nicks; nickl; nickl = nickl->next)
1009 if (!(nickl->status & NICK_CHOP))
1010 send_to_server("KICK %s %s :%s", chan, nickl->nick, reason);
1011 }
1012
1013 /*
1014 * give_or_take_ops() does a standard:
1015 * /mode [<channel>] +/-o[ooo] <nick> [.. .. ..]
1016 *
1017 * it gives/takes ops to/from all people in the args that are
1018 * on the specified channel (or current if no channel is specified)
1019 *
1020 * 07/05/97 does voice too. FUNCTION OVERLOAD!@#
1021 * 09/27/01 cleanup/optimization by jjd
1022 */
1023 void
give_or_take_ops(command,args,subargs)1024 give_or_take_ops(command, args, subargs)
1025 u_char *command, *args, *subargs;
1026 {
1027 u_char *opchan = UNULL;
1028 char *mstr = NULL;
1029 u_char sign, mch;
1030 int num_nicks = 0;
1031
1032 /* do we have a channel? */
1033 if (is_channel(args))
1034 {
1035 opchan = next_arg(args, &args);
1036 if (!(args && *args))
1037 {
1038 usage(command, "[#/&<channel>] <nick1> ... <nickn>");
1039 return;
1040 }
1041 }
1042 else if ((opchan = get_channel_by_refnum(0)) == NULL)
1043 {
1044 put_info("You are not on any channels!");
1045 return;
1046 }
1047
1048 /* plus or minus? */
1049 if ((my_strncmp(command, "OP", 2) == 0) || (my_strncmp(command, "VOICE", 5) == 0))
1050 sign = '+';
1051 else
1052 sign = '-';
1053
1054 /* voice or ops? */
1055 if (!my_strncmp(command, "VOICE", 5) || !my_strncmp(command, "DVOICE", 6))
1056 mch = 'v';
1057 else
1058 mch = 'o';
1059
1060 /* how many people were specified? */
1061 num_nicks = how_many(args, ' ') + 1;
1062 if (num_nicks >= 4)
1063 mstr = strfill(mch, 4);
1064 while (num_nicks >= 4)
1065 {
1066 u_char *nick1 = NULL, *nick2 = NULL, *nick3 = NULL, *nick4 = NULL;
1067
1068 nick1 = next_arg(args, &args);
1069 nick2 = next_arg(args, &args);
1070 nick3 = next_arg(args, &args);
1071 nick4 = next_arg(args, &args);
1072 send_to_server("MODE %s %c%s %s %s %s %s", opchan, sign, mstr, nick1, nick2, nick3, nick4);
1073 num_nicks -= 4;
1074 }
1075 if (num_nicks > 0)
1076 {
1077 mstr = strfill(mch, num_nicks);
1078 send_to_server("MODE %s %c%s %s", opchan, sign, mstr, args);
1079 }
1080 }
1081
1082 #ifdef ALLOW_OJ /* lets see if anyone misses, i won't */
1083 /*
1084 * on join ?
1085 * for /oj (op the last person to join)
1086 * this is bloat.
1087 */
1088 void
oj(char * command,char * args,char * subargs)1089 oj(char *command, char *args, char *subargs)
1090 {
1091 extern *joined_chan;
1092
1093 if (!joined_nick)
1094 return;
1095 else
1096 send_to_server("MODE %s +o %s", joined_chan, joined_nick);
1097 }
1098 #endif
1099
1100 /*
1101 * change a channel's key
1102 *
1103 * 09/27/01 cleaned up/optimized by jjd
1104 */
1105 void
chkey(command,args,subargs)1106 chkey(command, args, subargs)
1107 u_char *command, *args, *subargs;
1108 {
1109 u_char *mychan = NULL, *newkey = NULL;
1110 Channel *chan;
1111
1112 if (!(args && *args))
1113 {
1114 usage("chkey", "[<channel>] -|<new key>");
1115 return;
1116 }
1117 newkey = next_arg(args, &args);
1118 if (args && *args)
1119 {
1120 mychan = make_chan(newkey);
1121 newkey = next_arg(args, &args);
1122 }
1123 else if (!get_channel_by_refnum(0))
1124 {
1125 put_info("You are not on any channels!");
1126 return;
1127 }
1128 else
1129 mychan = get_channel_by_refnum(0);
1130
1131 /* am i on the channel? */
1132 chan = lookup_channel(mychan, from_server, 0);
1133 if (!chan)
1134 {
1135 put_info("You are not on %s.", mychan);
1136 return;
1137 }
1138
1139 /* check for ops */
1140 if (!(chan->status & CHAN_CHOP))
1141 {
1142 put_info("Changing the key requires ops.");
1143 return;
1144 }
1145
1146 /* change the key */
1147 if (chan->key)
1148 send_to_server("MODE %s -k %s", mychan, chan->key);
1149 if (my_strcmp(newkey, "-") != 0)
1150 send_to_server("MODE %s +k %s", mychan, newkey);
1151 }
1152
1153 /*
1154 * change the channel limit
1155 */
1156 void
change_channel_limit(command,args,subargs)1157 change_channel_limit(command, args, subargs)
1158 u_char *command, *args, *subargs;
1159 {
1160 u_char *limit, *chann;
1161 long ldlimit;
1162
1163 limit = next_arg(args, &args);
1164 if (!limit)
1165 {
1166 usage(command, "<limit/-> [<channel>]");
1167 return;
1168 }
1169
1170 /* check out the channel situation */
1171 if (((chann = next_arg(args, &args)) != NULL) && (my_strcmp(chann, "*") != 0))
1172 chann = (u_char *) make_chan(chann);
1173 else if ((chann = get_channel_by_refnum(0)) == NULL)
1174 {
1175 put_info("You are not on a channel.");
1176 return;
1177 }
1178
1179 ldlimit = my_atol(limit);
1180 if (ldlimit > 0)
1181 send_to_server("MODE %s +l %ld", chann, ldlimit);
1182 else if (my_strcmp(limit, "-") == 0)
1183 send_to_server("MODE %s -l", chann);
1184 else
1185 put_error("Invalid channel limit: %s", limit);
1186 }
1187
1188 /*
1189 * mass modes!
1190 */
1191 void
mass(command,args,subargs)1192 mass(command, args, subargs)
1193 u_char *command, *args, *subargs;
1194 {
1195 Channel *chanl;
1196 Nick *nickl;
1197 u_char *type, *chann;
1198 u_char mode;
1199 int dickmode = 0, count = 0;
1200 u_char tmpbuf1[1024];
1201
1202 if (!args || !*args)
1203 {
1204 usage(command, "[+|-]<mode> [<channel>]");
1205 return;
1206 }
1207 type = next_arg(args, &args);
1208 if (*type == '-')
1209 dickmode = 1;
1210 if (!isalpha(*type))
1211 type++;
1212 switch (*type)
1213 {
1214 case 'v':
1215 mode = 'v';
1216 break;
1217 case 'o':
1218 mode = 'o';
1219 break;
1220 default:
1221 usage(command, "[+|-]<mode> [<channel>]");
1222 return;
1223 }
1224 if ((chann = next_arg(args, &args)) == NULL)
1225 if ((chann = get_channel_by_refnum(0)) == NULL)
1226 {
1227 put_error("You must by on a channel to do mass modes..");
1228 return;
1229 }
1230 chann = (u_char *) make_chan(chann);
1231 if ((chanl = lookup_channel(chann, from_server, 0)) == NULL)
1232 {
1233 put_error("You're not on %s!", chann);
1234 return;
1235 }
1236 if (!is_chanop(chann, get_server_nickname(from_server)))
1237 {
1238 put_error("You must be opped to do mass modes.", chann);
1239 return;
1240 }
1241 put_info("Executing a mass %s%c on %s.", dickmode ? "-" : "+", mode, chanl->channel);
1242 if ((mode == 'o') && dickmode)
1243 {
1244 mdop("MDOP", chanl->channel, NULL);
1245 return;
1246 }
1247 bzero(tmpbuf1, sizeof(tmpbuf1));
1248 for (nickl = chanl->nicks; nickl; nickl = nickl->next)
1249 {
1250 if (my_strcmp(nickl->nick, get_server_nickname(from_server)) != 0)
1251 {
1252 if ((dickmode && mode == 'v' && (nickl->status & NICK_VOICE)) ||
1253 (!dickmode && mode == 'v' && !(nickl->status & NICK_VOICE) && !(nickl->status & NICK_CHOP)) ||
1254 (!dickmode && mode == 'o' && !(nickl->status & NICK_CHOP)))
1255 {
1256 strmcat(tmpbuf1, " ", sizeof(tmpbuf1) - 1);
1257 strmcat(tmpbuf1, nickl->nick, sizeof(tmpbuf1) - 1);
1258 count++;
1259 }
1260 }
1261 if (count == 4)
1262 {
1263 count = 0;
1264 send_to_server("MODE %s %s%s %s", chanl->channel, dickmode ? "-" : "+", strfill(mode, 4), tmpbuf1);
1265 bzero(tmpbuf1, sizeof(tmpbuf1));
1266 }
1267 }
1268 send_to_server("MODE %s %s%s %s", chanl->channel, dickmode ? "-" : "+", strfill(mode, count), tmpbuf1);
1269 return;
1270 }
1271
1272 /* dispatcher for abbreviated /mass commands:
1273 * /mop, /mvoice, /mdvoice
1274 */
1275 void
mass_abbrev(command,args,subargs)1276 mass_abbrev(command, args, subargs)
1277 u_char *command, *args, *subargs;
1278 {
1279 u_char *tmp;
1280
1281 tmp = (u_char *) dma_Malloc(strlen(args) + 4);
1282 if (strcmp(command, "MOP") == 0)
1283 {
1284 sprintf(tmp, "+o %s", args); /* safe, malloc()'d */
1285 mass("MOP", tmp, NULL);
1286 }
1287 else if (strcmp(command, "MVOICE") == 0)
1288 {
1289 sprintf(tmp, "+v %s", args); /* safe, malloc()'d */
1290 mass("MVOICE", tmp, NULL);
1291 }
1292 else if (strcmp(command, "MDVOICE") == 0)
1293 {
1294 sprintf(tmp, "-v %s", args); /* safe, malloc()'d */
1295 mass("MDVOICE", tmp, NULL);
1296 }
1297 dma_Free(&tmp);
1298 }
1299
1300 /*
1301 * super k-rad elite MASS DEOP code
1302 */
1303 void
mdop(command,args,subargs)1304 mdop(command, args, subargs)
1305 u_char *command, *args, *subargs;
1306 {
1307 #define DEADPPL_SIZE 1024
1308 #define MAX_DEADPPL 200
1309 #define MAX_SAFEPPL 20
1310 #define NINJA_BAN_MASK "ninja!irc@rulez"
1311 u_char *chann, deadppl[DEADPPL_SIZE][MAX_DEADPPL], *safeppl[MAX_SAFEPPL];
1312 u_char tmpbuf1[1024];
1313 Channel *chanl;
1314 Nick *nicks;
1315 int count = 0, lines = 0, i = 0, safecnt = 0, test = 0;
1316
1317 chann = next_arg(args, &args);
1318 if (chann && my_strcmp(chann, "-t") == 0)
1319 {
1320 test = 1;
1321 chann = next_arg(args, &args);
1322 }
1323 if (!chann)
1324 {
1325 usage(command, "[-t] <channel> [<nicks not to deop>]");
1326 return;
1327 }
1328 /* zero out deadppl and safeppl.. */
1329 for (i = 0; i < MAX_DEADPPL; i++)
1330 *deadppl[i] = 0;
1331 for (i = 0; i < MAX_SAFEPPL; i++)
1332 safeppl[i] = NULL;
1333
1334 if (my_strlen(args) > 0)
1335 {
1336 put_info("I promise not to deop: %s", args);
1337 safeppl[safecnt] = next_arg(args, &args);
1338 while (safeppl[safecnt] != NULL)
1339 {
1340 safecnt++;
1341 safeppl[safecnt] = next_arg(args, &args);
1342 }
1343 }
1344 if (my_strcmp(chann, asterik) == 0)
1345 chann = get_channel_by_refnum(0);
1346 else
1347 chann = (u_char *) make_chan(chann);
1348 if (!chann || !(chanl = lookup_channel(chann, from_server, CHAN_NOUNLINK)))
1349 {
1350 put_error("You're not on %s!", chann);
1351 return;
1352 }
1353 if (!test && !(chanl->status & CHAN_CHOP))
1354 {
1355 put_error("You must be opped to mass de-op!");
1356 return;
1357 }
1358 bzero(tmpbuf1, sizeof(tmpbuf1));
1359 for (nicks = chanl->nicks; nicks; nicks = nicks->next)
1360 {
1361 if ((strcmp(get_server_nickname(from_server), nicks->nick) != 0) &&
1362 (nicks->status & NICK_CHOP) && !nodeop(safeppl, nicks->nick))
1363 {
1364 if (*tmpbuf1)
1365 {
1366 strmcat(tmpbuf1, " ", sizeof(tmpbuf1) - 1);
1367 strmcat(tmpbuf1, nicks->nick, sizeof(tmpbuf1) - 1);
1368 }
1369 else
1370 snprintf(tmpbuf1, sizeof(tmpbuf1), "%s", nicks->nick);
1371 count++;
1372 }
1373 if (count == 3)
1374 {
1375 snprintf(deadppl[lines], DEADPPL_SIZE - 1, "MODE %s -b%s %s %s", chanl->channel,
1376 strfill('o', count), NINJA_BAN_MASK, tmpbuf1);
1377 *(deadppl[lines] + DEADPPL_SIZE - 1) = '\0';
1378 lines++;
1379 count = 0;
1380 *tmpbuf1 = '\0';
1381 }
1382 }
1383 if (count)
1384 {
1385 snprintf(deadppl[lines], DEADPPL_SIZE - 1, "MODE %s -b%s %s %s", chanl->channel,
1386 strfill('o', count), NINJA_BAN_MASK, tmpbuf1);
1387 *(deadppl[lines] + DEADPPL_SIZE - 1) = '\0';
1388 lines++;
1389 }
1390 if (lines == 0)
1391 {
1392 put_error("Nobody on %s is opped.", chanl->channel);
1393 return;
1394 }
1395 for (i = 0; i < lines; i++)
1396 {
1397 if (test)
1398 put_raw("%s", deadppl[i]);
1399 else
1400 send_to_server("%s", deadppl[i]);
1401 }
1402 }
1403
1404 /* this goes with /mdop */
1405 static int
nodeop(u_char * ppl[],u_char * user)1406 nodeop(u_char * ppl[], u_char * user)
1407 {
1408 int blehcnt = 0;
1409
1410 if (ppl[blehcnt] == NULL)
1411 return 0;
1412 do
1413 {
1414 if (!my_stricmp(ppl[blehcnt], user))
1415 return 1;
1416 blehcnt++;
1417 }
1418 while (ppl[blehcnt] != NULL);
1419 return 0;
1420 }
1421
1422 /*
1423 * ban/unban masks/nicks
1424 */
1425 void
do_ban_stuff(command,args,subargs)1426 do_ban_stuff(command, args, subargs)
1427 u_char *command, *args, *subargs;
1428 {
1429 int meany;
1430 u_char *person, *chann, *evil = NULL;
1431 u_char *ex, *at;
1432 Nick *nicks;
1433 Channel *c;
1434
1435 if (command[0] == 'B')
1436 meany = 1;
1437 else
1438 meany = 0;
1439 if ((person = next_arg(args, &args)) != NULL)
1440 {
1441 chann = next_arg(args, &args);
1442 if (!chann)
1443 chann = get_channel_by_refnum(0);
1444 if (!chann || !*chann)
1445 {
1446 put_info("You're not on a channel.");
1447 return;
1448 }
1449 if (!is_channel(chann))
1450 chann = make_chan(chann);
1451 /* now we should have a valid channel */
1452 c = lookup_channel(chann, from_server, CHAN_NOUNLINK);
1453 if (!c)
1454 return;
1455
1456 if (!(c->status & CHAN_CHOP))
1457 {
1458 put_info("You have no ops to add/remove bans with!");
1459 return;
1460 }
1461
1462 /* if we are specifying a mask instead of a nickname */
1463 ex = my_index(person, '!');
1464 at = my_index(person, '@');
1465 if (ex || at)
1466 {
1467 u_char theshiz[512];
1468
1469 if (!at && ex)
1470 snprintf(theshiz, sizeof(theshiz) - 1, "%s@*", person);
1471 else if (at && !ex)
1472 snprintf(theshiz, sizeof(theshiz) - 1, "*!%s", person);
1473 else
1474 my_strncpy(theshiz, person, sizeof(theshiz) - 1);
1475 theshiz[sizeof(theshiz)-1] = '\0';
1476 if (meany)
1477 send_to_server("MODE %s +b %s", chann, theshiz);
1478 else
1479 remove_matching_bans(theshiz, NULL, NULL, chann, 0);
1480 return;
1481 }
1482 else if ((nicks = find_nick(person, UNULL, from_server, c)) != NULL)
1483 {
1484 u_char *user = nicks->user;
1485
1486 if (user && *user == '~')
1487 user++;
1488 if (user && *user)
1489 user++;
1490 if (meany)
1491 {
1492 if (nicks->status & NICK_CHOP)
1493 send_to_server("MODE %s -o+b %s *!*%s@%s", chann, nicks->nick, user, cluster(nicks->host));
1494 else
1495 send_to_server("MODE %s +b *!*%s@%s", chann, user, cluster(nicks->host));
1496 }
1497 else
1498 remove_matching_bans(nicks->nick, user, nicks->host, chann, 0);
1499 evil--;
1500 return;
1501 }
1502 if (meany)
1503 add_to_whois_queue(person, ban_queue, "%s", chann);
1504 else
1505 add_to_whois_queue(person, unban_queue, "%s", chann);
1506 }
1507 else
1508 usage(command, "<nick/mask> [<channel>]");
1509 }
1510
1511 /*
1512 * /adds
1513 */
1514 void
addserver(command,args,subargs)1515 addserver(command, args, subargs)
1516 u_char *command, *args, *subargs;
1517 {
1518 int port_num = 0;
1519 int old_server = 0;
1520 u_char *password, *port, *nick, *server, *extra, *umode;
1521
1522 if (!(args && *args))
1523 {
1524 usage("adds", "<server>[:<port>:<password>:<nick>:<umode>]");
1525 return;
1526 }
1527 password = port = nick = extra = umode = UNULL;
1528 server = next_arg(args, &args);
1529 parse_server_info(&server, &port, &password, &nick, &umode, &extra);
1530 if (port && *port)
1531 {
1532 port_num = my_atoi(port);
1533 if (!port_num)
1534 port_num = irc_port;
1535 }
1536 else
1537 port_num = irc_port;
1538 old_server = from_server;
1539 add_to_server_list(server, port_num, password, nick, umode, 0);
1540 from_server = old_server;
1541 put_info("%s %d added to your server list.", server, port_num);
1542 }
1543
1544 /*
1545 * /rems
1546 */
1547 void
removeserver(command,args,subargs)1548 removeserver(command, args, subargs)
1549 u_char *command, *args, *subargs;
1550 {
1551 int port_num = 0;
1552 int old_server = 0;
1553 int servernum = 0;
1554 u_char *password, *port, *nick, *server, *extra, *umode;
1555
1556 if (!(args && *args))
1557 {
1558 usage("rems", "<#> or <server>[:<port>]");
1559 return;
1560 }
1561 password = port = nick = extra = umode = UNULL;
1562 server = next_arg(args, &args);
1563 parse_server_info(&server, &port, &password, &nick, &umode, &extra);
1564 if (port && *port)
1565 {
1566 port_num = my_atoi(port);
1567 if (!port_num)
1568 port_num = irc_port;
1569 }
1570 else
1571 port_num = irc_port;
1572
1573 old_server = from_server;
1574 if ((servernum = atoi(server)) > 0 && servernum <= number_of_servers)
1575 servernum--;
1576 else
1577 servernum = find_in_server_list(server, port_num, NULL);
1578
1579 if (servernum < 0 || servernum >= number_of_servers)
1580 {
1581 put_info("Unable to locate server \"%s\" in the server list.", server);
1582 return;
1583 }
1584
1585 if (server_list[servernum].connected || server_list[servernum].read != -1)
1586 put_info("Server #%d (%s:%d) is connected, not removing.", servernum + 1, server_list[servernum].name,
1587 server_list[servernum].port);
1588 else
1589 {
1590 put_info("Removed server #%d (%s:%d) from your list.", servernum + 1, server_list[servernum].name,
1591 server_list[servernum].port);
1592 remove_from_server_list(servernum);
1593 }
1594 from_server = old_server;
1595 }
1596
1597 /* this is an input prompt */
1598 void
short_playlog(u_char * data,u_char * line)1599 short_playlog(u_char * data, u_char * line)
1600 {
1601 if (!(strcasecmp(line, "Y")))
1602 playlog(NULL, NULL, NULL);
1603 else
1604 add_wait_prompt("Erase your stored messages? [y/N] ", short_eraselog, "", WAIT_PROMPT_LINE);
1605 }
1606
1607 /*
1608 * away: the /AWAY command. Keeps track of the away message locally, and
1609 * sends the command on to the server.
1610 * Only sets the current server away unless -all is specified
1611 * vars used: EMAIL_ADDRESS, SILENT_AWAY, DEFAULT_AWAY_MSG
1612 * if EMAIL_ADDRESS is non-NULL it is appened to the away message as
1613 * [email: blah@lemae.com], else ignored. if SILENT_AWAY is set, the away
1614 * messages will not be sent to the channel(s)
1615 */
1616 void
away(command,args,subargs)1617 away(command, args, subargs)
1618 u_char *command, *args, *subargs;
1619 {
1620 u_char tmpu_char[BIG_BUFFER_SIZE], *defaway = NULL;
1621 u_char awaymsg[1024], *arg1, *email;
1622 int old_server = from_server;
1623
1624 email = get_string_var(EMAIL_ADDRESS_VAR);
1625 if (args && *args)
1626 {
1627 if (*args == '-')
1628 {
1629 arg1 = next_arg(args, &args);
1630 if (my_strnicmp(arg1 + 1, "ALL", 3) == 0)
1631 {
1632 if ((args && *args) || ((defaway = get_string_var(DEFAULT_AWAY_MSG_VAR)) != NULL))
1633 snprintf(awaymsg, sizeof(awaymsg) - 1, "(%s)", args && *args ? args : defaway);
1634 else
1635 {
1636 put_info("Either provide a reason or set DEFAULT_AWAY_MSG to something.");
1637 return;
1638 }
1639 if (email)
1640 {
1641 snprintf(tmpu_char, sizeof(tmpu_char) - 1, " [email: %s]", email);
1642 strmcat(awaymsg, tmpu_char, sizeof(awaymsg) - 1);
1643 }
1644 for (from_server = 0; from_server < number_of_servers; from_server++)
1645 {
1646 if (server_list[from_server].away_set == 0)
1647 {
1648 server_list[from_server].away_set = time(NULL);
1649 server_list[from_server].away_count = 0;
1650 dma_strcpy(&server_list[from_server].away, awaymsg);
1651 if (server_list[from_server].connected)
1652 {
1653 if (!get_int_var(SILENT_AWAY_VAR))
1654 {
1655 snprintf(tmpu_char, sizeof(tmpu_char), "is out. %s", awaymsg);
1656 ame("AME", tmpu_char, NULL);
1657 }
1658 send_to_server("%s :%s", command, awaymsg);
1659 }
1660 }
1661 }
1662 from_server = old_server;
1663 open_away_log(awaymsg);
1664 update_all_status();
1665 return;
1666 }
1667 else
1668 {
1669 put_error("Unknown option: %s", arg1);
1670 return;
1671 }
1672 }
1673 else
1674 snprintf(awaymsg, sizeof(awaymsg) - 1, "(%s)", args);
1675 }
1676 else if ((defaway = get_string_var(DEFAULT_AWAY_MSG_VAR)) != NULL)
1677 snprintf(awaymsg, sizeof(awaymsg) - 1, "(%s)", defaway);
1678 else
1679 {
1680 put_info("Either provide a reason or set DEFAULT_AWAY_MSG to something.");
1681 return;
1682 }
1683 if (server_list[from_server].away_set != 0)
1684 {
1685 put_error("You're already set away on this server. Use /back.");
1686 return;
1687 }
1688 if (email)
1689 {
1690 snprintf(tmpu_char, sizeof(tmpu_char) - 1, " [email: %s]", email);
1691 strmcat(awaymsg, tmpu_char, sizeof(awaymsg) - 1);
1692 }
1693 if (!get_int_var(SILENT_AWAY_VAR))
1694 {
1695 snprintf(tmpu_char, sizeof(tmpu_char), "is out. %s", awaymsg);
1696 ame("AME", tmpu_char, NULL);
1697 }
1698 server_list[from_server].away_set = time(NULL);
1699 server_list[from_server].away_count = 0;
1700 dma_strcpy(&server_list[from_server].away, awaymsg);
1701 open_away_log(awaymsg);
1702 send_to_server("%s :%s", command, awaymsg);
1703 update_all_status();
1704 }
1705
1706 /*
1707 * same algorithm as away, but messages reflect being back and away gets unset.
1708 * -ALL is honored, if not set, only the current server is set back..
1709 * vars used: SILENT_AWAY, DEFAULT_BACK_MSG
1710 * they are fairly self explanatory
1711 * asks the user if they want to view their away messages if they get set back
1712 */
1713 void
back(command,args,subargs)1714 back(command, args, subargs)
1715 u_char *command, *args, *subargs;
1716 {
1717 u_char *defback = NULL, *arg1;
1718 u_char backmsg[1024], tmpu_char[BIG_BUFFER_SIZE];
1719 time_t atime;
1720 int old_server = from_server;
1721
1722 if (args && *args)
1723 {
1724 if (*args == '-')
1725 {
1726 arg1 = next_arg(args, &args);
1727 if (my_strnicmp(arg1 + 1, "ALL", 3) == 0)
1728 {
1729 if ((args && *args) || ((defback = get_string_var(DEFAULT_BACK_MSG_VAR)) != NULL))
1730 snprintf(backmsg, sizeof(backmsg), "(%s)", args && *args ? args : defback);
1731 else
1732 {
1733 put_info("Either provide a reason or set DEFAULT_BACK_MSG to something.");
1734 return;
1735 }
1736 for (from_server = 0; from_server < number_of_servers; from_server++)
1737 if (server_list[from_server].away_set != 0)
1738 {
1739 atime = time(NULL) - server_list[from_server].away_set;
1740 server_list[from_server].away_set = 0;
1741 server_list[from_server].away_count = 0;
1742 dma_Free(&server_list[from_server].away);
1743 if (server_list[from_server].connected)
1744 {
1745 if (!get_int_var(SILENT_AWAY_VAR))
1746 {
1747 snprintf(tmpu_char, sizeof(tmpu_char), "is back after %s. %s", ninja_etime(atime), backmsg);
1748 ame("AME", tmpu_char, NULL);
1749 }
1750 send_to_server("%s :", command);
1751 }
1752 }
1753 from_server = old_server;
1754 update_all_status();
1755 close_away_log(backmsg);
1756 add_wait_prompt("Play your stored messages? [y/N] ", short_playlog, "", WAIT_PROMPT_LINE);
1757 return;
1758 }
1759 else
1760 {
1761 put_error("Unknown option: %s", arg1);
1762 return;
1763 }
1764 }
1765 else
1766 snprintf(backmsg, sizeof(backmsg), "(%s)", args);
1767 }
1768 else if ((defback = get_string_var(DEFAULT_BACK_MSG_VAR)) != NULL)
1769 snprintf(backmsg, sizeof(backmsg), "(%s)", defback);
1770 else
1771 {
1772 put_info("Either provide a reason or set DEFAULT_BACK_MSG to something.");
1773 return;
1774 }
1775 if (server_list[from_server].away_set == 0)
1776 {
1777 put_error("You're not marked away on this server.");
1778 return;
1779 }
1780 atime = time(NULL) - server_list[from_server].away_set;
1781 if (!get_int_var(SILENT_AWAY_VAR))
1782 {
1783 snprintf(tmpu_char, sizeof(tmpu_char), "has returned after %s. %s", ninja_etime(atime), backmsg);
1784 ame("AME", tmpu_char, NULL);
1785 }
1786 server_list[from_server].away_set = 0;
1787 server_list[from_server].away_count = 0;
1788 dma_Free(&server_list[from_server].away);
1789 send_to_server("%s :", command);
1790 update_all_status();
1791 close_away_log(backmsg);
1792 add_wait_prompt("Play your stored messages? [y/N] ", short_playlog, "", WAIT_PROMPT_LINE);
1793 }
1794
1795 /*
1796 * /me on all channels
1797 */
1798 void
ame(command,args,subargs)1799 ame(command, args, subargs)
1800 u_char *command, *args, *subargs;
1801 {
1802 Channel *tmp;
1803
1804 if (!args || !*args)
1805 {
1806 usage(command, "<message>");
1807 return;
1808 }
1809 for (tmp = server_list[from_server].chan_list; tmp; tmp = tmp->next)
1810 {
1811 int old = set_lastlog_msg_level(LOG_ACTION);
1812
1813 save_message_from();
1814 send_action(tmp->channel, args);
1815 message_from(tmp->channel, LOG_ACTION);
1816 if (do_hook(SEND_ACTION_LIST, "%s %s", tmp->channel, args))
1817 put_raw("* %s %s", get_server_nickname(from_server), args);
1818 set_lastlog_msg_level(old);
1819 restore_message_from();
1820 }
1821 }
1822
1823 /*
1824 *
1825 * XXX: at some point i will merge this with IRCII /save
1826 */
1827 void
ninja_save(command,args,subargs)1828 ninja_save(command, args, subargs)
1829 u_char *command, *args, *subargs;
1830 {
1831 ChanGrep *channel;
1832 u_char *filename = NULL, tmpoutbuf[1024], ltb[512];
1833 FILE *outfile;
1834 int vcount = 0, scount = 0, ncount = 0, gcount = 0;
1835 int fcount = 0, ecount = 0, kcount = 0;
1836 int first = 1;
1837 u_char *na, *pa, *ni, *um;
1838
1839 if (qflag)
1840 {
1841 put_error("You started Ninja IRC with the -q flag, saving is disabled.");
1842 return;
1843 }
1844
1845 filename = NINJA_SAVE_FILE;
1846 if (*filename == '~')
1847 filename = expand_twiddle(filename);
1848 outfile = fopen(filename, "w");
1849 if (outfile == NULL)
1850 {
1851 put_error("Cannot open save file(%s), aborting save..", filename);
1852 if (CP(filename) != NINJA_SAVE_FILE)
1853 dma_Free(&filename);
1854 return;
1855 }
1856 if (CP(filename) != NINJA_SAVE_FILE)
1857 dma_Free(&filename);
1858 if (orignickname)
1859 fprintf(outfile, "ORIGNICK ON %s\n", orignickname);
1860 vcount = save_variables(outfile, 1);
1861 if (server_list)
1862 for (scount = 0; scount < number_of_servers; scount++)
1863 {
1864 na = server_list[scount].name;
1865 first = server_list[scount].port;
1866 pa = server_list[scount].password;
1867 ni = server_list[scount].nickname;
1868 um = server_list[scount].usermode;
1869 fprintf(outfile, "ADDS %s:%d:%s:%s:%s\n",
1870 na ? na : empty_string, first, pa ? pa : empty_string, ni ? ni : empty_string, um ? um : empty_string);
1871 }
1872 for (channel = grep_list; channel; channel = channel->next)
1873 {
1874 fprintf(outfile, "GREP %s %s\n", channel->channel, channel->words);
1875 gcount++;
1876 }
1877
1878 /* save the notify list... */
1879 ncount = save_notify(outfile);
1880
1881 /* friends, enemies, channel keys */
1882 fcount = save_friends(1);
1883 ecount = save_enemies(1);
1884 kcount = save_ckeys(1);
1885
1886 /* build the output string.. */
1887 first = 1;
1888 strcpy(tmpoutbuf, "Saved:");
1889 if (vcount)
1890 {
1891 if (!first)
1892 strmcat(tmpoutbuf, ",", sizeof(tmpoutbuf)-1);
1893 first = 0;
1894 snprintf(ltb, sizeof(ltb)-1,
1895 " %d variable%s", vcount, PLURAL(vcount));
1896 ltb[sizeof(ltb)-1] = '\0';
1897 strmcat(tmpoutbuf, ltb, sizeof(tmpoutbuf)-1);
1898 }
1899 if (scount)
1900 {
1901 if (!first)
1902 strmcat(tmpoutbuf, ",", sizeof(tmpoutbuf)-1);
1903 first = 0;
1904 snprintf(ltb, sizeof(ltb)-1,
1905 " %d server%s", scount, PLURAL(scount));
1906 ltb[sizeof(ltb)-1] = '\0';
1907 strmcat(tmpoutbuf, ltb, sizeof(tmpoutbuf)-1);
1908 }
1909 if (gcount)
1910 {
1911 if (!first)
1912 strmcat(tmpoutbuf, ",", sizeof(tmpoutbuf)-1);
1913 first = 0;
1914 snprintf(ltb, sizeof(ltb)-1,
1915 " %d grep entr%s", gcount, Y_PLURAL(gcount));
1916 ltb[sizeof(ltb)-1] = '\0';
1917 strmcat(tmpoutbuf, ltb, sizeof(tmpoutbuf)-1);
1918 }
1919 if (ncount)
1920 {
1921 if (!first)
1922 strmcat(tmpoutbuf, ",", sizeof(tmpoutbuf)-1);
1923 first = 0;
1924 snprintf(ltb, sizeof(ltb)-1,
1925 " %d notify entr%s", ncount, Y_PLURAL(ncount));
1926 ltb[sizeof(ltb)-1] = '\0';
1927 strmcat(tmpoutbuf, ltb, sizeof(tmpoutbuf)-1);
1928 }
1929 if (fcount)
1930 {
1931 if (!first)
1932 strmcat(tmpoutbuf, ",", sizeof(tmpoutbuf)-1);
1933 first = 0;
1934 snprintf(ltb, sizeof(ltb)-1,
1935 " %d friend%s", fcount, PLURAL(fcount));
1936 ltb[sizeof(ltb)-1] = '\0';
1937 strmcat(tmpoutbuf, ltb, sizeof(tmpoutbuf)-1);
1938 }
1939 if (ecount)
1940 {
1941 if (!first)
1942 strmcat(tmpoutbuf, ",", sizeof(tmpoutbuf)-1);
1943 first = 0;
1944 snprintf(ltb, sizeof(ltb)-1,
1945 " %d enem%s", ecount, Y_PLURAL(ecount));
1946 ltb[sizeof(ltb)-1] = '\0';
1947 strmcat(tmpoutbuf, ltb, sizeof(tmpoutbuf)-1);
1948 }
1949 if (kcount)
1950 {
1951 if (!first)
1952 strmcat(tmpoutbuf, ",", sizeof(tmpoutbuf)-1);
1953 first = 0;
1954 snprintf(ltb, sizeof(ltb)-1,
1955 " %d channel key%s", kcount, PLURAL(kcount));
1956 ltb[sizeof(ltb)-1] = '\0';
1957 strmcat(tmpoutbuf, ltb, sizeof(tmpoutbuf)-1);
1958 }
1959 if (!first)
1960 {
1961 strmcat(tmpoutbuf, ".", sizeof(tmpoutbuf) - 1);
1962 put_info("%s", tmpoutbuf);
1963 }
1964 fclose(outfile);
1965 }
1966
1967 /*
1968 * show the bans from cache..
1969 */
1970 void
show_ban_cache(command,args,subargs)1971 show_ban_cache(command, args, subargs)
1972 u_char *command, *args, *subargs;
1973 {
1974 put_error("Not implemented yet.");
1975 }
1976