From 29c1823334219c03b1ef4d6b4965529b73ff071b Mon Sep 17 00:00:00 2001
From: LiFeng <lifeng68@huawei.com>
Date: Mon, 13 Apr 2020 21:39:35 +0800
Subject: [PATCH 17/49] attach: add_terminal_fifos: Add terminal fifos
 dynamically

Signed-off-by: LiFeng <lifeng68@huawei.com>
---
 src/lxc/commands.c     | 94 +++++++++++++++++++++++++++++++++++++++++++++-----
 src/lxc/commands.h     |  8 +++++
 src/lxc/lxccontainer.c | 24 +++++++++++++
 src/lxc/terminal.c     | 57 ++++++++++++++++++++++++++++++
 src/lxc/terminal.h     |  4 +++
 5 files changed, 178 insertions(+), 9 deletions(-)

diff --git a/src/lxc/commands.c b/src/lxc/commands.c
index 991bca2..0ffc5c7 100644
--- a/src/lxc/commands.c
+++ b/src/lxc/commands.c
@@ -75,15 +75,18 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
 		[LXC_CMD_GET_CONFIG_ITEM]     		= "get_config_item",
 		[LXC_CMD_GET_NAME]            		= "get_name",
 		[LXC_CMD_GET_LXCPATH]         		= "get_lxcpath",
-		[LXC_CMD_ADD_STATE_CLIENT]		= "add_state_client",
-		[LXC_CMD_CONSOLE_LOG]			= "console_log",
+		[LXC_CMD_ADD_STATE_CLIENT]			= "add_state_client",
+		[LXC_CMD_CONSOLE_LOG]				= "console_log",
 		[LXC_CMD_SERVE_STATE_CLIENTS]		= "serve_state_clients",
 		[LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER]	= "seccomp_notify_add_listener",
 		[LXC_CMD_ADD_BPF_DEVICE_CGROUP]		= "add_bpf_device_cgroup",
-		[LXC_CMD_FREEZE]			= "freeze",
-		[LXC_CMD_UNFREEZE]			= "unfreeze",
-		[LXC_CMD_GET_CGROUP2_FD]		= "get_cgroup2_fd",
+		[LXC_CMD_FREEZE]					= "freeze",
+		[LXC_CMD_UNFREEZE]					= "unfreeze",
+		[LXC_CMD_GET_CGROUP2_FD]			= "get_cgroup2_fd",
 		[LXC_CMD_GET_INIT_PIDFD]        	= "get_init_pidfd",
+#ifdef HAVE_ISULAD
+		[LXC_CMD_SET_TERMINAL_FIFOS]  		= "set_terminal_fifos",
+#endif
 	};
 
 	if (cmd >= LXC_CMD_MAX)
@@ -1388,6 +1391,76 @@ static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
 	return 0;
 }
 
+#ifdef HAVE_ISULAD
+/*
+ * isulad: lxc_cmd_set_terminal_fifos: Set the fifos used for the container as terminal input/output
+ *
+ * @hashed_sock_name: hashed socket name
+ *
+ * Returns 0 when success, else when fail.
+ */
+int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath, const char *in_fifo,
+				const char *out_fifo, const char *err_fifo)
+{
+	int ret = 0, stopped = 0;
+	int len = 0;
+	char *tmp = NULL;
+	const char *split = "&&&&", *none_fifo_name = "none";
+	const char *cmd_in_fifo = in_fifo ? in_fifo : none_fifo_name;
+	const char *cmd_out_fifo = out_fifo ? out_fifo : none_fifo_name;
+	const char *cmd_err_fifo = err_fifo ? err_fifo : none_fifo_name;
+
+	if (len + strlen(cmd_in_fifo) + strlen(split) + strlen(cmd_out_fifo) +
+	     strlen(split) + strlen(cmd_err_fifo) == SIZE_MAX)
+		return -1;
+	len += strlen(cmd_in_fifo) + strlen(split) + strlen(cmd_out_fifo) + strlen(split) + strlen(cmd_err_fifo) + 1;
+	tmp = malloc(len);
+	if (tmp == NULL)
+		return -1;
+	ret = snprintf(tmp, len, "%s%s%s%s%s", cmd_in_fifo, split, cmd_out_fifo, split, cmd_err_fifo);
+	if (ret < 0 || ret >= len) {
+		ERROR("Failed to snprintf in fifo of command");
+		free(tmp);
+		return -1;
+	}
+
+	struct lxc_cmd_rr cmd = {
+		.req = {
+			.cmd = LXC_CMD_SET_TERMINAL_FIFOS,
+			.datalen = strlen(tmp)+1,
+			.data = tmp,
+		},
+	};
+
+	ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
+	if (ret < 0) {
+		ERROR("Failed to send command to container");
+		free(tmp);
+		return -1;
+	}
+
+	if (cmd.rsp.ret != 0) {
+		ERROR("Command response error:%d", cmd.rsp.ret);
+		free(tmp);
+		return -1;
+	}
+
+	free(tmp);
+	return 0;
+}
+
+static int lxc_cmd_set_terminal_fifos_callback(int fd, struct lxc_cmd_req *req,
+					struct lxc_handler *handler, struct lxc_epoll_descr *descr)
+{
+	struct lxc_cmd_rsp rsp;
+	memset(&rsp, 0, sizeof(rsp));
+
+	rsp.ret = lxc_terminal_add_fifos(handler->conf, req->data);;
+
+	return lxc_cmd_rsp_send(fd, &rsp);
+}
+#endif
+
 static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
 			   struct lxc_handler *handler,
 			   struct lxc_epoll_descr *descr)
@@ -1410,11 +1483,14 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
 		[LXC_CMD_CONSOLE_LOG]                 	= lxc_cmd_console_log_callback,
 		[LXC_CMD_SERVE_STATE_CLIENTS]         	= lxc_cmd_serve_state_clients_callback,
 		[LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] 	= lxc_cmd_seccomp_notify_add_listener_callback,
-		[LXC_CMD_ADD_BPF_DEVICE_CGROUP]		= lxc_cmd_add_bpf_device_cgroup_callback,
-		[LXC_CMD_FREEZE]			= lxc_cmd_freeze_callback,
-		[LXC_CMD_UNFREEZE]			= lxc_cmd_unfreeze_callback,
-		[LXC_CMD_GET_CGROUP2_FD]		= lxc_cmd_get_cgroup2_fd_callback,
+		[LXC_CMD_ADD_BPF_DEVICE_CGROUP]			= lxc_cmd_add_bpf_device_cgroup_callback,
+		[LXC_CMD_FREEZE]						= lxc_cmd_freeze_callback,
+		[LXC_CMD_UNFREEZE]						= lxc_cmd_unfreeze_callback,
+		[LXC_CMD_GET_CGROUP2_FD]				= lxc_cmd_get_cgroup2_fd_callback,
 		[LXC_CMD_GET_INIT_PIDFD]                = lxc_cmd_get_init_pidfd_callback,
+#ifdef HAVE_ISULAD
+		[LXC_CMD_SET_TERMINAL_FIFOS]  			= lxc_cmd_set_terminal_fifos_callback,
+#endif
 	};
 
 	if (req->cmd >= LXC_CMD_MAX)
diff --git a/src/lxc/commands.h b/src/lxc/commands.h
index 9e52484..95815e6 100644
--- a/src/lxc/commands.h
+++ b/src/lxc/commands.h
@@ -38,6 +38,9 @@ typedef enum {
 	LXC_CMD_UNFREEZE,
 	LXC_CMD_GET_CGROUP2_FD,
 	LXC_CMD_GET_INIT_PIDFD,
+#ifdef HAVE_ISULAD
+	LXC_CMD_SET_TERMINAL_FIFOS,
+#endif
 	LXC_CMD_MAX,
 } lxc_cmd_t;
 
@@ -130,4 +133,9 @@ extern int lxc_cmd_freeze(const char *name, const char *lxcpath, int timeout);
 extern int lxc_cmd_unfreeze(const char *name, const char *lxcpath, int timeout);
 extern int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath);
 
+#ifdef HAVE_ISULAD
+extern int lxc_cmd_set_terminal_fifos(const char *name, const char *lxcpath,
+				const char *in_fifo, const char *out_fifo, const char *err_fifo);
+#endif
+
 #endif /* __commands_h */
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index e27b63b..d0e6e2b 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -5421,6 +5421,29 @@ static bool do_lxcapi_want_open_stdin(struct lxc_container *c, bool state)
 }
 
 WRAP_API_1(bool, lxcapi_want_open_stdin, bool)
+
+/* isulad add clean resources */
+static bool do_lxcapi_add_terminal_fifo(struct lxc_container *c, const char *in_fifo, const char *out_fifo, const char *err_fifo)
+{
+	bool ret = true;
+
+	if (!c || !c->lxc_conf)
+		return false;
+	if (container_mem_lock(c)) {
+		ERROR("Error getting mem lock");
+		return false;
+	}
+
+	if (lxc_cmd_set_terminal_fifos(c->name, c->config_path, in_fifo, out_fifo, err_fifo)) {
+		ERROR("Error set console fifos");
+		ret = false;
+	}
+
+	container_mem_unlock(c);
+	return ret;
+}
+
+WRAP_API_3(bool, lxcapi_add_terminal_fifo, const char *, const char *, const char *)
 #endif
 
 struct lxc_container *lxc_container_new(const char *name, const char *configpath)
@@ -5567,6 +5590,7 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
 #ifdef HAVE_ISULAD
 	c->set_container_info_file = lxcapi_set_container_info_file;
 	c->set_terminal_init_fifos = lxcapi_set_terminal_default_fifos;
+	c->add_terminal_fifos = lxcapi_add_terminal_fifo;
 #endif
 	return c;
 
diff --git a/src/lxc/terminal.c b/src/lxc/terminal.c
index 775743d..4d7c2cd 100644
--- a/src/lxc/terminal.c
+++ b/src/lxc/terminal.c
@@ -1607,6 +1607,63 @@ err:
 	lxc_terminal_delete(terminal);
 	return -ENODEV;
 }
+
+/* isulad: add fifos dynamic*/
+int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames)
+{
+	int ret = 0;
+	struct lxc_terminal *terminal = &conf->console;
+	int fifofd_in = -1;
+	char *tmp = NULL, *saveptr = NULL, *in = NULL, *out = NULL, *err = NULL;
+	const char *none_fifo_name = "none";
+
+	tmp = safe_strdup(fifonames);
+
+	in = strtok_r(tmp, "&&&&", &saveptr);
+	if (!in) {
+		ret = -1;
+		goto free_out;
+	}
+	if (strcmp(in, none_fifo_name) == 0)
+		in = NULL;
+
+	out = strtok_r(NULL, "&&&&",  &saveptr);
+	if (!out) {
+		ret = -1;
+		goto free_out;
+	}
+	if (strcmp(out, none_fifo_name) == 0)
+		out = NULL;
+
+	err = strtok_r(NULL, "&&&&",  &saveptr);
+	if (!err) {
+		ret = -1;
+		goto free_out;
+	}
+	if (strcmp(err, none_fifo_name) == 0)
+		err = NULL;
+
+	ret = lxc_terminal_set_fifo(terminal, in, out, err, &fifofd_in);
+	if (ret < 0) {
+		ERROR("Faild to set fifos to console config");
+		ret = -1;
+		goto free_out;
+	}
+
+	if (lxc_mainloop_add_handler(terminal->descr, fifofd_in,
+	                             lxc_terminal_io_cb, terminal)) {
+		ERROR("console fifo not added to mainloop");
+		lxc_terminal_delete_fifo(fifofd_in, &terminal->fifos);
+		ret = -1;
+		goto free_out;
+	}
+
+free_out:
+	if (tmp)
+		free(tmp);
+	return ret;
+}
+
 #else
 int lxc_terminal_create(struct lxc_terminal *terminal)
 {
diff --git a/src/lxc/terminal.h b/src/lxc/terminal.h
index dfc03c6..b4160b3 100644
--- a/src/lxc/terminal.h
+++ b/src/lxc/terminal.h
@@ -274,4 +274,8 @@ extern void lxc_terminal_init(struct lxc_terminal *terminal);
 extern int lxc_terminal_map_ids(struct lxc_conf *c,
 				struct lxc_terminal *terminal);
 
+#ifdef HAVE_ISULAD
+int lxc_terminal_add_fifos(struct lxc_conf *conf, const char *fifonames);
+#endif
+
 #endif /* __LXC_TERMINAL_H */
-- 
1.8.3.1

