Browse Source

[Feat] [VMP] Update protocol, add pipe mapping support

xcbosa mbp16 5 months ago
parent
commit
89c724bad2
2 changed files with 266 additions and 12 deletions
  1. 133 6
      package/0xcvmkitosboot/src/vmprocess.c
  2. 133 6
      post_sbin/getty.c

+ 133 - 6
package/0xcvmkitosboot/src/vmprocess.c

@@ -20,7 +20,7 @@
 #define VMP_DEVICE_TX "/etc/.vmpdrvfna_tx"
 #define VMP_TID_MAX 64
 #define VMP_TX_POOL_SIZE 64
-#define VMP_STRBUF_LEN 128
+#define VMP_STRBUF_LEN 256
 
 typedef struct {
     short width;
@@ -31,6 +31,7 @@ typedef struct {
 
 typedef enum {
     rx_command_type_runproc,
+    rx_command_type_runpipe,
     rx_command_type_killproc,
     rx_command_type_lsproc,
     rx_command_type_sstdin,
@@ -77,6 +78,10 @@ typedef struct {
     int slave_pty;
     FD stdin_fd;
     rx_command_win_size win_size;
+    int use_pipe;
+    pipe_t pipe_in;
+    pipe_t pipe_out;
+    FD stdout_fd;
 } management_process;
 
 void debug_print_rx(rx_command rx) {
@@ -124,6 +129,7 @@ void tx_push(tx_command cmd) {
 
 #define CB_SUCC "succ"
 #define CB_NO_TID "no_tid"
+#define CB_NO_PIPE "no_pipe"
 #define CB_NO_PTY "no_pty"
 #define CB_TID_KILLED "tid_killed"
 #define CT_LAUNCH_FAIL "launch_fail"
@@ -142,7 +148,7 @@ void tx_push(tx_command cmd) {
 }
 #define CB_PUSH(pmagic, pterror, reason) CT_PUSH(tx_command_type_cb, pmagic, 0, pterror, reason)
 
-void *mproc_io_thread(management_process *mproc) {
+void *mproc_io_thread_pty(management_process *mproc) {
     char slave_name[256];
     if (openpty(&mproc->master_pty, &mproc->slave_pty, 
                slave_name, NULL, &mproc->win_size) == -1) {
@@ -248,6 +254,93 @@ void *mproc_io_thread(management_process *mproc) {
     return NULL;
 }
 
+void *mproc_io_thread_pipe(management_process *mproc) {
+    posix_spawn_file_actions_t actions;
+    posix_spawn_file_actions_init(&actions);
+    posix_spawn_file_actions_addclose(&actions, mproc->pipe_in[1]);
+    posix_spawn_file_actions_addclose(&actions, mproc->pipe_out[0]);
+    posix_spawn_file_actions_adddup2(&actions, mproc->pipe_in[0], STDIN_FILENO);
+    posix_spawn_file_actions_adddup2(&actions, mproc->pipe_out[1], STDOUT_FILENO);
+    char *const argv[] = {
+        "/bin/sh", "-c", mproc->command, NULL
+    };
+    char *const environment[] = {
+        NULL
+    };
+    int ret = posix_spawnp(&mproc->pid, argv[0], &actions, NULL, argv, environment);
+    posix_spawn_file_actions_destroy(&actions);
+    pthread_mutex_unlock(&processes_lock);
+    
+    if (ret != 0) {
+        close(mproc->pipe_in[0]);
+        close(mproc->pipe_in[1]);
+        close(mproc->pipe_out[0]);
+        close(mproc->pipe_out[1]);
+        CT_PUSH(tx_command_type_stoped, ret, mproc->tid, 1, CT_LAUNCH_FAIL);
+        mproc->inuse = 0;
+        return NULL;
+    }
+
+    close(mproc->pipe_in[0]);
+    close(mproc->pipe_out[1]);
+    mproc->stdin_fd = mproc->pipe_in[1];
+    mproc->stdout_fd = mproc->pipe_out[0];
+    int flags = fcntl(mproc->stdout_fd, F_GETFL, 0);
+    fcntl(mproc->stdout_fd, F_SETFL, flags | O_NONBLOCK);
+
+    char buf[VMP_STRBUF_LEN];
+    ssize_t nread = 0;
+    const char *exit_reason = "unknown";
+    int8_t exit_error = 0;
+    int64_t exit_magic = 0;
+    while (1) {
+        do {
+            bzero(buf, sizeof(buf));
+            nread = read(mproc->stdout_fd, buf, sizeof(buf));
+            if (nread > 0) {
+                tx_command cmd = {
+                    .type = tx_command_type_stdout,
+                    .tid = mproc->tid,
+                    .error = 0,
+                    .magic = 0,
+                    .sstdout_len = nread
+                };
+                bzero(&cmd.sstdout[0], VMP_STRBUF_LEN);
+                memcpy(cmd.sstdout, buf, nread);
+                tx_push(cmd);
+            }
+        }
+        while (nread == sizeof(buf)); // has next unread
+
+        int pid_status;
+        pid_t result = waitpid(mproc->pid, &pid_status, WNOHANG);
+        if (result == -1) {
+            exit_reason = "err_waitpid";
+            break;
+        }
+        if (result != 0) {
+            if (WIFEXITED(pid_status)) {
+                exit_reason = "normal";
+                exit_magic = WEXITSTATUS(pid_status);
+            }
+            else if (WIFSIGNALED(pid_status)) {
+                exit_reason = "sig";
+                exit_error = WIFSIGNALED(pid_status);
+            }
+            else {
+                exit_reason = "exit_unknown";
+            }
+            break;
+        }
+        usleep(100);
+    }
+
+    close(mproc->stdin_fd);
+    close(mproc->stdout_fd);
+    CT_PUSH(tx_command_type_stoped, exit_magic, mproc->tid, exit_error, exit_reason);
+    mproc->inuse = 0;
+}
+
 int8_t find_unused_mproc_nolock() {
     for (int8_t tid = 0; tid < VMP_TID_MAX; tid++) {
         if (!processes[tid].inuse) {
@@ -278,9 +371,41 @@ void rx_process(rx_command cmd) {
             mproc.inuse = 1;
             processes[tid] = mproc;
             mproc.win_size = cmd.win_size;
+            mproc.use_pipe = 0;
 
             CT_PUSH(tx_command_type_cb, cmd.magic, tid, 0, CB_SUCC);
-            pthread_create(&mproc.io_thread, NULL, &mproc_io_thread, &processes[tid]);
+            pthread_create(&mproc.io_thread, NULL, &mproc_io_thread_pty, &processes[tid]);
+            // processes_lock will unlock in mproc_io_thread
+            break;
+        }
+        case rx_command_type_runpipe: {
+            pthread_mutex_lock(&processes_lock);
+            int8_t tid = find_unused_mproc_nolock();
+            if (tid < 0) {
+                pthread_mutex_unlock(&processes_lock);
+                CB_PUSH(cmd.magic, 1, CB_NO_TID);
+                break;
+            }
+            
+            management_process mproc;
+            bzero(&mproc, sizeof(management_process));
+            memcpy(&mproc.command[0], cmd.sstdin, sizeof(mproc.command));
+            if (pipe(mproc.pipe_in) == -1 || pipe(mproc.pipe_out) == -1) {
+                pthread_mutex_unlock(&processes_lock);
+                close(mproc.pipe_in[0]);
+                close(mproc.pipe_in[1]);
+                close(mproc.pipe_out[0]);
+                close(mproc.pipe_out[1]);
+                CB_PUSH(cmd.magic, 1, CB_NO_PIPE);
+                break;
+            }
+            
+            mproc.tid = tid;
+            mproc.inuse = 1;
+            processes[tid] = mproc;
+            mproc.use_pipe = 1;
+            CT_PUSH(tx_command_type_cb, cmd.magic, tid, 0, CB_SUCC);
+            pthread_create(&mproc.io_thread, NULL, &mproc_io_thread_pipe, &processes[tid]);
             // processes_lock will unlock in mproc_io_thread
             break;
         }
@@ -351,7 +476,9 @@ void rx_process(rx_command cmd) {
                 CB_PUSH(cmd.magic, 1, CB_TID_KILLED);
                 break;
             }
-            ioctl(mproc->stdin_fd, TIOCGWINSZ, &cmd.win_size);
+            if (!mproc->use_pipe) {
+                ioctl(mproc->stdin_fd, TIOCGWINSZ, &cmd.win_size);
+            }
             pthread_mutex_unlock(&processes_lock);
             CB_PUSH(cmd.magic, 0, CB_SUCC);
             break;
@@ -369,11 +496,11 @@ int main() {
     RX = open(VMP_DEVICE_RX, 1101824);
     TX = open(VMP_DEVICE_TX, 1101825);
     if (RX < 0) {
-        printf("vmp: unable to open rx");
+        printf("XCVMKit-OS: unable to connect with host.\n");
         return -1;
     }
     if (TX < 0) {
-        printf("vmp: unable to open tx");
+        printf("XCVMKit-OS: unable to connect with host.\n");
         return -1;
     }
     pthread_mutex_init(&tx_lock, NULL);

+ 133 - 6
post_sbin/getty.c

@@ -20,7 +20,7 @@
 #define VMP_DEVICE_TX "/etc/.vmpdrvfna_tx"
 #define VMP_TID_MAX 64
 #define VMP_TX_POOL_SIZE 64
-#define VMP_STRBUF_LEN 128
+#define VMP_STRBUF_LEN 256
 
 typedef struct {
     short width;
@@ -31,6 +31,7 @@ typedef struct {
 
 typedef enum {
     rx_command_type_runproc,
+    rx_command_type_runpipe,
     rx_command_type_killproc,
     rx_command_type_lsproc,
     rx_command_type_sstdin,
@@ -77,6 +78,10 @@ typedef struct {
     int slave_pty;
     FD stdin_fd;
     rx_command_win_size win_size;
+    int use_pipe;
+    pipe_t pipe_in;
+    pipe_t pipe_out;
+    FD stdout_fd;
 } management_process;
 
 void debug_print_rx(rx_command rx) {
@@ -124,6 +129,7 @@ void tx_push(tx_command cmd) {
 
 #define CB_SUCC "succ"
 #define CB_NO_TID "no_tid"
+#define CB_NO_PIPE "no_pipe"
 #define CB_NO_PTY "no_pty"
 #define CB_TID_KILLED "tid_killed"
 #define CT_LAUNCH_FAIL "launch_fail"
@@ -142,7 +148,7 @@ void tx_push(tx_command cmd) {
 }
 #define CB_PUSH(pmagic, pterror, reason) CT_PUSH(tx_command_type_cb, pmagic, 0, pterror, reason)
 
-void *mproc_io_thread(management_process *mproc) {
+void *mproc_io_thread_pty(management_process *mproc) {
     char slave_name[256];
     if (openpty(&mproc->master_pty, &mproc->slave_pty, 
                slave_name, NULL, &mproc->win_size) == -1) {
@@ -248,6 +254,93 @@ void *mproc_io_thread(management_process *mproc) {
     return NULL;
 }
 
+void *mproc_io_thread_pipe(management_process *mproc) {
+    posix_spawn_file_actions_t actions;
+    posix_spawn_file_actions_init(&actions);
+    posix_spawn_file_actions_addclose(&actions, mproc->pipe_in[1]);
+    posix_spawn_file_actions_addclose(&actions, mproc->pipe_out[0]);
+    posix_spawn_file_actions_adddup2(&actions, mproc->pipe_in[0], STDIN_FILENO);
+    posix_spawn_file_actions_adddup2(&actions, mproc->pipe_out[1], STDOUT_FILENO);
+    char *const argv[] = {
+        "/bin/sh", "-c", mproc->command, NULL
+    };
+    char *const environment[] = {
+        NULL
+    };
+    int ret = posix_spawnp(&mproc->pid, argv[0], &actions, NULL, argv, environment);
+    posix_spawn_file_actions_destroy(&actions);
+    pthread_mutex_unlock(&processes_lock);
+    
+    if (ret != 0) {
+        close(mproc->pipe_in[0]);
+        close(mproc->pipe_in[1]);
+        close(mproc->pipe_out[0]);
+        close(mproc->pipe_out[1]);
+        CT_PUSH(tx_command_type_stoped, ret, mproc->tid, 1, CT_LAUNCH_FAIL);
+        mproc->inuse = 0;
+        return NULL;
+    }
+
+    close(mproc->pipe_in[0]);
+    close(mproc->pipe_out[1]);
+    mproc->stdin_fd = mproc->pipe_in[1];
+    mproc->stdout_fd = mproc->pipe_out[0];
+    int flags = fcntl(mproc->stdout_fd, F_GETFL, 0);
+    fcntl(mproc->stdout_fd, F_SETFL, flags | O_NONBLOCK);
+
+    char buf[VMP_STRBUF_LEN];
+    ssize_t nread = 0;
+    const char *exit_reason = "unknown";
+    int8_t exit_error = 0;
+    int64_t exit_magic = 0;
+    while (1) {
+        do {
+            bzero(buf, sizeof(buf));
+            nread = read(mproc->stdout_fd, buf, sizeof(buf));
+            if (nread > 0) {
+                tx_command cmd = {
+                    .type = tx_command_type_stdout,
+                    .tid = mproc->tid,
+                    .error = 0,
+                    .magic = 0,
+                    .sstdout_len = nread
+                };
+                bzero(&cmd.sstdout[0], VMP_STRBUF_LEN);
+                memcpy(cmd.sstdout, buf, nread);
+                tx_push(cmd);
+            }
+        }
+        while (nread == sizeof(buf)); // has next unread
+
+        int pid_status;
+        pid_t result = waitpid(mproc->pid, &pid_status, WNOHANG);
+        if (result == -1) {
+            exit_reason = "err_waitpid";
+            break;
+        }
+        if (result != 0) {
+            if (WIFEXITED(pid_status)) {
+                exit_reason = "normal";
+                exit_magic = WEXITSTATUS(pid_status);
+            }
+            else if (WIFSIGNALED(pid_status)) {
+                exit_reason = "sig";
+                exit_error = WIFSIGNALED(pid_status);
+            }
+            else {
+                exit_reason = "exit_unknown";
+            }
+            break;
+        }
+        usleep(100);
+    }
+
+    close(mproc->stdin_fd);
+    close(mproc->stdout_fd);
+    CT_PUSH(tx_command_type_stoped, exit_magic, mproc->tid, exit_error, exit_reason);
+    mproc->inuse = 0;
+}
+
 int8_t find_unused_mproc_nolock() {
     for (int8_t tid = 0; tid < VMP_TID_MAX; tid++) {
         if (!processes[tid].inuse) {
@@ -278,9 +371,41 @@ void rx_process(rx_command cmd) {
             mproc.inuse = 1;
             processes[tid] = mproc;
             mproc.win_size = cmd.win_size;
+            mproc.use_pipe = 0;
 
             CT_PUSH(tx_command_type_cb, cmd.magic, tid, 0, CB_SUCC);
-            pthread_create(&mproc.io_thread, NULL, &mproc_io_thread, &processes[tid]);
+            pthread_create(&mproc.io_thread, NULL, &mproc_io_thread_pty, &processes[tid]);
+            // processes_lock will unlock in mproc_io_thread
+            break;
+        }
+        case rx_command_type_runpipe: {
+            pthread_mutex_lock(&processes_lock);
+            int8_t tid = find_unused_mproc_nolock();
+            if (tid < 0) {
+                pthread_mutex_unlock(&processes_lock);
+                CB_PUSH(cmd.magic, 1, CB_NO_TID);
+                break;
+            }
+            
+            management_process mproc;
+            bzero(&mproc, sizeof(management_process));
+            memcpy(&mproc.command[0], cmd.sstdin, sizeof(mproc.command));
+            if (pipe(mproc.pipe_in) == -1 || pipe(mproc.pipe_out) == -1) {
+                pthread_mutex_unlock(&processes_lock);
+                close(mproc.pipe_in[0]);
+                close(mproc.pipe_in[1]);
+                close(mproc.pipe_out[0]);
+                close(mproc.pipe_out[1]);
+                CB_PUSH(cmd.magic, 1, CB_NO_PIPE);
+                break;
+            }
+            
+            mproc.tid = tid;
+            mproc.inuse = 1;
+            processes[tid] = mproc;
+            mproc.use_pipe = 1;
+            CT_PUSH(tx_command_type_cb, cmd.magic, tid, 0, CB_SUCC);
+            pthread_create(&mproc.io_thread, NULL, &mproc_io_thread_pipe, &processes[tid]);
             // processes_lock will unlock in mproc_io_thread
             break;
         }
@@ -351,7 +476,9 @@ void rx_process(rx_command cmd) {
                 CB_PUSH(cmd.magic, 1, CB_TID_KILLED);
                 break;
             }
-            ioctl(mproc->stdin_fd, TIOCGWINSZ, &cmd.win_size);
+            if (!mproc->use_pipe) {
+                ioctl(mproc->stdin_fd, TIOCGWINSZ, &cmd.win_size);
+            }
             pthread_mutex_unlock(&processes_lock);
             CB_PUSH(cmd.magic, 0, CB_SUCC);
             break;
@@ -369,11 +496,11 @@ int main() {
     RX = open(VMP_DEVICE_RX, 1101824);
     TX = open(VMP_DEVICE_TX, 1101825);
     if (RX < 0) {
-        printf("vmp: unable to open rx");
+        printf("XCVMKit-OS: unable to connect with host.\n");
         return -1;
     }
     if (TX < 0) {
-        printf("vmp: unable to open tx");
+        printf("XCVMKit-OS: unable to connect with host.\n");
         return -1;
     }
     pthread_mutex_init(&tx_lock, NULL);