Ejemplo n.º 1
0
static Logfile *	new_logfile (void)
{
	Logfile *log, *ptr;
	int	i;

	log = (Logfile *)new_malloc(sizeof(Logfile));

	/* Move it to the end of the list. */
	for (ptr = logfiles; ptr && ptr->next;)
		ptr = ptr->next;
	if (ptr)
		ptr->next = log;
	else
		logfiles = log;

	log->next = NULL;
	log->refnum = ++logref;
	last_logref = log->refnum;
	log->name = malloc_sprintf(NULL, "%d", log->refnum);
	log->filename = NULL;
	log->log = NULL;
	log->servref = from_server;
	log->type = LOG_TARGETS;
	log->targets = NULL;
	for (i = 0; i < MAX_TARGETS; i++)
		log->refnums[i] = -1;
	mask_setall(&log->mask);
	log->rewrite = NULL;
	log->mangler = 0;
	log->mangle_desc = NULL;
	log->active = 0;
	time(&log->activity);

	return log;
}
Ejemplo n.º 2
0
Archivo: timer.c Proyecto: tcava/bx2
/*
 * create_timer_ref:  returns the lowest unused reference number for a timer
 * All refnums that are not already in use are valid.
 *
 * The user is allowed to use any string as a refnum, we dont really care.
 * Automatically assigned refnums (when the user doesnt specify one) will
 * always be one more than the highest pending refnum.
 *
 * "refnum_gets" must be REFNUM_MAX + 1 bytes by definition of API.
 */
static	int	create_timer_ref (const char *refnum_wanted, char **refnum_gets)
{
	Timer	*tmp;
	int 	refnum = 0;
	char	*refnum_want;

	refnum_want = LOCAL_COPY(refnum_wanted);

	/* If the user doesnt care */
	if (*refnum_want == 0)
	{
		/* Find the lowest refnum available */
		for (tmp = PendingTimers; tmp; tmp = tmp->next)
		{
			if (refnum < my_atol(tmp->ref))
				refnum = my_atol(tmp->ref);
		}
		malloc_sprintf(refnum_gets, "%d", refnum + 1);
	}
	else
	{
		/* See if the refnum is available */
		if (get_timer(refnum_want))
			return -1;		/* Already in use */

		malloc_strcpy(refnum_gets, refnum_want);
	}

	return 0;
}
Ejemplo n.º 3
0
/*
 * help_topic:  Given a topic, we search the help directory, and try to
 * find the right file, if all is cool, and we can open it, or zcat it,
 * then we call help_prompt to get the actually displaying of the file
 * on the road.
 */
static	void	help_topic (char *path, char *name)
{
    char	*filename = (char *) 0;

    if (!name)
        return;

    /* what is the base name? */
    malloc_sprintf(&filename, "%s/%s", path, name);
    if (filename[strlen(filename)-1] == '/')
        chop(filename, 1);

    /* let uzfopen have all the fun */
    if ((help_fp = uzfopen(&filename, path, 1)))
    {
        /* Isnt this a heck of a lot better then the kludge you were using? */
        help_put_it(name, "*** Help on %s", name);
        help_prompt(name, NULL);
    }
    else
        help_put_it (name, "*** No help available on %s: Use ? for list of topics", name);

    new_free(&filename);
    return;
}
Ejemplo n.º 4
0
static void	update_mail_level2_mbox (void)
{
	Stat	stat_buf;
	int	status;
	int	count;

	status = poll_mbox_status(&stat_buf);

	/* There is no mail */
	if (status == 0)
	{
		mail_last_count = 0;
		if (mail_last_count_str)
			new_free(&mail_last_count_str);
	}

	/* If our count is invalid or there is new mail, recount mail */
	else if (mail_last_count == -1 || status == 2)
	{
	    /* So go ahead and recount the mails in mbox */
	    count = mbox_count();

	    if (count == 0)
		new_free(&mail_last_count_str);
	    else
	    {
		malloc_sprintf(&mail_last_count_str, "%d", count);

		/* 
		 * If there is new mail, or if we're switching to 
		 * /set mail 2, tell the user how many emails there are.
		 */
		if (count > mail_last_count)
		{
		    /* This is to avoid $0 in /on mail being wrong. */
		    if (mail_last_count < 0)
			mail_last_count = 0;

		    if (!mail_latch)
		    {
			mail_latch++;
			if (do_hook(MAIL_LIST, "%d %d", 
					count - mail_last_count, count))
			{
			    int lastlog_level = 
					set_lastlog_msg_level(LOG_CRAP);
			    say("You have new email.");
			    set_lastlog_msg_level(lastlog_level);
			}
			mail_latch--;
		    }
		}

		mbox_last_changed = stat_buf.st_ctime;
	        mbox_last_size = stat_buf.st_size;
		mail_last_count = count;
	    }
	}
}
Ejemplo n.º 5
0
/*
 * create_timer_ref:  returns the lowest unused reference number for a timer
 * All refnums that are not already in use are valid.
 *
 * The user is allowed to use any string as a refnum, we dont really care.
 * Automatically assigned refnums (when the user doesnt specify one) will
 * always be one more than the highest pending refnum.
 *
 * "refnum_gets" must be REFNUM_MAX + 1 bytes by definition of API.
 */
static	int	create_timer_ref (const char *refnum_wanted, char **refnum_gets)
{
	Timer	*tmp;
	int 	refnum = 0;
	char	*refnum_want;
	int	i, pts;

	refnum_want = LOCAL_COPY(refnum_wanted);

	/* If the user doesnt care */
	if (*refnum_want == 0)
	{
		/* So ... we count the number of times that exist. */
		for (pts = 0, tmp = PendingTimers; tmp; tmp = tmp->next)
			pts++;

		/* 
		 * Now, for all the numbers (0 .. [timer count + 1]), 
		 * at least one of those numbers *has* to be available,
		 */ 
		for (i = 0; i <= pts + 1; i++)
		{
			/* Are any timers named 'i'? */
			for (tmp = PendingTimers; tmp; tmp = tmp->next)
			{
				if (!is_number(tmp->ref))
					continue;
				if (i == my_atol(tmp->ref))
					break;
			}

			/* 
			 * If 'tmp' is null, then we didn't find a refnum 'i'.
			 * So 'i' is our winner!
			 */
			if (tmp == NULL)
			{
				malloc_sprintf(refnum_gets, "%d", i);
				break;
			}
		}
	}
	else
	{
		/* See if the refnum is available */
		if (get_timer(refnum_want))
			return -1;		/* Already in use */

		malloc_strcpy(refnum_gets, refnum_want);
	}

	return 0;
}
Ejemplo n.º 6
0
static void handle_swap(int windownum)
{
    char *p = NULL;

    malloc_sprintf(&p, "SWAP %d", windownum);
    t_parse_command("WINDOW", p);
    set_channel_window(curr_scr_win, get_current_channel_by_refnum(curr_scr_win->refnum), curr_scr_win->server);
    new_free(&p);
    set_input_prompt(curr_scr_win, get_string_var(INPUT_PROMPT_VAR), 0);
    update_input(UPDATE_ALL);
    update_all_windows();
}
Ejemplo n.º 7
0
void input_msgreply(char dumb, char *dumber)
{
    char *cmdchar;
    char *line, *cmd, *t;
    char *snick;
    NickTab *nick = NULL;
    int got_space = 0;

    if (!(cmdchar = get_string_var(CMDCHARS_VAR)))
	cmdchar = DEFAULT_CMDCHARS;

    t = line = m_strdup(get_input());
    if (t)
	got_space = strchr(t, ' ') ? 1 : 0;
    cmd = next_arg(line, &line);
    snick = next_arg(line, &line);
    if ((cmd && *cmd == *cmdchar && got_space) || !cmd) {

	if (cmd && *cmd == *cmdchar)
	    cmd++;
	if (in_completion == STATE_NORMAL && snick)
	    strncpy(new_nick, snick, sizeof(new_nick) - 1);

	if ((nick = getnextnick(new_nick, input_lastmsg, snick))) {
	    if (nick->nick && *(nick->nick)) {
		snick = nick->nick;
		malloc_strcpy(&input_lastmsg, nick->nick);
	    }
	}
	if (nick) {
	    char *tmp = NULL;

	    input_clear_line('\0', NULL);
	    if (get_fset_var(FORMAT_NICK_MSG_FSET))
		malloc_strcpy(&tmp,
			      stripansicodes(convert_output_format
					     (get_fset_var(FORMAT_NICK_MSG_FSET), "%s%s %s %s", cmdchar,
					      nick->type ? nick->type : cmd ? cmd : "msg", nick->nick, line ? line : empty_str)));
	    else
		malloc_sprintf(&tmp, "%s%s %s %s", cmdchar, nick->type ? nick->type : cmd ? cmd : "msg", nick->nick,
			       line ? line : empty_str);
	    set_input(tmp);
	    new_free(&tmp);
	} else
	    command_completion(0, NULL);
    } else
	command_completion(0, NULL);
    update_input(UPDATE_ALL);
    new_free(&t);
}
Ejemplo n.º 8
0
void add_autonick_input(char *nick, char *line)
{
    char *tmp1 = NULL;

    input_clear_line('\0', NULL);
    if ((do_hook(AR_REPLY_LIST, "%s", nick))) {
	if (get_fset_var(FORMAT_NICK_AUTO_FSET))
	    malloc_strcpy(&tmp1,
			  stripansicodes(convert_output_format
					 (get_fset_var(FORMAT_NICK_AUTO_FSET), "%s %s", nick, line ? line : empty_str)));
	else
	    malloc_sprintf(&tmp1, "%s: %s", nick, line);
	set_input(tmp1);
	new_free(&tmp1);
    }
    update_input(UPDATE_ALL);
}
Ejemplo n.º 9
0
int delay_check_auto (char *channel)
{
	ChannelList *chan = NULL;
	char *buffer = NULL;
	NickList *possible;	

	
	if (!channel || !*channel)
		return -1;
		
	if ((chan = lookup_channel(channel, from_server, CHAN_NOUNLINK)) == NULL)	
		return -1;

	for (possible = next_nicklist(chan, NULL); possible; possible = next_nicklist(chan, possible))
	{
		if ((possible->shitlist || possible->userlist) && (!(possible->sent_reop < 4) || !(possible->sent_deop < 4)))
		{
			malloc_sprintf(&buffer, "%s %s %s %d", channel, possible->nick, possible->host, from_server);
			add_timer(0, empty_string, 3 * 1000, 1, real_check_auto, buffer, NULL, -1, "check-auto");
		}
	}
	add_timer(0, empty_string, 5 * 1000, 1, delay_flush_all, m_sprintf("%s %d", channel, from_server), NULL, -1, "check-auto");
	return 0;
}
Ejemplo n.º 10
0
Archivo: main.c Proyecto: jnbek/TekNap
static	char	*parse_args (char *argv[], int argc, char **envp)
{
	int ac;
	int add_servers = 0;
	
	char *channel = NULL;
	char *ptr;
	
	*nickname = 0;
	*password = 0;

	if ((ptr = getenv("NAPNICK")))
		strmcpy(nickname, ptr, NICKNAME_LEN);
	if ((ptr = getenv("NAPPASS")))
		strmcpy(password, ptr, NICKNAME_LEN);
	if ((ptr = getenv("NAP_HOST")) || (ptr = getenv("NAPHOST")))
		malloc_strcpy(&LocalHostName, ptr);	

	for ( ac = 1; ac < argc; ac++ )
	{
		if (argv[ac][0] == '-')
		{
		    switch (argv[ac][1]) {

			case 'r': /* Load list of servers from this file */
			{
				char *what = empty_string;

				if (argv[ac][2])
					what = &argv[ac][2];
				else if (argv[ac+1] && argv[ac+1][0] != '-')
				{
					what = argv[ac+1];
					ac++;
				}
				else
					fprintf(stderr, "Missing argumenT to -r\n");

				if (*what)
				{
					add_servers = 1;
					malloc_strcpy(&ircservers_file, what);
				}
				break;
			}
			case 'a': /* add server, not replace */
			{
				add_servers = 1;
				if (argv[ac][2])
					fprintf(stderr, "Ignoring junk after -a\n");
				break;
			}
			case 'H':
			{
				char *what = empty_string;
				
				if (argv[ac][2])
					what = &(argv[ac][2]);
				else if (argv[ac+1] && argv[ac+1][0] != '-')
				{
					what = argv[ac+1];
					ac++;
				}
				else
				{
					fprintf(stderr, "Specify a hostname\n");
					exit(1);
				}
				malloc_strcpy(&LocalHostName, what);
				break;
			}
			case 'S': 
			{
				if (argv[ac][2])
				{
					char *what;
					what = &argv[ac][2];
					starting_server = my_atol(what);
				}
				else
				{
					ac++;
					starting_server = my_atol(argv[ac]);
				}
				break;
			}
			case 'n':
			{
				char *what = empty_string;

				if (argv[ac][2])
					what = &(argv[ac][2]);
				else if (argv[ac+1] && argv[ac+1][0] != '-')
				{
					what = argv[ac+1];
					ac++;
				}
				else
				{
					fprintf(stderr,"Missing argument for -n\n");
					exit(1);
				}
				strmcpy(nickname, what, NICKNAME_LEN);
				break;
			}
			case 'p':
			{
				char *pass = NULL;
				if ((pass = getpass("Enter Password :"******"%s %s\n", nap_version, internal_version); 
				exit(1);
#if defined(WINNT) || defined(EMX)
			case 's':
				setup_autoexec();
				exit(1);
#endif
			default:
				fprintf(stderr, "Unknown flag: %s\n",argv[ac]);
			case 'h':
				fprintf(stderr, "%s", switch_help);
#if defined(WINNT) || defined(EMX)
				fprintf(stderr, "%s", switch_help_w);
#endif
				exit(1);
		   } /* End of switch */
		}
		else
		{
			if (!strchr(argv[ac], '.'))
				strmcpy(nickname, argv[ac], NICKNAME_LEN);
			else
				build_server_list(argv[ac]);
		}
	}

	if ((ptr = getenv("NAPLIB")))
		irc_lib = m_opendup("/", ptr, "/", NULL);
	else
	{
		char *s;
		if ((s = expand_twiddle(NAPLIB)))
			irc_lib = s;
		else
			malloc_strcpy(&irc_lib, NAPLIB);
	}

	if ((ptr = getenv("NAPPATH")))
		malloc_strcpy(&irc_path, ptr);
	else
	{
#ifdef NAPPATH
		malloc_strcpy(&irc_path, NAPPATH);
#else
#ifdef WINNT
		malloc_strcpy(&irc_path, ".:~/TekNap:");
#else
		malloc_strcpy(&irc_path, ".:~/.TekNap:");
#endif
		irc_path = m_opendup(irc_lib, "/", "script", NULL);
#endif
	}

	if (LocalHostName)
	{
		struct hostent *hp;
		printf("Your hostname appears to be [%s]\n", LocalHostName);
		memset((void *)&LocalHostAddr, 0, sizeof(LocalHostAddr));
		if ((hp = gethostbyname(LocalHostName)))
			memcpy((void *)&LocalHostAddr.sin_addr, hp->h_addr, sizeof(struct in_addr));
 	} 
	
	if (!check_nickname(nickname))
	{
		fprintf(stderr, "\n Invalid Nickname\n");
		exit(1);
	}

	set_string_var(LOAD_PATH_VAR, irc_path);
	new_free(&irc_path);
	
	if ((ptr = getenv("HOME")))
		malloc_strcpy(&my_path, ptr);
	if (!my_path || !*my_path)
#ifdef WINNT
	{
		malloc_strcpy(&my_path, "//c/TekNap/");
		bsd_setenv("HOME", "//c/TekNap", 1);
	}
	if (access("//c/TekNap", F_OK) != 0)
	{
		fprintf(stderr, "Directory doesn't exist, creating //c/TekNap\n");
		mkdir("//c/TekNap", S_IWUSR|S_IRUSR|S_IXUSR);
	}		
#else
		malloc_strcpy(&my_path, "/");
#endif

#if defined(WINNT) || defined(__EMX__)
	convert_unix(my_path);
#endif
	if (!bircrc_file)
		malloc_sprintf(&bircrc_file, "%s%s", my_path, IRCRC_NAME);

	if ((ptr = getenv("NAPPORT")))
		nap_port = my_atol(ptr);


	if ((ptr = getenv("NAPSERVER")))
		build_server_list(ptr);
#ifdef DEFAULT_SERVER
	{
		if (!read_server_list())
		{
			ptr = LOCAL_COPY(DEFAULT_SERVER);
			build_server_list(ptr);
		}
	}	
#endif
	return (channel);
}
Ejemplo n.º 11
0
/*
 *  Protection levels
 *  1 Reop if de-oped
 *  2 De-op offender
 *  3 Kick  offender
 *  4 KickBan offender
 */
int check_prot(char *from, char *person, ChannelList *chan, BanList *thisban, NickList *n)
{
NickList *tmp = NULL;
NickList *kicker;
char *tmp_ban = NULL;
char *nick = NULL, *userhost = NULL, *p;

	
	if (!from || !*from || !person || !*person || !chan)
		return 0;

	if (!my_stricmp(person, from))
		return 0;

	tmp_ban = LOCAL_COPY(person);
	if ((p = strchr(tmp_ban, '!')))
	{
		nick = tmp_ban;
		*p++ = 0;
		userhost  = p;
	} else nick = person;

	if (!n)
	{
		if (!(tmp = find_nicklist_in_channellist(person, chan, 0)))
		{
			for (tmp = next_nicklist(chan, NULL); tmp; tmp = next_nicklist(chan, tmp))
			{
				if (wild_match(nick, tmp->nick) && wild_match(userhost, tmp->host) && tmp->userlist)
				{
					n = tmp;
					break;
				}
			}
		}
	}

	if (get_cset_int_var(chan->csets, USERLIST_CSET) && chan->chop && ((n && n->userlist) || 
		(tmp && tmp->userlist)))
	{
		UserList *user = NULL;		
		time_t current = now;
		if (n)
			user = n->userlist;
		else
			user = tmp->userlist;
		if (!user || (user && !check_channel_match(user->channels, chan->channel)))
			return 0;
		if (!(kicker = find_nicklist_in_channellist(from, chan, 0)))
			return 0;
		if ((user->flags & (PROT_DEOP | PROT_INVITE | PROT_BAN | PROT_KICK | PROT_REOP)))
		{
			int do_reop = 0;
			if (user->flags & PROT_DEOP)
			{
				if (!kicker->sent_deop)
				{
					if (!kicker->userlist || 
						(kicker->userlist && !(kicker->userlist->flags & PROT_DEOP)))
						send_to_server("MODE %s -o %s", chan->channel, from);
					kicker->sent_deop++;
				}
				do_reop = 1;
			}

			if (user->flags & PROT_INVITE)
			{
				
				if (thisban && !thisban->sent_unban)
				{
					thisban->sent_unban++;
					thisban->sent_unban_time = current;
					send_to_server("MODE %s -b %s", chan->channel, thisban->ban);
					send_to_server("INVITE %s %s", n?n->nick:tmp->nick, chan->channel);  
				}
			}
			if (user->flags & PROT_BAN)
			{
/*				do_reop = 1; */
				if (kicker->userlist)
					send_to_server("MODE %s -o %s", chan->channel, from);
				else 
				{
					char *h, *u;
					u = LOCAL_COPY(kicker->host);
					h = strchr(u, '@');
					*h++ = 0;
					send_to_server("MODE %s -o+b %s %s", chan->channel, kicker->nick, ban_it(kicker->nick, u, h, kicker->ip));
					if (get_int_var(AUTO_UNBAN_VAR))
						add_timer(0, empty_string, get_int_var(AUTO_UNBAN_VAR) * 1000, 1, timer_unban, m_sprintf("%d %s %s", from_server, chan->channel, ban_it(kicker->nick, u, h, kicker->ip)), NULL, -1, "auto-unban");
				}
			}
			if (user->flags & PROT_KICK)
			{
				if (kicker && (!kicker->userlist || (kicker->userlist && !(kicker->userlist->flags & PROT_KICK))))
					send_to_server("KICK %s %s :\002BitchX\002 Protected User", chan->channel, kicker->nick);
			}
			if ((user->flags & PROT_REOP) || do_reop)
			{
				/* added by Sergs [email protected] */
			        if (thisban)
				{
					if (thisban->sent_unban_time - current > 30)
					{
						thisban->sent_unban++;
						thisban->sent_unban_time = current;
						send_to_server("MODE %s -b %s", chan->channel, thisban->ban);
					} 
					else if (thisban->sent_unban < 3)
					{
						thisban->sent_unban++;
						thisban->sent_unban_time = current;
						send_to_server("MODE %s -b %s", chan->channel, thisban->ban);
					}
				}
				if (n && (!n->sent_reop || (n->sent_reop_time && (current - n->sent_reop_time > 60))))
				{
					char *u = NULL;
					malloc_sprintf(&u, "%s %s %s %s %d", chan->channel, n->nick, n->host, "o", from_server);
					add_timer(0, empty_string, 10 * 1000, 1, delay_opz, u, NULL, -1, "delay-ops");
					n->sent_reop++;
					n->sent_reop_time = current;
				}
			}
		}
		if ((user->flags & USER_FLAG_PROT) && (p = get_string_var(USER_FLAG_PROT_VAR)))
			run_user_flag("USER_FLAG_PROT", p, n, kicker);
		return 1;
	}
	return 0;
}
Ejemplo n.º 12
0
void userhost_ban(UserhostItem *stuff, char *nick1, char *args)
{
	char *temp;
	char *str= NULL;
	char *channel;
	ChannelList *c = NULL;
	NickList *n = NULL;

	char *ob = "-o+b";
	char *b = "+b";

	char *host = NULL, *nick = NULL, *user = NULL, *chan = NULL;
	WhowasList *whowas = NULL;
		
	int f**k = 0;
	int set_ignore = 0;
	
	
	channel = next_arg(args, &args);
	temp = next_arg(args, &args);

	f**k = !my_stricmp("F**K", args);
	set_ignore = !my_stricmp("BKI", args);
	
	if (!stuff || !stuff->nick || !nick1 || !strcmp(stuff->user, "<UNKNOWN>") || my_stricmp(stuff->nick, nick1))
	{
		if (nick1 && channel && (whowas = check_whowas_nick_buffer(nick1, channel, 0)))
		{
			nick = whowas->nicklist->nick;
			user = m_strdup(clear_server_flags(whowas->nicklist->host));
			host = strchr(user, '@');
			*host++ = 0;
			bitchsay("Using WhoWas info for ban of %s ", nick1);
			n = whowas->nicklist;
		}
		else if (nick1)
		{
			bitchsay("No match for the %s of %s on %s", f**k ? "F**k":"Ban", nick1, channel);
			return;
		}
	} 
	else
	{
		nick = stuff->nick;
		user = m_strdup(clear_server_flags(stuff->user));
		host = stuff->host;
	}

	if (!(my_stricmp(nick, get_server_nickname(from_server))))
	{
		bitchsay("Try to kick yourself again!!");
		new_free(&user);
		return;
	}

	if (is_on_channel(channel, from_server, nick))
		chan = channel;
	c = lookup_channel(channel, from_server, 0);
	if (c && !n)
		n = find_nicklist_in_channellist(nick, c, 0);
	send_to_server("MODE %s %s %s %s", channel, chan ? ob : b, chan?nick:empty_string, ban_it(nick, user, host, (n && n->ip)?n->ip:NULL));
	if (f**k)
	{
		malloc_sprintf(&str, "%s!*%s@%s %s 3 Auto-Shit", nick, user, host, channel);
#ifdef WANT_USERLIST
		add_shit(NULL, str, NULL, NULL);
#endif
		new_free(&str);
	} else if (set_ignore)
		ignore_nickname(ban_it("*", user, host, NULL)	, IGNORE_ALL, 0);
	new_free(&user);
}
Ejemplo n.º 13
0
void userhost_unban(UserhostItem *stuff, char *nick1, char *args)
{
char *tmp;
ChannelList *chan;
char *channel = NULL;
BanList *bans;

char *host = NULL;
char *ip_str = NULL;
WhowasList *whowas = NULL;
NickList *n = NULL;
int count = 0;
int old_server = from_server;

	
	if (!stuff || !stuff->nick || !nick1 || 
		!strcmp(stuff->user, "<UNKNOWN>") || 
		my_stricmp(stuff->nick, nick1))
	{
		if (nick1 && (whowas = check_whowas_nick_buffer(nick1, args, 0)))
		{
			malloc_sprintf(&host, "%s!%s", whowas->nicklist->nick, whowas->nicklist->host);
			bitchsay("Using WhoWas info for unban of %s ", nick1);
			n = whowas->nicklist;
		}
		else if (nick1)
		{
			bitchsay("No match for the unban of %s on %s", nick1, args);
			return;
		}
		if (!nick1)
			return;
	}
	else
	{
		tmp = clear_server_flags(stuff->user);
		malloc_sprintf(&host, "%s!%s@%s",stuff->nick, tmp, stuff->host); 
	}

	channel = next_arg(args, &args);
	if (args && *args)
		from_server = atoi(args);
	if (!(chan = prepare_command(&from_server, channel, NEED_OP)))
	{
		new_free(&host);
		return;
	}
	if (!n)
		n = find_nicklist_in_channellist(stuff->nick, chan, 0);

	if (n && n->ip)
	{
		size_t len = strlen(n->nick)+strlen(n->host)+strlen(n->ip)+10;
		ip_str = alloca(len); 
		*ip_str = 0;
		strmopencat(ip_str, len, stuff->nick, "!", stuff->user, "@", n->ip, NULL);
	}
	for (bans = chan->bans; bans; bans = bans->next)
	{
		if (!bans->sent_unban && (wild_match(bans->ban, host) || (ip_str && wild_match(bans->ban, ip_str))) )
		{
			add_mode(chan, "b", 0, bans->ban, NULL, get_int_var(NUM_BANMODES_VAR));
			bans->sent_unban++;
			count++;
		}			
	}	

	flush_mode_all(chan);
	if (!count)
		bitchsay("No match for Unban of %s on %s", nick1, args);
	new_free(&host);
	from_server = old_server;
}
Ejemplo n.º 14
0
void send_line(char dumb, char *dumber)
{
    int server;
    WaitPrompt *OldPrompt;

    server = from_server;
    from_server = get_window_server(0);
    unhold_a_window(curr_scr_win);
    if (current_screen->promptlist && current_screen->promptlist->type == WAIT_PROMPT_LINE) {
	OldPrompt = current_screen->promptlist;
	(*OldPrompt->func) (OldPrompt->data, get_input());
	set_input(empty_str);
	current_screen->promptlist = OldPrompt->next;
	new_free(&OldPrompt->data);
	new_free(&OldPrompt->prompt);
	new_free(&OldPrompt);
	change_input_prompt(-1);
    } else {
	char *line, *tmp = NULL;

	line = get_input();
	if (line && (*line != get_int_var(CMDCHARS_VAR)) && get_int_var(NICK_COMPLETION_VAR)) {
	    char auto_comp_char = ':';

	    if (!(auto_comp_char = (char) get_int_var(NICK_COMPLETION_CHAR_VAR)))
		auto_comp_char = ':';

	    /* possible nick completion */
	    if (strchr(line, auto_comp_char)) {
		char *p;
		struct channel *chan;
		struct nick_list *nick;
		char *channel;

		malloc_strcpy(&tmp, line);
		p = strchr(tmp, auto_comp_char);
		*p++ = 0;
		if (*tmp && *p && (channel = get_current_channel_by_refnum(0))) {
		    chan = lookup_channel(channel, from_server, 0);
		    for (nick = next_nicklist(chan, NULL); nick; nick = next_nicklist(chan, nick))
			if (!my_strnicmp(tmp, nick->nick, strlen(tmp)))
			    break;
		    if (nick) {
			if (get_fset_var(FORMAT_NICK_COMP_FSET))
			    malloc_strcpy(&tmp,
					  stripansicodes(convert_output_format
							 (get_fset_var(FORMAT_NICK_COMP_FSET), "%s %s", nick->nick, p)));
			else
			    malloc_sprintf(&tmp, "%s%c %s", nick->nick, auto_comp_char, p);
		    } else
			malloc_strcpy(&tmp, line);
		} else
		    malloc_strcpy(&tmp, line);
	    } else
		malloc_strcpy(&tmp, line);
	} else
	    malloc_strcpy(&tmp, line);
	if (do_hook(INPUT_LIST, "%s", tmp)) {
	    if (get_int_var(INPUT_ALIASES_VAR))
		parse_line(NULL, tmp, empty_str, 1, 0);
	    else
		parse_line(NULL, tmp, NULL, 1, 0);
	}
	update_input(UPDATE_ALL);
	new_free(&tmp);
    }
    new_free(&input_lastmsg);
    *new_nick = 0;
    in_completion = STATE_NORMAL;
    from_server = server;
}
Ejemplo n.º 15
0
NickList *check_auto(char *channel, NickList *nicklist, ChannelList *chan)
{

ShitList *shitptr = NULL;
UserList *userptr = NULL;
ChannelList *chan_ptr =  NULL;
char *ban;

	
	if (!channel || !*channel || !nicklist)
		return NULL;
	
	if (!chan)
	{
		ChannelList *chan2;
		chan2 = get_server_channels(from_server);
		chan_ptr = (ChannelList *) find_in_list((List **)&chan2, channel, 0);
	}
	else
		chan_ptr = chan;
	if (!chan_ptr)
		return NULL;		

	if (!chan_ptr->chop)
		return nicklist;
	userptr = nicklist->userlist;
	shitptr = nicklist->shitlist;


	if (userptr && !check_channel_match(userptr->channels, channel))
		userptr = NULL;
	if (shitptr && (!check_channel_match(shitptr->channels, channel) || isme(nicklist->nick)))
		shitptr = NULL;
		
	if (get_cset_int_var(chan_ptr->csets, SHITLIST_CSET) && shitptr != NULL && userptr == NULL)
	{
		char *theshit;
		time_t current = now;
		theshit = get_string_var(SHITLIST_REASON_VAR);
		switch(shitptr->level)
		{
		
			case 0:
				return nicklist;
				break;
			case 1:/* never give opz */
				if (nicklist->sent_deop < 4 && nick_isop(nicklist))
				{
					add_mode(chan_ptr, "o", 0, nicklist->nick, NULL, get_int_var(NUM_OPMODES_VAR));
					nicklist->sent_deop++;
					nicklist->sent_deop_time = current;
				}
				break;				
			case 2: /* Auto Kick  offender */
				add_mode(chan_ptr, NULL, 0, nicklist->nick, shitptr->reason?shitptr->reason:theshit, 0);
				break;
			case 3: /* kick ban the offender */
			case 4:	/* perm ban on offender */
				if (nicklist->sent_deop  < 4 || (nicklist->sent_deop < 4 && shitptr->level == 4))
				{
					send_to_server("MODE %s -o+b %s %s", channel, nicklist->nick, shitptr->filter);
					nicklist->sent_deop++;
					nicklist->sent_deop_time = current;
					if (get_int_var(AUTO_UNBAN_VAR) && shitptr->level != 4)
						add_timer(0, empty_string, get_int_var(AUTO_UNBAN_VAR) * 1000, 1, timer_unban, m_sprintf("%d %s %s", from_server, channel, shitptr->filter), NULL, -1, "auto-unban");
				}
				if (get_cset_int_var(chan_ptr->csets, KICK_IF_BANNED_CSET))
					send_to_server("KICK %s %s :%s", channel,
						nicklist->nick, (shitptr->reason && *shitptr->reason) ? shitptr->reason : theshit);
			default:
				break;
		}
		return nicklist;
	} 

	if (userptr && get_cset_int_var(chan_ptr->csets, USERLIST_CSET))
	{	
		char *buffer = NULL;
		time_t current = now;
		int done = 0;
		char *p = NULL;
		if (get_cset_int_var(chan_ptr->csets, AOP_CSET))
		{
			if ((userptr->flags & ADD_OPS))
			{
				done++;
				if (!userptr->password && !nicklist->sent_reop && !nick_isop(nicklist))
				{
					nicklist->sent_reop++;
					nicklist->sent_reop_time = current;
					if (!(userptr->flags & ADD_IOPS))
					{
						malloc_sprintf(&buffer, "%s %s %s %s %d", channel, nicklist->nick, nicklist->host, "o", from_server);
						add_timer(0, empty_string, 10 * 1000, 1, delay_opz, buffer, NULL, -1, "delay-ops");
					} 
					else
						send_to_server("MODE %s +o %s", chan_ptr->channel, nicklist->nick);
				}
			}
			else if ((userptr->flags & ADD_VOICE))
			{
				done++;
				if (!nicklist->sent_voice && !nick_isvoice(nicklist))
				{
					nicklist->sent_voice++;
					nicklist->sent_voice_time = current;
					if (!(userptr->flags & ADD_IOPS))
					{
						malloc_sprintf(&buffer, "%s %s %s %s %d", channel, nicklist->nick, nicklist->host, "v", from_server);
						add_timer(0, empty_string, 10 * 1000, 1, delay_opz, buffer, NULL, -1, "delay-ops");
					}
					else
						send_to_server("MODE %s +v %s", chan_ptr->channel, nicklist->nick);
				}
			}
		}
		if ((userptr->flags & USER_FLAG_OPS) && (p = get_string_var(USER_FLAG_OPS_VAR)))
		{
			done++;
			run_user_flag("USER_FLAG_OPS", p, nicklist, NULL);
		}
		if (done)
			return nicklist;
	}
	if (get_cset_int_var(chan_ptr->csets, KICK_IF_BANNED_CSET) && check_channel_match(get_string_var(PROTECT_CHANNELS_VAR), chan_ptr->channel))
	{
		char *ipban = NULL;
		char *u = NULL;
		if (!nicklist->host)
			return nicklist;
		ban = m_3dup(nicklist->nick, "!", nicklist->host);
		if (nicklist->ip && nicklist->host)
		{
			char *user = alloca(strlen(nicklist->host)+1);
			strcpy(user, nicklist->host);
			if ((u = strchr(user, '@')))
				*u = 0;
			ipban = m_opendup(nicklist->nick, "!", user, "@", nicklist->ip, NULL);
		}
		if (!isme(nicklist->nick) && (!eban_is_on_channel(ban, chan_ptr) && (ban_is_on_channel(ban, chan_ptr) || (ipban && ban_is_on_channel(ipban, chan_ptr)))) )
		{
			new_free(&ban);
			new_free(&ipban);
			if (nick_isop(nicklist) && !get_cset_int_var(chan_ptr->csets, KICK_OPS_CSET))
				return nicklist;
			my_send_to_server(from_server, "KICK %s %s :Banned", chan_ptr->channel, nicklist->nick);
		}
		new_free(&ban);
		new_free(&ipban);
	}
	return nicklist;
}
Ejemplo n.º 16
0
Archivo: timer.c Proyecto: tcava/bx2
/*
 * $timerctl(REFNUM refnum)
 * $timerctl(ADD <refnum> <interval> <events> <commands> <subargs> <window>)
 * $timerctl(DELETE <refnum>)
 * $timerctl(GET <refnum> [LIST])
 * $timerctl(SET <refnum> [ITEM] [VALUE])
 * $timerctl(REFNUMS)
 *
 * [LIST] and [ITEM] are one of the following
 *	TIMEOUT		The precise time the timer will be executed
 *	COMMAND		The commands that will be executed
 *	SUBARGS		The vaule of $* used when this timer is executed
 *	REPEATS		The number of times this timer will be executed
 *	INTERVAL	The interval of time between executions
 *	SERVER		The server this timer bound to
 *	WINDOW		The window this timer bound to
 */
char *	timerctl (char *input)
{
	char *	refstr;
	char *	listc;
	Timer *	t;
	int	len;

	GET_FUNC_ARG(listc, input);
	len = strlen(listc);
	if (!my_strnicmp(listc, "REFNUM", len)) {
		GET_FUNC_ARG(refstr, input);
		if (!(t = get_timer(refstr)))
			RETURN_EMPTY;
		RETURN_STR(t->ref);
	} else if (!my_strnicmp(listc, "REFNUMS", len)) {
		char *	retval = NULL;
		size_t	clue = 0;

		for (t = PendingTimers; t; t = t->next)
			malloc_strcat_word_c(&retval, space, t->ref, DWORD_DWORDS, &clue);
		RETURN_MSTR(retval);
	} else if (!my_strnicmp(listc, "ADD", len)) {
		RETURN_EMPTY;		/* XXX - Not implemented yet. */
	} else if (!my_strnicmp(listc, "DELETE", len)) {
		GET_FUNC_ARG(refstr, input);
		if (!(t = get_timer(refstr)))
			RETURN_EMPTY;
		if (t->callback)
			RETURN_EMPTY;
		RETURN_INT(remove_timer(refstr));
	} else if (!my_strnicmp(listc, "GET", len)) {
		GET_FUNC_ARG(refstr, input);
		if (!(t = get_timer(refstr)))
			RETURN_EMPTY;

		GET_FUNC_ARG(listc, input);
		len = strlen(listc);
		if (!my_strnicmp(listc, "TIMEOUT", len)) {
			return malloc_sprintf(NULL, "%ld %ld", (long) t->time.tv_sec,
						    (long) t->time.tv_usec);
		} else if (!my_strnicmp(listc, "COMMAND", len)) {
			if (t->callback)
				RETURN_EMPTY;
			RETURN_STR(t->command);
		} else if (!my_strnicmp(listc, "SUBARGS", len)) {
			if (t->callback)
				RETURN_EMPTY;
			RETURN_STR(t->subargs);
		} else if (!my_strnicmp(listc, "REPEATS", len)) {
			RETURN_INT(t->events);
		} else if (!my_strnicmp(listc, "INTERVAL", len)) {
			return malloc_sprintf(NULL, "%ld %ld", (long) t->interval.tv_sec,
						    (long) t->interval.tv_usec);
		} else if (!my_strnicmp(listc, "SERVER", len)) {
			if (t->domain != SERVER_TIMER)
				RETURN_INT(-1);
			RETURN_INT(t->domref);
		} else if (!my_strnicmp(listc, "WINDOW", len)) {
			if (t->domain != WINDOW_TIMER)
				RETURN_INT(-1);
			RETURN_INT(t->domref);
		}
	} else if (!my_strnicmp(listc, "SET", len)) {
		GET_FUNC_ARG(refstr, input);
		if (!(t = get_timer(refstr)))
			RETURN_EMPTY;

		/* Changing internal system timers is strictly prohibited */
		if (t->callback)
			RETURN_EMPTY;

		GET_FUNC_ARG(listc, input);
		len = strlen(listc);
		if (!my_strnicmp(listc, "TIMEOUT", len)) {
			time_t	tv_sec;
			long	tv_usec;

			GET_INT_ARG(tv_sec, input);
			GET_INT_ARG(tv_usec, input);
			t->time.tv_sec = tv_sec;
			t->time.tv_usec = tv_usec;
		} else if (!my_strnicmp(listc, "COMMAND", len)) {
			malloc_strcpy((char **)&t->command, input);
		} else if (!my_strnicmp(listc, "SUBARGS", len)) {
			malloc_strcpy(&t->subargs, input);
		} else if (!my_strnicmp(listc, "REPEATS", len)) {
			long	repeats;

			GET_INT_ARG(repeats, input);
			t->events = repeats;
		} else if (!my_strnicmp(listc, "INTERVAL", len)) {
			time_t	tv_sec;
			long	tv_usec;

			GET_INT_ARG(tv_sec, input);
			GET_INT_ARG(tv_usec, input);
			t->interval.tv_sec = tv_sec;
			t->interval.tv_usec = tv_usec;
		} else if (!my_strnicmp(listc, "SERVER", len)) {
			int	refnum;

			GET_INT_ARG(refnum, input);
			t->domain = SERVER_TIMER;
			t->domref = refnum;
		} else if (!my_strnicmp(listc, "WINDOW", len)) {
			int	refnum;

			GET_INT_ARG(refnum, input);
			t->domain = WINDOW_TIMER;
			t->domref = refnum;
		}
	} else
		RETURN_EMPTY;

	RETURN_EMPTY;
}
Ejemplo n.º 17
0
/*
 * numbered_command: does (hopefully) the right thing with the numbered
 * responses from the server.  I wasn't real careful to be sure I got them
 * all, but the default case should handle any I missed (sorry) 
 *
 * The format of a numeric looks like so:
 *
 *	:server-name XXX our-nick Arg1 Arg2 Arg3 ... :ArgN
 *
 * The last argument traditionally has a colon before it, but this is not
 * compulsary.  The BreakArgs function has already broken this up into 
 * words for us, so that what we get, looks like this:
 *
 *	server-name	-> 	from parameter
 *	XXX		->	comm parameter
 *	our-nick	->	ArgList[0]
 *	Arg1		->	ArgList[1]
 *	Arg2		->	ArgList[2]
 *	...			...
 *
 * BUT!  There's a wrinkle in the ointment.  The first thing we do is slurp
 * up ArgList[0] (our-nick) and put it in 'user'.  Then we increment the 
 * ArgList array, so what we actually end up with is:
 *
 *	server-name	-> 	from parameter
 *	XXX		->	comm parameter
 *	our-nick	->	user
 *	Arg1		->	ArgList[0]
 *	Arg2		->	ArgList[1]
 *	...			...
 *	ArgN		->	ArgList[N-1]
 *	NULL		->	ArgList[N]
 */
void 	numbered_command (const char *from, const char *comm, char const **ArgList)
{
	const char	*recipient;
	char *	target = NULL;
	char	*copy;
	int	i;
	int	old_current_numeric = current_numeric;
	int	numeric;
	int	l;

	/* All numerics must be in the range (000, 999) */
	if (!comm || !*comm)
		{ rfc1459_odd(from, comm, ArgList); return; }
	numeric = atol(comm);
	if (numeric < 0 || numeric >= FIRST_NAMED_HOOK - 1)
		{ rfc1459_odd(from, comm, ArgList); return; }

	/* All numerics must have a recipient (our nickname) */
	if (!ArgList[0])
		{ rfc1459_odd(from, comm, ArgList); return; }
	recipient = LOCAL_COPY(ArgList[0]);
	ArgList++;

	/* 
	 * Numerics may have a channel target as 1st argument
	 *
	 * We must make a copy of ArgList[0] to pass to message_from
	 * because display_message (above) will call PasteArgs which
	 * will destroy ArgList[0].
	 *
	 * Please note that we don't consume the ArgList[0] argument,
	 * we only peek at it to see if we should target a channel
	 * with message_from().
	 */
	if (ArgList[0])
		target = LOCAL_COPY(ArgList[0]);
	if (target && is_channel(target))
		l = message_from(target, LEVEL_OTHER);
	else
		l = message_from(NULL, LEVEL_OTHER);

	current_numeric = numeric;	/* must be negative of numeric! */

	/*
	 * This first switch statement is only used for those numerics
	 * which either need to perform some action before the numeric
	 * is offered to the user, or by those actions which need to offer
	 * the numeric to the user in some special manner.  
	 *
	 * Those numerics which require only special display if the user
	 * does not hook them, are handled below.
	 *
	 * Those numerics which require special action after the numeric
	 * is offered to the user, are also handled below.
	 *
	 * Each of these numerics must either "break" (go to step 2)
	 * or must "goto END" (goto step 3).
	 */
	switch (numeric)
	{
	/*
	 * I added the "set_server_nickname" here because the client
	 * when auto-fudging your nick will sometimes be confused as
	 * what your nickname really is when you connect.  Since the
	 * server always tells us who the message was set to (ie, us)
	 * we just kind of take it at its word.
	 */
	case 001:	/* #define RPL_WELCOME          001 */
	{
		server_is_registered(from_server, from, recipient);
		break;
	}

	/* 
	 * Now instead of the terribly horrible hack using numeric 002
	 * to get the server name/server version info, we use the 004
	 * numeric which is what is the most logical choice for it.
	 *
	 * If any of the arguments are missing, we don't abort, because
	 * the client needs 004 to sync.  Instead, we just pass in the
	 * NULL values and hope for the best...
	 */
	case 004:	/* #define RPL_MYINFO           004 */
	{
		const char 	*server = NULL, 
				*version = NULL;

		if (!(server = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		else if (!(version = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		set_server_version_string(from_server, version);
		break;
	}

	case 005:
	{
		int	arg;
		char	*set, *value;

		for (arg = 0; ArgList[arg] && !strchr(ArgList[arg], ' '); arg++) {
			set = LOCAL_COPY(ArgList[arg]);
			value = strchr(set, '=');
			if (value && *value) 
				*value++ = 0;

			if (*set == '+')	/* Parameter append */
			{
				const char *ov = get_server_005(from_server, ++set);
				value = malloc_strdup2(ov, value);
				set_server_005(from_server, set, value);
				new_free(&value);
			}
			if (*set == '-')	/* Parameter removal */
				set_server_005(from_server, ++set, NULL);
			else if (value && *value)
				set_server_005(from_server, set, value);
			else
				set_server_005(from_server, set, space);
		}
		break;
	}

	case 10:		/* EFNext "Use another server"	010 */
	{
		const char *new_server, *new_port_s, *message;
		int	new_port, old_server;
		char *	str = NULL;
		int	new_servref;

		PasteArgs(ArgList, 2);
		if (!(new_server = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(new_port_s = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(message = ArgList[2]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		new_port = (int)atol(ArgList[1]);

		/* Must do these things before calling "display_msg" */
		old_server = from_server;
		malloc_sprintf(&str, "%s:%d:::%s:", new_server, new_port, 
					get_server_group(from_server));
		if ((new_servref = str_to_servref(str)) == NOSERV)
			new_servref = str_to_newserv(str);
		change_window_server(old_server, new_servref);
		from_server = old_server;
		break;
	}

	case 14:		/* Erf/TS4 "cookie" numeric	014 */
	{
		const char *	cookie;

		PasteArgs(ArgList, 0);
		if (!(cookie = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		use_server_cookie(from_server);
		set_server_cookie(from_server, cookie);
		goto END;
	}

	case 42:		/* IRCNet's "unique id" numeric 042 */
	{
		const char *unique_id, *message;

		PasteArgs(ArgList, 1);
		if (!(unique_id = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(message = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		set_server_unique_id(from_server, unique_id);
		break;
	}

        case 301:               /* #define RPL_AWAY             301 */
        {
		const char *nick, *message;

		PasteArgs(ArgList, 1);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(message = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* Ach.  /on 301 doesn't offer 'from' as $0.  Bummer. */
                if (do_hook(current_numeric, "%s %s", nick, message))
		{
			/* XXXX Hack -- figure out another way */
			copy = alloca(IRCD_BUFFER_SIZE + 1);
			*copy = 0;

			for (i = 0; ArgList[i]; i++)
			{
				if (i)
					strlcat(copy, " ", IRCD_BUFFER_SIZE);
				strlcat(copy, ArgList[i], IRCD_BUFFER_SIZE);
			}
			goto DISPLAY;
		}
		goto END;
        }

	case 307:		/* #define RPL_USERIP           307 */
	case 340:		/* #define RPL_USERIP?          340 */
		if (!get_server_005(from_server, "USERIP"))
			break;
		/* FALLTHROUGH */
	case 302:		/* #define RPL_USERHOST         302 */
		userhost_returned(from_server, from, comm, ArgList);
		goto END;

	case 303:		/* #define RPL_ISON             303 */
		ison_returned(from_server, from, comm, ArgList);
		goto END;

	case 315:		/* #define RPL_ENDOFWHO         315 */
		who_end(from_server, from, comm, ArgList);
		goto END;

	case 321:		/* #define RPL_LISTSTART        321 */
	{
		const char *channel, *user_cnt, *line;

		channel = ArgList[0] = "Channel";
		user_cnt = ArgList[1] = "Users";
		line = ArgList[2] = "Topic";
		ArgList[3] = NULL;

		/* Then see if they want to hook /ON LIST */
		if (!do_hook(LIST_LIST, "%s %s %s", channel, user_cnt, line))
			goto END;

		/*
		 * Otherwise, this line is ok.
		 */
		break;
	}

	case 322:		/* #define RPL_LIST             322 */
	{
		const char *channel, *user_cnt, *line;
		int	cnt;
		int	funny_flags, funny_min, funny_max;
		const char *funny_match;

		PasteArgs(ArgList, 2);
		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(user_cnt = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(line = ArgList[2]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		funny_flags = get_server_funny_flags(from_server);
		funny_min = get_server_funny_min(from_server);
		funny_max = get_server_funny_max(from_server);
		funny_match = get_server_funny_match(from_server);

		/* List messages NEVER go to a chanwin */
		pop_message_from(l);
		l = message_from(NULL, LEVEL_OTHER);

		/*
		 * Do not display if the channel has no topic and the user asked
		 * for only channels with topics.
		 */
		if (funny_flags & FUNNY_TOPIC && !(line && *line))
			goto END;

		/*
		 * Do not display if the channel does not have the necessary 
		 * number of users the user asked for
		 */
		cnt = my_atol(user_cnt);
		if (funny_min && (cnt < funny_min))
			goto END;
		if (funny_max && (cnt > funny_max))
			goto END;

		/*
		 * Do not display if the channel is not private or public as the
		 * user requested.
		 */
		if ((funny_flags & FUNNY_PRIVATE) && (*channel != '*'))
			goto END;
		if ((funny_flags & FUNNY_PUBLIC) && (*channel == '*'))
			goto END;

		/*
		 * Do not display if the channel does not match the user's 
		 * supplied wildcard pattern
		 */
		if (funny_match && wild_match(funny_match, channel) == 0)
			goto END;

		/* Then see if they want to hook /ON LIST */
		if (!do_hook(LIST_LIST, "%s %s %s", channel, user_cnt, line))
			goto END;

		/*
		 * Otherwise, this line is ok.
		 */
		break;
	}

	case 324:		/* #define RPL_CHANNELMODEIS    324 */
	{
		const char      *mode, *channel;

		PasteArgs(ArgList, 1);
		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(mode = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* If we're waiting for MODE reply. */
		if (channel_is_syncing(channel, from_server))
		{
		    int	numonchannel, maxnum;

		    copy = LOCAL_COPY(channel);
		    update_channel_mode(channel, mode);
		    update_all_status();

		    if (is_channel_anonymous(copy, from_server))
			channel_not_waiting(copy, from_server);
		    else
		    {
			maxnum = get_server_max_cached_chan_size(from_server);
			if (maxnum >= 0)
			{
			    numonchannel = number_on_channel(copy, from_server);
			    if (numonchannel <= maxnum)
				whobase(from_server, copy, add_user_who, 
						add_user_end);
			    else
				channel_not_waiting(copy, from_server);
			}
			else
			    whobase(from_server, copy, add_user_who, 
					add_user_end);
		    }
		}

		break;
	}

	case 352:		/* #define RPL_WHOREPLY         352 */
		whoreply(from_server, NULL, comm, ArgList);
		goto END;

	case 353:		/* #define RPL_NAMREPLY         353 */
	{
		const char	*type, *channel, *line;

		PasteArgs(ArgList, 2);
		if (!(type = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(channel = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(line = ArgList[2]))
			{ line = empty_string; }

		if (channel_is_syncing(channel, from_server))
		{
		    char *line_copy = LOCAL_COPY(line);
		    char *nick;

		    while ((nick = next_arg(line_copy, &line_copy)) != NULL)
		    {
			/* XXX Hack to work around space at end of 353 */
			forcibly_remove_trailing_spaces(nick, NULL);

			/*
			 * 1999 Oct 29 -- This is a hack to compensate for
			 * a bug in older ircd implementations that can result
			 * in a truncated nickname at the end of a names reply.
			 * The last nickname in a names list is then always
			 * treated with suspicion until the WHO reply is 
			 * completed and we know that its not truncated. --esl
			 */
			if (!line || !*line)
				add_to_channel(channel, nick, from_server, 
								1, 0, 0, 0);
			else
				add_to_channel(channel, nick, from_server, 
								0, 0, 0, 0);
		    }

		    break;
		}
		else
		{
		    int	cnt;
		    const char	*ptr;
		    int	funny_flags, funny_min, funny_max;
		    const char *funny_match;

		    funny_flags = get_server_funny_flags(from_server);
		    funny_min = get_server_funny_min(from_server);
		    funny_max = get_server_funny_max(from_server);
		    funny_match = get_server_funny_match(from_server);

		    ptr = line;
		    for (cnt = -1; ptr; cnt++)
		    {
			if ((ptr = strchr(ptr, ' ')) != NULL)
				ptr++;
		    }

		    if (funny_min && (cnt < funny_min))
			goto END;
		    else if (funny_max && (cnt > funny_max))
			goto END;

		    if ((funny_flags & FUNNY_PRIVATE) && 
					(*type == '='))
			goto END;
		    if ((funny_flags & FUNNY_PUBLIC) && 
					((*type == '*') || (*type == '@')))
			goto END;

		    if (funny_match && wild_match(funny_match, channel) == 0)
			goto END;
		}

		/* Everything is OK. */
		break;
	}

	case 354:		/* #define RPL_XWHOREPLY	354 */
		xwhoreply(from_server, NULL, comm, ArgList);
		goto END;

	/* XXX Yea yea, these are out of order. so shoot me. */
	case 346:               /* #define RPL_INVITELIST (+I for erf) */
	case 348:               /* #define RPL_EXCEPTLIST (+e for erf) */
	case 367:		/* #define RPL_BANLIST */
		number_of_bans++;
		break;

	case 347:               /* #define END_OF_INVITELIST */
	case 349:               /* #define END_OF_EXCEPTLIST */
	case 368:		/* #define END_OF_BANLIST */
	{
		const char	*channel;

		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

#ifdef IRCII_LIKE_BAN_SUMMARY
		if (do_hook(current_numeric, "%s %s %d", 
			from, channel, number_of_bans))
#else
		if (do_hook(current_numeric, "%s %d %s", 
				from, number_of_bans, channel))
#endif
		{
			put_it("%s Total number of %s on %s - %d",
				banner(), 
                                numeric == 347 ? "invites" :
                               (numeric == 349 ? "exceptions" :
                               (numeric == 368 ? "bans" : "wounds")),
                                channel, number_of_bans);
		}
		goto END;
	}

	/* XXX Shouldn't this set "You're operator" flag for hybrid? */
	case 381: 		/* #define RPL_YOUREOPER        381 */
		if (!is_server_registered(from_server))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		break;

        /* ":%s 401 %s %s :No such nick/channel" */
	case 401:		/* #define ERR_NOSUCHNICK       401 */
	{
		const char	*nick;

		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		if (!is_channel(nick))
		    notify_mark(from_server, nick, 0, 0);

		break;
	}

	/* Bizarre dalnet extended who replies. */
        /* ":%s 402 %s %s :No such server" */
	case 402:
	{
		const char	*server;

		if (!(server = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		fake_who_end(from_server, from, comm, server);
		break;
	}

	/* Yet more bizarre dalnet extended who replies. */
	/* ":%s 522 %s :/WHO Syntax incorrect, use /who ? for help" */
        /* ":%s 523 %s :Error, /who limit of %d exceed." */
	case 522:
	case 523:
	{
		/* 
		 * This dalnet error message doesn't even give us the
		 * courtesy of telling us which who request was in error,
		 * so we have to guess.  Whee.
		 */
		fake_who_end(from_server, from, comm, NULL);
		break;
	}

	case 403:		/* #define ERR_NOSUCHCHANNEL    403 */
	{
		const char *	s;
		const char *	channel;
		const char *	message;

		PasteArgs(ArgList, 1);

		/* Some servers BBC and send back an empty reply. */
		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(message = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* Do not accept 403's from remote servers. */
		s = get_server_itsname(from_server);
		if (my_strnicmp(s, from, strlen(s)))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* 
		 * Some servers BBC and send this instead of a
		 * 315 numeric when a who request has been completed.
		 */
		if (fake_who_end(from_server, from, comm, channel))
			;

		/*
		 * If you try to JOIN or PART the "*" named channel, as may
		 * happen if epic gets confused, the server may tell us that
		 * channel does not exist.  But it would be death to try to 
		 * destroy that channel as epic will surely do the wrong thing!
		 * Otherwise, we somehow tried to reference a channel that
		 * this server claims does not exist; we blow the channel away
		 * for good measure.
		 */
		else if (strcmp(channel, "*"))
			remove_channel(channel, from_server);

		break;
	}

	case 421:		/* #define ERR_UNKNOWNCOMMAND   421 */
	{
		const char	*token;

		if (!(token = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		if (check_server_redirect(from_server, token))
			goto END;
		if (check_server_wait(from_server, token))
			goto END;

		break;
	}

	case 437:		/* av2.9's "Nick collision" numeric 437 */
				/* Also, undernet/dalnet "You are banned" */
				/* Also, av2.10's "Can't do that" numeric */
				/* Also, cs's "too many nick changes" num */
	{
		/*
		 * Ugh. What a total trainwreck this is.  Sometimes, I
		 * really hate all the ircd's out there in the world that
		 * have to be supported.
		 *
		 * Well, there are at least four different, occasionally
		 * scrutable ways we can get this numeric.
		 *
		 * 1a) On ircnet -- As an unregistered user, the NICK that
		 *	we are trying to register was used in the past 90
		 *	seconds or so.  The server expects us to send
		 *	another NICK request.
		 *		ARGV[0] IS NICK, REGISTERED IS NO
		 * 1b) On ircnet -- As a registered user, the NICK that 
		 *	we are trying to register was used in the past 90
		 *	seconds or so.  The server expects us not to do
		 * 	anything (like a 432 numeric).
		 *		ARGV[0] IS NICK, REGISTERED IS YES
		 * 2) On ircnet -- As a registered user, we are trying to
		 *	join a channel that was netsplit in the past 24 hours
		 *	or so.  The server expects us not to do anything.
		 *		ARGV[0] IS CHANNEL, REGISTERED IS YES
		 * 3) On undernet/dalnet -- As a registered user, who is
		 *	on a channel where we are banned, a NICK request
		 *	was rejected (because we are banned).  The server
		 *	expects us not to do anything.
		 *		ARGV[0] IS CHANNEL, REGISTERED IS YES
		 * 4) On a comstud efnet servers -- As a registered user, 
		 *	we have changed our nicknames too many times in
		 *	too short a time.  The server expects us not to do
		 *	anything.
		 *		ARGV[0] IS ERROR, ARGV[1] IS NULL.
		 *	I understand this numeric will be moving to 439.
		 */

		/*
		 * Weed out the comstud one first, since it's the most bizarre.
		 */
		if (ArgList[0] && ArgList[1] == NULL)
		{
			accept_server_nickname(from_server, recipient);
			break;
		}

		/*
		 * Now if it's a channel, it might be ircnet telling us we
		 * can't join the channel, or undernet telling us that we 
		 * can't change our nickname because we're banned.  The 
		 * easiest way to tell is to see if we are on the channel.
		 */
		if (is_channel(ArgList[0]))
		{
			/* XXX Is this really neccesary? */
			if (!im_on_channel(ArgList[0], from_server))
				remove_channel(ArgList[0], from_server);

			break;
		}

		/* 
		 * Otherwise, it's an ircnet "nick not available" error.
		 * Let the nickname reset numerics handle this mess.
		 */
		/* FALLTHROUGH */
	}

	case 432:		/* #define ERR_ERRONEUSNICKNAME 432 */
	case 433:		/* #define ERR_NICKNAMEINUSE    433 */ 
	case 438:		/* Undernet's "Stop changing your nick" */
	case 439:		/* Comstud's "Can't change nickname" */
	case 453:		/* EFnet/TS4 "nickname lost" numeric 453 */
	{
		const char	*nick;

		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* 
		 * This is a hack for BBC from inspircd.
		 * A 439 numeric received before 001 that is sent to the
		 * nickname we requested is NOT a rejection of that nickname,
		 * it is an informational message from inspircd.
		 */
		if (numeric == 439 && 
		    !is_server_registered(from_server) &&
		    !strcmp(recipient, get_pending_nickname(from_server)))
			break;

		nickname_change_rejected(from_server, recipient);

		if (!from)
			from = "-1";

		break;
	}

	case 442:		/* #define ERR_NOTONCHANNEL	442 */
	{
		const char *	s;
		const char *	channel;
		const char *	message;

		PasteArgs(ArgList, 1);

		/* Some servers BBC and send back an empty reply. */
		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(message = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* Do not accept this numeric from remote servers */
		s = get_server_itsname(from_server);
		if (my_strnicmp(s, from, strlen(s)))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* Do not ever delete the "*" channel */
		if (strcmp(ArgList[0], "*"))
		    remove_channel(ArgList[0], from_server);

		break;
	}

	case 451:		/* #define ERR_NOTREGISTERED    451 */
	/*
	 * Sometimes the server doesn't catch the USER line, so
	 * here we send a simplified version again  -lynx 
	 */
		register_server(from_server, NULL);
		break;

	case 462:		/* #define ERR_ALREADYREGISTRED 462 */
		change_server_nickname(from_server, NULL);
		break;

	case 477:		/* #define ERR_NEEDREGGEDNICK	477 */
		/* IRCnet has a different 477 numeric. */
		if (ArgList[0] && *ArgList[0] == '+')
			break;
		/* FALLTHROUGH */
	case 471:		/* #define ERR_CHANNELISFULL    471 */
	case 473:		/* #define ERR_INVITEONLYCHAN   473 */
	case 474:		/* #define ERR_BANNEDFROMCHAN   474 */
	case 475: 		/* #define ERR_BADCHANNELKEY    475 */
	case 476:		/* #define ERR_BADCHANMASK      476 */
	{
		const char	*channel;

		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		cant_join_channel(ArgList[0], from_server);
		break;
	}
	}

/* DEFAULT OFFER */
	/*
	 * This is the "default hook" case, where we offer to the user all of
	 * the numerics that were not offered above.  We simply catenate
	 * all of the arguments into a string and offer to the user.
	 * If the user bites, then we skip the "default display" section.
	 */
	copy = alloca(IRCD_BUFFER_SIZE + 1);
	*copy = 0;

	for (i = 0; ArgList[i]; i++)
	{
		if (i)
			strlcat(copy, " ", IRCD_BUFFER_SIZE);
		strlcat(copy, ArgList[i], IRCD_BUFFER_SIZE);
	}

	if (!do_hook(current_numeric, "%s %s", from, copy))
		goto END;

DISPLAY:
/* DEFAULT DISPLAY */
	if (!do_hook(NUMERIC_LIST, "%d %s %s", current_numeric, from, copy))
		goto END;

	/*
	 * This is the "default display" case, where if the user does not 
	 * hook the numeric, we output the message in some special way.
	 * If a numeric does not require special outputting, then we will
	 * just display it with ``display_msg''
	 */
	switch (numeric)
	{
	case 221: 		/* #define RPL_UMODEIS          221 */
	{
		const char *umode;

		PasteArgs(ArgList, 0);
		if (!(umode = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s Your user mode is \"%s\"", banner(), umode);
		break;
	}

	case 271:		/* #define SILENCE_LIST		271 */
	{
		const char *perp, *victim;

		PasteArgs(ArgList, 1);
		if (!(perp = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(victim = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s is ignoring %s", banner(), perp, victim);
		break;
	}

	case 301:		/* #define RPL_AWAY             301 */
	{
		const char *nick, *message;

		PasteArgs(ArgList, 1);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(message = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s is away: %s", banner(), nick, message);
		break;
	}

	case 311:		/* #define RPL_WHOISUSER        311 */
	{
		const char *nick, *user, *host, *channel, *name;

		PasteArgs(ArgList, 4);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(user = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(host = ArgList[2]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(channel = ArgList[3]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(name = ArgList[4]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s is %s@%s (%s)", banner(), nick, user, host, name);
		break;
	}

	case 312:		/* #define RPL_WHOISSERVER      312 */
	{
		const char *nick, *server, *pithy;

		PasteArgs(ArgList, 2);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(server = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(pithy = ArgList[2]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s on irc via server %s (%s)", banner(), server, pithy);
		break;
	}

	case 313:		/* #define RPL_WHOISOPERATOR    313 */
	{
		const char *nick, *message;

		PasteArgs(ArgList, 1);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(message = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s %s", banner(), ArgList[0], ArgList[1]);
		break;
	}

	case 314:		/* #define RPL_WHOWASUSER       314 */
	{
		const char *nick, *user, *host, *unused, *name;

		PasteArgs(ArgList, 4);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(user = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(host = ArgList[2]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(unused = ArgList[3]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(name = ArgList[4]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s was %s@%s (%s)",banner(), nick, user, host, name);
		break;
	}

	case 317:		/* #define RPL_WHOISIDLE        317 */
	{
		const char *nick, *idle_str, *startup_str;
		int		idle;
		const char *	unit;
		char 	startup_ctime[128];

		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(idle_str = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(startup_str = ArgList[2])) { /* No problem */; } 

		*startup_ctime = 0;
		if (startup_str)		/* Undernet/TS4 */
		{
		    time_t	startup;

		    if ((startup = atol(startup_str)) != 0)
			snprintf(startup_ctime, 128, ", signed on at %s", 
							my_ctime(startup));
		}

		if ((idle = atoi(idle_str)) > 59)
		{
			idle /= 60;
			unit = "minute";
		}
		else
			unit = "second";

		put_it ("%s %s has been idle %d %ss%s",
			banner(), nick, idle, unit, startup_ctime);
		break;
	}

	case 318:		/* #define RPL_ENDOFWHOIS       318 */
	{
		PasteArgs(ArgList, 0);
		display_msg(from, comm, ArgList);
		break;
	}

	case 319:		/* #define RPL_WHOISCHANNELS    319 */
	{
		const char *nick, *channels;

		PasteArgs(ArgList, 1);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(channels = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s on channels: %s", banner(), channels);
		break;
	}

	case 321:		/* #define RPL_LISTSTART	321 */
		/* Our screwy 321 handling demands this. BAH! */
		put_it("%s Channel Users Topic", banner());
		break;

	case 322:		/* #define RPL_LIST             322 */
	{
		static char format[25];
		static int last_width = -1;
		const char *channel, *user_cnt, *line;

		PasteArgs(ArgList, 2);
		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(user_cnt = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(line = ArgList[2]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* Figure out how to display this to the user. */
		if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR))
		{
			if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)))
				snprintf(format, 25, "%%-%u.%us %%-5s  %%s",
				(unsigned) last_width,
				(unsigned) last_width);
			else
				strlcpy(format, "%s\t%-5s  %s", sizeof format);
		}

		if (*channel == '*')
			say(format, "Prv", user_cnt, line);
		else
			say(format, check_channel_type(channel),
				user_cnt, line);

		break;
	}

	case 324:		/* #define RPL_CHANNELMODEIS    324 */
	{
		const char      *mode, *channel;

		PasteArgs(ArgList, 1);
		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(mode = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s Mode for channel %s is \"%s\"",
				banner(), channel, mode);
		break;
	}

	case 329:		/* #define CREATION_TIME	329 */
	{
		const char *channel, *time1_str, *time2_str, *time3_str;
		time_t	time1, time2, time3;

		PasteArgs(ArgList, 2);
		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(time1_str = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(time2_str = ArgList[2])) { /* No problem */; }
		if (!(time3_str = ArgList[3])) { /* No problem */; }


		/* Erf/TS4 support */
		if (time2_str && time3_str)
		{
			time1 = (time_t)my_atol(time1_str);
			time2 = (time_t)my_atol(time2_str);
			time3 = (time_t)my_atol(time3_str);

			put_it("%s Channel %s was created at %ld, "
				  "+c was last set at %ld, "
				  "and has been opless since %ld", banner(), 
					channel, time1, time2, time3);
		}
		else
		{
			time1 = (time_t)my_atol(time1_str);

			put_it("%s Channel %s was created at %s",
					banner(), channel, my_ctime(time1));
		}
		break;
	}

	case 330:		/* #define RPL_WHOISLOGGEDIN	330 */
	{
		const char *nick, *login, *reason;

		PasteArgs(ArgList, 2);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(login = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(reason = ArgList[2]))
			{ reason = "is logged in as"; }

		put_it("%s %s %s %s", banner(), nick, reason, login);
		break;
	}

	case 332:		/* #define RPL_TOPIC            332 */
	{
		const char *channel, *topic;

		PasteArgs(ArgList, 1);
		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(topic = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s Topic for %s: %s", banner(), channel, topic);
		break;
	}

	case 333:		/* #define RPL_TOPICWHOTIME	333 */
	{
		const char *channel, *nick, *when_str;
		time_t	howlong;

		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(nick = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(when_str = ArgList[2]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		howlong = time(NULL) - my_atol(when_str);
		put_it("%s The topic was set by %s %ld sec ago",banner(), 
				nick, howlong);
		break;
	}

	case 338:		/* #define RPL_WHOISACTUALLY	338 */
	{
		const char *who, *host;

		if (!(who = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(host = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s is actually using %s", banner(), who, host);
		break;
	}

	case 341:		/* #define RPL_INVITING         341 */
	{
		const char *nick, *channel;

		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(channel = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		pop_message_from(l);
		l = message_from(channel, LEVEL_OTHER);
		put_it("%s Inviting %s to channel %s", banner(), nick, channel);
		break;
	}

	case 351:		/* #define RPL_VERSION          351 */
	{
		const char *version, *itsname, *stuff;

		PasteArgs(ArgList, 2);
		if (!(version = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(itsname = ArgList[1])) {
			/* As a favor to larne, for inspired */
			put_it("%s Server %s", banner(), version);
			break;
		}
		if (!(stuff = ArgList[2]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s Server %s: %s %s",banner(), itsname, version, stuff);
		break;
	}

	case 353:		/* #define RPL_NAMREPLY         353 */
	{
		static int last_width;
		char format[41];
		const char	*type, *channel, *line;

		PasteArgs(ArgList, 2);
		if (!(type = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(channel = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(line = ArgList[2]))
			{ line = empty_string; }

		/* This is only for when the user joined the channel */
		if (channel_is_syncing(channel, from_server))
		{
			/* If the user bites on /ON NAMES, then skip the rest */
			pop_message_from(l);
			l = message_from(channel, LEVEL_OTHER);
			if (do_hook(NAMES_LIST, "%s %s", channel, line))
			    if (get_int_var(SHOW_CHANNEL_NAMES_VAR))
				say("Users on %s: %s",
					check_channel_type(channel), line);
			break;
		}

		/* If the user grabs /ON NAMES then just stop right here */
		if (!do_hook(NAMES_LIST, "%s %s", channel, line))
			break;

		/* This all is for when the user has not just joined channel */
		if (last_width != get_int_var(CHANNEL_NAME_WIDTH_VAR))
		{
			if ((last_width = get_int_var(CHANNEL_NAME_WIDTH_VAR)))
				snprintf(format, 40, "%%s: %%-%u.%us %%s",
					(unsigned char) last_width,
					(unsigned char) last_width);
			else
				strlcpy(format, "%s: %s\t%s", sizeof format);
		}
		else
			strlcpy(format, "%s: %s\t%s", sizeof format);

		pop_message_from(l);
		l = message_from(channel, LEVEL_OTHER);
		if (*type == '=') 
		{
		    if (last_width && ((int)strlen(channel) > last_width))
		    {
			char *channel_copy = LOCAL_COPY(channel);
			channel_copy[last_width-1] = '>';
			channel_copy[last_width] = 0;
			channel = channel_copy;
		    }
		    put_it(format, "Pub", check_channel_type(channel), line);
		}
		else if (*type == '*') 
		    put_it(format, "Prv", check_channel_type(channel), line);
		else if (*type == '@')
		    put_it(format, "Sec", check_channel_type(channel), line);

		break;
	}

	case 364:		/* #define RPL_LINKS            364 */
	{
		const char	*itsname, *uplink, *stuff;

		PasteArgs(ArgList, 2);
		if (!(itsname = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(uplink = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(stuff = ArgList[2])) { stuff = empty_string; }

		if (stuff)
			put_it("%s %-20s %-20s %s", banner(),
					itsname, uplink, stuff);
		else
			put_it("%s %-20s %s", banner(), itsname, uplink);

		break;
	}

	case 366:		/* #define RPL_ENDOFNAMES       366 */
	{
		const char	*channel;

		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		if (!channel_is_syncing(channel, from_server))
			display_msg(from, comm, ArgList);

		break;
	}

	case 346:               /* #define RPL_INVITELIST (+I for erf) */
	case 348:               /* #define RPL_EXCEPTLIST (+e for erf) */
	case 367:
	{
		const char	*channel, *ban, *perp, *when_str;
		time_t	howlong;

		if (!(channel = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(ban = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(perp = ArgList[2])) { /* No problem. */ }
		if (!(when_str = ArgList[3])) { /* No problem. */ }

		if (perp && when_str) 
		{
			howlong = time(NULL) - my_atol(when_str);
			put_it("%s %s %-25s set by %-10s %ld sec ago", 
				banner(), channel, ban, perp, howlong);
		}
		else
			put_it("%s %s %s", banner(), channel, ban);

		break;
	}

	case 401:		/* #define ERR_NOSUCHNICK       401 */
	{
		const char	*nick, *stuff;

		PasteArgs(ArgList, 1);
		if (!(nick = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		if (!(stuff = ArgList[1]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s: %s", banner(), nick, stuff);
		break;
	}

	case 219:		/* #define RPL_ENDOFSTATS       219 */
	case 232:		/* #define RPL_ENDOFSERVICES    232 */
	case 365:		/* #define RPL_ENDOFLINKS       365 */
	case 369:		/* #define RPL_ENDOFWHOWAS      369 */
	case 374:		/* #define RPL_ENDOFINFO        374 */
	case 394:		/* #define RPL_ENDOFUSERS       394 */
	{
		PasteArgs(ArgList, 0);
		display_msg(from, comm, ArgList);
		break;
	}

	case 471:		/* #define ERR_CHANNELISFULL    471 */
	{
		const char *message;

		PasteArgs(ArgList, 0);
		if (!(message = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s (Channel is full)", banner(), message);
		break;
	}
	case 473:		/* #define ERR_INVITEONLYCHAN   473 */
	{
		const char *message;

		PasteArgs(ArgList, 0);
		if (!(message = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s (You must be invited)", banner(), message);
		break;
	}
	case 474:		/* #define ERR_BANNEDFROMCHAN   474 */
	{
		const char *message;

		PasteArgs(ArgList, 0);
		if (!(message = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s (You are banned)", banner(), message);
		break;
	}
	case 475: 		/* #define ERR_BADCHANNELKEY    475 */
	{
		const char *message;

		PasteArgs(ArgList, 0);
		if (!(message = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s (You must give the correct key)", 
						banner(), message);
		break;
	}
	case 476:		/* #define ERR_BADCHANMASK      476 */
	{
		const char *message;

		PasteArgs(ArgList, 0);
		if (!(message = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		put_it("%s %s (Bad channel mask)", banner(), message);
		break;
	}
	case 477:		/* #define ERR_NEEDREGGEDNICK	477 */
	{
		const char *message;

		PasteArgs(ArgList, 0);
		if (!(message = ArgList[0]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }

		/* IRCnet has a different 477 numeric. */
		if (message && *message == '+')
		{
			display_msg(from, comm, ArgList);
			break;
		}

		PasteArgs(ArgList, 0);
		put_it("%s %s (You must use a registered nickname)", 
					banner(), message);
		break;
	}

	default:
		display_msg(from, comm, ArgList);
	}

END:
	/*
	 * This is where we clean up after our numeric.  Numeric-specific
	 * cleanups can occur here, and then below we reset the display
	 * settings.
	 */
	switch (numeric)
	{
	case 347:               /* #define END_OF_INVITELIST */
	case 349:               /* #define END_OF_EXCEPTLIST */
	case 368:
		number_of_bans = 0;
		break;
	case 464:		/* #define ERR_PASSWDMISMATCH   464 */
	{
		if (oper_command)
			oper_command = 0;
		else if (!is_server_registered(from_server))
		{
			say("Password required for connection to server %s",
				get_server_name(from_server));
			if (!dumb_mode)
			{
				add_wait_prompt("Server Password:", 
					password_sendline, NUMSTR(from_server),
					WAIT_PROMPT_LINE, 0);
			}
		}
	}
	}

	current_numeric = old_current_numeric;
	pop_message_from(l);
}