Beispiel #1
0
void reregister_server_if_needed() {
        time_t current_time;

        if (last_server_register == -1 || interval_reregister == 0)
                // feature disabled
                return;

        // don't stack zombies, do minimal housework
        waitpid(-1, NULL, WNOHANG);

        current_time = get_current_time();
        if ((current_time - last_server_register)/60 >= interval_reregister) {
                l0(OUTPUT_TYPE_INFO, "Reregistering to master server");
                last_server_register = current_time;
                int pid = fork();
                if (pid < 0) {
                        l1(OUTPUT_TYPE_ERROR, "Cannot fork: %s", strerror(errno));
                        return;
                }
                if (pid == 0) {
                        // Need to register from a separate process because master server will test us
                        register_server(1);
                        _exit(EXIT_SUCCESS);
                }
        }
}
hostinfo_t *register_host(char *hostname, enum locator_servicetype_t servicetype, char *servername)
{
	xtreePos_t handle;
	hostinfo_t *itm = NULL;

	handle = xtreeFind(hitree[servicetype], hostname);
	if (handle == xtreeEnd(hitree[servicetype])) {
		itm = (hostinfo_t *)calloc(1, sizeof(hostinfo_t));

		itm->hostname = strdup(hostname);
		xtreeAdd(hitree[servicetype], itm->hostname, itm);
	}
	else {
		itm = xtreeData(hitree[servicetype], handle);
	}

	/* If we dont know this server, then we must register it. If we do, just update the host record */
	handle = xtreeFind(sitree[servicetype], servername);
	if (handle == xtreeEnd(sitree[servicetype])) {
		dbgprintf("Registering default server '%s'\n", servername);
		itm->server = register_server(servername, servicetype, 1, 1, NULL);
	}
	else {
		serverinfo_t *newserver = xtreeData(sitree[servicetype], handle);

		if (itm->server && (itm->server != newserver)) {
			errprintf("Warning: Host %s:%s moved from %s to %s\n", 
				  hostname, servicetype_names[servicetype], itm->server->servername, newserver->servername);
		}

		itm->server = newserver;
	}

	return itm;
}
Beispiel #3
0
int main(int argc, char *argv[])
{
    securityd_init();
    register_server();
    register_timeout();
    CFRunLoopRun();
    return 0;
}
static void
spawn_server(int listening_sock)
{
    int len, dev, sock, sport;
    pid_t pid;
    char *argv[16];
    char msg[256];
    char portstr[128], devstr[128], sockstr[128];

    WARN(3, "listening request from client...\n");
    sock = accept(listening_sock, NULL, NULL);
    if (sock == -1) {
        WARN(0, "accept() error\n");
        exit(1);
    }
    recvMsgBySocket(sock, msg, sizeof(msg));
    sscanf(msg, "deviceid:%d", &dev); // deviceid to be handled by the server.

    sport = unused_server_port();
    sprintf(msg, "sport:%d", sport); // server port to be connected by the client.
    sendMsgBySocket(sock, msg);

    if (sport < 0) {
        WARN(0, "spawn_server: max possible ports already in use.\n");
        close(sock);
        return;
    }

    Nserver++;
    pid = fork();
    if (pid) { // parent
        signal(SIGCHLD, signal_from_child);
        WARN(3, "spawn a server with sock: %d\n", sock);
        register_server(pid, sport);
        close(sock);
    }
    else { // child
#if RPC_ONLY
        argv[0] = "dscudasvr_rpc";
#else
        argv[0] = "dscudasvr";
#endif
        sprintf(portstr, "-p%d", sport);
        argv[1] = portstr;
        sprintf(devstr, "-d%d", dev);
        argv[2] = devstr;
        sprintf(sockstr, "-S%d", sock);
        argv[3] = sockstr;
        argv[4] = (char *)NULL;
        WARN(3, "exec %s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
        execvp(argv[0], (char **)argv);
        perror(argv[0]);
        WARN(0, "execvp() failed.\n");
        WARN(0, "%s may not be in the PATH?\n", argv[0]);
        exit(1);
    }
}
Beispiel #5
0
/***********************************************************************
 *          DllUnregisterServer (shdocvw.@)
 */
HRESULT WINAPI DllUnregisterServer(void)
{
    HRESULT hres;

    hres = register_server(FALSE);
    if(FAILED(hres))
        return hres;

    return UnRegisterTypeLib(&LIBID_SHDocVw, 1, 1, LOCALE_SYSTEM_DEFAULT, SYS_WIN32);
}
Beispiel #6
0
/***********************************************************************
 *          DllRegisterServer (MSHTML.@)
 */
HRESULT WINAPI DllRegisterServer(void)
{
    HRESULT hres;

    hres = register_server(TRUE);
    if(SUCCEEDED(hres))
        load_gecko(FALSE);

    return hres;
}
Beispiel #7
0
int main() 
{
	/*Create a listening BSD server socket*/
	serv_sock = register_server();	

	server_loop(serv_sock);

	close(serv_sock);

	return 0;
}
Beispiel #8
0
/***********************************************************************
 *          DllRegisterServer (MSHTML.@)
 */
HRESULT WINAPI DllRegisterServer(void)
{
    HRESULT hres;

    hres = __wine_register_resources( hInst, NULL );
    if(SUCCEEDED(hres))
        hres = register_server(TRUE);
    if(SUCCEEDED(hres))
        load_gecko(FALSE);

    return hres;
}
Beispiel #9
0
void process_Regist_req(net::MsgNode* msg) {
    Regist::Req* req = static_cast<Regist::Req*>(msg->msg_data_);

    int id = req->my_id();
    if ((id & GATE_SERVER) == GATE_SERVER) {
        register_server(id, (uint64_t)msg->msg_conn_);
        TRACE_LOG("收到网关服务器的注册连接,ID为%d", id);
    } else {
        TRACE_LOG("逻辑服务器不接受的服务器类型,ID为%d", id);
        net::conn_close(msg->msg_conn_);
    }
}
Beispiel #10
0
/***********************************************************************
 *          DllRegisterServer (shdocvw.@)
 */
HRESULT WINAPI DllRegisterServer(void)
{
    ITypeLib *typelib;
    HRESULT hres;

    static const WCHAR shdocvwW[] = {'s','h','d','o','c','v','w','.','d','l','l',0};

    hres = register_server(TRUE);
    if(FAILED(hres))
        return hres;

    hres = LoadTypeLibEx(shdocvwW, REGKIND_REGISTER, &typelib);
    if(FAILED(hres)) {
        ERR("Could not load typelib: %08x\n", hres);
        return hres;
    }

    ITypeLib_Release(typelib);

    return hres;
}
Beispiel #11
0
void daemonize() {
        pid_t pid, sid;
        GList * retained_fds = NULL;
        int fd;

        // Using the file descriptor number 10 is not possible because newlines are checked
        // for message termination. Retain it.
        while (1) {
                fd = open("/dev/null", 0);
                if (fd == -1) {
                        l1(OUTPUT_TYPE_ERROR, "opening /dev/null: %s", strerror(errno));
                        exit(EXIT_FAILURE);
                }
                if (fd < 10) {
                        retained_fds = g_list_append(retained_fds, GINT_TO_POINTER(fd));
                } else if (fd == 10) {
                        break;
                } else {
                        // Past 10, so close this one and break
                        close(fd);
                        break;
                }
        }
        if (retained_fds) {
                g_list_foreach(retained_fds, close_fds, NULL);
                g_list_free(retained_fds);
        }

        if (debug_mode)
                return;

        last_server_register = get_current_time();

        pid = fork();
        if (pid < 0) {
                l1(OUTPUT_TYPE_ERROR, "Cannot fork: %s", strerror(errno));
                exit(EXIT_FAILURE);
        }
        if (pid > 0) {
                // Save pid if needed
                if (pidfile != NULL) {
                        FILE* f = fopen(pidfile, "w");
                        if (f == NULL) {
                                l2(OUTPUT_TYPE_ERROR, "Cannot open pidfile '%s' for writing: %s", pidfile, strerror(errno));
                        } else {
                                char* pid_s = asprintf_("%d\n", pid);
                                if (fwrite(pid_s, 1, strlen(pid_s), f) < strlen(pid_s))
                                        l1(OUTPUT_TYPE_ERROR, "Error writing pidfile to '%s'", pidfile);
                                fclose(f);
                                free(pid_s);
                        }
                }
                // Need to register from a separate process because master server will test us
                l0(OUTPUT_TYPE_INFO, "registering server");
                register_server(0);
                exit(EXIT_SUCCESS);
        }

        // Switch to specified used if needed
        if (user_to_switch != NULL) {
                struct passwd* user = getpwnam(user_to_switch);
                if (user) {
                        setgid(user->pw_gid);
                        setuid(user->pw_uid);
                } else {
                        l2(OUTPUT_TYPE_ERROR, "Cannot switch user to %s: %s", user_to_switch, strerror(errno));
                }
        }

        // Don't stay orphan
        sid = setsid();
        if (sid < 0) {
                l1(OUTPUT_TYPE_ERROR, "Cannot setsid: %s", strerror(errno));
                exit(EXIT_FAILURE);
        }

        // Don't lock a directory
        if (chdir("/") < 0) {
                l1(OUTPUT_TYPE_ERROR, "Cannot chdir: %s", strerror(errno));
                exit(EXIT_FAILURE);
        }
        printf("Entering daemon mode.\n");

        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);

        // Using the file descriptor number 0 is not possible due to the string-oriented protocol when
        // negociating the game (since C strings cannot contain the NULL char). Retain one file descriptor.
        fd = open("/dev/null", 0);
        if (fd == -1) {
                l1(OUTPUT_TYPE_ERROR, "opening /dev/null: %s", strerror(errno));
                exit(EXIT_FAILURE);
        }

        l0(OUTPUT_TYPE_INFO, "Entered daemon mode.");
}
void handle_request(char *buf)
{
	const char *delims = "|\r\n\t ";

	switch (buf[0]) {
	  case 'S':
		/* Register server|type|weight|sticky|extras */
		{
			char *tok, *servername = NULL;
			enum locator_servicetype_t servicetype = ST_MAX;
			int serverweight = 0;
			enum locator_sticky_t sticky = LOC_ROAMING;
			char *serverextras = NULL;

			tok = strtok(buf, delims); if (tok) { tok = strtok(NULL, delims); }
			if (tok) { servername = tok; tok = strtok(NULL, delims); }
			if (tok) { servicetype = get_servicetype(tok); tok = strtok(NULL, delims); }
			if (tok) { serverweight = atoi(tok); tok = strtok(NULL, delims); }
			if (tok) { sticky = ((atoi(tok) == 1) ? LOC_STICKY : LOC_ROAMING); tok = strtok(NULL, delims); }
			if (tok) { serverextras = tok; tok = strtok(NULL, delims); }

			if (servername && (servicetype != ST_MAX)) {
				dbgprintf("Registering server '%s' handling %s (weight %d, %s)\n",
					servername, servicetype_names[servicetype], serverweight,
					(sticky == LOC_STICKY ? "sticky" : "not sticky"));
				register_server(servername, servicetype, serverweight, sticky, serverextras);
				strcpy(buf, "OK");
			}
			else strcpy(buf, "BADSYNTAX");
		}
		break;

	  case 'D': case 'U': case 'F':
		/* Down/Up/Forget server|type */
		{
			char *tok, *servername = NULL;
			enum locator_servicetype_t servicetype = ST_MAX;

			tok = strtok(buf, delims); if (tok) { tok = strtok(NULL, delims); }
			if (tok) { servername = tok; tok = strtok(NULL, delims); }
			if (tok) { servicetype = get_servicetype(tok); tok = strtok(NULL, delims); }

			if (servername && (servicetype != ST_MAX)) {
				downup_server(servername, servicetype, buf[0]);
				strcpy(buf, "OK");
			}
			else strcpy(buf, "BADSYNTAX");
		}
		break;

	  case 'H':
		/* Register host|type|server */
		{
			char *tok, *hostname = NULL, *servername = NULL;
			enum locator_servicetype_t servicetype = ST_MAX;

			tok = strtok(buf, delims); if (tok) { tok = strtok(NULL, delims); }
			if (tok) { hostname = tok; tok = strtok(NULL, delims); }
			if (tok) { servicetype = get_servicetype(tok); tok = strtok(NULL, delims); }
			if (tok) { servername = tok; tok = strtok(NULL, delims); }

			if (hostname && (servicetype != ST_MAX) && servername) {
				dbgprintf("Registering type/host %s/%s handled by server %s\n",
					  servicetype_names[servicetype], hostname, servername);
				register_host(hostname, servicetype, servername);
				strcpy(buf, "OK");
			}
			else strcpy(buf, "BADSYNTAX");
		}
		break;

	  case 'M':
		/* Rename host|type|newhostname */
		{
			char *tok, *oldhostname = NULL, *newhostname = NULL;
			enum locator_servicetype_t servicetype = ST_MAX;

			tok = strtok(buf, delims); if (tok) { tok = strtok(NULL, delims); }
			if (tok) { oldhostname = tok; tok = strtok(NULL, delims); }
			if (tok) { servicetype = get_servicetype(tok); tok = strtok(NULL, delims); }
			if (tok) { newhostname = tok; tok = strtok(NULL, delims); }

			if (oldhostname && (servicetype != ST_MAX) && newhostname) {
				dbgprintf("Renaming type/host %s/%s to %s\n",
					  servicetype_names[servicetype], oldhostname, newhostname);
				if (rename_host(oldhostname, servicetype, newhostname)) {
					strcpy(buf, "OK");
				}
				else {
					strcpy(buf, "FAILED");
				}
			}
			else strcpy(buf, "BADSYNTAX");
		}
		break;

	  case 'X':
	  case 'Q':
		/* Query type|host */
		{
			char *tok, *hostname = NULL;
			enum locator_servicetype_t servicetype = ST_MAX;
			int extquery = (buf[0] == 'X');
			serverinfo_t *res = NULL;

			tok = strtok(buf, delims); if (tok) { tok = strtok(NULL, delims); }
			if (tok) { servicetype = get_servicetype(tok); tok = strtok(NULL, delims); }
			if (tok) { hostname = tok; tok = strtok(NULL, delims); }

			if ((servicetype != ST_MAX) && hostname) {
				res = find_server_by_host(servicetype, hostname);

				if (res) {
					/* This host is fixed on a specific server ... */
					if (res->serveractualweight > 0) {
						/* ... and that server is UP */
						sprintf(buf, "!|%s", res->servername);
					}
					else {
						/* ... and the server is DOWN, so we cannot service the request */
						strcpy(buf, "?");
					}
				}
				else {
					/* Roaming or un-registered host */
					res = find_server_by_type(servicetype);
					if (res) {
						if (res->sticky == LOC_STICKY) {
							dbgprintf("Host %s/%s now fixed on server %s\n", 
								  hostname, servicetype_names[servicetype], res->servername);
							register_host(hostname, servicetype, res->servername);
						}
						sprintf(buf, "*|%s", res->servername);
					}
					else {
						strcpy(buf, "?");
					}
				}

				if (res && extquery) {
					int blen = strlen(buf);

					snprintf(buf+blen, sizeof(buf)-blen-1, "|%s", res->serverextras);
				}
			}
			else strcpy(buf, "BADSYNTAX");
		}
		break;

	  case 'p':
		/* Locator ping */
		sprintf(buf, "PONG|%s", VERSION);
		break;

	  case '@':
		/* Save state */
		save_state();
		strcpy(buf, "OK");
		break;

	  default:
		strcpy(buf, "BADREQUEST");
		break;
	}
}
Beispiel #13
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 #14
0
int zmaster_server_main(int argc, char **argv)
{
    int op;
    char *test_listen = 0;

    parent_pid = getppid();
    test_mode = 1;
    reloading = 0;
    softstopping = 0;
    ev_status = 0;
    ev_listen = 0;
    local_ev_close_do_once = 1;
    signal(SIGPIPE, SIG_IGN);

    if (!zvar_progname) {
        zvar_progname = argv[0];
    }

    zvar_config_init();
    zvar_evbase_init();

    while ((op = getopt(argc, argv, "Ml:c:o:t:dv")) > 0) {
        switch (op) {
        case 'M':
            test_mode = 0;
            break;
        case 'l':
            test_listen = optarg;
            break;
        case 'c':
            zconfig_load(zvar_config, optarg);
            break;
        case 'o':
            {
                char *key, *value;
                key = zstrdup(optarg);
                value = strchr(key, '=');
                if (value) {
                    *value++ = 0;
                }
                zconfig_add(zvar_config, key, value);
                zfree(key);
            }
            break;
        case 't':
            zvar_master_server_listen_type = optarg[0];
            break;
        case 'd':
            zlog_set_level_from_console(ZLOG_DEBUG);
            break;
        case 'v':
            zlog_set_level_from_console(ZLOG_VERBOSE);
            break;
        default:
            zfatal("parameters error");
        }
    }

    zlog_set_level(zlog_parse_level(zconfig_get_str(zvar_config, "zlog_level", "info")));

    register_server(test_listen);

    {
        char *run_user = zconfig_get_str(zvar_config, "zrun_user", 0);
        if (!ZEMPTY(run_user)) {
            if (zchroot_user(0, run_user) < 0) {
                zfatal("change user %s(%m)", run_user);
            }
        }
    }

    if (zmaster_server_before_service) {
        zmaster_server_before_service();
    }

    while (1) {
        zevbase_dispatch(zvar_evbase, 0);
        if (zmaster_server_loop) {
            zmaster_server_loop();
        }
        if (reloading) {
            local_ev_close();
            if (getppid() != parent_pid) {
                break;
            }
        }
        if (softstopping) {
            local_ev_close();
            break;
        }
    }

    local_ev_close();

    if (zmaster_server_before_exit) {
        zmaster_server_before_exit();
    }

    zevtimer_fini(&reload_timer);

    zevbase_free(zvar_evbase);

    return 0;
}
Beispiel #15
0
/***********************************************************************
 *          DllRegisterServer (msimtf.@)
 */
HRESULT WINAPI DllRegisterServer(void)
{
    return register_server(TRUE);
}
Beispiel #16
0
/***********************************************************************
 *          DllUnregisterServer (msimtf.@)
 */
HRESULT WINAPI DllUnregisterServer(void)
{
    return register_server(FALSE);
}
Beispiel #17
0
/***********************************************************************
 *          DllUnregisterServer (MSHTML.@)
 */
HRESULT WINAPI DllUnregisterServer(void)
{
    HRESULT hres = __wine_unregister_resources( hInst, NULL );
    if(SUCCEEDED(hres)) hres = register_server(FALSE);
    return hres;
}
void load_state(void)
{
	char *tmpdir;
	char *fn;
	FILE *fd;
	char buf[4096];
	char *tname, *sname, *sconfweight, *sactweight, *ssticky, *sextra, *hname;
	enum locator_servicetype_t stype;

	tmpdir = xgetenv("XYMONTMP"); if (!tmpdir) tmpdir = "/tmp";
	fn = (char *)malloc(strlen(tmpdir) + 100);

	sprintf(fn, "%s/locator.servers.chk", tmpdir);
	fd = fopen(fn, "r");
	if (fd) {
		while (fgets(buf, sizeof(buf), fd)) {
			serverinfo_t *srv;

			tname = sname = sconfweight = sactweight = ssticky = sextra = NULL;

			tname = strtok(buf, "|\n");
			if (tname) sname = strtok(NULL, "|\n");
			if (sname) sconfweight = strtok(NULL, "|\n");
			if (sconfweight) sactweight = strtok(NULL, "|\n");
			if (sactweight) ssticky = strtok(NULL, "|\n");
			if (ssticky) sextra = strtok(NULL, "\n");

			if (tname && sname && sconfweight && sactweight && ssticky) {
				enum locator_sticky_t sticky = (atoi(ssticky) == 1) ? LOC_STICKY : LOC_ROAMING;

				stype = get_servicetype(tname);
				srv = register_server(sname, stype, atoi(sconfweight), sticky, sextra);
				srv->serveractualweight = atoi(sactweight);
				dbgprintf("Loaded server %s/%s (cweight %d, aweight %d, %s)\n",
					srv->servername, tname, srv->serverconfweight, srv->serveractualweight,
					(srv->sticky ? "sticky" : "not sticky"));
			}
		}
		fclose(fd);
	}

	for (stype = 0; (stype < ST_MAX); stype++) recalc_current(stype);

	sprintf(fn, "%s/locator.hosts.chk", tmpdir);
	fd = fopen(fn, "r");
	if (fd) {
		while (fgets(buf, sizeof(buf), fd)) {
			tname = hname = sname = NULL;

			tname = strtok(buf, "|\n");
			if (tname) hname = strtok(NULL, "|\n");
			if (hname) sname = strtok(NULL, "|\n");

			if (tname && hname && sname) {
				enum locator_servicetype_t stype = get_servicetype(tname);

				register_host(hname, stype, sname);
				dbgprintf("Loaded host %s/%s for server %s\n", hname, tname, sname);
			}
		}
		fclose(fd);
	}
}
int network_manager_init(DBusConnection *conn, struct network_conf *service_conf)
{
	GDBusMethodTable *methods = NULL;
	GDBusSignalTable *signals = NULL;

	conf = service_conf;

	if (conf->server_enabled && conf->connection_enabled) {
		methods = manager_methods;
		signals = connection_signals;
	} else if (conf->connection_enabled) {
		methods = connection_methods;
		signals = connection_signals;
	} else if (conf->server_enabled)
		methods = server_methods;
	else {
		error ("All interfaces were disabled");
		return -1;
	}

	if (bnep_init(conf->panu_script, conf->gn_script, conf->nap_script)) {
		error("Can't init bnep module");
		return -1;
	}

	/*
	 * There is one socket to handle the incomming connections. NAP,
	 * GN and PANU servers share the same PSM. The initial BNEP message
	 * (setup connection request) contains the destination service
	 * field that defines which service the source is connecting to.
	 */
	if (conf->server_enabled) {
		if (bridge_init(conf->gn_iface, conf->nap_iface) < 0) {
			error("Can't init bridge module");
			return -1;
		}

		if (server_init(conn, conf->iface_prefix, conf->security) < 0)
			return -1;
	}

	if (conf->connection_enabled) {
		if (connection_init(conn, conf->iface_prefix) < 0)
			return -1;
	}

	if (g_dbus_register_interface(conn, NETWORK_PATH,
					NETWORK_MANAGER_INTERFACE,
					methods, signals, NULL,
					NULL, manager_unregister) == FALSE) {
		error("Failed to register %s interface to %s",
				NETWORK_MANAGER_INTERFACE, NETWORK_PATH);
		return -1;
	}

	connection = dbus_connection_ref(conn);

	info("Registered manager path:%s", NETWORK_PATH);

	register_stored();

	/* Register PANU, GN and NAP servers if they don't exist */
	register_server(BNEP_SVC_PANU);
	register_server(BNEP_SVC_GN);
	register_server(BNEP_SVC_NAP);

	return 0;
}
Beispiel #20
0
int	main(int argc, char *argv[])
{
	uid_t	uid, euid;

	sbrk0 = (char *)sbrk((size_t)0);
	uid = getuid();
	euid = geteuid();

#ifdef	CHROOTDIR
	ircd_res_init();
	if (chdir(ROOT_PATH)!=0)
	{
		perror("chdir");
		(void)fprintf(stderr,"%s: Cannot chdir: %s.\n", IRCD_PATH,
			ROOT_PATH);
		exit(5);
	}
	if (chroot(ROOT_PATH)!=0)
	    {
		perror("chroot");
		(void)fprintf(stderr,"%s: Cannot chroot: %s.\n", IRCD_PATH,
			      ROOT_PATH);
		exit(5);
	    }
#endif /*CHROOTDIR*/

#ifdef	ZIP_LINKS
	if (zlib_version[0] == '0')
	    {
		fprintf(stderr, "zlib version 1.0 or higher required\n");
		exit(1);
	    }
	if (zlib_version[0] != ZLIB_VERSION[0])
	    {
        	fprintf(stderr, "incompatible zlib version\n");
		exit(1);
	    }
	if (strcmp(zlib_version, ZLIB_VERSION) != 0)
	    {
		fprintf(stderr, "warning: different zlib version\n");
	    }
#endif

	myargv = argv;
	(void)umask(077);                /* better safe than sorry --SRB */
	bzero((char *)&me, sizeof(me));

	make_server(&me);
	register_server(&me);

	version = make_version();	/* Generate readable version string */

	/*
	** All command line parameters have the syntax "-fstring"
	** or "-f string" (e.g. the space is optional). String may
	** be empty. Flag characters cannot be concatenated (like
	** "-fxyz"), it would conflict with the form "-fstring".
	*/
	while (--argc > 0 && (*++argv)[0] == '-')
	    {
		char	*p = argv[0]+1;
		int	flag = *p++;

		if (flag == '\0' || *p == '\0')
		{
			if (argc > 1 && argv[1][0] != '-')
			{
				p = *++argv;
				argc -= 1;
			}
			else
			{
				p = "";
			}
		}

		switch (flag)
		    {
                    case 'a':
			bootopt |= BOOT_AUTODIE;
			break;
		    case 'b':
			bootopt |= BOOT_BADTUNE;
			break;
		    case 'c':
			bootopt |= BOOT_CONSOLE;
			break;
		    case 'q':
			bootopt |= BOOT_QUICK;
			break;
#ifdef CMDLINE_CONFIG
		    case 'f':
                        (void)setuid((uid_t)uid);
			configfile = p;
			break;
#endif
		    case 'h':
			if (*p == '\0')
				bad_command();
			strncpyzt(me.serv->namebuf, p, sizeof(me.serv->namebuf));
			break;
		    case 'i':
			bootopt |= BOOT_INETD|BOOT_AUTODIE;
		        break;
		    case 'p':
			if (!strcmp(p, "strict"))
				bootopt |= BOOT_PROT|BOOT_STRICTPROT;
			else if (!strcmp(p, "on"))
				bootopt |= BOOT_PROT;
			else if (!strcmp(p, "off"))
				bootopt &= ~(BOOT_PROT|BOOT_STRICTPROT);
			else if (!strcmp(p, "standalone"))
				bootopt |= BOOT_STANDALONE;
			else
				bad_command();
			break;
		    case 's':
			bootopt |= BOOT_NOIAUTH;
			break;
		    case 't':
#ifdef DEBUGMODE
                        (void)setuid((uid_t)uid);
#endif
			bootopt |= BOOT_TTY;
			break;
		    case 'T':
			tunefile = p;
			break;
		    case 'v':
			(void)printf("ircd %s %s\n\tzlib %s\n\tircd.conf delimiter %c\n\t%s #%s\n",
				     version, serveropts,
#ifndef	ZIP_LINKS
				     "not used",
#else
				     zlib_version,
#endif
					IRCDCONF_DELIMITER,
				     creation, generation);
			  exit(0);
		    case 'x':
#ifdef	DEBUGMODE
                        (void)setuid((uid_t)uid);
			debuglevel = atoi(p);
			debugmode = *p ? p : "0";
			bootopt |= BOOT_DEBUG;
			break;
#else
			(void)fprintf(stderr,
				"%s: DEBUGMODE must be defined for -x y\n",
				myargv[0]);
			exit(0);
#endif
		    default:
			bad_command();
		    }
	    }

	if (strlen(tunefile) > 1023 || strlen(mybasename(tunefile)) > 42)
	{
		fprintf(stderr, "Too long tune filename\n");
		exit(-1);
	}
	if (argc > 0)
		bad_command(); /* This exits out */

#ifndef IRC_UID
	if ((uid != euid) && !euid)
	    {
		(void)fprintf(stderr,
			"ERROR: do not run ircd setuid root. Make it setuid a\
 normal user.\n");
		exit(-1);
	    }
Beispiel #21
0
HRESULT WINAPI DllUnregisterServer(void)
{
    HRESULT hr = __wine_unregister_resources( hInst, NULL );
    if (FAILED(hr)) return hr;
    return register_server(FALSE);
}