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