1 /*
2 * whois.c: Some tricky routines for querying the server for information
3 * about a nickname using WHOIS.... all the time hiding this from the user.
4 *
5 * Written By Michael Sandrof
6 *
7 * Copyright (c) 1990 Michael Sandrof.
8 * Copyright (c) 1991, 1992 Troy Rollo.
9 * Copyright (c) 1992-2000 Matthew R. Green.
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #undef MONITOR_Q /* this one is for monitoring of the 'whois queue' (debug) */
37
38 #include "irc.h"
39 #include "dma.h"
40 IRCII_RCSID("@(#)$Id: whois.c,v 1.41 2000/04/04 10:39:46 mrg Exp $");
41
42 #include "whois.h"
43 #include "hook.h"
44 #include "lastlog.h"
45 #include "vars.h"
46 #include "server.h"
47 #include "ignore.h"
48 #include "ircaux.h"
49 #include "notify.h"
50 #include "numbers.h"
51 #include "window.h"
52 #include "edit.h"
53 #include "output.h"
54 #include "parse.h"
55 #include "ctcp.h"
56
57 /* ninja includes! */
58 #include "friends.h"
59 #include "orignick.h"
60 #include "bans.h"
61 #include "ninja.h"
62
63 u_char whois_nick[] = "#WHOIS#";
64 u_char wait_nick[] = "#WAIT#";
65 u_char redirect_nick[] = "#RED#";
66
67 /* current setting for BEEP_ON_MSG */
68 int beep_on_level;
69
70 static int ignore_whois_crap = 0;
71 static int eat_away = 0;
72 /*
73 static WhoisStuff whois_stuff =
74 {
75 (u_char *) 0, (u_char *) 0, (u_char *) 0, (u_char *) 0, (u_char *) 0,
76 (u_char *) 0, (u_char *) 0, (u_char *) 0, (u_char *) 0, 0, 0, 0
77 };
78 */
79
80 /* WQ_head and WQ_tail point to the head and tail of the whois queue */
81 WhoisQueue *WQ_head = (WhoisQueue *) 0;
82 WhoisQueue *WQ_tail = (WhoisQueue *) 0;
83
84 static u_char show_away_flag = 0;
85
86 #ifdef HAVE_STDARG_H
87 static void typed_add_to_whois_queue _((int, u_char *, void (*)(WhoisStuff *, u_char *, u_char *), char *, va_list));
88 #else
89 static void typed_add_to_whois_queue();
90 #endif /* HAVE_STDARG_H */
91 static u_char *whois_queue_head _((int));
92 static int whois_type_head _((int));
93 static void (*whois_func_head _((int))) _((WhoisStuff *, u_char *, u_char *));
94 static WhoisQueue *remove_from_whois_queue _((int));
95
96 /* ninja code in here! */
97 void addhost_queue _((WhoisStuff *, u_char *, u_char *));
98
99 void
set_beep_on_msg(str)100 set_beep_on_msg(str)
101 u_char *str;
102 {
103 beep_on_level = parse_lastlog_level(str);
104 set_string_var(BEEP_ON_MSG_VAR, bits_to_lastlog_level(beep_on_level));
105 }
106
107 /*
108 * whois_queue_head: returns the nickname at the head of the whois queue, or
109 * NULL if the queue is empty. It does not modify the queue in any way.
110 */
111 static u_char *
whois_queue_head(server_index)112 whois_queue_head(server_index)
113 int server_index;
114 {
115 if ((WQ_head = (WhoisQueue *) get_server_qhead(server_index)) != NULL)
116 return (WQ_head->nick);
117 else
118 return ((u_char *) 0);
119 }
120
121 static int
whois_type_head(server_index)122 whois_type_head(server_index)
123 int server_index;
124 {
125 if ((WQ_head = (WhoisQueue *) get_server_qhead(server_index)) != NULL)
126 return (WQ_head->type);
127 else
128 return -1;
129 }
130
131 static void (*
132 whois_func_head (server_index)) _((WhoisStuff *, u_char *, u_char *))
133 int server_index;
134 {
135 if ((WQ_head = (WhoisQueue *) get_server_qhead(server_index)) != NULL)
136 return (WQ_head->func);
137 else
138 return NULL;
139 }
140
141 /*
142 * remove_from_whois_queue: removes the top element of the whois queue and
143 * returns the element as its function value. This routine repairs handles
144 * all queue stuff, but the returned element is mallocd and must be freed by
145 * the calling routine
146 */
147 static WhoisQueue *
remove_from_whois_queue(server_index)148 remove_from_whois_queue(server_index)
149 int server_index;
150 {
151 WhoisQueue *new;
152
153 #ifdef SUPPORT_ICB
154 if (get_server_version(server_index) == ServerICB)
155 {
156 yell("--- remove_from_whois_queue: panic? attempted on ICB server..");
157 return (NULL);
158 }
159 #endif
160 new = (WhoisQueue *) get_server_qhead(server_index);
161 set_server_qhead(server_index, new->next);
162 if (new->next == (WhoisQueue *) 0)
163 set_server_qtail(server_index, (WhoisQueue *) 0);
164 return (new);
165 }
166
167 /*
168 * clean_whois_queue: this empties out the whois queue. This is used after
169 * server reconnection to assure that no bogus entries are left in the whois
170 * queue
171 */
172 void
clean_whois_queue()173 clean_whois_queue()
174 {
175 WhoisQueue *thing;
176
177 while (whois_queue_head(from_server))
178 {
179 thing = remove_from_whois_queue(from_server);
180 new_free(&thing->nick);
181 new_free(&thing->text);
182 new_free(&thing);
183 }
184 ignore_whois_crap = 0;
185 eat_away = 0;
186 }
187
188 /*
189 * ison_returned: this is called when numeric 303 is received in
190 * numbers.c. ISON must always be the property of the WHOIS queue.
191 * Although we will check first that the top element expected is
192 * actually an ISON.
193 */
194 /*ARGSUSED*/
195 void
ison_returned(from,ArgList)196 ison_returned(from, ArgList)
197 u_char *from,
198 **ArgList;
199 {
200 WhoisQueue *thing;
201
202 if (whois_type_head(parsing_server_index) == WHOIS_ISON)
203 {
204 thing = remove_from_whois_queue(parsing_server_index);
205 thing->func((WhoisStuff *) 0, thing->nick, ArgList[0]? ArgList[0] : empty_string);
206 new_free(&thing->nick);
207 new_free(&thing->text);
208 new_free(&thing);
209 }
210 else
211 ison_now((WhoisStuff *) 0, ArgList[0] ? ArgList[0] : empty_string, (u_char *) 0);
212 }
213
214 /* userhost_returned: this is called when numeric 302 is received in
215 * numbers.c. USERHOST must also remain the property of the WHOIS
216 * queue. Sending it without going via the WHOIS queue will cause
217 * the queue to become corrupted.
218 *
219 * While USERHOST gives us similar information to WHOIS, this routine's
220 * format is a little different to those that handle the WHOIS numerics.
221 * A list of nicks can be supplied to USERHOST, and any of those
222 * nicks are not currently signed on, it will just omit reporting it.
223 * this means we must go through the list of nicks returned and check
224 * them for missing entries. This means stepping through the requested
225 * nicks one at a time.
226 *
227 * A side effect of this is that user initiated USERHOST requests get
228 * reported as separate replies even though one request gets made and
229 * only one reply is actually received. This should make it easier for
230 * people wanting to use USERHOST for their own purposes.
231 *
232 * In this routine, cnick points to all the information in the next
233 * entry from the returned data.
234 */
235 /*ARGSUSED*/
236 void
userhost_returned(from,ArgList)237 userhost_returned(from, ArgList)
238 u_char *from,
239 **ArgList;
240 {
241 WhoisQueue *thing;
242 WhoisStuff *whois_stuff = NULL;
243 u_char *nick,
244 *cnick = NULL,
245 *tnick;
246 u_char *user,
247 *cuser = (u_char *) 0;
248 u_char *host,
249 *chost = (u_char *) 0;
250 int ishere,
251 cishere = 1;
252 int isoper,
253 cisoper = 0;
254 int noton,
255 isuser,
256 parsed;
257 u_char *queue_nicks;
258
259 if (!ArgList[0])
260 return;
261 if (whois_type_head(parsing_server_index) == WHOIS_USERHOST)
262 {
263 isuser = (whois_func_head(parsing_server_index) == USERHOST_USERHOST);
264 whois_stuff = get_server_whois_stuff(parsing_server_index);
265 thing = remove_from_whois_queue(parsing_server_index);
266 queue_nicks = thing->nick;
267 }
268 else
269 {
270 isuser = 1;
271 thing = (WhoisQueue *) 0;
272 queue_nicks = (u_char *) 0;
273 whois_stuff = NULL;
274 }
275 parsed = 0;
276 while ((parsed || (cnick = next_arg(ArgList[0], ArgList))) ||
277 queue_nicks)
278 {
279 if (queue_nicks)
280 {
281 tnick = next_arg(queue_nicks, &queue_nicks);
282 if (!*queue_nicks)
283 queue_nicks = (u_char *) 0;
284 }
285 else
286 tnick = NULL;
287 if (cnick && !parsed)
288 {
289 if (!(cuser = my_index(cnick,'=')))
290 break;
291 if (*(cuser - 1) == '*')
292 {
293 *(cuser - 1) = '\0';
294 cisoper = 1;
295 }
296 else
297 cisoper = 0;
298 *cuser++ = '\0';
299 if (*cuser++ == '+')
300 cishere = 1;
301 else
302 cishere = 0;
303 if (!(chost = my_index(cuser, '@')))
304 break;
305 *chost++ = '\0';
306 parsed = 1;
307 }
308 if (!cnick || (tnick && my_stricmp(cnick, tnick)))
309 {
310 if (tnick)
311 nick = tnick;
312 else
313 nick = cnick;
314 user = host = UP("<UNKNOWN>");
315 isoper = 0;
316 ishere = 1;
317 noton = 1;
318 }
319 else
320 {
321 nick = cnick;
322 user = cuser;
323 host = chost;
324 isoper = cisoper;
325 ishere = cishere;
326 noton = parsed = 0;
327 }
328 if (!isuser)
329 {
330 malloc_strcpy(&whois_stuff->nick, nick);
331 malloc_strcpy(&whois_stuff->user, user);
332 malloc_strcpy(&whois_stuff->host, host);
333 whois_stuff->oper = isoper;
334 whois_stuff->not_on = noton;
335 if (!ishere)
336 malloc_strcpy(&whois_stuff->away, empty_string);
337 else
338 new_free(&whois_stuff->away);
339 thing->func(whois_stuff, tnick, thing->text);
340 new_free(&whois_stuff->away);
341 }
342 else
343 {
344 if (do_hook(current_numeric, "%s %s %s %s %s", nick,
345 isoper ? "+" : "-", ishere ? "+" : "-", user, host))
346 put_it("%s%s is %s@%s%s%s", numeric_banner(), /* numeric banner has the space in ninja */
347 nick, user, host, isoper ?
348 (u_char *) " (Is an IRC operator)" : empty_string,
349 ishere ? empty_string : (u_char *) " (away)");
350 }
351 }
352 if (thing)
353 {
354 new_free(&thing->nick);
355 new_free(&thing->text);
356 new_free(&thing);
357 }
358 }
359
360 /*
361 * whois_name: routine that is called when numeric 311 is received in
362 * numbers.c. This routine parses out the information in the numeric and
363 * saves it until needed (see whois_server()). If the whois queue is empty,
364 * this routine simply displays the data in the normal fashion. Why would
365 * the queue ever be empty, you ask? If the user does a "WHOIS *" or any
366 * other whois with a wildcard, you will get multiple returns from the
367 * server. So, instead of attempting to handle each of these, only the first
368 * is handled, and the others fall through. It is up to the programmer to
369 * prevent wildcards from interfering with what they want done. See
370 * channel() in edit.c
371 */
372 void
whois_name(from,ArgList)373 whois_name(from, ArgList)
374 u_char *from;
375 u_char **ArgList;
376 {
377 u_char *nick,
378 *user,
379 *host,
380 *channel,
381 *ptr,
382 *name;
383 WhoisStuff *whois_stuff;
384 Friend *f;
385
386 PasteArgs(ArgList, 4);
387 nick = ArgList[0];
388 user = ArgList[1];
389 host = ArgList[2];
390 channel = ArgList[3];
391 name = ArgList[4];
392 if (!nick || !user || !host || !channel || !name)
393 return;
394 whois_stuff = get_server_whois_stuff(parsing_server_index);
395 if ((ptr = whois_queue_head(parsing_server_index))
396 && (whois_type_head(parsing_server_index) & (WHOIS_WHOIS|WHOIS_ISON2))
397 && (my_stricmp(ptr, nick) == 0))
398 {
399 malloc_strcpy(&whois_stuff->nick, nick);
400 malloc_strcpy(&whois_stuff->user, user);
401 malloc_strcpy(&whois_stuff->host, host);
402 malloc_strcpy(&whois_stuff->name, name);
403 malloc_strcpy(&whois_stuff->channel, channel);
404 new_free(&whois_stuff->away);
405 whois_stuff->oper = 0;
406 whois_stuff->chop = 0;
407 whois_stuff->not_on = 0;
408 ignore_whois_crap = 1;
409 eat_away = 1;
410 }
411 else
412 {
413 ignore_whois_crap = 0;
414 eat_away = 0;
415 if (do_hook(current_numeric, "%s %s %s %s %s %s", from, nick,
416 user, host, channel, name))
417 {
418 put_it("%s%s is %s@%s (%s)", numeric_banner(), nick,
419 user, host, name);
420
421 f = get_friend_by_nuh(nick, user, host);
422 if (f)
423 {
424 FChan *fc;
425 u_char tb[512];
426
427 tb[0] = '\0';
428 for (fc = f->channels; fc; fc = fc->next)
429 {
430 strmcat(tb, " ", sizeof(tb)-1);
431 strmcat(tb, fc->channel, sizeof(tb)-1);
432 if (fc->modes)
433 {
434 strmcat(tb, "(+", sizeof(tb)-1);
435 my_strmcat(tb, recreate_cmode(fc), sizeof(tb)-1);
436 strmcat(tb, ")", sizeof(tb)-1);
437 }
438 }
439 /* XXX: perhaps a FRIEND_LIST or something for hooking would be nice */
440 put_info("Friend: %s%s", f->nick, tb);
441 }
442 }
443 }
444 }
445
446 /*
447 * whowas_name: same as whois_name() above but it is called with a numeric of
448 * 314 when the user does a WHOWAS or when a WHOIS'd user is no longer on IRC
449 * and has set the AUTO_WHOWAS variable.
450 */
451 void
whowas_name(from,ArgList)452 whowas_name(from, ArgList)
453 u_char *from;
454 u_char **ArgList;
455 {
456 u_char *nick,
457 *user,
458 *host,
459 *channel,
460 *ptr,
461 *name;
462 WhoisStuff *whois_stuff;
463 int lastlog_level;
464
465 PasteArgs(ArgList, 4);
466 nick = ArgList[0];
467 user = ArgList[1];
468 host = ArgList[2];
469 channel = ArgList[3];
470 name = ArgList[4];
471 if (!nick || !user || !host || !channel || !name)
472 return;
473
474 lastlog_level = set_lastlog_msg_level(LOG_CRAP);
475 whois_stuff = get_server_whois_stuff(parsing_server_index);
476 if ((ptr = whois_queue_head(parsing_server_index))
477 && (whois_type_head(parsing_server_index) & (WHOIS_WHOIS|WHOIS_ISON2))
478 && (my_stricmp(ptr, nick) == 0))
479 {
480 malloc_strcpy(&whois_stuff->nick, nick);
481 malloc_strcpy(&whois_stuff->user, user);
482 malloc_strcpy(&whois_stuff->host, host);
483 malloc_strcpy(&whois_stuff->name, name);
484 malloc_strcpy(&whois_stuff->channel, channel);
485 new_free(&whois_stuff->away);
486 whois_stuff->oper = 0;
487 whois_stuff->chop = 0;
488 whois_stuff->not_on = 1;
489 ignore_whois_crap = 1;
490 }
491 else
492 {
493 ignore_whois_crap = 0;
494 if (do_hook(current_numeric, "%s %s %s %s %s %s", from, nick,
495 user, host, channel, name))
496 put_it("%s%s was %s@%s (%s) on channel %s",
497 numeric_banner(), nick, user, host, name,
498 (*channel == '*') ? (u_char *) "*private*" : channel);
499 }
500 set_lastlog_msg_level(lastlog_level);
501 }
502
503 void
whois_channels(from,ArgList)504 whois_channels(from, ArgList)
505 u_char *from;
506 u_char **ArgList;
507 {
508 u_char *ptr;
509 u_char *line;
510 WhoisStuff *whois_stuff;
511
512 PasteArgs(ArgList, 1);
513 line = ArgList[1];
514 whois_stuff = get_server_whois_stuff(parsing_server_index);
515 if ((ptr = whois_queue_head(parsing_server_index))
516 && (whois_type_head(parsing_server_index) & (WHOIS_WHOIS|WHOIS_ISON2))
517 && whois_stuff->nick
518 && (my_stricmp(ptr, whois_stuff->nick) == 0))
519 {
520 if (whois_stuff->channels == (u_char *) 0)
521 malloc_strcpy(&whois_stuff->channels, line);
522 else
523 malloc_strcat(&whois_stuff->channels, line);
524 }
525 else
526 {
527 if (do_hook(current_numeric, "%s %s", from, line))
528 {
529 u_char *p, *p2, *free_p = UNULL;
530 int cnt = 0;
531
532 dma_strcpy(&free_p, line);
533 p = free_p;
534 while ((p2 = next_arg(p, &p)))
535 cnt++;
536 dma_Free(&free_p);
537 put_it("%son channel%s: %s", numeric_banner(), cnt > 1 ? UP("s") : empty_string, line);
538 }
539 }
540 }
541
542 /*
543 * whois_server: Called in numbers.c when a numeric of 312 is received. If
544 * all went well, this routine collects the needed information, pops the top
545 * element off the queue and calls the function as described above in
546 * WhoisQueue. It then releases all the mallocd data. If the queue is empty
547 * (same case as described in whois_name() above), the information is simply
548 * displayed in the normal fashion. Added a check to see if whois_stuff->nick
549 * is NULL. This can happen if something is added to an empty whois queue
550 * between the whois name being received and the server.
551 */
552 void
whois_server(from,ArgList)553 whois_server(from, ArgList)
554 u_char *from;
555 u_char **ArgList;
556 {
557 u_char *server,
558 *ptr;
559 u_char *line;
560 WhoisStuff *whois_stuff;
561
562 show_away_flag = 1;
563 if (!ArgList[0] || !ArgList[1])
564 return;
565 if (ArgList[2])
566 {
567 server = ArgList[1];
568 line = ArgList[2];
569 }
570 else
571 {
572 server = ArgList[0];
573 line = ArgList[1];
574 }
575 whois_stuff = get_server_whois_stuff(parsing_server_index);
576 if ((ptr = whois_queue_head(parsing_server_index))
577 && (whois_type_head(parsing_server_index) & (WHOIS_WHOIS|WHOIS_ISON2))
578 && whois_stuff->nick && /* This is *weird* */
579 (my_stricmp(ptr, whois_stuff->nick) == 0))
580 {
581 malloc_strcpy(&whois_stuff->server, server);
582 malloc_strcpy(&whois_stuff->server_stuff, line);
583 }
584 else
585 {
586 if (do_hook(current_numeric, "%s %s %s", from, server, line))
587 put_it("%son irc via server %s (%s)",
588 numeric_banner(), server, line);
589 }
590 }
591
592 /*
593 * whois_oper: This displays the operator status of a user, as returned by
594 * numeric 313 from the server. If the ignore_whois_crap flag is set,
595 * nothing is dispayed.
596 */
597 void
whois_oper(from,ArgList)598 whois_oper(from, ArgList)
599 u_char *from;
600 u_char **ArgList;
601 {
602 WhoisStuff *whois_stuff;
603
604 whois_stuff = get_server_whois_stuff(parsing_server_index);
605 PasteArgs(ArgList, 1);
606 if (ignore_whois_crap)
607 whois_stuff->oper = 1;
608 else
609 {
610 u_char *nick;
611
612 if ((nick = ArgList[0]) != NULL)
613 {
614 if (do_hook(current_numeric, "%s %s %s", from, nick,
615 ArgList[1]))
616 put_it("%s%s %s%s", numeric_banner(), nick,
617 ArgList[1], (get_server_version(parsing_server_index) >
618 Server2_7) ? empty_string
619 : (u_char *) " (is an IRC operator)");
620 }
621 }
622 }
623
624 void
whois_lastcom(from,ArgList)625 whois_lastcom(from, ArgList)
626 u_char *from;
627 u_char **ArgList;
628 {
629 if (!ignore_whois_crap)
630 {
631 u_char *nick, *idle_str;
632 int idle;
633 time_t sot = 0;
634
635 if (ArgList[2])
636 PasteArgs(ArgList, 3);
637 else
638 PasteArgs(ArgList, 2);
639
640 if ((nick = ArgList[0]) && (idle_str = ArgList[1]) &&
641 do_hook(current_numeric, "%s %s %s %s", from,
642 nick, idle_str, ArgList[2]))
643 {
644 if (ArgList[2])
645 sot = my_atol(ArgList[2]);
646 idle = my_atoi(idle_str);
647 if (sot)
648 {
649 u_char tmp[64];
650 my_strmcpy(tmp, ninja_date(&sot), sizeof(tmp)-1);
651 put_it("%s%s has been idle for %s, signed on %s at %s", numeric_banner(),
652 nick, ninja_etime(idle),
653 tmp, ninja_ctime(&sot));
654 }
655 else
656 put_it("%s%s has been idle for %s", numeric_banner(),
657 nick, ninja_etime(idle));
658 }
659 }
660 }
661
662 /*
663 * whois_chop: This displays the operator status of a user, as returned by
664 * numeric 313 from the server. If the ignore_whois_crap flag is set,
665 * nothing is dispayed.
666 */
667 void
whois_chop(from,ArgList)668 whois_chop(from, ArgList)
669 u_char *from;
670 u_char **ArgList;
671 {
672 WhoisStuff *whois_stuff;
673
674 whois_stuff = get_server_whois_stuff(parsing_server_index);
675 PasteArgs(ArgList, 1);
676 if (ignore_whois_crap)
677 whois_stuff->chop = 1;
678 else
679 {
680 u_char *nick;
681
682 if ((nick = ArgList[0]) != NULL)
683 {
684 if (do_hook(current_numeric, "%s %s %s",from, nick,
685 ArgList[1]))
686 put_it("%s%s (is a channel operator)",
687 numeric_banner(), nick, ArgList[1]);
688 }
689 }
690 }
691
692 void
end_of_whois(from,ArgList)693 end_of_whois(from, ArgList)
694 u_char *from;
695 u_char **ArgList;
696 {
697 u_char *nick;
698 u_char *ptr;
699 WhoisStuff *whois_stuff;
700
701 whois_stuff = get_server_whois_stuff(parsing_server_index);
702
703 show_away_flag = 0;
704 set_server_whois(parsing_server_index,1);
705 if ((nick = ArgList[0]) != NULL)
706 {
707 ptr = whois_queue_head(parsing_server_index);
708 if (ptr && (whois_type_head(parsing_server_index) & (WHOIS_WHOIS|WHOIS_ISON2)) && (my_stricmp(ptr, nick) == 0))
709 {
710 WhoisQueue *thing;
711
712 thing = remove_from_whois_queue(parsing_server_index);
713 whois_stuff->not_on = 0;
714 thing->func(whois_stuff, thing->nick, thing->text);
715 new_free(&whois_stuff->channels);
716 new_free(&thing->nick);
717 new_free(&thing->text);
718 new_free(&thing);
719 ignore_whois_crap = 0;
720 return;
721 }
722 PasteArgs(ArgList, 0);
723 if (do_hook(current_numeric, "%s %s", from, ArgList[0]))
724 if (get_int_var(SHOW_END_OF_MSGS_VAR))
725 display_msg(from, ArgList);
726 }
727 }
728
729 /*
730 * no_such_nickname: Handler for numeric 401, the no such nickname error. If
731 * the nickname given is at the head of the queue, then this routine pops the
732 * top element from the queue, sets the whois_stuff->flag to indicate that the
733 * user is no longer on irc, then calls the func() as normal. It is up to
734 * that function to set the ignore_whois_crap variable which will determine
735 * if any other information is displayed or not.
736 *
737 * that is, it used to. now it does bugger all, seeing all the functions that
738 * used to use it, now use no such command. -phone, april 1993.
739 */
740 /*ARGSUSED*/
741 void
no_such_nickname(from,ArgList)742 no_such_nickname(from, ArgList)
743 u_char *from,
744 **ArgList;
745 {
746 u_char *nick;
747 u_char *ptr;
748 WhoisStuff *whois_stuff;
749
750 whois_stuff = get_server_whois_stuff(parsing_server_index);
751 ptr = whois_queue_head(parsing_server_index);
752 PasteArgs(ArgList, 1);
753 nick = ArgList[0];
754 nchk_orignick(nick);
755 if (*nick == '!')
756 {
757 u_char *name = nick+1;
758
759 if (ptr && (whois_type_head(parsing_server_index) & (WHOIS_WHOIS|WHOIS_ISON2)) && !my_strcmp(ptr, name))
760 {
761 WhoisQueue *thing;
762
763 /* There's a query in the WhoisQueue : assume it's
764 completed and remove it from the queue -Sol */
765
766 thing = remove_from_whois_queue(parsing_server_index);
767 whois_stuff->not_on = 0;
768 thing->func(whois_stuff, thing->nick, thing->text);
769 new_free(&whois_stuff->channels);
770 new_free(&thing->nick);
771 new_free(&thing->text);
772 new_free(&thing);
773 ignore_whois_crap = 0;
774 return;
775 }
776 return;
777 }
778 notify_mark(nick, 0, 0, 0, 0, 0);
779 if (ptr && (whois_type_head(parsing_server_index) == WHOIS_ISON2) &&
780 !my_strcmp(ptr, nick))
781 {
782 WhoisQueue *thing;
783
784 /* Remove query from queue. Don't display anything. -Sol */
785
786 thing = remove_from_whois_queue(parsing_server_index);
787 new_free(&whois_stuff->channels);
788 new_free(&thing->nick);
789 new_free(&thing->text);
790 new_free(&thing);
791 ignore_whois_crap = 0;
792 return;
793 }
794 if (do_hook(current_numeric, "%s %s %s", from, nick, ArgList[1]))
795 put_it("%s%s: %s", numeric_banner(), nick, ArgList[1]);
796 if ((get_server_version(parsing_server_index) > Server2_5) &&
797 get_int_var(AUTO_WHOWAS_VAR))
798 send_to_server("WHOWAS %s", nick);
799 }
800
801 /*
802 * user_is_away: called when a 301 numeric is received. Nothing is displayed
803 * by this routine if the ignore_whois_crap flag is set
804 */
805 /*ARGSUSED*/
806 void
user_is_away(from,ArgList)807 user_is_away(from, ArgList)
808 u_char *from,
809 **ArgList;
810 {
811 static u_char *last_away_msg = (u_char *) 0,
812 *last_away_nick = (u_char *) 0;
813 u_char *message,
814 *who;
815 WhoisStuff *whois_stuff;
816
817 if (!from)
818 return;
819
820 PasteArgs(ArgList, 1);
821 whois_stuff = get_server_whois_stuff(parsing_server_index);
822
823 if ((who = ArgList[0]) && (message = ArgList[1]))
824 {
825 if (whois_stuff->nick && (!my_strcmp(who, whois_stuff->nick)) &&
826 eat_away)
827 malloc_strcpy(&whois_stuff->away, message);
828 else
829 {
830 if (get_int_var(ANTI_IDLE_VAR)
831 && server_list[parsing_server_index].in_ping
832 && my_stricmp(who, get_server_nickname(parsing_server_index)) == 0)
833 return;
834
835 if (!show_away_flag && get_int_var(SHOW_AWAY_ONCE_VAR))
836 {
837 if (!last_away_msg
838 || my_strcmp(last_away_nick, from)
839 || my_strcmp(last_away_msg, message))
840 {
841 malloc_strcpy(&last_away_nick, from);
842 malloc_strcpy(&last_away_msg, message);
843 }
844 else
845 return;
846 }
847
848 if (do_hook(current_numeric, "%s %s", who, message))
849 put_it("%s%s is away: %s",numeric_banner(),
850 who, message);
851 }
852 eat_away = 0;
853 }
854 }
855
856 /*
857 * The stuff below this point are all routines suitable for use in the
858 * add_to_whois_queue() call as the func parameter
859 */
860
861 /*
862 * whois_ignore_msgs: This is used when you are ignoring MSGs using the
863 * user@hostname format
864 */
865 void
whois_ignore_msgs(stuff,nick,text)866 whois_ignore_msgs(stuff, nick, text)
867 WhoisStuff *stuff;
868 u_char *nick;
869 u_char *text;
870 {
871 u_char *ptr;
872 int level;
873
874 if (stuff)
875 {
876 ptr = (u_char *) new_malloc(my_strlen(stuff->user) +
877 my_strlen(stuff->host) + 2);
878 my_strcpy(ptr, stuff->user);
879 my_strcat(ptr, "@");
880 my_strcat(ptr, stuff->host);
881 if (is_ignored(ptr, IGNORE_MSGS) != IGNORED)
882 {
883 save_message_from();
884 level = set_lastlog_msg_level(LOG_MSG);
885 message_from(stuff->nick, LOG_MSG);
886 if (sed == 1 && !do_hook(ENCRYPTED_PRIVMSG_LIST,"%s %s", stuff->nick,text))
887 {
888 set_lastlog_msg_level(level);
889 restore_message_from();
890 return;
891 }
892 if (do_hook(MSG_LIST, "%s %s", stuff->nick, text))
893 {
894 if (server_list[parsing_server_index].away_set)
895 {
896 time_t t;
897 u_char *msg = (u_char *) 0;
898
899 t = time(0);
900 msg = (u_char *) new_malloc(my_strlen(text)
901 + 20);
902 sprintf(CP(msg), "%s <%.16s>", text,
903 ctime(&t));
904 put_it("*%s* %s", stuff->nick, msg);
905 new_free(&msg);
906 beep_em(get_int_var(BEEP_WHEN_AWAY_VAR));
907 }
908 else
909 {
910 put_it("*%s* %s", stuff->nick, text);
911 beep_em(get_int_var(BEEP_ON_MSG_VAR));
912 }
913 }
914 if (beep_on_level & LOG_MSG)
915 beep_em(1);
916 set_lastlog_msg_level(level);
917 message_from((u_char *) 0, LOG_CURRENT);
918 notify_mark(nick, 1, 0, stuff->user, stuff->host, stuff->away ? 1 : 0);
919 }
920 else
921 send_to_server("NOTICE %s :%s is ignoring you.",
922 nick, get_server_nickname(parsing_server_index));
923 new_free(&ptr);
924 }
925 restore_message_from();
926 }
927
928 /*ARGSUSED*/
929 void
whois_nickname(stuff,nick,text)930 whois_nickname(stuff,nick,text)
931 WhoisStuff *stuff;
932 u_char *nick;
933 u_char *text;
934 {
935 if (stuff)
936 {
937 if (!(my_stricmp(stuff->user,username)) &&
938 (!my_stricmp(stuff->host,hostname)))
939 set_server_nickname(parsing_server_index,nick);
940 }
941 }
942
943 /*
944 * whois_ignore_notices: This is used when you are ignoring NOTICEs using the
945 * user@hostname format
946 */
947 /*ARGSUSED*/
948 void
whois_ignore_notices(stuff,nick,text)949 whois_ignore_notices(stuff, nick, text)
950 WhoisStuff *stuff;
951 u_char *nick;
952 u_char *text;
953 {
954 u_char *ptr;
955 int level;
956
957 if (stuff)
958 {
959 ptr = (u_char *) new_malloc(my_strlen(stuff->user) +
960 my_strlen(stuff->host) + 2);
961 my_strcpy(ptr, stuff->user);
962 my_strcat(ptr, "@");
963 my_strcat(ptr, stuff->host);
964 if (is_ignored(ptr, IGNORE_NOTICES) != IGNORED)
965 {
966 level = set_lastlog_msg_level(LOG_NOTICE);
967 save_message_from();
968 message_from(stuff->nick, LOG_NOTICE);
969 if (sed == 0 && !do_hook(ENCRYPTED_NOTICE_LIST,"%s %s", stuff->nick, text))
970 {
971 restore_message_from();
972 return;
973 }
974 if (do_hook(NOTICE_LIST, "%s %s", stuff->nick, text))
975 put_it("-%s- %s", stuff->nick, text);
976 set_lastlog_msg_level(level);
977 restore_message_from();
978 }
979 new_free(&ptr);
980 }
981 }
982
983 /*
984 * whois_ignore_invites: This is used when you are ignoring INVITES using the
985 * user@hostname format
986 */
987 void
whois_ignore_invites(stuff,nick,text)988 whois_ignore_invites(stuff, nick, text)
989 WhoisStuff *stuff;
990 u_char *nick;
991 u_char *text;
992 {
993 u_char *ptr;
994
995 if (stuff)
996 {
997 ptr = (u_char *) new_malloc(my_strlen(stuff->user) +
998 my_strlen(stuff->host) + 2);
999 my_strcpy(ptr, stuff->user);
1000 my_strcat(ptr, "@");
1001 my_strcat(ptr, stuff->host);
1002 if (is_ignored(ptr, IGNORE_INVITES) != IGNORED)
1003 {
1004 if (do_hook(INVITE_LIST, "%s %s", stuff->nick, text))
1005 say("%s invites you to channel %s",
1006 stuff->nick, text);
1007 malloc_strcpy(&invite_channel, text);
1008 }
1009 else
1010 send_to_server("NOTICE %s :%s is ignoring you.",
1011 nick, get_server_nickname(parsing_server_index));
1012 new_free(&ptr);
1013 }
1014 }
1015
1016 /*
1017 * whois_ignore_walls: This is used when you are ignoring WALLS using the
1018 * user@hostname format
1019 */
1020 /*ARGSUSED*/
1021 void
whois_ignore_walls(stuff,nick,text)1022 whois_ignore_walls(stuff, nick, text)
1023 WhoisStuff *stuff;
1024 u_char *nick;
1025 u_char *text;
1026 {
1027 u_char *ptr;
1028 int level;
1029
1030 level = set_lastlog_msg_level(LOG_WALL);
1031 save_message_from();
1032 message_from(stuff->nick, LOG_WALL);
1033 if (stuff)
1034 {
1035 ptr = (u_char *) new_malloc(my_strlen(stuff->user) +
1036 my_strlen(stuff->host) + 2);
1037 my_strcpy(ptr, stuff->user);
1038 my_strcat(ptr, "@");
1039 my_strcat(ptr, stuff->host);
1040 if (is_ignored(ptr, IGNORE_WALLS) != IGNORED)
1041 {
1042 if (do_hook(WALL_LIST, "%s %s", stuff->nick, text))
1043 put_it("#%s# %s", stuff->nick, text);
1044 if (beep_on_level & LOG_WALL)
1045 beep_em(1);
1046 }
1047 new_free(&ptr);
1048 }
1049 set_lastlog_msg_level(level);
1050 save_message_from();
1051 }
1052
1053 void
convert_to_whois()1054 convert_to_whois()
1055 {
1056 u_char *NextAsked;
1057 u_char *Names;
1058 WhoisQueue *thing;
1059 #ifdef USE_ISON_NOTIFY
1060 void (*func) _((WhoisStuff *, u_char *, u_char *)); */
1061 #endif
1062 if (!(whois_type_head(parsing_server_index) & (WHOIS_USERHOST|WHOIS_WHOIS|WHOIS_ISON2)))
1063 {
1064 say("Server does not support USERHOST");
1065 return; /* USERHOST sent interactively. */
1066 }
1067 thing = remove_from_whois_queue(parsing_server_index);
1068 switch(thing->type)
1069 {
1070 case WHOIS_ISON:
1071 Names = thing->nick;
1072 while ( (NextAsked = next_arg(Names, &Names)))
1073 {
1074 #ifdef USE_ISON_NOTIFY
1075 if (thing->func == ison_notify)
1076 {
1077 func = (void (*) _((WhoisStuff *, u_char *, u_char *))) whois_notify;
1078 add_to_whois_queue(NextAsked, func, "%s", NextAsked);
1079 }
1080 else
1081 say("Server does not support ISON");
1082 #endif
1083 }
1084 break;
1085 case WHOIS_USERHOST:
1086 add_to_whois_queue(thing->nick, thing->func, "%s", thing->text);
1087 break;
1088 }
1089 new_free(&thing->nick);
1090 new_free(&thing->text);
1091 new_free(&thing);
1092 }
1093
1094
1095 /*
1096 * Ninja irc does not use ISON for notify
1097 */
1098 #ifdef USE_ISON_NOTIFY
1099 void
ison_notify(unused,AskedFor,AreOn)1100 ison_notify(unused, AskedFor, AreOn)
1101 WhoisStuff *unused;
1102 u_char *AskedFor;
1103 u_char *AreOn;
1104 {
1105 u_char *NextAsked;
1106 u_char *NextGot;
1107
1108 NextGot = next_arg(AreOn, &AreOn);
1109 while ((NextAsked = next_arg(AskedFor, &AskedFor)) != NULL)
1110 {
1111 if (NextGot && !my_stricmp(NextAsked, NextGot))
1112 {
1113 notify_mark(NextAsked, NFY_ONLINE, NFY_FROM_QRY);
1114 NextGot = next_arg(AreOn, &AreOn);
1115 }
1116 else
1117 notify_mark(NextAsked, !NFY_ONLINE, NFY_FROM_QRY);
1118 }
1119 }
1120 #endif
1121
1122 /*
1123 * whois_notify: used by the routines in notify.c to tell when someone has
1124 * signed on or off irc
1125 */
1126 /*ARGSUSED*/
1127 void
whois_notify(stuff,nick,text)1128 whois_notify(stuff, nick, text)
1129 WhoisStuff *stuff;
1130 u_char *nick;
1131 u_char *text;
1132 {
1133 int level;
1134
1135 level = set_lastlog_msg_level(LOG_CRAP);
1136 if (stuff)
1137 notify_mark(stuff->nick, NFY_ONLINE, NFY_FROM_QRY, stuff->user, stuff->host, (stuff->away) ? 1 : 0);
1138 else
1139 notify_mark(nick, !NFY_ONLINE, NFY_FROM_QRY, NFY_NO_USER, NFY_NO_HOST, !NFY_AWAY);
1140 set_lastlog_msg_level(level);
1141 }
1142
1143 void
whois_new_wallops(stuff,nick,text)1144 whois_new_wallops(stuff, nick, text)
1145 WhoisStuff *stuff;
1146 u_char *nick;
1147 u_char *text;
1148 {
1149 int flag,
1150 level;
1151 u_char *high;
1152
1153 flag = is_ignored(nick, IGNORE_WALLOPS);
1154 if (flag != IGNORED)
1155 {
1156 if (flag == HIGHLIGHTED)
1157 high = &highlight_char;
1158 else
1159 high = empty_string;
1160 if (stuff && (ignore_usernames & IGNORE_WALLOPS))
1161 {
1162 u_char *ptr;
1163
1164 ptr = (u_char *) new_malloc(my_strlen(stuff->user) +
1165 my_strlen(stuff->host) + 2);
1166 my_strcpy(ptr, stuff->user);
1167 my_strcat(ptr, "@");
1168 my_strcat(ptr, stuff->host);
1169 if (is_ignored(ptr, IGNORE_WALLOPS) == IGNORED)
1170 {
1171 new_free(&ptr);
1172 return;
1173 }
1174 new_free(&ptr);
1175 }
1176 save_message_from();
1177 message_from(nick, LOG_WALLOP);
1178 level = set_lastlog_msg_level(LOG_WALLOP);
1179 if (stuff)
1180 {
1181 if (do_hook(WALLOP_LIST, "%s %s %s", nick,
1182 (stuff->oper ? "+" : "-"), text))
1183 put_it("%s!%s%s!%s %s", high, nick,
1184 stuff->oper ? asterik : empty_string,
1185 high, text);
1186 }
1187 else
1188 {
1189 if (do_hook(WALLOP_LIST, "%s - %s", nick, text))
1190 put_it("%s!%s!%s %s", high, nick, high, text);
1191 }
1192 if (beep_on_level & LOG_WALLOP)
1193 beep_em(1);
1194 set_lastlog_msg_level(level);
1195 restore_message_from();
1196 }
1197 }
1198
1199 /* I put the next routine down here to keep my compile quiet */
1200
1201 /*
1202 * add_to_whois_queue: This routine is called whenever you want to do a WHOIS
1203 * or WHOWAS. What happens is this... each time this function is called it
1204 * adds a new element to the whois queue using the nick and func as in
1205 * WhoisQueue, and creating the text element using the format and args. It
1206 * then issues the WHOIS or WHOWAS.
1207 */
1208 void
1209 #ifdef HAVE_STDARG_H
add_to_whois_queue(u_char * nick,void (* func)_ ((WhoisStuff *,u_char *,u_char *)),char * format,...)1210 add_to_whois_queue(u_char *nick, void (*func) _((WhoisStuff *, u_char *, u_char *)), char *format, ...)
1211 #else
1212 add_to_whois_queue(nick, func, format, arg1, arg2,
1213 arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
1214 u_char *nick;
1215 void (*func) _((WhoisStuff *, u_char *, u_char *));
1216 char *format,
1217 *arg1,
1218 *arg2,
1219 *arg3,
1220 *arg4,
1221 *arg5,
1222 *arg6,
1223 *arg7,
1224 *arg8,
1225 *arg9,
1226 *arg10;
1227 #endif /* HAVE_STDARG_H */
1228 {
1229 int Type;
1230 #ifdef HAVE_STDARG_H
1231 va_list vlist;
1232
1233 va_start(vlist, format);
1234 #endif /* HAVE_STDARG_H */
1235
1236 if (func == USERHOST_USERHOST
1237 || func == userhost_cmd_returned
1238 || func == orignick_queue
1239 || func == ban_queue
1240 || func == unban_queue
1241 || func == addhost_queue)
1242 Type = WHOIS_USERHOST;
1243 else if (func == whois_notify)
1244 Type = WHOIS_ISON2;
1245 else
1246 Type = WHOIS_WHOIS;
1247 #ifdef HAVE_STDARG_H
1248 typed_add_to_whois_queue(Type, nick, func, format, vlist);
1249 va_end(vlist);
1250 #else
1251 typed_add_to_whois_queue(Type, nick, func, format, arg1, arg2,
1252 arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
1253 #endif /* HAVE_STDARG_H */
1254 }
1255
1256 /*
1257 * note that typed_add_to_whois_queue() ignores the final (fifth and
1258 * beyond) parameter if the 4th is NULL. we use the va_list variable
1259 * here instead of 0 to work around picky compilers.
1260 */
1261 void
1262 add_ison_to_whois(nick, func)
1263 void (*func) _((WhoisStuff *, u_char *, u_char *));
1264 u_char *nick;
1265 {
1266 #ifdef HAVE_STDARG_H
1267 va_list vlist;
1268
1269 memset(&vlist, 0, sizeof(vlist));
1270 typed_add_to_whois_queue(WHOIS_ISON, nick, func, (char *) 0, vlist);
1271 #else
1272 typed_add_to_whois_queue(WHOIS_ISON, nick, func, (char *) 0, 0);
1273 #endif /* HAVE_STDARG_H */
1274 }
1275
1276 void
1277 add_userhost_to_whois(nick, func)
1278 void (*func) _((WhoisStuff *, u_char *, u_char *));
1279 u_char *nick;
1280 {
1281 #ifdef HAVE_STDARG_H
1282 va_list vlist;
1283
1284 memset(&vlist, 0, sizeof(vlist));
1285 typed_add_to_whois_queue(WHOIS_USERHOST, nick, func, (char *) 0, vlist);
1286 #else
1287 typed_add_to_whois_queue(WHOIS_USERHOST, nick, func, (char *) 0, 0);
1288 #endif /* HAVE_STDARG_H */
1289 }
1290
1291 static void
1292 #ifdef HAVE_STDARG_H
typed_add_to_whois_queue(int type,u_char * nick,void (* func)_ ((WhoisStuff *,u_char *,u_char *)),char * format,va_list vlist)1293 typed_add_to_whois_queue(int type, u_char *nick, void (*func) _((WhoisStuff *, u_char *, u_char *)), char *format, va_list vlist)
1294 #else
1295 typed_add_to_whois_queue(type, nick, func, format,
1296 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
1297 int type;
1298 u_char *nick;
1299 void (*func) _((WhoisStuff *, u_char *, u_char *));
1300 char *format,
1301 *arg1,
1302 *arg2,
1303 *arg3,
1304 *arg4,
1305 *arg5,
1306 *arg6,
1307 *arg7,
1308 *arg8,
1309 *arg9,
1310 *arg10;
1311 #endif /* HAVE_STDARG_H */
1312 {
1313 u_char lbuf[BIG_BUFFER_SIZE + 1];
1314 WhoisQueue *new;
1315 u_char *p = nick;
1316
1317 #ifdef SUPPORT_ICB
1318 if (get_server_version(from_server) == ServerICB)
1319 {
1320 yell("--- typed_add_to_whois_queue: panic? attempted on ICB server..");
1321 return;
1322 }
1323 #endif
1324 if ((nick == (u_char *) 0) || ! is_server_connected(from_server) ||
1325 (server_list[from_server].write == -1)) /* XXX STOP-GAP -Sol */
1326 return;
1327
1328 for (; *p == ' ' || *p == '\t'; p++);
1329 if (!*p)
1330 return; /* nick should always be a non-blank string, but
1331 I'd rather check because of a "ISON not enough
1332 parameters" coming from the server -Sol */
1333
1334 if (my_index(nick, '*') == (u_char *) 0)
1335 {
1336 new = (WhoisQueue *) new_malloc(sizeof(WhoisQueue));
1337 /*
1338 new->text = (u_char *) 0;
1339 new->nick = (u_char *) 0;
1340 new->next = (WhoisQueue *) 0;
1341 */
1342 new->func = func;
1343 new->type = type;
1344 if (format)
1345 {
1346 #ifdef HAVE_STDARG_H
1347 vsnprintf(CP(lbuf), sizeof(lbuf)-1, format, vlist);
1348 #else
1349 snprintf(CP(lbuf), sizeof(lbuf)-1, format, arg1, arg2, arg3, arg4, arg5,
1350 arg6, arg7, arg8, arg9, arg10);
1351 #endif /* HAVE_STDARG_H */
1352 lbuf[sizeof(lbuf)-1] = '\0';
1353 malloc_strcpy(&(new->text), lbuf);
1354 }
1355 malloc_strcpy(&(new->nick), nick);
1356 if ((void *) get_server_qhead(from_server) == (void *) 0)
1357 set_server_qhead(from_server, new);
1358 if (get_server_qtail(from_server))
1359 ((WhoisQueue *) get_server_qtail(from_server))->next = new;
1360 set_server_qtail(from_server, new);
1361 switch(type)
1362 {
1363 case WHOIS_ISON:
1364 #ifdef MONITOR_Q
1365 put_it("+++ ISON %s", nick);
1366 #endif /* MONITOR_Q */
1367 send_to_server("ISON %s", nick);
1368 break;
1369 case WHOIS_USERHOST:
1370 #ifdef MONITOR_Q
1371 put_it("+++ USERHOST %s", nick);
1372 #endif /* MONITOR_Q */
1373 send_to_server("USERHOST %s", nick);
1374 break;
1375 case WHOIS_WHOIS:
1376 case WHOIS_ISON2:
1377 #ifdef MONITOR_Q
1378 put_it("+++ WHOIS %s", nick);
1379 #endif /* MONITOR_Q */
1380 send_to_server("WHOIS %s", nick);
1381 if (!get_server_whois(from_server))
1382 send_to_server("WHOIS !%s", nick);
1383 /* postfix with nick so we know who we're
1384 talking about -Sol */
1385 /* send "WHOIS !nick" and expect
1386 "!nick: No such nick/channel" :
1387 it means the real query was completed
1388 and the dummy query is to be ignored
1389 in no_such_nickname() -Sol */
1390 break;
1391 }
1392 }
1393 }
1394
1395 extern void
1396 userhost_cmd_returned(stuff, nick, text)
1397 WhoisStuff *stuff;
1398 u_char *nick;
1399 u_char *text;
1400 {
1401 u_char args[BIG_BUFFER_SIZE + 1];
1402
1403 my_strmcpy(args, stuff->nick ? stuff->nick : empty_string, sizeof(args)-1);
1404 my_strmcat(args, stuff->oper ? " + " : " - ", sizeof(args)-1);
1405 my_strmcat(args, stuff->away ? "+ " : "- ", sizeof(args)-1);
1406 my_strmcat(args, stuff->user ? stuff->user : empty_string, sizeof(args)-1);
1407 my_strmcat(args, " ", sizeof(args)-1);
1408 my_strmcat(args, stuff->host ? stuff->host : empty_string, sizeof(args)-1);
1409 parse_line((u_char *) 0, text, args, 0, 0, 1);
1410 }
1411
1412
1413 /* below here are ninja specific add ons */
1414
1415
1416 /*
1417 * Ninja IRC uses this instead of ison_notify
1418 */
1419 void
userhost_notify(wistuff,AskedFor,AreOn)1420 userhost_notify(wistuff, AskedFor, AreOn)
1421 WhoisStuff *wistuff;
1422 u_char *AskedFor;
1423 u_char *AreOn;
1424 {
1425 if (wistuff->not_on || !wistuff->nick)
1426 notify_mark(AskedFor, 0, 1, 0, 0, 0);
1427 else
1428 notify_mark(wistuff->nick, 1, 1, wistuff->user, wistuff->host, wistuff->away ? 1 : 0);
1429 }
1430
1431 /*
1432 * for adding friend hosts
1433 */
1434 void
addhost_queue(stuff,nick,text)1435 addhost_queue(stuff, nick, text)
1436 WhoisStuff *stuff;
1437 u_char *nick;
1438 u_char *text;
1439 {
1440 u_char *foo, *realnick;
1441 u_char tb1[1024];
1442
1443 if (!stuff || !stuff->nick || !nick || !my_strcmp(stuff->user, "<UNKNOWN>") || my_stricmp(stuff->nick, nick))
1444 {
1445 put_error("No user@host for nickname \"%s\".", nick);
1446 return;
1447 }
1448
1449 /* skip any leading ~ */
1450 foo = stuff->user;
1451 if (foo && *foo == '~')
1452 foo++;
1453
1454 realnick = next_arg(text, &text);
1455 if (!realnick)
1456 realnick = stuff->nick;
1457 snprintf(tb1, sizeof(tb1) - 1, "%s *!%s@%s", realnick, foo ? foo : empty_string, cluster(stuff->host));
1458 tb1[sizeof(tb1)-1] = '\0';
1459 fcmd_add_host(tb1);
1460 }
1461
1462