add interactive mode for /bin/sh entrypoint
This commit is contained in:
parent
8ab9a46d96
commit
76f7d7d1af
@ -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);
|
||||
|
39
src/data.c
39
src/data.c
@ -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
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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
|
||||
|
81
src/system.c
81
src/system.c
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user