Esempio n. 1
0
static void event_text(const char *data, SERVER_REC *server, EXEC_WI_REC *item)
{
	if (!IS_EXEC_WI(item)) return;

	net_sendbuffer_send(item->process->out, data, strlen(data));
	net_sendbuffer_send(item->process->out, "\n", 1);
        signal_stop();
}
Esempio n. 2
0
/* Send `data' to dcc chat. */
void dcc_chat_send(CHAT_DCC_REC *dcc, const char *data)
{
	g_return_if_fail(IS_DCC_CHAT(dcc));
        g_return_if_fail(dcc->sendbuf != NULL);
	g_return_if_fail(data != NULL);

	net_sendbuffer_send(dcc->sendbuf, data, strlen(data));
	net_sendbuffer_send(dcc->sendbuf, "\n", 1);
}
Esempio n. 3
0
void irc_server_send_data(IRC_SERVER_REC *server, const char *data, int len)
{
	if (net_sendbuffer_send(server->handle, data, len) == -1) {
		/* something bad happened */
		server->connection_lost = TRUE;
		return;
	}

	g_get_current_time(&server->last_cmd);

	/* A bit kludgy way to do the flood protection. In ircnet, there
	   actually is 1sec / 100 bytes penalty, but we rather want to deal
	   with the max. 1000 bytes input buffer problem. If we send more
	   than that with the burst, we'll get excess flooded. */
	if (len < 100 || server->cmd_queue_speed <= 10)
		server->wait_cmd.tv_sec = 0;
	else {
		memcpy(&server->wait_cmd, &server->last_cmd, sizeof(GTimeVal));
		server->wait_cmd.tv_sec += 2 + len/100;
	}
}
Esempio n. 4
0
/* DCC SERVER: text received */
static void dcc_server_msg(SERVER_DCC_REC *dcc, const char *msg)
{
	g_return_if_fail(IS_DCC_SERVER(dcc));
	g_return_if_fail(msg != NULL);

	/* Check for CHAT protocol */
	if (g_strncasecmp(msg, "100 ", 4) == 0) {
		msg += 4;
		/* Check if this server is accepting chat requests.*/
		if (dcc->accept_chat) {
			/* Connect and start DCC Chat */
			char *str;
			CHAT_DCC_REC *dccchat = dcc_chat_create(dcc->server, NULL, msg, "chat");

			dccchat->starttime = time(NULL);
			dccchat->handle = dcc->handle;
			dccchat->sendbuf = net_sendbuffer_create(dccchat->handle, 0);
			memcpy(&dccchat->addr, &dcc->addr, sizeof(IPADDR));
			net_ip2host(&dccchat->addr, dccchat->addrstr);
			dccchat->port = dcc->port;
			dccchat->tagread = g_input_add(dccchat->handle, G_INPUT_READ,
						       (GInputFunction) dcc_chat_input, dccchat);

			dcc->connection_established = 1;
			signal_emit("dcc connected", 1, dccchat);

			str = g_strdup_printf("101 %s\n",
					      (dccchat->server) ? dccchat->server->nick : "??");
			net_sendbuffer_send(dccchat->sendbuf, str, strlen(str));
			g_free(str);
		}
	}

	/* Check for FSERVE protocol */
	if (g_strncasecmp(msg, "110 ", 4) == 0) {
		msg += 4;
		/* Check if this server is accepting fserve requests.*/
		if (dcc->accept_fserve) {
			/* TODO - Connect and start DCC Fserve */
		}
	}

	/* Check for SEND protocol */
	if (g_strncasecmp(msg, "120 ", 4) == 0) {
		msg += 4;
		/* Check if this server is accepting send requests.*/
		if (dcc->accept_send) {
			/* Connect and start DCC Send */
			GET_DCC_REC *dccget;
			char **params, *fname, *nick;
			int paramcount, len, quoted = FALSE;
			uoff_t size;

			/* 120 clientnickname filesize filename */
			params = g_strsplit(msg, " ", -1);
			paramcount = strarray_length(params);

			if (paramcount < 3) {
				g_strfreev(params);
				signal_stop();
				return;
			}

			nick = params[0];
			size = str_to_uofft(params[1]);
			fname = g_strjoinv(" ", &params[2]);

			len = strlen(fname);
			if (len > 1 && *fname == '"' && fname[len-1] == '"') {
				/* "file name" - MIRC sends filenames with spaces like this */
				fname[len-1] = '\0';
				g_memmove(fname, fname+1, len);
				quoted = TRUE;
			}

			dccget = dcc_get_create(dcc->server, NULL, nick, fname);
			dccget->handle = dcc->handle;
			dccget->target = g_strdup(dcc->server ? dcc->server->nick : "??");
			memcpy(&dccget->addr, &dcc->addr, sizeof(dcc->addr));
			if (dccget->addr.family == AF_INET) {
				net_ip2host(&dccget->addr, dccget->addrstr);
			} else {
				/* with IPv6, show it to us as it was sent */
				memcpy(dccget->addrstr, dcc->addrstr, sizeof(dccget->addrstr));
			}
			dccget->port = dcc->port;
			dccget->size = size;
			dccget->file_quoted = quoted;
			dccget->from_dccserver = 1;

			dcc->connection_established = 1;
			signal_emit("dcc request", 2, dccget, dccget->addrstr);

			g_strfreev(params);
			g_free(fname);
		}
	}

	signal_stop();
}
Esempio n. 5
0
static void sig_server_event(IRC_SERVER_REC *server, const char *line,
			     const char *nick, const char *address)
{
	GSList *tmp;
        void *client;
        const char *signal;
	char *event, *args;
        int redirected;

	g_return_if_fail(line != NULL);
	if (!IS_IRC_SERVER(server))
		return;

	/* get command.. */
	event = g_strconcat("event ", line, NULL);
	args = strchr(event+6, ' ');
	if (args != NULL) *args++ = '\0'; else args = "";
	while (*args == ' ') args++;
	ascii_strdown(event);

	signal = server_redirect_peek_signal(server, nick, event, args, &redirected);
	if ((signal != NULL && strncmp(signal, "proxy ", 6) != 0) ||
	    (signal == NULL && redirected)) {
		/* we want to send this to one client (or proxy itself) only */
		/* proxy only */
		g_free(event);
		return;
	}

	if (signal != NULL) {
                server_redirect_get_signal(server, nick, event, args);
		if (sscanf(signal+6, "%p", &client) == 1) {
			/* send it to specific client only */
			if (g_slist_find(proxy_clients, client) != NULL)
				net_sendbuffer_send(((CLIENT_REC *) client)->handle, next_line->str, next_line->len);
			g_free(event);
                        signal_stop();
			return;
		}
	}

        if (g_strcmp0(event, "event privmsg") == 0 &&
	    strstr(args, " :\001") != NULL &&
	    strstr(args, " :\001ACTION") == NULL) {
		/* CTCP - either answer ourself or forward it to one client */
		for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
	        	CLIENT_REC *rec = tmp->data;

			if (rec->want_ctcp == 1) {
                        	/* only CTCP for the chatnet where client is connected to will be forwarded */
                        	if (strstr(rec->proxy_address, server->connrec->chatnet) != NULL) {
					net_sendbuffer_send(rec->handle,
							    next_line->str, next_line->len);
					signal_stop();
				}
			}
		}
		g_free(event);
		return;
	}

	if (g_strcmp0(event, "event ping") == 0 ||
	    g_strcmp0(event, "event pong") == 0) {
		/* We want to answer ourself to PINGs and CTCPs.
		   Also hide PONGs from clients. */
		g_free(event);
		return;
	}

	/* send the data to clients.. */
        proxy_outdata_all(server, "%s", next_line->str);

	g_free(event);
}
Esempio n. 6
0
static void handle_exec(const char *args, GHashTable *optlist,
			WI_ITEM_REC *item)
{
	PROCESS_REC *rec;
        char *target, *level;
	int notice, signum, interactive, target_nick, target_channel;

	/* check that there's no unknown options. we allowed them
	   because signals can be used as options, but there should be
	   only one unknown option: the signal name/number. */
	signum = cmd_options_get_signal("exec", optlist);
	if (signum == -2)
                return;

	if (*args == '\0') {
		exec_show_list();
                return;
	}

	target = NULL;
	notice = FALSE;

	if (g_hash_table_lookup(optlist, "in") != NULL) {
		rec = process_find(g_hash_table_lookup(optlist, "in"), TRUE);
		if (rec != NULL) {
			net_sendbuffer_send(rec->out, args, strlen(args));
			net_sendbuffer_send(rec->out, "\n", 1);
		}
		return;
	}

	/* check if args is a process ID or name. if it's ID but not found,
	   complain about it and fail immediately */
	rec = process_find(args, *args == '%');
	if (*args == '%' && rec == NULL)
		return;

        /* common options */
        target_channel = target_nick = FALSE;
	if (g_hash_table_lookup(optlist, "out") != NULL) {
                /* redirect output to active channel/query */
		if (item == NULL)
			cmd_return_error(CMDERR_NOT_JOINED);
		target = (char *) window_item_get_target(item);
		target_channel = IS_CHANNEL(item);
		target_nick = IS_QUERY(item);
	} else if (g_hash_table_lookup(optlist, "msg") != NULL) {
                /* redirect output to /msg <nick> */
		target = g_hash_table_lookup(optlist, "msg");
	} else if (g_hash_table_lookup(optlist, "notice") != NULL) {
		target = g_hash_table_lookup(optlist, "notice");
                notice = TRUE;
	}

        /* options that require process ID/name as argument */
	if (rec == NULL &&
	    (signum != -1 || g_hash_table_lookup(optlist, "close") != NULL)) {
		printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
			  "Unknown process name: %s", args);
		return;
	}
	if (g_hash_table_lookup(optlist, "close") != NULL) {
		/* forcibly close the process */
                process_destroy(rec, -1);
                return;
	}

	if (signum != -1) {
		/* send a signal to process */
                kill(rec->pid, signum);
                return;
	}

        interactive = g_hash_table_lookup(optlist, "interactive") != NULL;
	if (*args == '%') {
		/* do something to already existing process */
		char *name;

		if (target != NULL) {
                        /* redirect output to target */
			g_free_and_null(rec->target);
			rec->target = g_strdup(target);
                        rec->notice = notice;
		}

                name = g_hash_table_lookup(optlist, "name");
		if (name != NULL) {
			/* change window name */
			g_free_not_null(rec->name);
			rec->name = *name == '\0' ? NULL : g_strdup(name);
		} else if (target == NULL &&
			   (rec->target_item == NULL || interactive)) {
			/* no parameters given,
			   redirect output to the active window */
			g_free_and_null(rec->target);
			rec->target_win = active_win;

			if (rec->target_item != NULL)
				exec_wi_destroy(rec->target_item);

			if (interactive) {
				rec->target_item =
					exec_wi_create(active_win, rec);
			}
		}
                return;
	}

        /* starting a new process */
	rec = g_new0(PROCESS_REC, 1);
	rec->pid = -1;
        rec->shell = g_hash_table_lookup(optlist, "nosh") == NULL;

	process_exec(rec, args);
	if (rec->pid == -1) {
                /* pipe() or fork() failed */
		g_free(rec);
		cmd_return_error(CMDERR_ERRNO);
	}

        rec->id = process_get_new_id();
	rec->target = g_strdup(target);
	rec->target_win = active_win;
	rec->target_channel = target_channel;
	rec->target_nick = target_nick;
        rec->args = g_strdup(args);
	rec->notice = notice;
        rec->silent = g_hash_table_lookup(optlist, "-") != NULL;
        rec->quiet = g_hash_table_lookup(optlist, "quiet") != NULL;
	rec->name = g_strdup(g_hash_table_lookup(optlist, "name"));

	level = g_hash_table_lookup(optlist, "level");
	rec->level = level == NULL ? MSGLEVEL_CLIENTCRAP : level2bits(level);

	rec->read_tag = g_input_add(rec->in, G_INPUT_READ,
				    (GInputFunction) sig_exec_input_reader,
				    rec);
	processes = g_slist_append(processes, rec);

	if (rec->target == NULL && interactive)
		rec->target_item = exec_wi_create(active_win, rec);

	signal_emit("exec new", 1, rec);
}