drop stdin/stdout/stderr and Lua default files
This isn't necessarily for sandboxing, but they don't really work right now in the presence of ncurses, and it seems better to not include broken stuff. Maybe we can get them to coexist with ncurses down the road.
This commit is contained in:
parent
5c1bf1aaff
commit
1e63a579d7
|
@ -132,6 +132,11 @@ libraries. However, a few things are different from conventional Lua:
|
|||
effectively:
|
||||
- `os.execute`
|
||||
- `io.popen`
|
||||
* Some functions are disabled because they don't seem to make sense in an
|
||||
ncurses environment. This includes the Lua notions of default files, which
|
||||
start out as stdin/stdout.
|
||||
- `io.input`, `io.read`
|
||||
- `io.output`, `io.write`, `io.flush`
|
||||
* Some functions in lcurses have [additional smarts](https://github.com/lcurses/lcurses/blob/master/lib/curses.lua).
|
||||
Teliva is [consistent with the underlying ncurses](https://github.com/akkartik/teliva/blob/main/src/lcurses/curses.lua).
|
||||
|
||||
|
|
128
src/liolib.c
128
src/liolib.c
|
@ -20,13 +20,6 @@
|
|||
|
||||
|
||||
|
||||
#define IO_INPUT 1
|
||||
#define IO_OUTPUT 2
|
||||
|
||||
|
||||
static const char *const fnames[] = {"input", "output"};
|
||||
|
||||
|
||||
static int pushresult (lua_State *L, int i, const char *filename) {
|
||||
int en = errno; /* calls to Lua API may change this value */
|
||||
if (i) {
|
||||
|
@ -92,16 +85,6 @@ static FILE **newfile (lua_State *L) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
** function to (not) close the standard files stdin, stdout, and stderr
|
||||
*/
|
||||
static int io_noclose (lua_State *L) {
|
||||
lua_pushnil(L);
|
||||
lua_pushliteral(L, "cannot close standard file");
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** function to close regular files
|
||||
*/
|
||||
|
@ -121,8 +104,6 @@ static int aux_close (lua_State *L) {
|
|||
|
||||
|
||||
static int io_close (lua_State *L) {
|
||||
if (lua_isnone(L, 1))
|
||||
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
|
||||
tofile(L); /* make sure argument is a file */
|
||||
return aux_close(L);
|
||||
}
|
||||
|
@ -163,47 +144,6 @@ static int io_tmpfile (lua_State *L) {
|
|||
}
|
||||
|
||||
|
||||
static FILE *getiofile (lua_State *L, int findex) {
|
||||
FILE *f;
|
||||
lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
|
||||
f = *(FILE **)lua_touserdata(L, -1);
|
||||
if (f == NULL)
|
||||
luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
static int g_iofile (lua_State *L, int f, const char *mode) {
|
||||
if (!lua_isnoneornil(L, 1)) {
|
||||
const char *filename = lua_tostring(L, 1);
|
||||
if (filename) {
|
||||
FILE **pf = newfile(L);
|
||||
*pf = fopen(filename, mode);
|
||||
if (*pf == NULL)
|
||||
fileerror(L, 1, filename);
|
||||
}
|
||||
else {
|
||||
tofile(L); /* check that it's a valid file handle */
|
||||
lua_pushvalue(L, 1);
|
||||
}
|
||||
lua_rawseti(L, LUA_ENVIRONINDEX, f);
|
||||
}
|
||||
/* return current value */
|
||||
lua_rawgeti(L, LUA_ENVIRONINDEX, f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int io_input (lua_State *L) {
|
||||
return g_iofile(L, IO_INPUT, "r");
|
||||
}
|
||||
|
||||
|
||||
static int io_output (lua_State *L) {
|
||||
return g_iofile(L, IO_OUTPUT, "w");
|
||||
}
|
||||
|
||||
|
||||
static int io_readline (lua_State *L);
|
||||
|
||||
|
||||
|
@ -222,20 +162,13 @@ static int f_lines (lua_State *L) {
|
|||
|
||||
|
||||
static int io_lines (lua_State *L) {
|
||||
if (lua_isnoneornil(L, 1)) { /* no arguments? */
|
||||
/* will iterate over default input */
|
||||
lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
|
||||
return f_lines(L);
|
||||
}
|
||||
else {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
FILE **pf = newfile(L);
|
||||
*pf = fopen(filename, "r");
|
||||
if (*pf == NULL)
|
||||
fileerror(L, 1, filename);
|
||||
aux_lines(L, lua_gettop(L), 1);
|
||||
return 1;
|
||||
}
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
FILE **pf = newfile(L);
|
||||
*pf = fopen(filename, "r");
|
||||
if (*pf == NULL)
|
||||
fileerror(L, 1, filename);
|
||||
aux_lines(L, lua_gettop(L), 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -354,11 +287,6 @@ static int g_read (lua_State *L, FILE *f, int first) {
|
|||
}
|
||||
|
||||
|
||||
static int io_read (lua_State *L) {
|
||||
return g_read(L, getiofile(L, IO_INPUT), 1);
|
||||
}
|
||||
|
||||
|
||||
static int f_read (lua_State *L) {
|
||||
return g_read(L, tofile(L), 2);
|
||||
}
|
||||
|
@ -405,11 +333,6 @@ static int g_write (lua_State *L, FILE *f, int arg) {
|
|||
}
|
||||
|
||||
|
||||
static int io_write (lua_State *L) {
|
||||
return g_write(L, getiofile(L, IO_OUTPUT), 1);
|
||||
}
|
||||
|
||||
|
||||
static int f_write (lua_State *L) {
|
||||
return g_write(L, tofile(L), 2);
|
||||
}
|
||||
|
@ -442,12 +365,6 @@ static int f_setvbuf (lua_State *L) {
|
|||
}
|
||||
|
||||
|
||||
|
||||
static int io_flush (lua_State *L) {
|
||||
return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
static int f_flush (lua_State *L) {
|
||||
return pushresult(L, fflush(tofile(L)) == 0, NULL);
|
||||
}
|
||||
|
@ -455,16 +372,16 @@ static int f_flush (lua_State *L) {
|
|||
|
||||
static const luaL_Reg iolib[] = {
|
||||
{"close", io_close},
|
||||
{"flush", io_flush},
|
||||
{"input", io_input},
|
||||
/* no 'flush' since Teliva is ncurses-based */
|
||||
/* no 'input' since Teliva is ncurses-based */
|
||||
{"lines", io_lines},
|
||||
{"open", io_open},
|
||||
{"output", io_output},
|
||||
/* no popen without sandboxing it */
|
||||
{"read", io_read},
|
||||
/* no 'output' since Teliva is ncurses-based */
|
||||
/* no 'popen' without sandboxing it */
|
||||
/* no 'read' since Teliva is ncurses-based */
|
||||
{"tmpfile", io_tmpfile},
|
||||
{"type", io_type},
|
||||
{"write", io_write},
|
||||
/* no 'write' since Teliva is ncurses-based */
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -491,18 +408,6 @@ static void createmeta (lua_State *L) {
|
|||
}
|
||||
|
||||
|
||||
static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
|
||||
*newfile(L) = f;
|
||||
if (k > 0) {
|
||||
lua_pushvalue(L, -1);
|
||||
lua_rawseti(L, LUA_ENVIRONINDEX, k);
|
||||
}
|
||||
lua_pushvalue(L, -2); /* copy environment */
|
||||
lua_setfenv(L, -2); /* set it */
|
||||
lua_setfield(L, -3, fname);
|
||||
}
|
||||
|
||||
|
||||
static void newfenv (lua_State *L, lua_CFunction cls) {
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_pushcfunction(L, cls);
|
||||
|
@ -512,17 +417,10 @@ static void newfenv (lua_State *L, lua_CFunction cls) {
|
|||
|
||||
LUALIB_API int luaopen_io (lua_State *L) {
|
||||
createmeta(L);
|
||||
/* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
|
||||
newfenv(L, io_fclose);
|
||||
lua_replace(L, LUA_ENVIRONINDEX);
|
||||
/* open library */
|
||||
luaL_register(L, LUA_IOLIBNAME, iolib);
|
||||
/* create (and set) default files */
|
||||
newfenv(L, io_noclose); /* close function for default files */
|
||||
createstdfile(L, stdin, IO_INPUT, "stdin");
|
||||
createstdfile(L, stdout, IO_OUTPUT, "stdout");
|
||||
createstdfile(L, stderr, 0, "stderr");
|
||||
lua_pop(L, 1); /* pop environment for default files */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue