aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2025-01-03 10:46:12 +0100
committerPřemysl Eric Janouch <p@janouch.name>2025-01-03 10:46:12 +0100
commitbd264787c167368e11c4397aac3e84440b7f1f17 (patch)
tree47c18262ea87ec0ce08b0f8d19f4ab9d8293f986 /tools
parenta6e7cb553f9cc136cb7358385ca266d40a33523d (diff)
downloadliberty-bd264787c167368e11c4397aac3e84440b7f1f17.tar.gz
liberty-bd264787c167368e11c4397aac3e84440b7f1f17.tar.xz
liberty-bd264787c167368e11c4397aac3e84440b7f1f17.zip
WIP
Diffstat (limited to 'tools')
-rw-r--r--tools/wdye/wdye.c104
1 files changed, 58 insertions, 46 deletions
diff --git a/tools/wdye/wdye.c b/tools/wdye/wdye.c
index 31652c6..3985abf 100644
--- a/tools/wdye/wdye.c
+++ b/tools/wdye/wdye.c
@@ -191,7 +191,7 @@ struct process
{
int terminal_fd; ///< Process stdin/stdout/stderr
pid_t pid; ///< Process ID
- // TODO(p): Either `TERMINAL *` or read-out values.
+ int ref_term; ///< Terminal information
};
static struct process *
@@ -200,6 +200,10 @@ xlua_process_new (lua_State *L)
struct process *self = lua_newuserdata (L, sizeof *self);
luaL_setmetatable (L, XLUA_PROCESS_METATABLE);
memset (self, 0, sizeof *self);
+
+ self->terminal_fd = -1;
+ self->pid = -1;
+ self->ref_term = LUA_NOREF;
return self;
}
@@ -211,6 +215,7 @@ xlua_process_gc (lua_State *L)
xclose (self->terminal_fd);
if (self->pid != -1)
kill (self->pid, SIGKILL);
+ luaL_unref (L, LUA_REGISTRYINDEX, self->ref_term);
return 0;
}
@@ -237,8 +242,6 @@ xlua_process_send (lua_State *L)
static luaL_Reg xlua_process_table[] =
{
{ "__gc", xlua_process_gc },
-// { "__index", xlua_process_index },
-// { "__newindex", xlua_process_newindex },
{ "expect", xlua_process_expect },
{ "send", xlua_process_send },
{ NULL, NULL }
@@ -246,13 +249,34 @@ static luaL_Reg xlua_process_table[] =
// --- Terminal ----------------------------------------------------------------
-// TODO(p): Probably create an object to interact with tinfo.
+static bool
+load_terminfo (const char *term, struct str_map *strings)
+{
+ // TODO(p): See if we can get away with using a bogus FD.
+ int err = 0;
+ TERMINAL *saved_term = set_curterm (NULL);
+ if (setupterm ((char *) term, STDOUT_FILENO, &err) != OK)
+ {
+ set_curterm (saved_term);
+ return false;
+ }
+
+ for (size_t i = 0; strfnames[i]; i++)
+ {
+ const char *value = tigetstr (strnames[i]);
+ if (value && value != (char *) -1)
+ str_map_set (strings, strfnames[i], xstrdup (value));
+ }
+ del_curterm (set_curterm (saved_term));
+ return true;
+}
// --- Library -----------------------------------------------------------------
struct xlua_spawn_context
{
struct str_map env; ///< Subprocess environment map
+ struct str_map term; ///< terminfo database strings
struct strv envv; ///< Subprocess environment vector
struct strv argv; ///< Subprocess argument vector
@@ -264,6 +288,9 @@ xlua_spawn_context_make (void)
{
struct xlua_spawn_context self = {};
self.env = str_map_make (free);
+ self.term = str_map_make (free);
+
+ // XXX: It might make sense to enable starting from an empty environment.
for (char **p = environ; *p; p++)
{
const char *equals = strchr (*p, '=');
@@ -283,6 +310,7 @@ static void
xlua_spawn_context_free (struct xlua_spawn_context *self)
{
str_map_free (&self->env);
+ str_map_free (&self->term);
strv_free (&self->envv);
strv_free (&self->argv);
@@ -317,31 +345,6 @@ environ_map_serialize (struct str_map *env, struct strv *envv)
xstrdup_printf ("%s=%s", iter.link->key, value));
}
-static bool
-xlua_load_terminal (lua_State *L, const char *term)
-{
- // TODO(p): See if we can get away with using a bogus FD.
- int err = 0;
- TERMINAL *saved_term = set_curterm (NULL);
- if (setupterm ((char *) term, STDOUT_FILENO, &err) != OK)
- {
- set_curterm (saved_term);
- return false;
- }
-
- for (size_t i = 0; strfnames[i]; i++)
- {
- const char *name = strfnames[i];
- const char *value = tigetstr (strnames[i]);
- if (value && value != (char *) -1)
- continue;
- }
-
- del_curterm (set_curterm (saved_term));
-
- return true;
-}
-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static int
@@ -349,28 +352,24 @@ xlua_spawn_protected (lua_State *L)
{
struct xlua_spawn_context *ctx = lua_touserdata (L, 1);
- // TODO(p): Consider taking the TERM from the passed environ,
- // or defaulting to inherited TERM. These should match anyway.
-
- // Step 1: Prepare a terminal object.
- (void) xlua_getfield (L, 1, "term", LUA_TSTRING, true);
- const char *term = lua_tostring (L, -1);
-
-
- // TODO(p): Process the terminal name,
- // possibly by creating another indexable Lua object/table.
- // - Remember to use a default when `term == NULL`.
-
- lua_pop (L, 1);
-
- // Step 2: Prepare process environment.
+ // Step 1: Prepare process environment.
if (xlua_getfield (L, 1, "environ", LUA_TTABLE, true))
{
environ_map_update (&ctx->env, L);
lua_pop (L, 1);
}
+ char *term = str_map_find (&ctx->env, "TERM");
+ if (!term)
+ {
+ print_debug ("setting a default TERM");
+ str_map_set (&ctx->env, "TERM", (term = xstrdup ("dumb")));
+ }
environ_map_serialize (&ctx->env, &ctx->envv);
+ // Step 2: Load terminal information.
+ if (!load_terminfo (term, &ctx->term))
+ luaL_error (L, "failed to initialize terminfo for %s", term);
+
// Step 3: Prepare process command line.
size_t argc = lua_rawlen (L, 1);
for (size_t i = 1; i <= argc; i++)
@@ -391,6 +390,18 @@ xlua_spawn_protected (lua_State *L)
// This will get garbage collected as appropriate on failure.
struct process *process = xlua_process_new (L);
+ // This could be made into an object that can adjust winsize/termios.
+ lua_createtable (L, 0, ctx->term.len);
+ struct str_map_iter iter = str_map_iter_make (&ctx->term);
+ const char *value = NULL;
+ while ((value = str_map_iter_next (&iter)))
+ {
+ lua_pushstring (L, iter.link->key);
+ lua_pushstring (L, value);
+ lua_settable (L, -3);
+ }
+ process->ref_term = luaL_ref (L, LUA_REGISTRYINDEX);
+
// Step 5: Spawn the process, which gets a new process group.
process->pid =
pty_fork (&process->terminal_fd, NULL, NULL, NULL, &ctx->error);
@@ -497,8 +508,9 @@ main (int argc, char *argv[])
print_error ("%s: %s", path, lua_tostring (g.L, -1));
lua_pop (g.L, 1);
}
-
- // TODO(p): Do we need to pop the error handler?
+ lua_pop (g.L, 1);
lua_close (g.L);
+
+ poller_free (&g.poller);
return 0;
}