aboutsummaryrefslogblamecommitdiff
path: root/src/sysbin/lx/lxsyslib.c
blob: 72c9882f5cf892c796219c50e80e0e260bc582d3 (plain) (tree)























                              


























                                                                                
                                       















































































































                                                
                                     

                                   
                                        






























                                                                         

 





































































































































































                                                                              
                                                             















                                  


















                                      


              







                                           
/*
** Lua eXtended system library
*/

#define lxsyslib_c
#define LUA_LIB

#include <lua/lprefix.h>


#include <errno.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <lua/lua.h>

#include <lua/lauxlib.h>
#include <lua/lualib.h>

#include "lxlib.h"


static int sys_dbg_print(lua_State *L) {
  const char *str = luaL_checkstring(L, 1);
  sc_dbg_print(str);
  return 0;
}

static int sys_yield(lua_State *L) {
  sc_yield();
  return 0;
}

static int sys_exit(lua_State *L) {
  int code = luaL_checkinteger(L, 1);
  sc_exit(code);
  return 0;
}

static int sys_usleep(lua_State *L) {
  int usecs = luaL_checkinteger(L, 1);
  sc_usleep(usecs);
  return 0;
}

/*
    Missing syscalls :
    - sys_new_thread, exit_thread -> into specific threading library
    - mmap, mmap_file, mchmap, munmap -> into specific memory-related library ??
    - ioctl, fctl -> into ioctl library
*/

static int sys_create(lua_State *L) {
  const char *name = luaL_checkstring(L, 1);
  int type = luaL_checkinteger(L, 2);
  lua_pushboolean(L, sc_create(name, type));
  return 1;
}

static int sys_delete(lua_State *L) {
  const char *name = luaL_checkstring(L, 1);
  lua_pushboolean(L, sc_delete(name));
  return 1;
}

static int sys_move(lua_State *L) {
  const char *oldname = luaL_checkstring(L, 1);
  const char *newname = luaL_checkstring(L, 2);
  lua_pushboolean(L, sc_move(oldname, newname));
  return 1;
}

static int sys_stat(lua_State *L) {
  const char* name = luaL_checkstring(L, 1);
  stat_t s;
  if (sc_stat(name, &s)) {
    lua_createtable(L, 0, 3);
    setintfield(L, "type", s.type);
    setintfield(L, "access", s.access);
    setintfield(L, "size", s.size);
  } else {
    lua_pushnil(L);
  }
  return 1;
}


static int sys_open(lua_State *L) {
  const char* name = luaL_checkstring(L, 1);
  int mode = luaL_checkinteger(L, 2);
  fd_t fh = sc_open(name, mode);
  if (fh) {
    lua_pushinteger(L, fh);
  } else {
    lua_pushnil(L);
  }
  return 1;
}

static int sys_close(lua_State *L) {
  int fd = luaL_checkinteger(L, 1);
  sc_close(fd);
  return 0;
}

static int sys_read(lua_State *L) {
  int fd = luaL_checkinteger(L, 1);
  int offset = luaL_checkinteger(L, 2);
  int len = luaL_checkinteger(L, 3);

  luaL_Buffer b;
  char* bufptr = luaL_buffinitsize(L, &b, len);
  int ret = sc_read(fd, offset, len, bufptr);

  luaL_pushresultsize(&b, ret);
  lua_pushinteger(L, ret);
  return 2;
}

static int sys_write(lua_State *L) {
  int fd = luaL_checkinteger(L, 1);
  int offset = luaL_checkinteger(L, 2);
  const char* str = luaL_checkstring(L, 3);
  int len = luaL_len(L, 3);

  int ret = sc_write(fd, offset, len, str);
  lua_pushinteger(L, ret);
  return 1;
}

static int sys_readdir(lua_State *L) {
  int fd = luaL_checkinteger(L, 1);
  int ent_no = luaL_checkinteger(L, 2);

  dirent_t d;
  bool ret = sc_readdir(fd, ent_no, &d);
  if (ret) {
    lua_createtable(L, 0, 4);
    setstrfield(L, "name", d.name);
    setintfield(L, "type", d.st.type);
    setintfield(L, "access", d.st.access);
    setintfield(L, "size", d.st.size);
  } else {
    lua_pushnil(L);
  }
  return 1;
}

static int sys_stat_open(lua_State *L) {
  int fd = luaL_checkinteger(L, 1);
  stat_t s;
  if (sc_stat_open(fd, &s)) {
    lua_createtable(L, 0, 3);
    setintfield(L, "type", s.type);
    setintfield(L, "access", s.access);
    setintfield(L, "size", s.size);
  } else {
    lua_pushnil(L);
  }
  return 1;
}

static int sys_select(lua_State *L) {
  luaL_checktype(L, 1, LUA_TTABLE);
  int nfds = luaL_len(L, 1);
  int timeout = luaL_checkinteger(L, 2);

  sel_fd_t *fds = (sel_fd_t*)malloc(nfds*sizeof(sel_fd_t));
  if (fds == NULL)
    luaL_error(L, "Out of memory, could not allocate %d sel_fd_t", nfds);

  for (int i = 0; i < nfds; i++) {
    lua_rawgeti(L, 1, i+1);
    luaL_checktype(L, -1, LUA_TTABLE);

    lua_rawgeti(L, -1, 1);
    fds[i].fd = luaL_checkinteger(L, -1);
    lua_pop(L, 1);
    
    lua_rawgeti(L, -1, 2);
    fds[i].req_flags = luaL_checkinteger(L, -1);
    lua_pop(L, 2);
  }

  bool result = sc_select(fds, nfds, timeout);

  for (int i = 0; i < nfds; i++) {
    lua_rawgeti(L, 1, i+1);
    lua_pushinteger(L, fds[i].got_flags);
    lua_rawseti(L, -2, 3);
    lua_pop(L, 1);
  }

  free(fds);

  lua_pushboolean(L, result);
  return 1;
}

static int sys_make_channel(lua_State *L) {
  bool blocking = lx_checkboolean(L, 1);
  fd_pair_t pair = sc_make_channel(blocking);
  lua_pushinteger(L, pair.a);
  lua_pushinteger(L, pair.b);
  return 2;
}

static int sys_make_shm(lua_State *L) {
  int size = luaL_checkinteger(L, 1);
  int fd = sc_make_shm(size);
  if (fd) {
    lua_pushinteger(L, fd);
  } else {
    lua_pushnil(L);
  }
  return 1;
}

static int sys_gen_token(lua_State *L) {
  int fd = luaL_checkinteger(L, 1);
  token_t t;
  if (sc_gen_token(fd, &t)) {
    lua_pushlstring(L, t.bytes, TOKEN_LENGTH);
  } else {
    lua_pushnil(L);
  }
  return 1;
}

static int sys_use_token(lua_State *L) {
  const char* tok = luaL_checkstring(L, 1);
  if (!(luaL_len(L, 1) == TOKEN_LENGTH)) {
    luaL_argerror(L, 1, "invalid token length");
  }
  token_t t;
  memcpy(t.bytes, tok, TOKEN_LENGTH);
  fd_t f = sc_use_token(&t);
  if (f) {
    lua_pushinteger(L, f);
  } else {
    lua_pushnil(L);
  }
  return 1;
}

static int sys_make_fs(lua_State *L) {
  const char* name = luaL_checkstring(L, 1);
  const char* driver = luaL_checkstring(L, 2);
  int source = luaL_checkinteger(L, 3);
  const char* options = luaL_checkstring(L, 4);
  lua_pushboolean(L, sc_make_fs(name, driver, source, options));
  return 1;
}

static int sys_fs_add_source(lua_State *L) {
  const char* fs = luaL_checkstring(L, 1);
  int source = luaL_checkinteger(L, 2);
  const char* options = luaL_checkstring(L, 3);
  lua_pushboolean(L, sc_fs_add_source(fs, source, options));
  return 1;
}

static int sys_fs_subfs(lua_State *L) {
  const char* name = luaL_checkstring(L, 1);
  const char* orig_fs = luaL_checkstring(L, 2);
  const char* root = luaL_checkstring(L, 3);
  int ok_modes = luaL_checkinteger(L, 4);
  lua_pushboolean(L, sc_fs_subfs(name, orig_fs, root, ok_modes));
  return 1;
}

static int sys_fs_remove(lua_State *L) {
  const char* name = luaL_checkstring(L, 1);
  sc_fs_remove(name);
  return 0;
}

static int sys_new_proc(lua_State *L) {
  lua_pushinteger(L, sc_new_proc());
  return 1;
}

static int sys_bind_fs(lua_State *L) {
  int pid = luaL_checkinteger(L, 1);
  const char* new_name = luaL_checkstring(L, 2);
  const char* name = luaL_checkstring(L, 3);
  lua_pushboolean(L, sc_bind_fs(pid, new_name, name));
  return 1;
}

static int sys_bind_subfs(lua_State *L) {
  int pid = luaL_checkinteger(L, 1);
  const char* new_name = luaL_checkstring(L, 2);
  const char* fs = luaL_checkstring(L, 3);
  const char* root = luaL_checkstring(L, 4);
  int ok_modes = luaL_checkinteger(L, 5);
  lua_pushboolean(L, sc_bind_subfs(pid, new_name, fs, root, ok_modes));
  return 1;
}

static int sys_bind_make_fs(lua_State *L) {
  int pid = luaL_checkinteger(L, 1);
  const char* new_name = luaL_checkstring(L, 2);
  const char* driver = luaL_checkstring(L, 3);
  fd_t source = luaL_checkinteger(L, 4);
  const char* options = luaL_checkstring(L, 5);
  lua_pushboolean(L, sc_bind_make_fs(pid, new_name, driver, source, options));
  return 1;
}

static int sys_bind_fd(lua_State *L) {
  int pid = luaL_checkinteger(L, 1);
  int new_fd = luaL_checkinteger(L, 2);
  int fd = luaL_checkinteger(L, 3);
  lua_pushboolean(L, sc_bind_fd(pid, new_fd, fd));
  return 1;
}

static int sys_proc_exec(lua_State *L) {
  int pid = luaL_checkinteger(L, 1);
  const char *name = luaL_checkstring(L, 2);
  lua_pushboolean(L, sc_proc_exec(pid, name));
  return 1;
}

static int sys_proc_status(lua_State *L) {
  int pid = luaL_checkinteger(L, 1);
  proc_status_t s;
  if (sc_proc_status(pid, &s)) {
    lua_createtable(L, 0, 3);
    setintfield(L, "pid", s.pid);
    setintfield(L, "status",s.status);
    setintfield(L, "exit_code", s.exit_code);
  } else {
    lua_pushnil(L);
  }
  return 1;
}

static int sys_proc_kill(lua_State *L) {
  int pid = luaL_checkinteger(L, 1);
  proc_status_t s;
  if (sc_proc_kill(pid, &s)) {
    lua_createtable(L, 0, 3);
    setintfield(L, "pid", s.pid);
    setintfield(L, "status",s.status);
    setintfield(L, "exit_code", s.exit_code);
  } else {
    lua_pushnil(L);
  }
  return 1;
}

static int sys_proc_wait(lua_State *L) {
  int pid = luaL_checkinteger(L, 1);
  bool wait = lx_checkboolean(L, 2);
  proc_status_t s;
  sc_proc_wait(pid, wait, &s);
  lua_createtable(L, 0, 3);
  setintfield(L, "pid", s.pid);
  setintfield(L, "status",s.status);
  setintfield(L, "exit_code", s.exit_code);
  return 1;
}

/* }====================================================== */

static const luaL_Reg syslib[] = {
  {"dbg_print", sys_dbg_print},
  {"yield",     sys_yield},
  {"exit",      sys_exit},
  {"usleep",    sys_usleep},
  {"create",    sys_create},
  {"delete",    sys_delete},
  {"move",      sys_move},
  {"stat",      sys_stat},
  {"open",      sys_open},
  {"close",     sys_close},
  {"read",      sys_read},
  {"write",     sys_write},
  {"readdir",   sys_readdir},
  {"stat_open", sys_stat_open},
  {"select",    sys_select},
  {"make_channel",sys_make_channel},
  {"make_shm",  sys_make_shm},
  {"gen_token", sys_gen_token},
  {"use_token", sys_use_token},
  {"make_fs",   sys_make_fs},
  {"fs_add_source",sys_fs_add_source},
  {"fs_subfs",  sys_fs_subfs},
  {"fs_remove", sys_fs_remove},
  {"new_proc",  sys_new_proc},
  {"bind_fs",   sys_bind_fs},
  {"bind_subfs",sys_bind_subfs},
  {"bind_make_fs",sys_bind_make_fs},
  {"bind_fd",   sys_bind_fd},
  {"proc_exec", sys_proc_exec},
  {"proc_status",sys_proc_status},
  {"proc_kill", sys_proc_kill},
  {"proc_wait", sys_proc_wait},
  
  {NULL, NULL}
};


LUAMOD_API int lx_open_sys (lua_State *L) {
  luaL_newlib(L, syslib);
  return 1;
}


/* vim: set sts=2 ts=2 sw=2 tw=0 et :*/