add interactive mode for /bin/sh entrypoint

This commit is contained in:
Antoine 2020-07-19 23:17:39 +02:00
parent 8ab9a46d96
commit 76f7d7d1af
6 changed files with 117 additions and 21 deletions

View File

@ -39,12 +39,12 @@ int container_create(void *stuff)
}
// run container command
if (run_subprocess_async(cloneArgs->argv) != 0)
if (run_subprocess_async(cloneArgs->argc, cloneArgs->argv) != 0)
{
error_handler_container(c, "failed to execvp arguments");
}
free(c); // free twice don't know why but maybe clone lost
free(c); // free twice don't know why but maybe clone lost c reference
c = NULL;
// we end container
@ -75,7 +75,7 @@ pid_t run_container(container_t *c)
{
error_handler_container(c, "failed to run_container clone");
}
// lets wait on our child process here before we, the parent, exits
// lets wait on our child process here before we, the parent, exit
if (waitpid(pid, NULL, 0) == -1)
{
error_handler_container(c, "failed to wait pid %d", pid);

View File

@ -68,4 +68,43 @@ char *read_infinite_fd(int fd)
return stdout_buffer;
}
/**
* Read stdin and write to file descriptor
*/
void write_infinite_fd(int fd)
{
char *stdin_buffer = new_array(1024);
int x = 0;
printf("$ ");
fflush(stdout);
while ((x = read(STDIN_FILENO, stdin_buffer, sizeof(stdin_buffer))) > 0)
{
write(fd, stdin_buffer, sizeof(stdin_buffer));
init_array(stdin_buffer, sizeof(stdin_buffer));
printf("$ ");
fflush(stdout);
}
free(stdin_buffer);
}
/**
* Function use to filter char* array
* copy src char* into dst if function is true
* Return dst length
*/
int filter_char_array(int src_length, char **src, char **dst, char_predicate filter_func)
{
int dst_size = 0;
for (int i = 0; i < src_length; i++)
{
if ((*filter_func)(src[i]))
{
dst[dst_size] = src[i];
dst_size++;
}
}
return dst_size;
}
#endif

View File

@ -12,6 +12,7 @@ int main(int argc, char *const argv[])
}
struct clone_args cloneArgs;
cloneArgs.argc = argc - 1;
cloneArgs.argv = &argv[1];
cloneArgs.hostname = "container-hostname";

View File

@ -4,6 +4,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include "./type.h"
@ -19,15 +20,20 @@ void error(const char *sys_msg, ...);
void last_error(const char *sys_msg, ...);
// system.c
int run_subprocess_async(char *const *argv);
int run_subprocess_async(int argc, char *const *argv);
int run_subprocess(char *const *argv);
int pivot_root(char *mount_dir);
int clean_pivot_root(char *a);
void remount();
bool is_interactive(char *str);
bool is_not_interactive(char *str);
bool contain_interactive(int argc, char *const *argv);
// data.c
char *new_array(size_t size);
void init_array(char *arr, size_t size);
char *read_infinite_fd(int fd);
void write_infinite_fd(int fd);
int filter_char_array(int src_length, char **src, char **dst, char_predicate filter_func);
#endif

View File

@ -13,6 +13,7 @@
#include <sys/syscall.h>
#include <signal.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <sys/wait.h>
#include <string.h>
@ -111,13 +112,21 @@ int run_subprocess(char *const *argv)
/**
* Run external binary into new sub process
*/
int run_subprocess_async(char *const *argv)
int run_subprocess_async(int argc, char *const *argv)
{
pid_t pid;
bool run_interactive = contain_interactive(argc, argv);
// if container is running in interactive mode remove "-i" from argv
if (run_interactive)
{
char **dst_argv = (char **)malloc(sizeof(char *) * argc);
argc = filter_char_array(argc, (char **)argv, dst_argv, is_not_interactive);
argv = dst_argv;
}
// pipe to permit child => parent comunication
int pipefd[2];
pipe(pipefd);
// pipe to permit parent => child comunication
int pipe_parent_to_child_fd[2];
pipe(pipe_parent_to_child_fd);
if ((pid = fork()) == -1)
{
@ -125,13 +134,10 @@ int run_subprocess_async(char *const *argv)
}
else if (pid == 0)
{
close(pipefd[0]); // close reading end in the child
close(pipe_parent_to_child_fd[1]); // close writing end in the child
printf("[CHILD] : running\n");
dup2(pipefd[1], 1); // send stdout to the pipe
dup2(pipefd[1], 2); // send stderr to the pipe
close(pipefd[1]); // this descriptor is no longer needed
dup2(pipe_parent_to_child_fd[0], STDIN_FILENO); // send pipe to the stdin
errno = execvp(argv[0], argv);
return errno;
@ -140,20 +146,23 @@ int run_subprocess_async(char *const *argv)
{
int child_status;
close(pipefd[1]); // close the write end of the pipe in the parent
close(pipe_parent_to_child_fd[0]); // close the read end of the pipe in the parent
// if container is running in interactive mode
if (run_interactive)
{
// read stdin write infinity
write_infinite_fd(pipe_parent_to_child_fd[1]);
}
close(pipe_parent_to_child_fd[1]); // this descriptor is no longer needed
// wait child if long task is in progress
waitpid(pid, &child_status, 0);
if (WIFEXITED(child_status))
{
char *stdout_buffer = read_infinite_fd(pipefd[0]);
printf("[PARENT] child stdout : \n%s\n", stdout_buffer);
free(stdout_buffer);
close(pipefd[0]); // close the descriptor is no longer needed
int es = WEXITSTATUS(child_status);
printf("[PARENT] Exit status was %d\n", es);
return es;
}
}
@ -161,4 +170,42 @@ int run_subprocess_async(char *const *argv)
return EXIT_FAILURE;
}
/**
* Return true if char* str is equal to "-i"
*/
bool is_interactive(char *str)
{
if (strcmp(str, "-i") == 0)
{
return true;
}
return false;
}
/**
* Return true if char* str is not equal to "-i"
* opposite of is_interactive
*/
bool is_not_interactive(char *str)
{
return !is_interactive(str);
}
/**
* Return true if argv char* array contain "-i"
*/
bool contain_interactive(int argc, char *const *argv)
{
bool res = false;
for (int i = 0; i < argc; i++)
{
if (is_interactive(argv[i]))
{
res = true;
break;
}
}
return res;
}
#endif

View File

@ -6,6 +6,7 @@
*/
struct clone_args
{
int argc;
char *const *argv;
const char *hostname;
};
@ -19,4 +20,6 @@ typedef struct container_t
struct clone_args cloneArgs;
} container_t;
typedef bool (*char_predicate)(char *);
#endif