Beispiel #1
0
/* cancel_clients()
 *
 * inputs	- client who sent us the message, client with fake
 *		  direction, command
 * outputs	- a given warning about the fake direction
 * side effects -
 */
static void
cancel_clients(struct Client *client_p, struct Client *source_p, char *cmd)
{
	/* ok, fake prefix happens naturally during a burst on a nick
	 * collision with TS5, we cant kill them because one client has to
	 * survive, so we just send an error.
	 */
	if(IsServer(source_p) || IsMe(source_p))
	{
		sendto_realops_flags(UMODE_DEBUG, L_ALL,
				     "Message for %s[%s] from %s",
				     source_p->name, source_p->from->name,
				     get_server_name(client_p, SHOW_IP));
	}
	else
	{
		sendto_realops_flags(UMODE_DEBUG, L_ALL,
				     "Message for %s[%s@%s!%s] from %s (TS, ignored)",
				     source_p->name,
				     source_p->username,
				     source_p->host,
				     source_p->from->name,
				     get_server_name(client_p, SHOW_IP));
	}
}
Beispiel #2
0
/**
  * @brief connect to switch and send an init package of online information when online is launched
  */
void connect_to_switch()
{
	DEBUG_LOG("do  connect_to_switch");
	switch_fd = connect_to_service(config_get_strval("service_switch"), 0, 65535, 1);
	if (switch_fd != -1) {
		//连上时
 		is_add_timer_to_connect_switch=false;
	   	static uint32_t seqno = 0;
		sw_report_online_info_in sw_in;
	 	sw_in.domain_id= config_get_intval("domain", 0);
		sw_in.online_id= get_server_id();
		memcpy(sw_in.online_name,get_server_name(),sizeof(sw_in.online_name)); 
		memcpy(sw_in.online_ip,get_server_ip(),sizeof(sw_in.online_ip)); 
		sw_in.online_port=get_server_port();
		sw_in.seqno=seqno;
		g_sprite_map->get_userid_list(sw_in.userid_list);

	 	sw_in.user_num=sw_in.userid_list.size() ;
	
	    ++seqno;
	    send_msg_to_switch(NULL,sw_report_online_info_cmd,0,&sw_in );

		KDEBUG_LOG(0, "BEGIN CONNECTING TO CENTRAL ONLINE AND SEND INIT PKG");
	}else{//
		if(! is_add_timer_to_connect_switch){//还没有加入定时器
			DEBUG_LOG("ADD TIMER connect_switch ");
			g_timer_map->add_timer( TimeVal(3),n_sw_report_online_info,0 );
			is_add_timer_to_connect_switch=true;
		}
	}
}
Beispiel #3
0
/* remove_unknown()
 *
 * inputs	- client who gave us message, supposed sender, buffer
 * output	- 
 * side effects	- kills issued for clients, squits for servers
 */
static void
remove_unknown(struct Client *client_p, char *lsender, char *lbuffer)
{
	int slen = strlen(lsender);

	/* meepfoo	is a nickname (KILL)
	 * #XXXXXXXX	is a UID (KILL)
	 * #XX		is a SID (SQUIT)
	 * meep.foo	is a server (SQUIT)
	 */
	if((IsDigit(lsender[0]) && slen == 3) || 
	   (strchr(lsender, '.') != NULL))
	{
		sendto_realops_flags(UMODE_DEBUG, L_ALL,
				     "Unknown prefix (%s) from %s, Squitting %s",
				     lbuffer, get_server_name(client_p, SHOW_IP), lsender);

		sendto_one(client_p,
			   ":%s SQUIT %s :(Unknown prefix (%s) from %s)",
			   get_id(&me, client_p), lsender, 
			   lbuffer, client_p->name);
	}
	else
		sendto_one(client_p, ":%s KILL %s :%s (Unknown Client)", 
			   get_id(&me, client_p), lsender, me.name);
}
Beispiel #4
0
static	void parse_server_notice(char *from, char *line)
{
	int	flag = 0;
	int	up_status = 0;
const	char	*f;	
				
	f = from;
	if (!f || !*f)
		if (!(f = get_server_itsname(from_server)))
			f = get_server_name(from_server);
			
	if (*line != '*'  && *line != '#' && strncmp(line, "MOTD ", 4))
		flag = 1;
	else
		flag = 0;

	if (do_hook(SERVER_NOTICE_LIST, flag?"%s *** %s":"%s %s", f, line))
	{
#ifdef WANT_OPERVIEW
		if (handle_oper_vision(f, line, &up_status))
			reset_display_target();
		else 
#endif
		if (strstr(line, "***"))
		{
			set_display_target(NULL, LOG_SNOTE);
#ifdef WANT_OPERVIEW
			if (get_int_var(OV_VAR) && !(get_server_ircop_flags(from_server) & SERVER_CRAP))
				goto done1;
#endif
			if (do_hook(SERVER_NOTICE_LIST, flag ? "%s *** %s" : "%s %s", f, line))
			{
				char *for_;
				for_ = next_arg(line,&line);
				serversay(1, from_server, "%s", 
				convert_output_format(fget_string_var(FORMAT_SERVER_NOTICE_FSET), "%s %s %s", update_clock(GET_TIME), 
				f, stripansicodes(line)));
				add_last_type(&last_servermsg[0], MAX_LAST_MSG, NULL, NULL, NULL, line);
			}
		}
		else
		{
			set_display_target(NULL, LOG_SNOTE);
#ifdef WANT_OPERVIEW
			if (get_int_var(OV_VAR) && !(get_server_ircop_flags(from_server) & SERVER_CRAP))
				goto done1;
#endif
			if (do_hook(SERVER_NOTICE_LIST, flag ? "%s *** %s" : "%s %s", f, line))
				serversay(1, from_server, "%s", 
				convert_output_format(fget_string_var(FORMAT_SERVER_NOTICE_FSET), "%s %s %s", update_clock(GET_TIME), 
				f, stripansicodes(line)));
			add_last_type(&last_servermsg[0], MAX_LAST_MSG, NULL, NULL, NULL, line);
		}
	}
	if (up_status)
		update_all_status(current_window, NULL, 0);
done1:
	reset_display_target();
}
Beispiel #5
0
void PhysicsServerManager::on_servers_changed() {

	String physics_servers("DEFAULT");
	for (int i = get_servers_count() - 1; 0 <= i; --i) {
		physics_servers += "," + get_server_name(i);
	}
	ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers));
}
Beispiel #6
0
utility_retcode_t init_rtsp_server(struct rtsp_server *server)
{
	FUNC_ENTER;

	syscalls_memset(server, 0, sizeof(*server));
	get_server_name(server->name, sizeof(server->name));
	get_server_host(server->host, sizeof(server->host));
	get_server_port(&server->port);

	FUNC_RETURN;
	return UTILITY_SUCCESS;
}
void exec_server_process(int (*socket_pairs)[2]) {
    pid_t pid = fork();
    if (pid == 0) {
        const int client_num = get_client_count();
        close_all_client_fd_except(socket_pairs, client_num, -1);
        for (int i = 0; i < client_num; i++) {
            move_fd(client_fd(i), socket_pairs[i][kFdConnectToServer]);
        }
        execv(get_server_name(), NULL);
        exit(0);
    }
}
Beispiel #8
0
/* send_linebuf()
 *
 * inputs	- client to send to, linebuf to attach
 * outputs	-
 * side effects - linebuf is attached to client
 */
static int
_send_linebuf(struct Client *to, buf_head_t *linebuf)
{
    if(IsMe(to))
    {
        sendto_realops_snomask(SNO_GENERAL, L_ALL, "Trying to send message to myself!");
        return 0;
    }

    if(!MyConnect(to) || IsIOError(to))
        return 0;

    if(linebuf_len(&to->localClient->buf_sendq) > get_sendq(to))
    {
        if(IsServer(to))
        {
            sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                   "Max SendQ limit exceeded for %s: %u > %lu",
                                   get_server_name(to, HIDE_IP),
                                   linebuf_len(&to->localClient->buf_sendq),
                                   get_sendq(to));

            ilog(L_SERVER, "Max SendQ limit exceeded for %s: %u > %lu",
                 log_client_name(to, SHOW_IP),
                 linebuf_len(&to->localClient->buf_sendq),
                 get_sendq(to));
        }

        if(IsClient(to))
            to->flags |= FLAGS_SENDQEX;

        dead_link(to);
        return -1;
    }
    else
    {
        /* just attach the linebuf to the sendq instead of
         * generating a new one
         */
        linebuf_attach(&to->localClient->buf_sendq, linebuf);
    }

    /*
     ** Update statistics. The following is slightly incorrect
     ** because it counts messages even if queued, but bytes
     ** only really sent. Queued bytes get updated in SendQueued.
     */
    to->localClient->sendM += 1;
    me.localClient->sendM += 1;
    if(linebuf_len(&to->localClient->buf_sendq) > 0)
        send_queued_write(to->localClient->fd, to);
    return 0;
}
Beispiel #9
0
void got_initial_version_28 (char **ArgList)
{
	char *server, *sversion, *user_modes, *channel_modes;

	server = ArgList[0];
	sversion = ArgList[1];
	user_modes = ArgList[2];
	channel_modes = ArgList[3];
		
	if (sversion)
	{
		if (!strncmp(sversion, "2.8", 3))
		{
			if (strstr(sversion, "mu") || strstr(sversion, "me"))
				set_server_version(from_server, Server_u2_8);
			else if (strstr(sversion, "hybrid-6"))
				set_server_version(from_server, Server2_8hybrid6);
			else if (strstr(sversion, "hybrid"))
				set_server_version(from_server, Server2_8hybrid);
			else if (strstr(sversion, "comstud"))
				set_server_version(from_server, Server2_8comstud);
			else if (strstr(channel_modes, "che"))
				set_server_version(from_server, Server2_8ts4); 
			else
				set_server_version(from_server, Server2_8);
		}
		else if (!strncmp(sversion, "2.9", 3))
		        set_server_version(from_server, Server2_9);
		else if (!strncmp(sversion, "2.10", 4))
	        	set_server_version(from_server, Server2_10);
		else if (!strncmp(sversion, "u2.9", 4))
			set_server_version(from_server, Server_u2_9);
		else if (!strncmp(sversion, "u2.10", 4))
			set_server_version(from_server, Server_u2_10);
		else if (!strncmp(sversion, "u3.0", 4))
			set_server_version(from_server, Server_u3_0);
		else
			set_server_version(from_server, Server2_8);
	} else
		set_server_version(from_server, Server2_8);

	set_server_version_string(from_server, sversion ? sversion : "2.8");
	set_server_itsname(from_server, server);
	reconnect_all_channels(from_server);

	reset_display_target();
	reinstate_user_modes();
	if (use_nat_address == 1)
		userhostbase(get_server_nickname(from_server), get_nat_address, 1, "%s", get_server_nickname(from_server));
	update_all_status(current_window, NULL, 0);
	do_hook(CONNECT_LIST, "%s %d %s", get_server_name(from_server), get_server_port(from_server), get_server_itsname(from_server));
}
Beispiel #10
0
char *ov_server(int server)
{
	char *c;
	char *d;
	static char tmpstr[61];
	char *string = get_server_itsname(server);
	    
	if (!string || !*string)
		string = get_server_name(server);
	if (!string || !*string)
		return  empty_string;
	strmcpy(tmpstr, string, 60);
	if (!(c = strrchr(tmpstr,'.')))
		return(string);
	*c = 0;
	if (!(d = strrchr(tmpstr, '.'))) 
		d = ++c; /* Extract domain */
	d++;
	return(d);
}
Beispiel #11
0
static int
ssl_open(const char *name, char *suffix, struct stream **streamp, uint8_t dscp)
{
    int error, fd;

    error = ssl_init();
    if (error) {
        return error;
    }

    error = inet_open_active(SOCK_STREAM, suffix, OFP_PORT, NULL, &fd,
                             dscp);
    if (fd >= 0) {
        int state = error ? STATE_TCP_CONNECTING : STATE_SSL_CONNECTING;
        return new_ssl_stream(xstrdup(name), get_server_name(suffix),
                              fd, CLIENT, state, streamp);
    } else {
        VLOG_ERR("%s: connect: %s", name, ovs_strerror(error));
        return error;
    }
}
Beispiel #12
0
static void p_kill(char *from, char **ArgList)
{
    char sc[20];
    int port;
    int local = 0;

    port = get_server_port(from_server);
    if (ArgList[1] && strstr(ArgList[1], get_server_name(from_server)))
	if (!strchr(from, '.'))
	    local = 1;
    snprintf(sc, 19, "+%i %d", from_server, port);

    close_server(from_server, empty_str);
    clean_whois_queue();
    window_check_servers();
    set_input_prompt(curr_scr_win, get_string_var(INPUT_PROMPT_VAR), 0);

    if (strchr(from, '.')) {
	say("Server [%s] has rejected you (probably due to a nick collision)", from);
	t_parse_command("SERVER", NULL);
    } else {
	if (local && get_int_var(NEXT_SERVER_ON_LOCAL_KILL_VAR)) {
	    int i = from_server + 1;

	    if (i >= number_of_servers)
		i = 0;
	    snprintf(sc, 19, "+%i", i);
	    from_server = -1;
	}
	if (do_hook(DISCONNECT_LIST, "Killed by %s (%s)", from, ArgList[1] ? ArgList[1] : "(No Reason Given)"))
	    put_it("%s",
		   convert_output_format(get_format(FORMAT_KILL_FSET), "%s %s", update_clock(GET_TIME),
					 ArgList[1] ? ArgList[1] : "You have been Killed"));
	if (get_int_var(AUTO_RECONNECT_VAR))
	    t_parse_command("SERVER", NULL);
    }
    update_all_status(curr_scr_win, NULL, 0);
}
Beispiel #13
0
static void p_pong(char *from, char **ArgList)
{
    int is_server = 0;
    int i;

    if (!ArgList[0])
	return;
    is_server = match("*.*", ArgList[0]);
    if (in_server_ping && is_server) ;
    {
	int old_from_server = from_server;

	for (i = 0; i < number_of_servers; i++) {
	    if ((!my_stricmp(ArgList[0], get_server_name(i)) || !my_stricmp(ArgList[0], get_server_itsname(i)))
		&& is_server_connected(i)) {
		int old_lag = server_list[i].lag;

		from_server = i;
		server_list[i].lag = time(NULL) - server_list[i].lag_time;
		in_server_ping--;
		if (old_lag != server_list[i].lag)
		    status_update(1);
		from_server = old_from_server;
		return;
	    }
	}
	from_server = old_from_server;
    }
    if (check_ignore(from, FromUserHost, NULL, IGNORE_PONGS | IGNORE_CRAP, NULL) != IGNORED) {
	if (!is_server)
	    return;
	if (!ArgList[1])
	    say("%s: PONG received from %s", ArgList[0], from);
	else
	    say("%s: PING received from %s %s", ArgList[0], from, ArgList[1]);
    }
}
Beispiel #14
0
/* new_request_stat()
 *
 * Register statistics about client requests. Returns the newly generated
 * and unique id.
 * */
int
new_request_stat			(unsigned long ip_num, const char * type, char * user_agent)
{
    int i, auto_id, client_id_len, child_id;
    char * query, * server_id, * client_id, * tmp_id;
    unsigned char * uchar_sign;
    GeoIPRecord * record;
    MYSQL_RES * result;
    MYSQL_ROW row;
    char * add_info;
	
    /* TODO: browser and opsys detection. */
    const char browser [] = UNKNOWN_FIELD;
    const char opsys [] = UNKNOWN_FIELD;
	
    /* Check if statistic data gathering is enabled. */
    if (stats_enabled != 1)
    {
	return (EXIT_SUCCESS);
    }

    child_id = get_child_pos();
    server_id = (char *)get_server_name();
	
    /* Calculate unique digest. */
    uchar_sign = malloc(SHA_DIGEST_LENGTH);
    client_id = malloc(SIGN_LEN + 1);
    client_id_len = asprintf(&tmp_id, "%lu", ip_num);
    SHA1((unsigned char *)tmp_id, client_id_len, uchar_sign);
    free(tmp_id);
	
    for (i = 0; i < SHA_DIGEST_LENGTH; i++)
    {
	sprintf(client_id + i * 2, "%02x", uchar_sign[i]);
    }

    free(uchar_sign);
	
    if ((record = GeoIP_record_by_ipnum(gi_db, ip_num)) != NULL)
    {
	asprintf(&query, "INSERT INTO requests (%s) VALUES ('%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', CURRENT_TIMESTAMP())",
		 REQUEST_FIELDS, client_id, server_id, child_id, type, browser, opsys, record->city, record->country_name);
	GeoIPRecord_delete(record);
    }
    else
    {
	asprintf(&query, "INSERT INTO requests (%s) VALUES ('%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', CURRENT_TIMESTAMP())",
		 REQUEST_FIELDS, client_id, server_id, child_id, type, browser, opsys, UNKNOWN_FIELD, UNKNOWN_FIELD);
    }
	
    /* MySQL threaded interaction.
     * Multithread clients sharing the same connection *must* enclose
     * mysql_query() and mysql_store_result() in a lock to prevent access
     * from other threads.
     * */
	
    /* Insert data and get the last autoincremented value. */
    pthread_mutex_lock(&stat_lock);
    if (mysql_query(db_conn, query) != 0)
    {
	pthread_mutex_unlock(&stat_lock);
	log_message(ERROR, EMSG_INSERT, query);
	free(client_id);
	free(server_id);
	free(query);
	return (ECOD_INSERT);
    }

    pthread_mutex_unlock(&stat_lock);
    free(client_id);
    free(query);
    asprintf(&query, "SELECT MAX(id) FROM requests WHERE server_id = '%s' AND child_id = %d", server_id, child_id);
    free(server_id);
	
    pthread_mutex_lock(&stat_lock);
    if (mysql_query(db_conn, query) != 0)
    {
	pthread_mutex_unlock(&stat_lock);
	log_message(ERROR, EMSG_SELECT, query);
	free(query);
	return (ECOD_SELECT);
    }
	
    if ((result = mysql_store_result(db_conn)) != NULL)
    {
	pthread_mutex_unlock(&stat_lock);
	free(query);
	row = mysql_fetch_row(result);
	auto_id = atoi(row[0]);
	mysql_free_result(result);
	asprintf(&add_info, "Request ID: %d\n", auto_id);
	log_message(MESSAGE, IMSG_NEWREQSTAT, add_info);
	free(add_info);
    }
    else
    {
	pthread_mutex_unlock(&stat_lock);
	log_message(ERROR, EMSG_SELECT, query);
	free(query);
	return (ECOD_SELECT);
    }

    return (auto_id);
}
Beispiel #15
0
void gossip_thread_server(char *LOGFILE, void (*event_loop)(EXTENDED_CLIENT_SLOT *), int TIMEOUT, void *data)
{
  /* the first child is the actual server */
  
  int fclient;
  char *buf;
  int buflen;

  char *Auth_token = get_broker_Authorization();
  /* int chgbuflen = FALSE; */
  unsigned int Bauth_token = 0;

  int fserver;
  int server_port;
  int ipaddr;
  int b0, b1, b2, b3;
  int myuid = getuid();
  int client_uid, client_pid, client_auth;
  int PING_INTERVAL;
  
  unsigned char buffer[16];
  
  fd_set rfds;
  struct timeval tv = {0};


  /*   the second child will act as a watchdog and PINGs its parent periodically */
  /*   it will exit when parent has exited and therefore no longer accepts connections */
  
  /* miscellaneous initializations + get Authorization token */
  
  set_timeout_counter( TIMEOUT/get_ping_interval() ); /* set ping number */
  PING_INTERVAL = get_ping_interval();                /* get ping interval */
  
  if(Auth_token == NULL) 
    {
      fprintf(stderr, "Authorization token failure \n");
      exit(1);
    }

  sscanf( Auth_token, "%u", &Bauth_token );
  
  /*   get a socket */
  fserver = get_sock_net();
   
  /*   set buffer sizes for socket */
  set_sock_opt( fserver );
  
  /*   bind to a free port, get port number */
  server_port = bind_sock_to_port( fserver );
  
  /*   parent writes host:port and exits after disconnecting stdin, stdout, and stderr */
  ipaddr = get_own_ip_address();  /* get own IP address as 32 bit integer */

  b0 = ipaddr >> 24; /* split IP address */
  b1 = ipaddr >> 16;
  b2 = ipaddr >> 8;
  b3 = ipaddr;
  b0 &= 255;
  b1 &= 255;
  b2 &= 255;
  b3 &= 255;

  buf = (char *)malloc(1024);
  /* host_name = (char *)malloc(128); */

  if ( !buf )
    {
      fprintf(stderr, "channel buffer is NULL !!!, exiting\n");
      exit(1);
    }
 
  snprintf(buf, 1023, "%d.%d.%d.%d:%d", b0, b1, b2, b3, server_port);
  
  /* fprintf(stderr, "Launching Server at host : \"%s\" \n",  buf); */
  
  set_host_and_port(LOGFILE, buf);  /* write to channel info file */
                                    /* write as A.B.C.D:port */
    
  fprintf(stderr, "Launching Server at host: \"%s\" using port: \"%d\"\n", get_server_name(buf), server_port );
  
  sprintf(buf, "%s.LOG", LOGFILE);
  
  fclose(stdout); /* close and reopen STDOUT  */
  fclose(stderr); /* close and reopen STDERR */
  
  freopen(buf, "w", stdout);  
  freopen(buf, "w", stderr);
  
  if( fork() > 0 ) 
    {
      fprintf(stderr, "Exiting from parent process !!!\n");
      exit(0);  /* parent exits now */
    }
  
  setpgrp(); /* get into another process group */
  
  /* set NO BUFFERING for STDOUT and STDERR */
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);

  client_auth = 0;
  client_pid = 0;
  client_uid = 0;
  
    
  listen(fserver, 32767);

  /* #ifdef NEVERTRUE */

  /* pinging part */
  if( (ping_pid = fork()) == 0 )
    {
      int watchdog_client;
      int ping_ord = 0;
      char *pingbuf;

      pingbuf = (char *)malloc(128);
      close(fserver);
            
      sleep(PING_INTERVAL);
      
      while(watchdog_client = connect_to_localport(server_port))
	{
	  /* send PING command with ping counter */

	  sprintf(pingbuf, "PING %d", ping_ord++);
	
	  if(watchdog_client > 0)
	    {
	      write(watchdog_client, pingbuf, strlen(pingbuf));
	      close(watchdog_client);
	    }
	  else
	    {
	      fprintf(stderr, "End of Pinging Time, Server not responding !!!\n");
	      exit(0);
	    }
	  sleep(PING_INTERVAL);
	  
	}
      

      if(pingbuf != NULL)
	free(pingbuf);

      exit(0);
    }
  else if (ping_pid < 0)
    {
      fprintf(stderr, "Error: cannot fork server process, pid = %d\n", ping_pid);
    }
  /* #endif */


  /* fd_set rfds; */
  /* struct timeval tv; */

  tv.tv_sec = 5;
  tv.tv_usec = 0;
 
  /* back to first child, loop on connection requests */
  while( fclient = accept_from_sock(fserver) )
    {
      /* timeout */

      FD_ZERO(&rfds);
      FD_SET(fclient, &rfds);

      if (select(fclient+1, &rfds, NULL, NULL, &tv))
	{
	  buflen = read(fclient, buf, NCARMAX); /* get LOGIN command */
	  
	}
      else
	{
	  exit(1);
	}
     
      buf[buflen > 0 ? buflen : 0] = '\0';
      
      if(get_active_channels() <= 0 && exit_flag)
	{
	  fprintf(stderr, "Exiting from server, active channels: %d\n", get_active_channels());
	  store_all_channels_data();
	  close(fclient);
	  fprintf(stderr, "Server EXITING !\n");
	  
	  if(ping_pid > 0)
	    { 
	      kill(ping_pid, 9);
	    }
	  
	  exit(1);
	}

      if(strncmp(buf, "PING", 4) == 0) /* PING ? */
	{
	  /* echo to logfile */
	  fprintf(stderr, "Server: PING %d (%d)\n",                                                                              TIMEOUT/get_ping_interval() - get_timeout_counter(),                                                  get_timeout_counter());
	  close(fclient);
	  if(get_timeout_counter() <= 0 || ( ( get_active_channels() <= 0) && exit_flag ) )
	    {
	      /* Before exiting save any pending data buffer(s) 
		 to corresponding subchannel file(s) */
	      store_all_channels_data();

	      /**********NEW*********/
	      /* if(get_last_channel()) */
	      /**********NEW*********/
	      fprintf(stderr, "TIMEOUT detected, EXITING \n");
	      
	      if(ping_pid > 0)
		{ 
		  kill(ping_pid, 9);
		}

	      exit(1);
	    }

	  decrement_timeout_counter();
	  continue;    /* go service next connection request */
	}
      
      /* validate login command, check client uid against server uid,
       verify that authorization token is the right one,
       register client pid as connected if connection accepted */
      



      if(strncmp(buf, "LOGIN", 5) == 0) 
	{
	  client_uid = -1 ;
	  client_pid = -1 ;
	  

	  /* sscanf(buf, "LOGIN %d %d %u", &client_uid, &client_pid, &client_auth); */
	  sscanf(buf, "LOGIN %d %d %u", &client_uid, &client_pid, &client_auth);

	  
	  /* reject connection if not my uid 
	     or bad authorization token or not
	     a LOGIN command */

	  if( client_uid != myuid || md5_ssh( buffer ) )
	    { 
	      printf("Client Authentication FAILED\n");
	      continue;
	    }


	  else /*  LOGIN accepted, process next command  */
	    {
	      send_ack_nack(fclient, IS_OK); /* Positive ACK, LOGIN  accepted  */
	      /* printf("SSH Digest: %x\n", buffer); */  
    
	      /*  start a new thread to handle user request  */
	      start_client_thread_2((void *)&user_server, client_uid, client_pid, fclient, buf, data , (void *)event_loop);

	      continue;
	    }
	}

      else
	{
	  fprintf(stderr, "LOGIN command expected: %s\n", buf);
	  send_ack_nack(fclient, NOT_OK);  /*  Negative ACK, LOGIN rejected  */
	}
      
    } /* end while accept is successful */

  printf("Accept from socket failed, exiting !!!, fserver = %d\n", fserver);

  if(ping_pid > 0)
    {
      kill(ping_pid, 9);
    }

  if(buf)
    free(buf);
  
  exit(1);
}
Beispiel #16
0
/*
 * This parses NOTICEs that are sent from that wacky ircd we are connected
 * to, and 'to' is guaranteed not to be a channel.
 */
static 	void 	parse_local_server_notice (const char *from, const char *to, const char *line)
{
	int	lastlog_level;
	const char *	f;

	f = from;
	if (!f || !*f)
		if (!(f = get_server_itsname(from_server)))
			f = get_server_name(from_server);

	/* OPERator Notices */
	if (!strncmp(line, "*** Notice -- ", 13))
	{
		if (!strncmp(line + 14, "Received KILL message for ", 26))
			if (kill_message(f, line + 40))
				return;

		message_from(to, LOG_OPNOTE);
		lastlog_level = set_lastlog_msg_level(LOG_OPNOTE);
		if (!do_hook(OPER_NOTICE_LIST, "%s %s", f, line + 14))
			return;
	}

	/* NOTEs */
	else if (!strncmp(line, "Note", 4))
	{
		char *note_from = NULL;
		char *point = NULL;

		if (strlen(line) > 10)
		{
			/* Skip the "Note From" part */
			note_from = LOCAL_COPY(line + 10); 

			if ((point = strchr(note_from, '!')))
			{
				*point++ = 0;
				FromUserHost = line;
				if ((point = strchr(FromUserHost, ' ')))
				{
					*point++ = 0;
					parse_note(note_from, point);
				}
				FromUserHost = empty_string;
			}
		}
		return;
	}

	lastlog_level = set_lastlog_msg_level(LOG_SNOTE);
	message_from(to, LOG_SNOTE);

	/* Check to see if the notice already has its own header... */
	if (do_hook(GENERAL_NOTICE_LIST, "%s %s %s", f, to, line))
	{
	    if (*line == '*' || *line == '#')
	    {
		if (do_hook(SERVER_NOTICE_LIST, "%s %s", f, line))
			put_it("%s", line);
	    }
	    else
		if (do_hook(SERVER_NOTICE_LIST, "%s *** %s", f, line))
			say("%s", line);
	}

	if (lastlog_level)
		message_from(NULL, lastlog_level);
}
Beispiel #17
0
void check_serverlag(int server)
{
	int i;
	struct timeval tv;
	int ofs = from_server;
	get_time(&tv);
	if (server == -1)
	{
		for (i = 0; i < server_list_size(); i++)
		{
			if (is_connected(i) && !get_server_sping(i))
			{
				from_server = i;
				if (!get_server_ircmode(i) && (get_server_admin(i) > USER_USER))
				{
					send_ncommand(CMDS_SPING, "%s LAG %lu %lu", get_server_itsname(i) ? get_server_itsname(i):get_server_name(i), tv.tv_sec, tv.tv_usec);
					set_server_sping(i, 1);
				}
			}
		}
		from_server = ofs;
		return;
	}
	if (is_connected(server) && !get_server_sping(server) && (get_server_admin(server) > USER_USER))
	{
		if (!get_server_ircmode(server))
		{
			send_ncommand(CMDS_SPING, "%s LAG %lu %lu", get_server_itsname(server) ? get_server_itsname(server) : get_server_name(server), tv.tv_sec, tv.tv_usec);
			set_server_sping(server, 1);
		}
	}
}
Beispiel #18
0
/*
 * The main handler for those wacky NOTICE commands...
 * This is as much like p_privmsg as i can get away with.
 */
void 	p_notice (const char *from, const char *comm, const char **ArgList)
{
	const char 	*target, *message;
	int		level,
			hook_type;
	const char *	flood_channel = NULL;
	char *		high;

	PasteArgs(ArgList, 1);
	if (!(target = ArgList[0]))
		{ rfc1459_odd(from, comm, ArgList); return; }
	if (!(message = ArgList[1]))
		{ rfc1459_odd(from, comm, ArgList); return; }

	set_server_doing_notice(from_server, 1);
	sed = 0;

	/* Do normal /CTCP reply handling */
	/* XXX -- Casting "message" to (char *) is cheating. */
	message = do_notice_ctcp(from, target, (char *)
#ifdef HAVE_INTPTR_T
							(intptr_t)
#endif
								message);
	if (!*message) {
		set_server_doing_notice(from_server, 0);
		return;
	}

	/* Check to see if it is a "Server Notice" */
	if ((!from || !*from) || !strcmp(get_server_itsname(from_server), from))
	{
		parse_local_server_notice(from, target, message);
		set_server_doing_notice(from_server, 0);
		return;
	}
	/* For pesky prefix-less NOTICEs substitute the server's name */
	if (!from || !*from)
		from = get_server_name(from_server);

	/*
	 * Note that NOTICEs from servers are not "server notices" unless
	 * the target is not a channel (ie, it is sent to us).  Any notice
	 * that is sent to a channel is a normal NOTICE, notwithstanding
	 * _who_ sent it.
	 */
	if (is_channel(target) && im_on_channel(target, from_server))
	{
		flood_channel = target;
		hook_type = PUBLIC_NOTICE_LIST;
	}
	else if (!is_me(from_server, target))
	{
		flood_channel = NULL;
		hook_type = NOTICE_LIST;
	}
	else
	{
		flood_channel = NULL;
		hook_type = NOTICE_LIST;
		target = from;
	}

	/* Check for /ignore's */
	switch (check_ignore_channel(from, FromUserHost, target, IGNORE_NOTICES))
	{
		case IGNORED:
			set_server_doing_notice(from_server, 0);
			return;
		case HIGHLIGHTED:
			high = highlight_char;
			break; /* oops! */
		default:
			high = empty_string;
	}

	/* Let the user know if it is an encrypted notice */
	/* Note that this is always hooked, even during a flood */
	if (sed)
	{
		int	do_return = 1;

		sed = 0;
		level = set_lastlog_msg_level(LOG_NOTICE);
		message_from(target, LOG_NOTICE);

		if (do_hook(ENCRYPTED_NOTICE_LIST, "%s %s %s", 
				from, target, message))
			do_return = 0;

		set_lastlog_msg_level(level);
		message_from(NULL, LOG_CRAP);

		if (do_return) {
			set_server_doing_notice(from_server, 0);
			return;
		}
	}

	if (new_check_flooding(from, FromUserHost, flood_channel, 
					message, NOTICE_FLOOD)) {
		set_server_doing_notice(from_server, 0);
		return;
	}


	/* Beep the user if they asked us to */
	if (beep_on_level & LOG_NOTICE)
		beep_em(1);

	/* Go ahead and throw it to the user */
	level = set_lastlog_msg_level(LOG_NOTICE);
	message_from(target, LOG_NOTICE);

	if (do_hook(GENERAL_NOTICE_LIST, "%s %s %s", from, target, message))
	{
	    if (hook_type == NOTICE_LIST)
	    {
		if (do_hook(hook_type, "%s %s", from, message))
			put_it("%s-%s-%s %s", high, from, high, message);
	    }
	    else
	    {
		if (do_hook(hook_type, "%s %s %s", from, target, message))
			put_it("%s-%s:%s-%s %s", high, from, target, high, 
							message);
	    }
	}

	/* Clean up and go home. */
	set_lastlog_msg_level(level);
	message_from(NULL, LOG_CRAP);
	set_server_doing_notice(from_server, 0);

	/* Alas, this is not protected by protocol enforcement. :( */
	notify_mark(from_server, from, 1, 0);
}
Beispiel #19
0
/*
 * got_initial_version_28: this is called when ircii gets the serial
 * number 004 reply.  We do this becuase the 004 numeric gives us the
 * server name and version in an easy to use fashion, and doesnt
 * rely on the syntax or construction of the 002 numeric.
 *
 * Hacked as neccesary by jfn, May 1995
 */
void 	got_initial_version_28 (const char *server, const char *version, const char *umodes)
{
	/* Worthless 004 reply.  Hope for the best! */
	if (!server || !version || !umodes)
	{
		set_server_version(from_server, Server2_8);
		set_server_version_string(from_server, "<none provided>");
		set_server_itsname(from_server, get_server_name(from_server));
	}
	else
	{
		if (!strncmp(version, "2.8", 3))
		{
			if (strstr(version, "mu") || strstr(version, "me"))
				set_server_version(from_server, Server_u2_8);
			else
				set_server_version(from_server, Server2_8);
		}
		else if (!strncmp(version, "2.9", 3))
			set_server_version(from_server, Server2_9);
		else if (!strncmp(version, "2.10", 4))
			set_server_version(from_server, Server2_10);
		else if (!strncmp(version, "u2.9", 4))
			set_server_version(from_server, Server_u2_9);
		else if (!strncmp(version, "u2.10", 4))
			set_server_version(from_server, Server_u2_10);
		else if (!strncmp(version, "u3.0", 4))
			set_server_version(from_server, Server_u3_0);
		else
			set_server_version(from_server, Server2_8);

		set_server_version_string(from_server, version);
		set_server_itsname(from_server, server);
		set_possible_umodes(from_server, umodes);
	}

	reconnect_all_channels();
	server_did_rejoin_channels(from_server);
	message_from(NULL, LOG_CRAP);
	reinstate_user_modes();

	if (never_connected)
	{
		never_connected = 0;
		permit_status_update(1);

		if (!ircrc_loaded)
			load_ircrc();

		if (default_channel)
		{
			e_channel("JOIN", default_channel, empty_string);
			new_free(&default_channel);
		}
	}
	else if (get_server_away(from_server))
		set_server_away(from_server, get_server_away(from_server));

	update_all_status();
	do_hook(CONNECT_LIST, "%s %d %s", get_server_name(from_server),
		get_server_port(from_server), get_server_itsname(from_server));
	window_check_channels();
}
Beispiel #20
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	*target;
	char	*copy;
	int	i;
	int	lastlog_level;
	int	old_current_numeric = current_numeric;
	int	numeric;

	/* All numerics must have a target (our nickname) */
	if (!comm || !*comm)
		{ rfc1459_odd(from, comm, ArgList); return; }
	numeric = atol(comm);
	if (numeric < 0 || numeric > 999)
		{ rfc1459_odd(from, comm, ArgList); return; }

	if (!(target = ArgList[0]))
		{ rfc1459_odd(from, comm, ArgList); return; }
	ArgList++;

	lastlog_level = set_lastlog_msg_level(LOG_CRAP);
	if (ArgList[0] && is_channel(ArgList[0]))
		message_from(ArgList[0], LOG_CRAP);
	else
		message_from(NULL, LOG_CRAP);

	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 */
	{
		Timeval i;

                i.tv_sec = 0;
                i.tv_usec = 50000;
                select(0, NULL, NULL, NULL, &i);

		accept_server_nickname(from_server, target);
		server_is_registered(from_server, 1);
		userhostbase(from_server, NULL, got_my_userhost, 1);
		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, 
				*umodes = NULL;

		/* The 004 numeric is too import to "odd server stuff" over. */
		/* So if the reply is useless, we'll just wing it */
		if (!(server = ArgList[0]))
			server = version = umodes = NULL;
		else if (!(version = ArgList[1]))
			server = version = umodes = NULL;
		else if (!(umodes = ArgList[2]))
			server = version = umodes = NULL;
		else
		{
		  /* Work around ratbox-1.2-3. */
		  if (!my_stricmp(umodes, "(brown"))
		   if (ArgList[3] && !my_stricmp(ArgList[3], "paper"))
		    if (ArgList[4] && !my_stricmp(ArgList[4], "bag"))
		     if (ArgList[5] && !my_stricmp(ArgList[5], "release)"))
		     {
			if (!(umodes = ArgList[6]))
				{ rfc1459_odd(from, comm, ArgList); goto END; }
		     }
		}

		got_initial_version_28(server, version, umodes);
		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);
			}
			else 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;

		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 = atol(ArgList[1]);

		/* Must do these things before calling "display_msg" */
		old_server = from_server;
		add_to_server_list(new_server, new_port, NULL, NULL,
				get_server_group(from_server), NULL, 0);
		server_reconnects_to(old_server, from_server);
		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;
		const char *	message;

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

		set_server_unique_id(from_server, unique_id);
		if (do_hook(current_numeric, "%s %s %s", 
					from, unique_id, message))
			goto DISPLAY;
		goto END;
	}

        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))
			goto DISPLAY;
		goto END;
        }

	case 340:		/* #define RPL_USERIP           307 */
		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);

		/*
		 * 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();

		    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);
#if 0
		    goto END;
#endif
		}

		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);
		    }

		    message_from(channel, LOG_CRAP);
		    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 (!get_int_var(SHOW_END_OF_MSGS_VAR))
			goto END;

		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);
		    if (get_int_var(AUTO_WHOWAS_VAR))
		    {
			int foo = get_int_var(NUM_OF_WHOWAS_VAR);

			if (foo > -1)
				send_to_server("WHOWAS %s %d", nick, foo);
			else
				send_to_server("WHOWAS %s", nick);
		    }
		}

		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 432:		/* #define ERR_ERRONEUSNICKNAME 432 */
	{
		const char	*nick;

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

		if (!my_stricmp(target, nick))
			yell("WARNING:  Strange invalid nick message received."
					"  You are probably lagged.");
		else if (get_int_var(AUTO_NEW_NICK_VAR))
			fudge_nickname(from_server);
		else
			reset_nickname(from_server);

		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, target);
			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, a nick command failed.  Oh boy.
		 * If we are registered, abort the nick change and
		 * hope for the best.
		 */
		if (is_server_registered(from_server))
		{
			accept_server_nickname(from_server, target);
			break;
		}

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

	case 433:		/* #define ERR_NICKNAMEINUSE    433 */ 
	case 438:		/* EFnet/TS4 "nick collision" numeric 438 */
	case 453:		/* EFnet/TS4 "nickname lost" numeric 453 */
	{
		const char	*nick;

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

		if (!my_stricmp(target, nick))
			/* 
			 * This should stop the "rolling nicks" in their tracks.
			 */
			yell("WARNING:  Strange invalid nick message received."
					"  You are probably lagged.");
		else if (get_int_var(AUTO_NEW_NICK_VAR))
			fudge_nickname(from_server);
		else
			reset_nickname(from_server);

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

		break;
	}

	case 439:		/* Comstud's "Can't change nickname" */
	{
		accept_server_nickname(from_server, target);
		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 465:		/* #define ERR_YOUREBANNEDCREEP 465 */
	{
		/* 
		 * There used to be a say() here, but if we arent 
		 * connected to a server, then doing say() is not
		 * a good idea.  So now it just doesnt do anything.
		 */
		server_reconnects_to(from_server, NOSERV);
		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 */
	/*
	 * 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);
		if (get_int_var(SHOW_END_OF_MSGS_VAR))
			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 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; }

		message_from(channel, LOG_CRAP);
		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]))
			{ rfc1459_odd(from, comm, ArgList); goto END; }
		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 */
			message_from(channel, LOG_CRAP);
			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);

		message_from(channel, LOG_CRAP);
		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 (!get_int_var(SHOW_END_OF_MSGS_VAR))
			break;

		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:		/* +I on erf */
	case 348:		/* +e on erf */
	case 367:		/* +b */
	{
		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);
		if (get_int_var(SHOW_END_OF_MSGS_VAR))
			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 */
	{
		char	server_num[8];

		if (oper_command)
			oper_command = 0;
		else if (!is_server_registered(from_server))
		{
			server_reconnects_to(from_server, NOSERV);
			say("Password required for connection to server %s",
				get_server_name(from_server));
			if (!dumb_mode)
			{
				strlcpy(server_num, ltoa(from_server), sizeof server_num);
				add_wait_prompt("Server Password:", 
					password_sendline,
				       server_num, WAIT_PROMPT_LINE, 0);
			}
		}
	}
	}

	current_numeric = old_current_numeric;
	set_lastlog_msg_level(lastlog_level);
	message_from(NULL, LOG_CRAP);
}
Beispiel #21
0
int mysql_select(eng_ctx_t* eng_ctx) {
    int ret = 0;

    MYSQL* wmysql;
    MYSQL* rmysql;       

    MYSQL_RES* wmysql_result;  
    MYSQL_RES* rmysql_result;
   
    MYSQL_ROW wrow;
    MYSQL_ROW rrow;
    int wnum_fields;
    int rnum_fields;
    int wnum_rows;
    int rnum_rows;

    size_t* wlengths;
    size_t* rlengths;

    wmysql = get_server_mysql(eng_ctx->write_server); 
    ret = mysql_select_db(wmysql, database);
    if (ret != 0) {
        return ret;
    }

    sql_gen(eng_ctx, SELECT);
    my_assert(eng_ctx->sql);
    
    const char* sql = eng_ctx->sql;
    
    // get pre data value from write server
    ret = mysql_real_query(wmysql, sql, strlen(sql));
    if (ret != 0) {
        log_debug("%s", mysql_error(wmysql));
        return ret;
    }

    eng_ctx->stats.nselect++;       
    g_stat.nselect = __sync_add_and_fetch(&g_stat.nselect, 1);

    wmysql_result = mysql_store_result(wmysql);
    wnum_fields   = mysql_num_fields(wmysql_result);
    wnum_rows     = mysql_num_rows(wmysql_result);
    wrow          = mysql_fetch_row(wmysql_result);
    wlengths      = mysql_fetch_lengths(wmysql_result);

    if (0 == wnum_rows) {
        mysql_free_result(wmysql_result);
        return 1;       // this obj do not exist in mysql
    }

    // get data from other nodes    
    for (int i = 0; i < eng_ctx->nread_server; i++) {
        rmysql = get_server_mysql(eng_ctx->read_servers[i]);       
        ret = mysql_select_db(rmysql, database);

        if (ret != 0) {
            log_warn("can not connect to server:%s, db:%s", 
                get_server_name(eng_ctx->read_servers[i]), database);
            continue;
        }

        ret = mysql_real_query(rmysql, sql, strlen(sql));
        if (ret != 0) {
            log_debug("%s", mysql_error(rmysql));
            continue;
        }

        set_sql_read_time(eng_ctx);
        eng_ctx->stats.nselect++;       
        g_stat.nselect = __sync_add_and_fetch(&g_stat.nselect, 1);

        rmysql_result = mysql_store_result(rmysql);
        rnum_fields   = mysql_num_fields(rmysql_result);
        rnum_rows     = mysql_num_rows(rmysql_result);
        rrow          = mysql_fetch_row(rmysql_result);
        rlengths      = mysql_fetch_lengths(rmysql_result);

        if (rnum_rows > 0) {
            for (int j = 0; j < wnum_fields; j++) {
                if (strncmp(wrow[j], rrow[j], wlengths[j]) != 0) {

#ifdef READABLE_DATA_LOG
                    char* logbuf_offset = eng_ctx->data_inconsist_log_buf; 
                    
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Check ERROR !!!\n");
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Command: %s ", cmdtype_toString(eng_ctx->prev_cmd));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Host: %15s ", get_server_name(eng_ctx->write_server));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Table: %s ", get_table_name(eng_ctx->table));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Key: %.*s ", 20, wrow[0]);
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Value: %.*s ...\n", 8, wrow[1]);

                    logbuf_offset += sprintf(logbuf_offset, "Command: SELECT ");
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Host: %15s ", get_server_name(eng_ctx->read_servers[i]));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Table: %s ", get_table_name(eng_ctx->table));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Key: %.*s ", 20, rrow[0]);
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Value: %.*s ...\n\n", 8, rrow[1]);

                    *(logbuf_offset) = '\0';

                    fprintf(stderr, "%s", eng_ctx->data_inconsist_log_buf);
#else
                    /*
                    log_error("Data inconsistent detected!");
                    log_error("Write server is %s, read server is %s", 
                            get_server_name(eng_ctx->write_server), 
                            get_server_name(eng_ctx->read_servers[i]));
                    log_error("Last command is %s", 
                            cmdtype_toString(eng_ctx->prev_cmd));
                    log_error("There are %lld microseconds since last successful" 
                            "sql request", diff_sql_write_read_time(eng_ctx));

                    abort();
                    */
#endif                    
                    g_stat.ncheck_fail = __sync_add_and_fetch(&g_stat.ncheck_fail, 1);
                    abort();
                    
                }

            }
        } 
        else {
#ifdef READABLE_DATA_LOG
                    char* logbuf_offset = eng_ctx->data_inconsist_log_buf; 
                    
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Check ERROR !!!\n");
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Command: %s ", cmdtype_toString(eng_ctx->prev_cmd));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Host: %15s ", get_server_name(eng_ctx->write_server));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Table: %s ", get_table_name(eng_ctx->table));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Key: %.*s ", 20, wrow[0]);
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Value: %.*s ...\n", 8, wrow[1]);

                    logbuf_offset += sprintf(logbuf_offset, "Command: SELECT ");
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Host: %15s ", get_server_name(eng_ctx->read_servers[i]));
                    logbuf_offset += sprintf(logbuf_offset, 
                        "Table: %s ", get_table_name(eng_ctx->table));
                    logbuf_offset += sprintf(logbuf_offset, "Key: NULL ");
                    logbuf_offset += sprintf(logbuf_offset, "Value: NULL \n\n"); 

                    *(logbuf_offset) = '\0';

                    fprintf(stderr, "%s", eng_ctx->data_inconsist_log_buf);
#else                 
            /*       
            log_error("Data inconsistent detected!");
            log_error("Write server is %s, read server is %s", 
                    get_server_name(eng_ctx->write_server), 
                    get_server_name(eng_ctx->read_servers[i]));
            log_error("Last command is %s", 
                    cmdtype_toString(eng_ctx->prev_cmd));
            log_error("There are %lld microseconds since last successful" 
                    "sql request", diff_sql_write_read_time(eng_ctx));

            abort();
            */
#endif   
            g_stat.ncheck_fail = __sync_add_and_fetch(&g_stat.ncheck_fail, 1);         
            abort();
        }

        mysql_free_result(rmysql_result);
    }   
    
    mysql_free_result(wmysql_result);
    return 0;
}