The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=6a2c624b35a0c760b00b9a34c10b7ea0c240c677

commit 6a2c624b35a0c760b00b9a34c10b7ea0c240c677
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2025-07-09 05:12:31 +0000
Commit:     Kyle Evans <kev...@freebsd.org>
CommitDate: 2025-07-09 05:12:31 +0000

    flua: fbsd: return a process handle to operate on when we exec()
    
    This gives us some way to be able to write to stdin if we want to, or
    as a future improvement, will allow us to extract stdout from the
    process.  The handle is setup to close and waitpid() on close/gc so that
    existing users wouldn't necessarily leak for the lifetime of the script
    if they weren't adopted to the new model.
    
    Reviewed by:    bapt
    Differential Revision:  https://reviews.freebsd.org/D50538
---
 libexec/flua/modules/lfbsd.c | 94 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 86 insertions(+), 8 deletions(-)

diff --git a/libexec/flua/modules/lfbsd.c b/libexec/flua/modules/lfbsd.c
index 6279474f8388..a361fa25601b 100644
--- a/libexec/flua/modules/lfbsd.c
+++ b/libexec/flua/modules/lfbsd.c
@@ -2,6 +2,7 @@
  * SPDX-License-Identifier: BSD-2-Clause
  *
  * Copyright 2023 Baptiste Daroussin <b...@freebsd.org>
+ * Copyright (C) 2025 Kyle Evans <kev...@freebsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted providing that the following conditions~
@@ -38,6 +39,13 @@
 #include "lauxlib.h"
 #include "lfbsd.h"
 
+#define        FBSD_PROCESSHANDLE      "fbsd_process_t*"
+
+struct fbsd_process {
+       int     pid;
+       int     stdin_fileno;
+};
+
 extern char **environ;
 
 static const char**
@@ -65,7 +73,8 @@ luaL_checkarraystrings(lua_State *L, int arg)
 static int
 lua_exec(lua_State *L)
 {
-       int r, pstat;
+       struct fbsd_process *proc;
+       int r;
        posix_spawn_file_actions_t action;
        int stdin_pipe[2] = {-1, -1};
        pid_t pid;
@@ -81,6 +90,9 @@ lua_exec(lua_State *L)
                return (3);
        }
 
+       proc = lua_newuserdata(L, sizeof(*proc));
+       proc->stdin_fileno = stdin_pipe[1];
+
        posix_spawn_file_actions_init(&action);
        posix_spawn_file_actions_adddup2(&action, stdin_pipe[0], STDIN_FILENO);
        posix_spawn_file_actions_addclose(&action, stdin_pipe[1]);
@@ -91,6 +103,7 @@ lua_exec(lua_State *L)
                close(stdin_pipe[0]);
                close(stdin_pipe[1]);
                posix_spawn_file_actions_destroy(&action);
+               lua_pop(L, 2);  /* Pop off the process handle and args. */
 
                lua_pushnil(L);
                lua_pushstring(L, strerror(r));
@@ -98,12 +111,26 @@ lua_exec(lua_State *L)
                return (3);
        }
 
+       lua_pop(L, 1);
+
        close(stdin_pipe[0]);
        posix_spawn_file_actions_destroy(&action);
 
-       while (waitpid(pid, &pstat, 0) == -1) {
-               if (errno != EINTR) {
-                       close(stdin_pipe[1]);
+       proc->pid = pid;
+       luaL_setmetatable(L, FBSD_PROCESSHANDLE);
+
+       return 1;
+}
+
+static int
+lua_process_close(lua_State *L)
+{
+       struct fbsd_process *proc;
+       int pstat, r;
+
+       proc = luaL_checkudata(L, 1, FBSD_PROCESSHANDLE);
+       while (waitpid(proc->pid, &pstat, 0) == -1) {
+               if ((r = errno) != EINTR) {
                        lua_pushnil(L);
                        lua_pushstring(L, strerror(r));
                        lua_pushinteger(L, r);
@@ -111,18 +138,60 @@ lua_exec(lua_State *L)
                }
        }
 
-       if (WEXITSTATUS(pstat) != 0) {
+       if (!WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) {
                lua_pushnil(L);
                lua_pushstring(L, "Abnormal termination");
+               return (2);
+       }
+
+       if (proc->stdin_fileno >= 0)
+               close(proc->stdin_fileno);
+       proc->stdin_fileno = -1;
+
+       lua_pushboolean(L, 1);
+       return 1;
+}
+
+static int
+lua_process_stdin(lua_State *L)
+{
+       struct fbsd_process *proc;
+       luaL_Stream *p;
+       FILE *fp;
+       int r;
+
+       proc = luaL_checkudata(L, 1, FBSD_PROCESSHANDLE);
+       fp = fdopen(proc->stdin_fileno, "w");
+       if (fp == NULL) {
+               r = errno;
+
+               lua_pushnil(L);
+               lua_pushstring(L, strerror(r));
                lua_pushinteger(L, r);
                return (3);
        }
 
-       close(stdin_pipe[1]);
-       lua_pushinteger(L, pid);
-       return 1;
+       p = lua_newuserdata(L, sizeof(*p));
+       p->closef = &lua_process_close;
+       p->f = fp;
+       luaL_setmetatable(L, LUA_FILEHANDLE);
+       return (1);
 }
 
+#define PROCESS_SIMPLE(n)      { #n, lua_process_ ## n }
+static const struct luaL_Reg fbsd_process[] = {
+       PROCESS_SIMPLE(close),
+       PROCESS_SIMPLE(stdin),
+       { NULL, NULL },
+};
+
+static const struct luaL_Reg fbsd_process_meta[] = {
+       { "__index", NULL },
+       { "__gc", lua_process_close },
+       { "__close", lua_process_close },
+       { NULL, NULL },
+};
+
 #define REG_SIMPLE(n)  { #n, lua_ ## n }
 static const struct luaL_Reg fbsd_lib[] = {
        REG_SIMPLE(exec),
@@ -134,5 +203,14 @@ int
 luaopen_fbsd(lua_State *L)
 {
        luaL_newlib(L, fbsd_lib);
+
+       luaL_newmetatable(L, FBSD_PROCESSHANDLE);
+       luaL_setfuncs(L, fbsd_process_meta, 0);
+
+       luaL_newlibtable(L, fbsd_process);
+       luaL_setfuncs(L, fbsd_process, 0);
+       lua_setfield(L, -2, "__index");
+       lua_pop(L, 1);
+
        return (1);
 }

Reply via email to