1 /*
2  * parse.c: handles messages from the server.   Believe it or not.  I
3  * certainly wouldn't if I were you.
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 #include "irc.h"
37 #include "dma.h"
38 IRCII_RCSID("@(#)$Id: parse.c,v 1.76 2000/04/04 03:10:57 mrg Exp $");
39 
40 #include "server.h"
41 
42 #include "vars.h"
43 #include "ctcp.h"
44 #include "hook.h"
45 #include "edit.h"
46 #include "ignore.h"
47 #include "whois.h"
48 #include "lastlog.h"
49 #include "ircaux.h"
50 #include "funny.h"
51 #include "irccrypt.h"
52 #include "ircterm.h"
53 #include "flood.h"
54 #include "window.h"
55 #include "screen.h"
56 #include "output.h"
57 #include "numbers.h"
58 #include "parse.h"
59 #include "notify.h"
60 
61 #include "channels.h"
62 #include "ninja.h"
63 #include "nincache.h"
64 #include "tabkey.h"
65 #include "ninredir.h"
66 #include "orignick.h"
67 
68 /*
69  * moved to channels.c
70  *
71 #define STRING_CHANNEL '+'
72 #define MULTI_CHANNEL '#'
73 #define LOCAL_CHANNEL '&'
74 #define SAFE_CHANNEL '!'
75  */
76 
77 /*
78  * moved to parse.h:
79  *
80 #define	MAXPARA	15	/ * Taken from the ircd * /
81  *
82  *
83 static	void	BreakArgs _((u_char *, u_char **, u_char **));
84  */
85 
86 static	void	p_linreply _((u_char **));
87 /* static	void	p_ping _((u_char **)); */
88 static	void	p_topic _((u_char *, u_char **));
89 static	void	p_wall _((u_char *, u_char **));
90 static	void	p_wallops _((u_char *, u_char **));
91 static	void	p_privmsg _((u_char *, u_char **));
92 /*static	void	p_msgcmd _((u_char *, u_char **));*/
93 static	void	p_quit _((u_char *, u_char **));
94 static	void	p_pong _((u_char *, u_char **));
95 static	void	p_error _((u_char *, u_char **));
96 static	void	p_channel _((u_char *, u_char **));
97 static	void	p_invite _((u_char *, u_char **));
98 static	void	p_server_kill _((u_char *, u_char **));
99 static	void	p_nick _((u_char *, u_char **, int, u_char *));
100 static	void	p_mode _((u_char *, u_char **));
101 static	void	p_kick _((u_char *, u_char **));
102 static	void	p_part _((u_char *, u_char **));
103 
104 /*
105  * joined_nick: the nickname of the last person who joined the current
106  * channel
107  */
108 	u_char	*joined_nick = (u_char *) 0;
109 
110 /* public_nick: nick of the last person to send a message to your channel */
111 	u_char	*public_nick = (u_char *) 0;
112 
113 /* User and host information from server 2.7 */
114 	u_char	*FromUserHost = (u_char *) 0;
115 
116 /* ninja likes them seperated too */
117 	u_char	*FromUser = UNULL;
118 	u_char	*FromHost = UNULL;
119 
120 /* doing a PRIVMSG */
121 	int	doing_privmsg = 0;
122 
123 /*
124  *
125  * THIS WAS MOVED TO CHANNELS.C WHERE IT BELONGS
126  *
127  * is_channel: determines if the argument is a channel.  If it's a number,
128  * begins with MULTI_CHANNEL and has no '*', or STRING_CHANNEL, then its a
129  * channel.
130  *
131 int
132 is_channel(to)
133 	u_char	*to;
134 {
135 	int	version;
136 
137 	if (to == 0)
138 		return (0);
139 
140 	version = get_server_version(from_server);
141 	return ((version < Server2_7 && (isdigit(*to) || (*to == STRING_CHANNEL)
142 		|| *to == '-'))
143 		|| (version > Server2_5 && *to == MULTI_CHANNEL)
144 		|| (version > Server2_7 && *to == LOCAL_CHANNEL)
145 		|| (version > Server2_8 && *to == STRING_CHANNEL)
146 		|| (version > Server2_9 && *to == SAFE_CHANNEL)
147 		|| (version == ServerICB && my_stricmp(to, get_server_icbgroup(from_server)) == 0));
148 }
149  *
150  */
151 
152 u_char	*
PasteArgs(Args,StartPoint)153 PasteArgs(Args, StartPoint)
154 	u_char	**Args;
155 	int	StartPoint;
156 {
157 	int	i;
158 
159 	for (; StartPoint; Args++, StartPoint--)
160 		if (!*Args)
161 			return (u_char *) 0;
162 	for (i = 0; Args[i] && Args[i+1]; i++)
163 		Args[i][my_strlen(Args[i])] = ' ';
164 	Args[1] = (u_char *) 0;
165 	return Args[0];
166 }
167 
168 /*
169  * BreakArgs: breaks up the line from the server, in to where its from,
170  * setting FromUserHost if it should be, and returns all the arguements
171  * that are there.   Re-written by phone, dec 1992.
172  */
173 void
BreakArgs(Input,Sender,OutPut)174 BreakArgs(Input, Sender, OutPut)
175 	u_char	*Input;
176 	u_char	**Sender;
177 	u_char	**OutPut;
178 {
179 	u_char	*s = Input,
180 		*t;
181 	int	ArgCount = 0;
182 
183 	/*
184 	 * Get sender from :sender and user@host if :nick!user@host
185 	 */
186    	dma_Free(&FromUserHost);
187    	dma_Free(&FromUser);
188    	dma_Free(&FromHost);
189 
190 	if (*Input == ':')
191 	{
192 		u_char	*tmp;
193 
194 		*Input++ = '\0';
195 		if ((s = (u_char *) my_index(Input, ' ')) != (u_char *) 0)
196 			*s++ = '\0';
197 		*Sender = Input;
198 		if ((tmp = (u_char *) my_index(*Sender, '!')) != (u_char *) 0)
199 		{
200 		   *tmp++ = '\0';
201 		   dma_strcpy(&FromUserHost, tmp);
202 
203 		   /* save the user and host vars too */
204 		   t = my_index(FromUserHost, '@');
205 		   if (t)
206 		     {
207 			/* well it modifies it... */
208 			*t = '\0';
209 			dma_strcpy(&FromUser, FromUserHost);
210 			/* but it puts it back! */
211 			*t++ = '@';
212 			dma_strcpy(&FromHost, t);
213 		     }
214 
215 		}
216 	}
217 	else
218 		*Sender = empty_string;
219 
220 	if (!s)
221 		return;
222 
223 	for (;;)
224 	{
225 		while (*s == ' ')
226 			*s++ = '\0';
227 
228 		if (!*s)
229 			break;
230 
231 		if (*s == ':')
232 		{
233 			for (t = s; *t; t++)
234 				*t = *(t + 1);
235 			OutPut[ArgCount++] = s;
236 			break;
237 		}
238 		OutPut[ArgCount++] = s;
239 		if (ArgCount >= MAXPARA)
240 			break;
241 
242 		for (; *s != ' ' && *s; s++)
243 			;
244 	}
245 	OutPut[ArgCount] = (u_char *) 0;
246 }
247 
248 /* beep_em: Not hard to figure this one out */
249 void
beep_em(beeps)250 beep_em(beeps)
251 	int	beeps;
252 {
253 	int	cnt,
254 		i;
255 
256 	for (cnt = beeps, i = 0; i < cnt; i++)
257 		term_beep();
258 }
259 
260 /* in response to a TOPIC message from the server */
261 static	void
p_topic(from,ArgList)262 p_topic(from, ArgList)
263 	u_char	*from,
264 		**ArgList;
265 {
266    int	flag, ch_flag = !IGNORED;
267 
268    if (!from)
269      return;
270    flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
271    if (ArgList[1])
272      ch_flag = double_ignore(ArgList[0], NULL, IGNORE_CRAP);
273    if (flag == IGNORED || ch_flag == IGNORED)
274      return;
275 
276    save_message_from();
277    if (!ArgList[1])
278      {
279 	message_from((u_char *) 0, LOG_CRAP);
280 	if (do_hook(TOPIC_LIST, "%s * %s", from, ArgList[0]))
281 	  {
282 	     if (my_strlen(ArgList[0]) >= 1)
283 	       say("%s has changed the topic to %s", from, ArgList[0]);
284 	     else
285 	       say("%s has removed the topic", from);
286 	  }
287      }
288    else
289      {
290 	message_from(ArgList[0], LOG_CRAP);
291 	if (do_hook(TOPIC_LIST, "%s %s %s", from, ArgList[0], ArgList[1]))
292 	  {
293 	     if (my_strlen(ArgList[1]) >= 1)
294 	       say("%s has changed the topic on channel %s to %s",
295 		   from, ArgList[0], ArgList[1]);
296 	     else
297 	       say("%s has removed the topic on channel %s",
298 		   from, ArgList[0]);
299 	  }
300      }
301    restore_message_from();
302 }
303 
304 static	void
p_linreply(ArgList)305 p_linreply(ArgList)
306 	u_char	**ArgList;
307 {
308 	PasteArgs(ArgList, 0);
309 	say("%s", ArgList[0]);
310 }
311 
312 static	void
p_wall(from,ArgList)313 p_wall(from, ArgList)
314 	u_char	*from,
315 		**ArgList;
316 {
317 	int	flag,
318 		level;
319 	u_char	*line;
320 	u_char	*high;
321 
322 	if (!from)
323 		return;
324 	PasteArgs(ArgList, 0);
325 	if (!(line = ArgList[0]))
326 		return;
327 	flag = double_ignore(from, FromUserHost, IGNORE_WALLS);
328 	save_message_from();
329 	message_from(from, LOG_WALL);
330 	if (flag != IGNORED)
331 	{
332 		if (flag == HIGHLIGHTED)
333 			high = &highlight_char;
334 		else
335 			high = empty_string;
336 		if ((flag != DONT_IGNORE) && (ignore_usernames & IGNORE_WALLS)
337 				&& !FromUserHost)
338 			add_to_whois_queue(from, whois_ignore_walls, "%s",line);
339 		else
340 		{
341 			level = set_lastlog_msg_level(LOG_WALL);
342 			if (check_flooding(from, WALL_FLOOD, line) &&
343 					do_hook(WALL_LIST, "%s %s", from, line))
344 				put_it("%s#%s#%s %s", high, from, high, line);
345 			if (beep_on_level & LOG_WALL)
346 				beep_em(1);
347 			set_lastlog_msg_level(level);
348 		}
349 	}
350 	restore_message_from();
351 }
352 
353 static	void
p_wallops(from,ArgList)354 p_wallops(from, ArgList)
355 	u_char	*from,
356 		**ArgList;
357 {
358 	int	flag, level;
359 	u_char	*line;
360 
361 	if (!from)
362 		return;
363 	if (!(line = PasteArgs(ArgList, 0)))
364 		return;
365 	flag = double_ignore(from, FromUserHost, IGNORE_WALLOPS);
366 	level = set_lastlog_msg_level(LOG_WALLOP);
367 	save_message_from();
368 	message_from(from, LOG_WALLOP);
369 	if (my_index(from, '.'))
370 	{
371 		u_char	*high;
372 
373 		if (flag != IGNORED)
374 		{
375 			if (flag == HIGHLIGHTED)
376 				high = &highlight_char;
377 			else
378 				high = empty_string;
379 			if (do_hook(WALLOP_LIST, "%s S %s", from, line))
380 				put_it("%s!%s!%s %s", high, from, high, line);
381 			if (beep_on_level & LOG_WALLOP)
382 				beep_em(1);
383 		}
384 	}
385 	else
386 	{
387 		if (get_int_var(USER_WALLOPS_VAR))
388 		{
389 			if ((flag != DONT_IGNORE) && (check_flooding(from, WALLOP_FLOOD, line)))
390 			add_to_whois_queue(from, whois_new_wallops, "%s", line);
391 		}
392 		else if (my_strcmp(from, get_server_nickname(get_window_server(0))) != 0)
393 			put_it("!%s! %s", from, line);
394 	}
395 	set_lastlog_msg_level(level);
396 	restore_message_from();
397 }
398 
399 /*ARGSUSED*/
400 void
whoreply(from,ArgList)401 whoreply(from, ArgList)
402 	u_char	**ArgList,
403 		*from;
404 {
405 	static	u_char	format[64];
406 	static	int	last_width = -1;
407    static	int	showhops = -1;
408 	int	ok = 1;
409 	u_char	*channel,
410 		*user,
411 		*host,
412 		*server,
413 		*nick,
414 		*status,
415 		*name,
416    		*hops;
417 	int	i;
418 
419 	FILE	*fip;
420 	u_char	buf_data[BUFSIZ];
421 
422    if (showhops != get_int_var(SHOW_WHO_HOPCOUNT_VAR))
423      showhops = get_int_var(SHOW_WHO_HOPCOUNT_VAR);
424 
425 	if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR))
426 	{
427 	   if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)) != 0)
428 	     {
429 		snprintf(CP(format), sizeof(format)-1,
430 			 "%%-%u.%us %%-9s |%%-3s",
431 			 (u_char) last_width,
432 			 (u_char) last_width);
433 		format[sizeof(format)-1] = '\0';
434 	     }
435 	   else
436 	     my_strmcpy(format, "%s\t%-9s |%-3s", sizeof(format)-1);
437 	   if (showhops)
438 	     my_strmcat(format, " %2s", sizeof(format)-1);
439 	   my_strmcat(format, "|", sizeof(format)-1);
440 	   my_strmcat(format, " %s@%s (%s)", sizeof(format)-1);
441 	}
442 	i = 0;
443 	channel = user = host = server = nick = status = name = hops = empty_string;
444 	if (ArgList[i])
445 		channel = ArgList[i++];
446 	if (ArgList[i])
447 		user = ArgList[i++];
448 	if (ArgList[i])
449 		host = ArgList[i++];
450 	if (ArgList[i])
451 		server = ArgList[i++];
452 	if (ArgList[i])
453 		nick = ArgList[i++];
454 	if (ArgList[i])
455 		status = ArgList[i++];
456 	PasteArgs(ArgList, i);
457 
458 	if (*status == 'S')	/* this only true for the header WHOREPLY */
459 	{
460 		channel = UP("Channel");
461 		if (((who_mask & WHO_FILE) == 0) || (fopen (CP(who_file), "r")))
462 		{
463 			if (do_hook(WHO_LIST, "%s %s %s %s %s %s", channel,
464 					nick, status, user, host, ArgList[6]))
465 		     	{
466 				if (showhops)
467 					put_it(CP(format), channel, nick, status, UP(" #"), user,
468 						host, ArgList[6]);
469 			   	else
470 					put_it(CP(format), channel, nick, status, user,
471 						host, ArgList[6]);
472 			   return;
473 			}
474 		}
475 	}
476 
477    if (ArgList[i])
478      name = ArgList[i];
479    if (*name == ':')
480      name++;
481    if (isdigit(*name) && my_index(name, ' '))
482      hops = next_arg(name, &name);
483 
484 
485 	if (who_mask)
486 	{
487 		if (who_mask & WHO_HERE)
488 			ok = ok && (*status == 'H');
489 		if (who_mask & WHO_AWAY)
490 			ok = ok && (*status == 'G');
491 		if (who_mask & WHO_OPS)
492 			ok = ok && (*(status + 1) == '*');
493 		if (who_mask & WHO_LUSERS)
494 			ok = ok && (*(status + 1) != '*');
495 		if (who_mask & WHO_CHOPS)
496 			ok = ok && ((*(status + 1) == '@') ||
497 			(*(status + 2) == '@'));
498 		if (who_mask & WHO_NAME)
499 			ok = ok && wild_match(who_name, user);
500 		if (who_mask & WHO_NICK)
501 			ok = ok && wild_match(who_nick, nick);
502 		if (who_mask & WHO_HOST)
503 			ok = ok && wild_match(who_host, host);
504 		if (who_mask & WHO_REAL)
505 			ok = ok && wild_match(who_real, name);
506 		if (who_mask & WHO_SERVER)
507 			ok = ok && wild_match(who_server, server);
508 		if (who_mask & WHO_FILE)
509 		{
510 			ok = 0;
511 			cannot_open = (u_char *) 0;
512 			if ((fip = fopen(CP(who_file), "r")) != (FILE *) 0)
513 			{
514 				while (fgets ((char *)buf_data, BUFSIZ, fip) !=
515 								(char *) 0)
516 				{
517 					buf_data[my_strlen(buf_data)-1] = '\0';
518 					ok = ok || wild_match(buf_data, nick);
519 				}
520 				fclose (fip);
521 			} else
522 				cannot_open = who_file;
523 		}
524 	}
525 	if (ok)
526 	{
527 		if (do_hook(WHO_LIST, "%s %s %s %s %s %s", channel, nick,
528 				status, user, host, name))
529 		{
530 			if (showhops)
531 				put_it(CP(format), channel, nick, status, hops, user, host,
532 					name);
533 			else
534 				put_it(CP(format), channel, nick, status, user, host,
535 					name);
536 		}
537 	}
538 }
539 
540 static	void
p_privmsg(from,Args)541 p_privmsg(from, Args)
542 	u_char	*from,
543 		**Args;
544 {
545 	int	level,
546 		flag,
547      		ch_flag = !IGNORED,
548 		list_type,
549 		flood_type,
550 		log_type;
551 	u_char	ignore_type;
552 	u_char	*ptr,
553 		*to;
554 	u_char	*high;
555 	int	no_flood;
556 
557 	if (!from)
558 		return;
559 	PasteArgs(Args, 1);
560 	to = Args[0];
561 	ptr = Args[1];
562 	if (!to || !ptr)
563 		return;
564 	save_message_from();
565 
566 	if (is_channel(to))
567 	{
568 		message_from(to, LOG_MSG);
569 		malloc_strcpy(&public_nick, from);
570 		if (!is_on_channel(to, parsing_server_index, from))
571 		{
572 			log_type = LOG_PUBLIC;
573 			ignore_type = IGNORE_PUBLIC;
574 			list_type = PUBLIC_MSG_LIST;
575 			flood_type = PUBLIC_FLOOD;
576 		}
577 		else
578 		{
579 			log_type = LOG_PUBLIC;
580 			ignore_type = IGNORE_PUBLIC;
581 			if (is_current_channel(to, parsing_server_index, 0))
582 				list_type = PUBLIC_LIST;
583 			else
584 				list_type = PUBLIC_OTHER_LIST;
585 			flood_type = PUBLIC_FLOOD;
586 		}
587 	}
588 	else
589 	{
590 		message_from(from, LOG_MSG);
591 		flood_type = MSG_FLOOD;
592 		if (my_stricmp(to, get_server_nickname(parsing_server_index)))
593 		{
594 			log_type = LOG_WALL;
595 			ignore_type = IGNORE_WALLS;
596 			list_type = MSG_GROUP_LIST;
597 		}
598 		else
599 		{
600 			log_type = LOG_MSG;
601 			ignore_type = IGNORE_MSGS;
602 			list_type = MSG_LIST;
603 		}
604 	}
605 	flag = double_ignore(from, FromUserHost, ignore_type);
606    	ch_flag = double_ignore(to, UNULL, ignore_type);
607 	switch (flag)
608 	{
609 	case IGNORED:
610 		if ((list_type == MSG_LIST) && get_int_var(SEND_IGNORE_MSG_VAR))
611 			send_to_server("NOTICE %s :%s is ignoring you", from,
612 					get_server_nickname(parsing_server_index));
613 		goto out;
614 	case HIGHLIGHTED:
615 		high = &highlight_char;
616 		break;
617 	default:
618 		high = empty_string;
619 		break;
620 	}
621 
622    if (ch_flag == IGNORED)
623      goto out;
624 
625 	level = set_lastlog_msg_level(log_type);
626 	ptr = do_ctcp(from, to, ptr);
627 	if (!ptr || !*ptr)
628 		goto out;
629 	if ((flag != DONT_IGNORE) && (ignore_usernames & ignore_type) && !FromUserHost)
630 		add_to_whois_queue(from, whois_ignore_msgs, "%s", ptr);
631 	else
632 	{
633 		no_flood = check_flooding(from, flood_type, ptr);
634 		if (sed == 0 || do_hook(ENCRYPTED_PRIVMSG_LIST,"%s %s %s",from, to, ptr))
635 		{
636 		switch (list_type)
637 		{
638 		case PUBLIC_MSG_LIST:
639 		   	if (!checkgrep(to, ptr))
640 		     		goto out;
641 			if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr))
642 			    put_it("%s(%s/%s)%s %s", high, from, to, high, ptr);
643 			break;
644 		case MSG_GROUP_LIST:
645 			if (no_flood && do_hook(list_type, "%s %s %s", from, to, ptr))
646 			    put_it("%s-%s:%s-%s %s", high, from, to, high, ptr);
647 			break;
648 		case MSG_LIST:
649 			if (!no_flood)
650 				break;
651 
652 			malloc_strcpy(&recv_nick, from);
653 			if (away_set)
654 				beep_em(get_int_var(BEEP_WHEN_AWAY_VAR));
655 			if (do_hook(list_type, "%s %s", from, ptr))
656 			{
657 			    if (server_list[parsing_server_index].away_set)
658 			    {
659 				time_t t;
660 				u_char *msg = (u_char *) 0;
661 
662 				t = time((time_t *) 0);
663 				msg = (u_char *) new_malloc(my_strlen(ptr) + 20);
664 				sprintf(CP(msg), "%s <%.16s>", ptr, ctime(&t));
665 				put_it("%s*%s(%s)*%s %s",
666 				       high, from, FromUserHost, high, msg);
667 				new_free(&msg);
668 			    }
669 			   else
670 			     put_it("%s*%s(%s)*%s %s", high, from, FromUserHost, high, ptr);
671 			}
672 		   if (server_list[parsing_server_index].away_set)
673 		     add_to_awaylog("*%s(%s)* %s", from, FromUserHost, ptr);
674 		   addredirect(REDIRECT_MSG, "*%s(%s)* %s", from, FromUserHost, ptr);
675 		   add_tab_key(0, "msg ", from);
676 		   break;
677 		case PUBLIC_LIST:
678 			if (get_int_var(MAKE_NOTICE_MSG_VAR))
679 				doing_privmsg = 1;
680 		   	if (!checkgrep(to, ptr))
681 		     		goto out;
682 			if (no_flood && do_hook(list_type, "%s %s %s", from,
683 			    to, ptr))
684 				put_it("%s<%s>%s %s", high, from, high, ptr);
685 			doing_privmsg = 0;
686 			break;
687 		case PUBLIC_OTHER_LIST:
688 			if (get_int_var(MAKE_NOTICE_MSG_VAR))
689 				doing_privmsg = 1;
690 		   	if (!checkgrep(to, ptr))
691 		     		goto out;
692 			if (no_flood && do_hook(list_type, "%s %s %s", from,
693 			    to, ptr))
694 				put_it("%s<%s:%s>%s %s", high, from, to, high,
695 					ptr);
696 			doing_privmsg = 0;
697 			break;
698 		}
699 		if (beep_on_level & log_type)
700 			beep_em(1);
701 		}
702 	}
703 	set_lastlog_msg_level(level);
704 out:
705 	restore_message_from();
706 }
707 
708 #if 0
709 static	void
710 p_msgcmd(from, ArgList)
711 	u_char	*from,
712 		**ArgList;
713 {
714 	u_char	*high,
715 		*channel,
716 		*text;
717 	int	log_type,
718 		no_flooding;
719 	int	flag;
720 
721 	if (!from)
722 		return;
723 	flag = double_ignore(from, FromUserHost, IGNORE_PUBLIC);
724 	switch (flag)
725 	{
726 	case IGNORED:
727 		return;
728 	case HIGHLIGHTED:
729 		high = &highlight_char;
730 		break;
731 	default:
732 		high = empty_string;
733 		break;
734 	}
735 	if ((channel = real_channel()) == (u_char *) 0)
736 		return;
737 	text = do_ctcp(from, channel, ArgList[0]);
738 	if (!text || !*text)
739 		return;
740 	malloc_strcpy((u_char **) &public_nick, from);
741 	log_type = set_lastlog_msg_level(LOG_PUBLIC);
742 	no_flooding = check_flooding(from, PUBLIC_FLOOD, text);
743 	save_message_from();
744 	message_from(channel, LOG_PUBLIC);
745 	if (is_current_channel(channel, parsing_server_index, 0))
746 	{
747 		if (get_int_var(MAKE_NOTICE_MSG_VAR))
748 				doing_privmsg = 1;
749 		if (no_flooding && do_hook(PUBLIC_LIST, "%s %s %s", from, channel, text))
750 			put_it("%s<%s>%s %s", high, from, high, text);
751 		doing_privmsg = 0;
752 	}
753 	else
754 	{
755 		if (get_int_var(MAKE_NOTICE_MSG_VAR))
756 				doing_privmsg = 1;
757 		if (no_flooding && do_hook(PUBLIC_OTHER_LIST, "%s %s %s", from,
758 				channel, text))
759 			put_it("%s<%s:%s>%s %s", high, from, channel, high,
760 				text);
761 		doing_privmsg = 0;
762 	}
763 	restore_message_from();
764 	if (beep_on_level & LOG_PUBLIC)
765 		beep_em(1);
766 	set_lastlog_msg_level(log_type);
767 }
768 #endif
769 
770 /*ARGSUSED*/
771 static	void
p_quit(from,ArgList)772 p_quit(from, ArgList)
773 	u_char	*from,
774 		**ArgList;
775 {
776 	int	one_prints = 0;
777 	u_char	*chan;
778 	u_char	*Reason;
779 	int	flag, ch_flag;
780 
781 	if (!from)
782 		return;
783 	flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
784 	save_message_from();
785 	if (flag != IGNORED)
786 	{
787 		PasteArgs(ArgList, 0);
788 		Reason = ArgList[0] ? ArgList[0] : q_mark;
789 		for (chan = walk_channels(from, 1, parsing_server_index); chan; chan = walk_channels(from, 0, -1))
790 		{
791 		   ch_flag = double_ignore(chan, NULL, IGNORE_CRAP);
792 		   message_from(chan, LOG_CRAP);
793 		   if (ch_flag != IGNORED
794 		       && checkgrep(chan, Reason)
795 		       && do_hook(CHANNEL_SIGNOFF_LIST, "%s %s %s", chan, from, Reason))
796 		     one_prints = 1;
797 		}
798 		if (one_prints)
799 		{
800 		   message_from(what_channel(from, parsing_server_index), LOG_CRAP);
801 		   if (do_hook(SIGNOFF_LIST, "%s %s", from, Reason))
802 		     say("SignOff: %s (%s)", from, Reason);
803 		}
804 	}
805 	message_from((u_char *) 0, LOG_CURRENT);
806 
807    /* XXX: check for netsplits */
808 	remove_from_channel((u_char *) 0, from, parsing_server_index);
809 	notify_mark(from, 0, 0, UNULL, UNULL, 0);
810 	nchk_orignick(from);
811 
812 	restore_message_from();
813 }
814 
815 /*ARGSUSED*/
816 static	void
p_pong(from,ArgList)817 p_pong(from, ArgList)
818 	u_char	*from,
819 		**ArgList;
820 {
821 	int	flag;
822 
823 	if (!from)
824 		return;
825 	flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
826 	if (flag == IGNORED)
827 		return;
828 
829 	if (ArgList[0])
830 		say("%s: PONG received from %s", ArgList[0], from);
831 }
832 
833 /*ARGSUSED*/
834 static	void
p_error(from,ArgList)835 p_error(from, ArgList)
836 	u_char	*from,
837 		**ArgList;
838 {
839 	PasteArgs(ArgList, 0);
840 	if (!ArgList[0])
841 		return;
842 	say("%s", ArgList[0]);
843 }
844 
845 static	void
p_channel(from,ArgList)846 p_channel(from, ArgList)
847 	u_char	*from;
848 	u_char	**ArgList;
849 {
850 	int	join;
851 	u_char	*channel;
852 	int	flag, ch_flag;
853 	u_char	*s, *ov = NULL;
854 	int	chan_oper = 0, chan_voice = 0;
855 
856 	if (!from)
857 		return;
858 	flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
859 	if (my_strcmp(ArgList[0], zero))
860 	{
861 		join = 1;
862 		channel = ArgList[0];
863 		/*
864 		 * this \007 should be \a but a lot of compilers are
865 		 * broken.  *sigh*  -mrg
866 		 */
867 		if ((ov = s = my_index(channel, '\007')))
868 		{
869 			*s = '\0';
870 			ov++;
871 			while (*++s)
872 			{
873 				if (*s == 'o')
874 					chan_oper = 1;
875 				if (*s == 'v')
876 					chan_voice = 1;
877 
878 			}
879 		}
880 		malloc_strcpy(&joined_nick, from);
881 	}
882 	else
883 	{
884 		channel = zero;
885 		join = 0;
886 	}
887    /*
888     * this channel cache maintenance is handled in nincache.c
889     *
890     *
891 	if (!my_stricmp(from, get_server_nickname(parsing_server_index)))
892 	{
893 		if (join)
894 		{
895 			add_channel(channel, parsing_server_index, CHAN_JOINED, (ChannelList *) 0);
896 			if (get_server_version(parsing_server_index) == Server2_5)
897 				send_to_server("NAMES %s", channel);
898 			send_to_server("MODE %s", channel);
899 		}
900 		else
901 			remove_channel(channel, parsing_server_index);
902 	}
903 	else
904 	{
905 		if (join)
906 			add_to_channel(channel, from, parsing_server_index, chan_oper, chan_voice);
907 		else
908 			remove_from_channel(channel, from, parsing_server_index);
909 	}
910     *
911     */
912 	if (join)
913 	{
914 		if (!get_channel_oper(channel, parsing_server_index))
915 			in_on_who = 1;
916 		save_message_from();
917 		message_from(channel, LOG_CRAP);
918 	   	ch_flag = double_ignore(channel, NULL, IGNORE_CRAP);
919 		if (flag != IGNORED
920 		    && ch_flag != IGNORED)
921 	     	{
922 		   u_char tbuf[512];
923 
924 		   my_strmcpy(tbuf, from, sizeof(tbuf)-1);
925 		   my_strmcat(tbuf, " ", sizeof(tbuf)-1);
926 		   if (FromUserHost)
927 		     {
928 			my_strmcat(tbuf, "(", sizeof(tbuf)-1);
929 			my_strmcat(tbuf, FromUserHost, sizeof(tbuf)-1);
930 			my_strmcat(tbuf, ") ", sizeof(tbuf)-1);
931 		     }
932 		   my_strmcat(tbuf, "has joined channel ", sizeof(tbuf)-1);
933 		   my_strmcat(tbuf, channel, sizeof(tbuf)-1);
934 		   if (ov && *ov)
935 		     {
936 			my_strmcat(tbuf, " +", sizeof(tbuf)-1);
937 			my_strmcat(tbuf, ov, sizeof(tbuf)-1);
938 		     }
939 		   if (checkgrep(channel, tbuf)
940 		       && do_hook(JOIN_LIST, "%s %s %s", from,
941 				  channel, ov ? ov : empty_string))
942 		     put_info("%s", tbuf);
943 		}
944 		restore_message_from();
945 		in_on_who = 0;
946 	}
947    	else
948      		say("someone left!");
949 }
950 
951 static	void
p_invite(from,ArgList)952 p_invite(from, ArgList)
953 	u_char	*from,
954 		**ArgList;
955 {
956 	u_char	*high;
957 	int	flag, ch_flag;
958 
959 	if (!from)
960 		return;
961 	flag = double_ignore(from, FromUserHost, IGNORE_INVITES);
962 	switch (flag)
963 	{
964 	case IGNORED:
965 		if (get_int_var(SEND_IGNORE_MSG_VAR))
966 			send_to_server("NOTICE %s :%s is ignoring you",
967 				from, get_server_nickname(parsing_server_index));
968 		return;
969 	case HIGHLIGHTED:
970 		high = &highlight_char;
971 		break;
972 	default:
973 		high = empty_string;
974 		break;
975 	}
976 	if (ArgList[0] && ArgList[1])
977 	{
978 		ch_flag = double_ignore(ArgList[1], NULL, IGNORE_INVITES);
979 		if ((flag != DONT_IGNORE)
980 		    && ch_flag != DONT_IGNORE
981 		    && (ignore_usernames & IGNORE_INVITES)
982 		    && !FromUserHost)
983 			add_to_whois_queue(from, whois_ignore_invites, "%s", ArgList[1]);
984 		else
985 		{
986 			save_message_from();
987 			message_from(from, LOG_CRAP);
988 			if (do_hook(INVITE_LIST, "%s %s", from, ArgList[1]))
989 				say("%s%s(%s)%s invites you to channel %s", high,
990 						from, FromUserHost, high, ArgList[1]);
991 		   	if (server_list[parsing_server_index].away_set)
992 		     	  add_to_awaylog("%s(%s) invites you to channel %s",
993 						from, FromUserHost, ArgList[1]);
994 			restore_message_from();
995 			malloc_strcpy(&invite_channel, ArgList[1]);
996 			malloc_strcpy(&recv_nick, from);
997 		}
998 	}
999 }
1000 
1001 static	void
p_server_kill(from,ArgList)1002 p_server_kill(from, ArgList)
1003 	u_char	*from,
1004 		**ArgList;
1005 {
1006 	/*
1007 	 * this is so bogus checking for a server name having a '.'
1008 	 * in it - phone, april 1993.
1009 	 */
1010 	if (my_index(from, '.'))
1011 		say("You have been rejected by server %s %s", from,
1012 		    ArgList[1] ? ArgList[1] : UP("(No Reason Given)"));
1013 	else
1014 	{
1015 		say("You have been killed by operator %s %s", from,
1016 			ArgList[1] ? ArgList[1] : (u_char *) "(No Reason Given)");
1017 
1018 	   /* if we were away and missed this output, put it in the log */
1019 	   if (server_list[parsing_server_index].away_set)
1020 	     add_to_awaylog("You were killed by operator %s %s", from,
1021 			    ArgList[1] ? ArgList[1] : (u_char *) "(No Reason Given)");
1022 
1023 #ifdef FASCIST_QUIT_ON_OPERATOR_KILL
1024 		irc_exit();
1025 #endif /* FASCIST_QUIT_ON_OPERATOR_KILL */
1026 	}
1027 	close_server(parsing_server_index, empty_string);
1028 	window_check_servers();
1029 	if (!connected_to_server)
1030 		say("Use /SERVER to reconnect to a server");
1031 }
1032 
1033 /*
1034  * this has been moved to nincache..
1035  *
1036 static	void
1037 p_ping(ArgList)
1038 	u_char	**ArgList;
1039 {
1040 	PasteArgs(ArgList, 0);
1041 	send_to_server("PONG :%s", ArgList[0]);
1042 }
1043  */
1044 
1045 static	void
p_nick(from,ArgList,its_me,fnick)1046 p_nick(from, ArgList, its_me, fnick)
1047 	u_char	*from,
1048 		**ArgList, *fnick;
1049 {
1050 	int	one_prints = 0;
1051 	u_char	*chan;
1052 	u_char	*line;
1053 	int	flag, ch_flag;
1054 
1055 	if (!from)
1056 		return;
1057 	flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
1058 	line = ArgList[0];
1059    /*
1060     * moved some of this to nincache.c
1061     *
1062     * its_me is now passed in from parse_server()
1063     *
1064 	if (my_stricmp(from, get_server_nickname(parsing_server_index)) == 0){
1065 		if (parsing_server_index == primary_server)
1066 			malloc_strcpy(&nickname, line);
1067 		set_server_nickname(parsing_server_index, line);
1068 		its_me = 1;
1069 	}
1070     *
1071     *
1072     *
1073     * this is just a bit hackish, if it_me, then we were the person changing their nick...
1074     *
1075     * that means we now have to look for channels with my new nickname and report that
1076     * the nick change occurred! (from -> current nick)
1077     *
1078     */
1079 
1080 	save_message_from();
1081 	if (flag != IGNORED)
1082 	{
1083 		for (chan = walk_channels(fnick, 1, parsing_server_index); chan;
1084 				chan = walk_channels(fnick, 0, -1))
1085 		{
1086 		   ch_flag = double_ignore(chan, UNULL, IGNORE_CRAP);
1087 		   message_from(chan, LOG_CRAP);
1088 		   if (ch_flag != IGNORED
1089 		       && checkgrep(chan, UNULL)
1090 		       && do_hook(CHANNEL_NICK_LIST, "%s %s %s", chan, from, line))
1091 		     one_prints = 1;
1092 		}
1093 		if (one_prints)
1094 		{
1095 		   if (its_me)
1096 		     message_from((u_char *) 0, LOG_CRAP);
1097 		   else
1098 		     message_from(what_channel(fnick, parsing_server_index), LOG_CRAP);
1099 		   if (do_hook(NICKNAME_LIST, "%s %s", from, line))
1100 		     say("%s is now known as %s", from, line);
1101 		}
1102 	}
1103    /*
1104     * more stuff that's moved to nincache.c
1105     *
1106 	rename_nick(from, line, parsing_server_index);
1107 	if (my_stricmp(from, line))
1108 	{
1109 		message_from((u_char *) 0, LOG_CURRENT);
1110 		notify_mark(from, 0, 0);
1111 		notify_mark(line, 1, 0);
1112 	}
1113     */
1114 	restore_message_from();
1115 }
1116 
1117 static	void
p_mode(from,ArgList)1118 p_mode(from, ArgList)
1119 	u_char	*from,
1120 		**ArgList;
1121 {
1122 	u_char	*channel;
1123 	u_char	*line;
1124 	int	flag, ch_flag;
1125 
1126 	if (!from)
1127 		return;
1128 	flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
1129 	PasteArgs(ArgList, 1);
1130 	channel = ArgList[0];
1131 	line = ArgList[1];
1132 	save_message_from();
1133 	message_from(channel, LOG_CRAP);
1134 	if (channel && line)
1135 	{
1136 		if (is_channel(channel))
1137 		{
1138    			ch_flag = double_ignore(channel, UNULL, IGNORE_CRAP);
1139 			if (flag != IGNORED
1140 			    && ch_flag != IGNORED
1141 			    && checkgrep(channel, UNULL)
1142 			    && do_hook(MODE_LIST, "%s %s %s",
1143 					from, channel, line))
1144 				say("Mode change \"%s\" on channel %s by %s",
1145 						line, channel, from);
1146 		   /*
1147 		    * moved to nincache.c
1148 		    *
1149 			update_channel_mode(channel, parsing_server_index, line);
1150 		    */
1151 		}
1152 		else
1153 		{
1154 			if (flag != IGNORED && do_hook(MODE_LIST, "%s %s %s",
1155 					from, channel, line))
1156 				say("Mode change \"%s\" for user %s by %s",
1157 						line, channel, from);
1158 		   /*
1159 		    * moved to nincache.c
1160 		    *
1161 			update_user_mode(line);
1162 		    */
1163 		}
1164 		update_all_status();
1165 	}
1166 	restore_message_from();
1167 }
1168 
1169 static	void
p_kick(from,ArgList)1170 p_kick(from, ArgList)
1171 	u_char	*from,
1172 		**ArgList;
1173 {
1174 	u_char	*channel,
1175 		*who,
1176 		*comment;
1177    	int flag, ch_flag, w_flag;
1178 
1179 	if (!from)
1180 		return;
1181 	channel = ArgList[0];
1182 	who = ArgList[1];
1183 	comment = ArgList[2];
1184 
1185 	if (channel && who)
1186 	{
1187    		flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
1188    		w_flag = double_ignore(who, UNULL, IGNORE_CRAP);
1189    		ch_flag = double_ignore(channel, UNULL, IGNORE_CRAP);
1190 
1191 		save_message_from();
1192 		message_from(channel, LOG_CRAP);
1193 		if (my_stricmp(who, get_server_nickname(parsing_server_index)) == 0)
1194 		{
1195 		   if (comment && *comment)
1196 		     {
1197 			if (do_hook(KICK_LIST, "%s %s %s %s", who,
1198 				    from, channel, comment))
1199 			  say("You have been kicked off channel %s by %s (%s)",
1200 			      channel, from, comment);
1201 			if (server_list[parsing_server_index].away_set)
1202 			  add_to_awaylog("You have been kicked off channel %s by %s (%s)",
1203 					 channel, from, comment);
1204 		     }
1205 		   else
1206 		     {
1207 			if (do_hook(KICK_LIST, "%s %s %s", who, from,
1208 				    channel))
1209 			  say("You have been kicked off channel %s by %s",
1210 			      channel, from);
1211 			if (server_list[parsing_server_index].away_set)
1212 			  add_to_awaylog("You have been kicked off channel %s by %s",
1213 					 channel, from);
1214 		     }
1215 		   /*
1216 		    * handled in nincache.c
1217 		    *
1218 			remove_channel(channel, parsing_server_index);
1219 			update_all_status();
1220 		    */
1221 		}
1222 		else
1223 		{
1224 		   if (flag != IGNORED
1225 		       && w_flag != IGNORED
1226 		       && ch_flag != IGNORED)
1227 		     {
1228 			if (comment && *comment)
1229 			  {
1230 			     if (checkgrep(channel, comment)
1231 				 && do_hook(KICK_LIST, "%s %s %s %s", who,
1232 					    from, channel, comment))
1233 			       say("%s has been kicked off channel %s by %s (%s)",
1234 				   who, channel, from, comment);
1235 			  }
1236 			else
1237 			  {
1238 			     if (checkgrep(channel, UNULL)
1239 				 && do_hook(KICK_LIST, "%s %s %s", who, from,
1240 					 channel))
1241 			       say("%s has been kicked off channel %s by %s",
1242 				   who, channel, from);
1243 			  }
1244 		   /*
1245 		    * handled in nincache.c
1246 		    *
1247 			remove_from_channel(channel, who, parsing_server_index);
1248 		    */
1249 		     }
1250 		}
1251 		restore_message_from();
1252 	}
1253 }
1254 
1255 static	void
p_part(from,ArgList)1256 p_part(from, ArgList)
1257 	u_char	*from,
1258 		**ArgList;
1259 {
1260 	u_char	*channel;
1261 	u_char	*comment;
1262 	int	flag, ch_flag;
1263 
1264 	if (!from)
1265 		return;
1266 	flag = double_ignore(from, FromUserHost, IGNORE_CRAP);
1267 	channel = ArgList[0];
1268    /*
1269     * argh.. we don't care if we're on the channel or not.. just go on
1270     *
1271 	if (!is_on_channel(channel, parsing_server_index, from))
1272 		return;
1273     */
1274    	ch_flag = double_ignore(channel, UNULL, IGNORE_CRAP);
1275 	comment = ArgList[1];
1276 	if (!comment)
1277 		comment = empty_string;
1278 	in_on_who = 1;
1279 	if (flag != IGNORED
1280 	    && ch_flag != IGNORED)
1281 	{
1282 		save_message_from();
1283 		message_from(channel, LOG_CRAP);
1284 		if (checkgrep(channel, UNULL)
1285 		    && do_hook(LEAVE_LIST, "%s %s %s", from, channel, comment))
1286 		{
1287 			if (comment && *comment != '\0')
1288 				say("%s has left %s (%s)", from, channel, comment);
1289 			else
1290 				say("%s has left %s", from, channel);
1291 		}
1292 		restore_message_from();
1293 	}
1294    /*
1295     * handled in nincache.c
1296     *
1297 	if (my_stricmp(from, get_server_nickname(parsing_server_index)) == 0)
1298 		remove_channel(channel, parsing_server_index);
1299 	else
1300 		remove_from_channel(channel, from, parsing_server_index);
1301     */
1302 	in_on_who = 0;
1303 }
1304 
1305 
1306 /*
1307  * parse_server: parses messages from the server, doing what should be done
1308  * with them
1309  */
1310 void
parse_server(line)1311 parse_server(line)
1312 	u_char	*line;
1313 {
1314 	server_list[parsing_server_index].parse_server(line);
1315 }
1316 
1317 void
irc2_parse_server(line)1318 irc2_parse_server(line)
1319 	u_char	*line;
1320 {
1321 	u_char	*from,
1322 		*comm,
1323 		*end,
1324 		*copy = (u_char *) 0;
1325 	int	numeric, flag = 0;
1326 	u_char	**ArgList;
1327 	u_char	*TrueArgs[MAXPARA + 1];
1328    	u_char	*str_flag = UNULL;
1329 
1330 	if ((u_char *) 0 == line)
1331 		return;
1332 
1333 	end = my_strlen(line) + line;
1334 	if (*--end == '\n')
1335 		*end-- = '\0';
1336 	if (*end == '\r')
1337 		*end-- = '\0';
1338 
1339    /* do the cache stuff in nincache.c */
1340    if (!parse_into_cache(line, &flag, &str_flag))
1341      return;
1342 
1343 	if (*line == ':')
1344 	{
1345 		if (!do_hook(RAW_IRC_LIST, "%s", line + 1))
1346 			return;
1347 	}
1348 	else if (!do_hook(RAW_IRC_LIST, "%s %s", "*", line))
1349 		return;
1350 
1351 	malloc_strcpy(&copy, line);
1352 	ArgList = TrueArgs;
1353 	BreakArgs(copy, &from, ArgList);
1354 
1355 	if (!(comm = (*ArgList++)))
1356 		return;		/* Empty line from server - ByeBye */
1357 
1358 	/*
1359 	 * XXX!!!
1360 	 * this should fail on '1xxx'!!!
1361 	 */
1362 	if (0 != (numeric = my_atoi(comm)))
1363 		numbered_command(from, numeric, ArgList);
1364 	else if (my_strcmp(comm, "NAMREPLY") == 0)
1365 		funny_namreply(from, ArgList);
1366 	else if (my_strcmp(comm, "WHOREPLY") == 0)
1367 		whoreply(from, ArgList);
1368 	else if (my_strcmp(comm, "NOTICE") == 0)
1369 		parse_notice(from, ArgList);
1370 	/* everything else is handled locally */
1371 	else if (my_strcmp(comm, "PRIVMSG") == 0)
1372 		p_privmsg(from, ArgList);
1373 	else if (my_strcmp(comm, "JOIN") == 0)
1374 		p_channel(from, ArgList);
1375 	else if (my_strcmp(comm, "PART") == 0)
1376 		p_part(from, ArgList);
1377 	else if (my_strcmp(comm, "CHANNEL") == 0)
1378 		p_channel(from, ArgList);
1379 	else if (my_strcmp(comm, "MSG") == 0)
1380 		/*p_msgcmd(from, ArgList)*/;
1381 	else if (my_strcmp(comm, "QUIT") == 0)
1382 		p_quit(from, ArgList);
1383 	else if (my_strcmp(comm, "WALL") == 0)
1384 		p_wall(from, ArgList);
1385 	else if (my_strcmp(comm, "WALLOPS") == 0)
1386 		p_wallops(from, ArgList);
1387 	else if (my_strcmp(comm, "LINREPLY") == 0)
1388 		p_linreply(ArgList);
1389 /*	else if (my_strcmp(comm, "PING") == 0)
1390 		p_ping(ArgList);
1391  */
1392 	else if (my_strcmp(comm, "TOPIC") == 0)
1393 		p_topic(from, ArgList);
1394 	else if (my_strcmp(comm, "PONG") == 0)
1395 		p_pong(from, ArgList);
1396 	else if (my_strcmp(comm, "INVITE") == 0)
1397 		p_invite(from, ArgList);
1398 	else if (my_strcmp(comm, "NICK") == 0)
1399 		p_nick(from, ArgList, flag, str_flag);
1400 	else if (my_strcmp(comm, "KILL") == 0)
1401 		p_server_kill(from, ArgList);
1402 	else if (my_strcmp(comm, "MODE") == 0)
1403 		p_mode(from, ArgList);
1404 	else if (my_strcmp(comm, "KICK") == 0)
1405 		p_kick(from, ArgList);
1406 	else if (my_strcmp(comm, "ERROR") == 0)
1407 		p_error(from, ArgList);
1408 	else if (my_strcmp(comm, "ERROR:") == 0) /* Server bug makes this a must */
1409 		p_error(from, ArgList);
1410 	else
1411 	{
1412 		PasteArgs(ArgList, 0);
1413 		if (from)
1414 			put_error("Odd server stuff: \"%s %s\" (%s)", comm,
1415 				ArgList[0], from);
1416 		else
1417 			put_error("Odd server stuff: \"%s %s\"", comm, ArgList[0]);
1418 	}
1419    dma_Free(&str_flag);
1420 	new_free(&copy);
1421 }
1422