From 9a0fe10987725bbdde7c738b81bfc199f9c9ab3d Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Sat, 10 Feb 2024 00:46:40 -0600 Subject: [PATCH] lib: move non-raw processing into lua This fixes logging so that we actually log the control characters used, and we can distinguish between a control character that was actually sent and one that was escaped. Signed-off-by: Kyle Evans --- lib/core/orch_lua.c | 74 ++------------------------------------------ lib/orch/process.lua | 38 ++++++++++++++++++++++- 2 files changed, 39 insertions(+), 73 deletions(-) diff --git a/lib/core/orch_lua.c b/lib/core/orch_lua.c index 4d81c03..123f6f8 100644 --- a/lib/core/orch_lua.c +++ b/lib/core/orch_lua.c @@ -320,7 +320,7 @@ orchlua_spawn(lua_State *L) proc->term = NULL; proc->status = 0; proc->pid = 0; - proc->buffered = proc->eof = proc->raw = proc->released = false; + proc->buffered = proc->eof = proc->released = false; proc->error = false; luaL_setmetatable(L, ORCHLUA_PROCESSHANDLE); @@ -583,7 +583,7 @@ orchlua_process_write(lua_State *L) struct orch_process *self; const char *buf; char *processed; - size_t bufsz, procsz, totalsz; + size_t bufsz, totalsz; ssize_t writesz; int fd; bool quoted; @@ -593,9 +593,6 @@ orchlua_process_write(lua_State *L) processed = NULL; quoted = false; - if (self->raw) - goto sendit; - processed = malloc(bufsz); if (processed == NULL) { luaL_pushfail(L); @@ -603,57 +600,6 @@ orchlua_process_write(lua_State *L) return (2); } - procsz = 0; - - /* - * If we're not in raw mode, we process some sequences that would not - * normally be processed. - */ - for (size_t i = 0; i < bufsz; i++) { - char c, esc; - - c = buf[i]; - if (quoted) { - quoted = false; - processed[procsz++] = c; - continue; - } - - switch (c) { - case '^': - if (i == bufsz - 1) { - free(processed); - luaL_pushfail(L); - lua_pushstring(L, - "Incomplete CNTRL character at end of buffer"); - return (2); - } - - esc = buf[i + 1]; - if (esc < 0x40 /* @ */ || esc > 0x5f /* _ */) { - free(processed); - luaL_pushfail(L); - lua_pushfstring(L, "Invalid escape of '%c'", esc); - return (2); - } - - processed[procsz++] = esc - 0x40; - - /* Eat the next character. */ - i++; - break; - case '\\': - quoted = true; - break; - default: - processed[procsz++] = c; - break; - } - } - - buf = processed; - bufsz = procsz; -sendit: fd = self->termctl; totalsz = 0; while (totalsz < bufsz) { @@ -677,21 +623,6 @@ orchlua_process_write(lua_State *L) return (1); } -static int -orchlua_process_raw(lua_State *L) -{ - struct orch_process *self; - bool wasraw; - - self = luaL_checkudata(L, 1, ORCHLUA_PROCESSHANDLE); - wasraw = self->raw; - if (lua_gettop(L) > 1) - self->raw = lua_toboolean(L, 2); - - lua_pushboolean(L, wasraw); - return (1); -} - static int orchlua_process_release(lua_State *L) { @@ -842,7 +773,6 @@ static const luaL_Reg orchlua_process[] = { PROCESS_SIMPLE(close), PROCESS_SIMPLE(read), PROCESS_SIMPLE(write), - PROCESS_SIMPLE(raw), PROCESS_SIMPLE(release), PROCESS_SIMPLE(released), PROCESS_SIMPLE(term), diff --git a/lib/orch/process.lua b/lib/orch/process.lua index e8a0c5e..e9c31eb 100644 --- a/lib/orch/process.lua +++ b/lib/orch/process.lua @@ -90,6 +90,7 @@ function Process:new(cmd, ctx) pwrap._process = assert(core.spawn(table.unpack(cmd))) pwrap.buffer = MatchBuffer:new(pwrap, ctx) pwrap.ctx = ctx + pwrap.is_raw = false pwrap.term = assert(pwrap._process:term()) local mask = pwrap.term:fetch("lflag") @@ -116,10 +117,45 @@ function Process:read(func, timeout) end end function Process:raw(is_raw) + local prev_raw = self.is_raw self.is_raw = is_raw - return self._process:raw(is_raw) + return prev_raw end function Process:write(data) + if not self.is_raw then + -- Convert ^[A-Z] -> cntrl sequence + local quoted = false + for i = 1, #data do + if i > #data then + break + end + + local ch = data:sub(i, i) + + if quoted then + quoted = false + elseif ch == "\\" then + quoted = true + data = data:sub(1, i - 1) .. data:sub(i + 1) + elseif ch == "^" then + if did_quote then + error("Huh") + end + if i == #data then + error("Incomplete CNTRL character at end of buffer") + end + + local esch = data:sub(i + 1, i + 1) + local esc = string.byte(esch) + if esc < 0x40 or esc > 0x5f then + error("Invalid escape of '" .. esch .. "'") + end + + esch = string.char(esc - 0x40) + data = data:sub(1, i - 1) .. esch .. data:sub(i + 2) + end + end + end if self.log then self.log:write(data) end