1506f3640SKyle Evans /*- 2c2caf3b3SKyle Evans * Copyright (c) 2019, 2023 Kyle Evans <kevans@FreeBSD.org> 3506f3640SKyle Evans * 4c2caf3b3SKyle Evans * SPDX-License-Identifier: BSD-2-Clause 5506f3640SKyle Evans */ 6506f3640SKyle Evans 7405e3338SEd Maste #include <sys/stat.h> 81726db7aSMark Johnston #include <sys/utsname.h> 9c2caf3b3SKyle Evans #include <sys/wait.h> 10405e3338SEd Maste 11405e3338SEd Maste #include <errno.h> 12*f35ccf46SStefan Eßer #include <fnmatch.h> 13a1ab15abSBaptiste Daroussin #include <grp.h> 14c2caf3b3SKyle Evans #include <libgen.h> 15a1ab15abSBaptiste Daroussin #include <pwd.h> 16c2caf3b3SKyle Evans #include <stdlib.h> 17405e3338SEd Maste #include <string.h> 18506f3640SKyle Evans #include <unistd.h> 19506f3640SKyle Evans 20506f3640SKyle Evans #include <lua.h> 21506f3640SKyle Evans #include "lauxlib.h" 22506f3640SKyle Evans #include "lposix.h" 23506f3640SKyle Evans 24506f3640SKyle Evans /* 25506f3640SKyle Evans * Minimal implementation of luaposix needed for internal FreeBSD bits. 26506f3640SKyle Evans */ 27c2caf3b3SKyle Evans static int 28c2caf3b3SKyle Evans lua__exit(lua_State *L) 29c2caf3b3SKyle Evans { 30c2caf3b3SKyle Evans int code, narg; 31c2caf3b3SKyle Evans 32c2caf3b3SKyle Evans narg = lua_gettop(L); 33c2caf3b3SKyle Evans luaL_argcheck(L, narg == 1, 1, "_exit takes exactly one argument"); 34c2caf3b3SKyle Evans 35c2caf3b3SKyle Evans code = luaL_checkinteger(L, 1); 36c2caf3b3SKyle Evans _exit(code); 37c2caf3b3SKyle Evans } 38c2caf3b3SKyle Evans 39c2caf3b3SKyle Evans static int 40c2caf3b3SKyle Evans lua_basename(lua_State *L) 41c2caf3b3SKyle Evans { 42c2caf3b3SKyle Evans char *inpath, *outpath; 43c2caf3b3SKyle Evans int narg; 44c2caf3b3SKyle Evans 45c2caf3b3SKyle Evans narg = lua_gettop(L); 46c2caf3b3SKyle Evans luaL_argcheck(L, narg > 0, 1, "at least one argument required"); 47c2caf3b3SKyle Evans inpath = strdup(luaL_checkstring(L, 1)); 48c2caf3b3SKyle Evans if (inpath == NULL) { 49c2caf3b3SKyle Evans lua_pushnil(L); 50c2caf3b3SKyle Evans lua_pushstring(L, strerror(ENOMEM)); 51c2caf3b3SKyle Evans lua_pushinteger(L, ENOMEM); 52c2caf3b3SKyle Evans return (3); 53c2caf3b3SKyle Evans } 54c2caf3b3SKyle Evans 55c2caf3b3SKyle Evans outpath = basename(inpath); 56c2caf3b3SKyle Evans lua_pushstring(L, outpath); 57c2caf3b3SKyle Evans free(inpath); 58c2caf3b3SKyle Evans return (1); 59c2caf3b3SKyle Evans } 60506f3640SKyle Evans 61506f3640SKyle Evans static int 62405e3338SEd Maste lua_chmod(lua_State *L) 63405e3338SEd Maste { 64405e3338SEd Maste int n; 65405e3338SEd Maste const char *path; 66405e3338SEd Maste mode_t mode; 67405e3338SEd Maste 68405e3338SEd Maste n = lua_gettop(L); 69405e3338SEd Maste luaL_argcheck(L, n == 2, n > 2 ? 3 : n, 70405e3338SEd Maste "chmod takes exactly two arguments"); 71405e3338SEd Maste path = luaL_checkstring(L, 1); 72405e3338SEd Maste mode = (mode_t)luaL_checkinteger(L, 2); 73405e3338SEd Maste if (chmod(path, mode) == -1) { 74405e3338SEd Maste lua_pushnil(L); 75405e3338SEd Maste lua_pushstring(L, strerror(errno)); 76405e3338SEd Maste lua_pushinteger(L, errno); 77c2caf3b3SKyle Evans return (3); 78405e3338SEd Maste } 79405e3338SEd Maste lua_pushinteger(L, 0); 80c2caf3b3SKyle Evans return (1); 81405e3338SEd Maste } 82405e3338SEd Maste 83405e3338SEd Maste static int 84a1ab15abSBaptiste Daroussin lua_chown(lua_State *L) 85a1ab15abSBaptiste Daroussin { 86a1ab15abSBaptiste Daroussin int n; 87a1ab15abSBaptiste Daroussin const char *path; 88a1ab15abSBaptiste Daroussin uid_t owner = (uid_t) -1; 89a1ab15abSBaptiste Daroussin gid_t group = (gid_t) -1; 90a1ab15abSBaptiste Daroussin 91a1ab15abSBaptiste Daroussin n = lua_gettop(L); 92a1ab15abSBaptiste Daroussin luaL_argcheck(L, n > 1, n, 93a1ab15abSBaptiste Daroussin "chown takes at least two arguments"); 94a1ab15abSBaptiste Daroussin path = luaL_checkstring(L, 1); 95a1ab15abSBaptiste Daroussin if (lua_isinteger(L, 2)) 96a1ab15abSBaptiste Daroussin owner = (uid_t) lua_tointeger(L, 2); 97a1ab15abSBaptiste Daroussin else if (lua_isstring(L, 2)) { 98a1ab15abSBaptiste Daroussin struct passwd *p = getpwnam(lua_tostring(L, 2)); 99a1ab15abSBaptiste Daroussin if (p != NULL) 100a1ab15abSBaptiste Daroussin owner = p->pw_uid; 101a1ab15abSBaptiste Daroussin else 102a1ab15abSBaptiste Daroussin return (luaL_argerror(L, 2, 103a1ab15abSBaptiste Daroussin lua_pushfstring(L, "unknown user %s", 104a1ab15abSBaptiste Daroussin lua_tostring(L, 2)))); 105a1ab15abSBaptiste Daroussin } else if (!lua_isnoneornil(L, 2)) { 106a1ab15abSBaptiste Daroussin const char *type = luaL_typename(L, 2); 107a1ab15abSBaptiste Daroussin return (luaL_argerror(L, 2, 108a1ab15abSBaptiste Daroussin lua_pushfstring(L, "integer or string expected, got %s", 109a1ab15abSBaptiste Daroussin type))); 110a1ab15abSBaptiste Daroussin } 111a1ab15abSBaptiste Daroussin 112a1ab15abSBaptiste Daroussin if (lua_isinteger(L, 3)) 113a1ab15abSBaptiste Daroussin group = (gid_t) lua_tointeger(L, 3); 114a1ab15abSBaptiste Daroussin else if (lua_isstring(L, 3)) { 115a1ab15abSBaptiste Daroussin struct group *g = getgrnam(lua_tostring(L, 3)); 116a1ab15abSBaptiste Daroussin if (g != NULL) 117a1ab15abSBaptiste Daroussin group = g->gr_gid; 118a1ab15abSBaptiste Daroussin else 119a1ab15abSBaptiste Daroussin return (luaL_argerror(L, 3, 120280f11f1SBaptiste Daroussin lua_pushfstring(L, "unknown group %s", 121a1ab15abSBaptiste Daroussin lua_tostring(L, 3)))); 122a1ab15abSBaptiste Daroussin } else if (!lua_isnoneornil(L, 3)) { 123a1ab15abSBaptiste Daroussin const char *type = luaL_typename(L, 3); 124a1ab15abSBaptiste Daroussin return (luaL_argerror(L, 3, 125a1ab15abSBaptiste Daroussin lua_pushfstring(L, "integer or string expected, got %s", 126a1ab15abSBaptiste Daroussin type))); 127a1ab15abSBaptiste Daroussin } 128a1ab15abSBaptiste Daroussin 129a1ab15abSBaptiste Daroussin if (chown(path, owner, group) == -1) { 130a1ab15abSBaptiste Daroussin lua_pushnil(L); 131a1ab15abSBaptiste Daroussin lua_pushstring(L, strerror(errno)); 132a1ab15abSBaptiste Daroussin lua_pushinteger(L, errno); 133a1ab15abSBaptiste Daroussin return (3); 134a1ab15abSBaptiste Daroussin } 135a1ab15abSBaptiste Daroussin lua_pushinteger(L, 0); 136a1ab15abSBaptiste Daroussin return (1); 137a1ab15abSBaptiste Daroussin } 138a1ab15abSBaptiste Daroussin 139a1ab15abSBaptiste Daroussin static int 140c2caf3b3SKyle Evans lua_pclose(lua_State *L) 141506f3640SKyle Evans { 142c2caf3b3SKyle Evans int error, fd, n; 143506f3640SKyle Evans 144506f3640SKyle Evans n = lua_gettop(L); 145c2caf3b3SKyle Evans luaL_argcheck(L, n == 1, 1, 146c2caf3b3SKyle Evans "close takes exactly one argument (fd)"); 147c2caf3b3SKyle Evans 148c2caf3b3SKyle Evans fd = luaL_checkinteger(L, 1); 149c2caf3b3SKyle Evans if (fd < 0) { 150c2caf3b3SKyle Evans error = EBADF; 151c2caf3b3SKyle Evans goto err; 152c2caf3b3SKyle Evans } 153c2caf3b3SKyle Evans 154c2caf3b3SKyle Evans if (close(fd) == 0) { 155c2caf3b3SKyle Evans lua_pushinteger(L, 0); 156c2caf3b3SKyle Evans return (1); 157c2caf3b3SKyle Evans } 158c2caf3b3SKyle Evans 159c2caf3b3SKyle Evans error = errno; 160c2caf3b3SKyle Evans err: 161c2caf3b3SKyle Evans lua_pushnil(L); 162c2caf3b3SKyle Evans lua_pushstring(L, strerror(error)); 163c2caf3b3SKyle Evans lua_pushinteger(L, error); 164c2caf3b3SKyle Evans return (3); 165c2caf3b3SKyle Evans 166506f3640SKyle Evans } 167506f3640SKyle Evans 1681726db7aSMark Johnston static int 169*f35ccf46SStefan Eßer lua_fnmatch(lua_State *L) 170*f35ccf46SStefan Eßer { 171*f35ccf46SStefan Eßer const char *pattern, *string; 172*f35ccf46SStefan Eßer int flags, n; 173*f35ccf46SStefan Eßer 174*f35ccf46SStefan Eßer n = lua_gettop(L); 175*f35ccf46SStefan Eßer luaL_argcheck(L, n == 2 || n == 3, 4, "need 2 or 3 arguments"); 176*f35ccf46SStefan Eßer 177*f35ccf46SStefan Eßer pattern = luaL_checkstring(L, 1); 178*f35ccf46SStefan Eßer string = luaL_checkstring(L, 2); 179*f35ccf46SStefan Eßer flags = luaL_optinteger(L, 3, 0); 180*f35ccf46SStefan Eßer lua_pushinteger(L, fnmatch(pattern, string, flags)); 181*f35ccf46SStefan Eßer 182*f35ccf46SStefan Eßer return (1); 183*f35ccf46SStefan Eßer } 184*f35ccf46SStefan Eßer 185*f35ccf46SStefan Eßer static int 1861726db7aSMark Johnston lua_uname(lua_State *L) 1871726db7aSMark Johnston { 1881726db7aSMark Johnston struct utsname name; 1891726db7aSMark Johnston int error, n; 1901726db7aSMark Johnston 1911726db7aSMark Johnston n = lua_gettop(L); 1921726db7aSMark Johnston luaL_argcheck(L, n == 0, 1, "too many arguments"); 1931726db7aSMark Johnston 1941726db7aSMark Johnston error = uname(&name); 1951726db7aSMark Johnston if (error != 0) { 1961726db7aSMark Johnston error = errno; 1971726db7aSMark Johnston lua_pushnil(L); 1981726db7aSMark Johnston lua_pushstring(L, strerror(error)); 1991726db7aSMark Johnston lua_pushinteger(L, error); 2001726db7aSMark Johnston return (3); 2011726db7aSMark Johnston } 2021726db7aSMark Johnston 2031726db7aSMark Johnston lua_newtable(L); 2041726db7aSMark Johnston #define setkv(f) do { \ 2051726db7aSMark Johnston lua_pushstring(L, name.f); \ 2061726db7aSMark Johnston lua_setfield(L, -2, #f); \ 2071726db7aSMark Johnston } while (0) 2081726db7aSMark Johnston setkv(sysname); 2091726db7aSMark Johnston setkv(nodename); 2101726db7aSMark Johnston setkv(release); 2111726db7aSMark Johnston setkv(version); 2121726db7aSMark Johnston setkv(machine); 2131726db7aSMark Johnston #undef setkv 2141726db7aSMark Johnston 2151726db7aSMark Johnston return (1); 2161726db7aSMark Johnston } 2171726db7aSMark Johnston 218c2caf3b3SKyle Evans static int 219c2caf3b3SKyle Evans lua_dirname(lua_State *L) 220c2caf3b3SKyle Evans { 221c2caf3b3SKyle Evans char *inpath, *outpath; 222c2caf3b3SKyle Evans int narg; 223c2caf3b3SKyle Evans 224c2caf3b3SKyle Evans narg = lua_gettop(L); 225c2caf3b3SKyle Evans luaL_argcheck(L, narg > 0, 1, 226c2caf3b3SKyle Evans "dirname takes at least one argument (path)"); 227c2caf3b3SKyle Evans inpath = strdup(luaL_checkstring(L, 1)); 228c2caf3b3SKyle Evans if (inpath == NULL) { 229c2caf3b3SKyle Evans lua_pushnil(L); 230c2caf3b3SKyle Evans lua_pushstring(L, strerror(ENOMEM)); 231c2caf3b3SKyle Evans lua_pushinteger(L, ENOMEM); 232c2caf3b3SKyle Evans return (3); 233c2caf3b3SKyle Evans } 234c2caf3b3SKyle Evans 235c2caf3b3SKyle Evans outpath = dirname(inpath); 236c2caf3b3SKyle Evans lua_pushstring(L, outpath); 237c2caf3b3SKyle Evans free(inpath); 238c2caf3b3SKyle Evans return (1); 239c2caf3b3SKyle Evans } 240c2caf3b3SKyle Evans 241c2caf3b3SKyle Evans static int 242c2caf3b3SKyle Evans lua_fork(lua_State *L) 243c2caf3b3SKyle Evans { 244c2caf3b3SKyle Evans pid_t pid; 245c2caf3b3SKyle Evans int narg; 246c2caf3b3SKyle Evans 247c2caf3b3SKyle Evans narg = lua_gettop(L); 248c2caf3b3SKyle Evans luaL_argcheck(L, narg == 0, 1, "too many arguments"); 249c2caf3b3SKyle Evans 250c2caf3b3SKyle Evans pid = fork(); 251c2caf3b3SKyle Evans if (pid < 0) { 252c2caf3b3SKyle Evans lua_pushnil(L); 253c2caf3b3SKyle Evans lua_pushstring(L, strerror(errno)); 254c2caf3b3SKyle Evans lua_pushinteger(L, errno); 255c2caf3b3SKyle Evans return (3); 256c2caf3b3SKyle Evans } 257c2caf3b3SKyle Evans 258c2caf3b3SKyle Evans lua_pushinteger(L, pid); 259c2caf3b3SKyle Evans return (1); 260c2caf3b3SKyle Evans } 261c2caf3b3SKyle Evans 262c2caf3b3SKyle Evans static int 263c2caf3b3SKyle Evans lua_getpid(lua_State *L) 264c2caf3b3SKyle Evans { 265c2caf3b3SKyle Evans int narg; 266c2caf3b3SKyle Evans 267c2caf3b3SKyle Evans narg = lua_gettop(L); 268c2caf3b3SKyle Evans luaL_argcheck(L, narg == 0, 1, "too many arguments"); 269c2caf3b3SKyle Evans lua_pushinteger(L, getpid()); 270c2caf3b3SKyle Evans return (1); 271c2caf3b3SKyle Evans } 272c2caf3b3SKyle Evans 273c2caf3b3SKyle Evans static int 274c2caf3b3SKyle Evans lua_pipe(lua_State *L) 275c2caf3b3SKyle Evans { 276c2caf3b3SKyle Evans int error, fd[2], narg; 277c2caf3b3SKyle Evans 278c2caf3b3SKyle Evans narg = lua_gettop(L); 279c2caf3b3SKyle Evans luaL_argcheck(L, narg == 0, 1, "too many arguments"); 280c2caf3b3SKyle Evans 281c2caf3b3SKyle Evans error = pipe(fd); 282c2caf3b3SKyle Evans if (error != 0) { 283c2caf3b3SKyle Evans lua_pushnil(L); 284c2caf3b3SKyle Evans lua_pushstring(L, strerror(errno)); 285c2caf3b3SKyle Evans lua_pushinteger(L, errno); 286c2caf3b3SKyle Evans return (1); 287c2caf3b3SKyle Evans } 288c2caf3b3SKyle Evans 289c2caf3b3SKyle Evans lua_pushinteger(L, fd[0]); 290c2caf3b3SKyle Evans lua_pushinteger(L, fd[1]); 291c2caf3b3SKyle Evans return (2); 292c2caf3b3SKyle Evans } 293c2caf3b3SKyle Evans 294c2caf3b3SKyle Evans static int 295c2caf3b3SKyle Evans lua_read(lua_State *L) 296c2caf3b3SKyle Evans { 297c2caf3b3SKyle Evans char *buf; 298c2caf3b3SKyle Evans ssize_t ret; 299c2caf3b3SKyle Evans size_t sz; 300c2caf3b3SKyle Evans int error, fd, narg; 301c2caf3b3SKyle Evans 302c2caf3b3SKyle Evans narg = lua_gettop(L); 303c2caf3b3SKyle Evans luaL_argcheck(L, narg == 2, 1, 304c2caf3b3SKyle Evans "read takes exactly two arguments (fd, size)"); 305c2caf3b3SKyle Evans 306c2caf3b3SKyle Evans fd = luaL_checkinteger(L, 1); 307c2caf3b3SKyle Evans sz = luaL_checkinteger(L, 2); 308c2caf3b3SKyle Evans 309c2caf3b3SKyle Evans if (fd < 0) { 310c2caf3b3SKyle Evans error = EBADF; 311c2caf3b3SKyle Evans goto err; 312c2caf3b3SKyle Evans } 313c2caf3b3SKyle Evans 314c2caf3b3SKyle Evans buf = malloc(sz); 315c2caf3b3SKyle Evans if (buf == NULL) 316c2caf3b3SKyle Evans goto err; 317c2caf3b3SKyle Evans 318c2caf3b3SKyle Evans /* 319c2caf3b3SKyle Evans * For 0-byte reads, we'll still push the empty string and let the 320c2caf3b3SKyle Evans * caller deal with EOF to match lposix semantics. 321c2caf3b3SKyle Evans */ 322c2caf3b3SKyle Evans ret = read(fd, buf, sz); 323c2caf3b3SKyle Evans if (ret >= 0) 324c2caf3b3SKyle Evans lua_pushlstring(L, buf, ret); 325c2caf3b3SKyle Evans else if (ret < 0) 326c2caf3b3SKyle Evans error = errno; /* Save to avoid clobber by free() */ 327c2caf3b3SKyle Evans 328c2caf3b3SKyle Evans free(buf); 329c2caf3b3SKyle Evans if (error != 0) 330c2caf3b3SKyle Evans goto err; 331c2caf3b3SKyle Evans 332c2caf3b3SKyle Evans /* Just the string pushed. */ 333c2caf3b3SKyle Evans return (1); 334c2caf3b3SKyle Evans err: 335c2caf3b3SKyle Evans lua_pushnil(L); 336c2caf3b3SKyle Evans lua_pushstring(L, strerror(error)); 337c2caf3b3SKyle Evans lua_pushinteger(L, error); 338c2caf3b3SKyle Evans return (3); 339c2caf3b3SKyle Evans } 340c2caf3b3SKyle Evans 341c2caf3b3SKyle Evans static int 342c2caf3b3SKyle Evans lua_realpath(lua_State *L) 343c2caf3b3SKyle Evans { 344c2caf3b3SKyle Evans const char *inpath; 345c2caf3b3SKyle Evans char *outpath; 346c2caf3b3SKyle Evans int narg; 347c2caf3b3SKyle Evans 348c2caf3b3SKyle Evans narg = lua_gettop(L); 349c2caf3b3SKyle Evans luaL_argcheck(L, narg > 0, 1, "at least one argument required"); 350c2caf3b3SKyle Evans inpath = luaL_checkstring(L, 1); 351c2caf3b3SKyle Evans 352c2caf3b3SKyle Evans outpath = realpath(inpath, NULL); 353c2caf3b3SKyle Evans if (outpath == NULL) { 354c2caf3b3SKyle Evans lua_pushnil(L); 355c2caf3b3SKyle Evans lua_pushstring(L, strerror(errno)); 356c2caf3b3SKyle Evans lua_pushinteger(L, errno); 357c2caf3b3SKyle Evans return (3); 358c2caf3b3SKyle Evans } 359c2caf3b3SKyle Evans 360c2caf3b3SKyle Evans lua_pushstring(L, outpath); 361c2caf3b3SKyle Evans free(outpath); 362c2caf3b3SKyle Evans return (1); 363c2caf3b3SKyle Evans } 364c2caf3b3SKyle Evans 365c2caf3b3SKyle Evans static int 366c2caf3b3SKyle Evans lua_wait(lua_State *L) 367c2caf3b3SKyle Evans { 368c2caf3b3SKyle Evans pid_t pid; 369c2caf3b3SKyle Evans int options, status; 370c2caf3b3SKyle Evans int narg; 371c2caf3b3SKyle Evans 372c2caf3b3SKyle Evans narg = lua_gettop(L); 373c2caf3b3SKyle Evans 374c2caf3b3SKyle Evans pid = -1; 375c2caf3b3SKyle Evans status = options = 0; 376c2caf3b3SKyle Evans if (narg >= 1 && !lua_isnil(L, 1)) 377c2caf3b3SKyle Evans pid = luaL_checkinteger(L, 1); 378c2caf3b3SKyle Evans if (narg >= 2 && !lua_isnil(L, 2)) 379c2caf3b3SKyle Evans options = luaL_checkinteger(L, 2); 380c2caf3b3SKyle Evans 381c2caf3b3SKyle Evans pid = waitpid(pid, &status, options); 382c2caf3b3SKyle Evans if (pid < 0) { 383c2caf3b3SKyle Evans lua_pushnil(L); 384c2caf3b3SKyle Evans lua_pushstring(L, strerror(errno)); 385c2caf3b3SKyle Evans lua_pushinteger(L, errno); 386c2caf3b3SKyle Evans return (3); 387c2caf3b3SKyle Evans } 388c2caf3b3SKyle Evans 389c2caf3b3SKyle Evans lua_pushinteger(L, pid); 390c2caf3b3SKyle Evans if (pid == 0) { 391c2caf3b3SKyle Evans lua_pushliteral(L, "running"); 392c2caf3b3SKyle Evans return (2); 393c2caf3b3SKyle Evans } 394c2caf3b3SKyle Evans 395c2caf3b3SKyle Evans if (WIFCONTINUED(status)) { 396c2caf3b3SKyle Evans lua_pushliteral(L, "continued"); 397c2caf3b3SKyle Evans return (2); 398c2caf3b3SKyle Evans } else if(WIFSTOPPED(status)) { 399c2caf3b3SKyle Evans lua_pushliteral(L, "stopped"); 400c2caf3b3SKyle Evans lua_pushinteger(L, WSTOPSIG(status)); 401c2caf3b3SKyle Evans return (3); 402c2caf3b3SKyle Evans } else if (WIFEXITED(status)) { 403c2caf3b3SKyle Evans lua_pushliteral(L, "exited"); 404c2caf3b3SKyle Evans lua_pushinteger(L, WEXITSTATUS(status)); 405c2caf3b3SKyle Evans return (3); 406c2caf3b3SKyle Evans } else if (WIFSIGNALED(status)) { 407c2caf3b3SKyle Evans lua_pushliteral(L, "killed"); 408c2caf3b3SKyle Evans lua_pushinteger(L, WTERMSIG(status)); 409c2caf3b3SKyle Evans return (3); 410c2caf3b3SKyle Evans } 411c2caf3b3SKyle Evans 412c2caf3b3SKyle Evans return (1); 413c2caf3b3SKyle Evans } 414c2caf3b3SKyle Evans 415c2caf3b3SKyle Evans static int 416c2caf3b3SKyle Evans lua_write(lua_State *L) 417c2caf3b3SKyle Evans { 418c2caf3b3SKyle Evans const char *buf; 419c2caf3b3SKyle Evans size_t bufsz, sz; 420c2caf3b3SKyle Evans ssize_t ret; 421c2caf3b3SKyle Evans off_t offset; 422c2caf3b3SKyle Evans int error, fd, narg; 423c2caf3b3SKyle Evans 424c2caf3b3SKyle Evans narg = lua_gettop(L); 425c2caf3b3SKyle Evans luaL_argcheck(L, narg >= 2, 1, 426c2caf3b3SKyle Evans "write takes at least two arguments (fd, buf, sz, off)"); 427c2caf3b3SKyle Evans luaL_argcheck(L, narg <= 4, 5, 428c2caf3b3SKyle Evans "write takes no more than four arguments (fd, buf, sz, off)"); 429c2caf3b3SKyle Evans 430c2caf3b3SKyle Evans fd = luaL_checkinteger(L, 1); 431c2caf3b3SKyle Evans if (fd < 0) { 432c2caf3b3SKyle Evans error = EBADF; 433c2caf3b3SKyle Evans goto err; 434c2caf3b3SKyle Evans } 435c2caf3b3SKyle Evans 436c2caf3b3SKyle Evans buf = luaL_checkstring(L, 2); 437c2caf3b3SKyle Evans 438c2caf3b3SKyle Evans bufsz = sz = lua_rawlen(L, 2); 439c2caf3b3SKyle Evans if (narg >= 3 && !lua_isnil(L, 3)) 440c2caf3b3SKyle Evans sz = luaL_checkinteger(L, 3); 441c2caf3b3SKyle Evans 442c2caf3b3SKyle Evans offset = 0; 443c2caf3b3SKyle Evans if (narg >= 4 && !lua_isnil(L, 4)) 444c2caf3b3SKyle Evans offset = luaL_checkinteger(L, 4); 445c2caf3b3SKyle Evans 446c2caf3b3SKyle Evans if ((size_t)offset > bufsz || offset + sz > bufsz) { 447c2caf3b3SKyle Evans lua_pushnil(L); 448c2caf3b3SKyle Evans lua_pushfstring(L, 449c2caf3b3SKyle Evans "write: invalid access offset %zu, size %zu in a buffer size %zu", 450c2caf3b3SKyle Evans offset, sz, bufsz); 451c2caf3b3SKyle Evans lua_pushinteger(L, EINVAL); 452c2caf3b3SKyle Evans return (3); 453c2caf3b3SKyle Evans } 454c2caf3b3SKyle Evans 455c2caf3b3SKyle Evans ret = write(fd, buf + offset, sz); 456c2caf3b3SKyle Evans if (ret < 0) { 457c2caf3b3SKyle Evans error = errno; 458c2caf3b3SKyle Evans goto err; 459c2caf3b3SKyle Evans } 460c2caf3b3SKyle Evans 461c2caf3b3SKyle Evans lua_pushinteger(L, ret); 462c2caf3b3SKyle Evans return (1); 463c2caf3b3SKyle Evans err: 464c2caf3b3SKyle Evans lua_pushnil(L); 465c2caf3b3SKyle Evans lua_pushstring(L, strerror(error)); 466c2caf3b3SKyle Evans lua_pushinteger(L, error); 467c2caf3b3SKyle Evans return (3); 468c2caf3b3SKyle Evans } 469c2caf3b3SKyle Evans 470c2caf3b3SKyle Evans #define REG_DEF(n, func) { #n, func } 471c2caf3b3SKyle Evans #define REG_SIMPLE(n) REG_DEF(n, lua_ ## n) 472c2caf3b3SKyle Evans static const struct luaL_Reg libgenlib[] = { 473c2caf3b3SKyle Evans REG_SIMPLE(basename), 474c2caf3b3SKyle Evans REG_SIMPLE(dirname), 475c2caf3b3SKyle Evans { NULL, NULL }, 476c2caf3b3SKyle Evans }; 477c2caf3b3SKyle Evans 478c2caf3b3SKyle Evans static const struct luaL_Reg stdliblib[] = { 479c2caf3b3SKyle Evans REG_SIMPLE(realpath), 480c2caf3b3SKyle Evans { NULL, NULL }, 481c2caf3b3SKyle Evans }; 482c2caf3b3SKyle Evans 483*f35ccf46SStefan Eßer static const struct luaL_Reg fnmatchlib[] = { 484*f35ccf46SStefan Eßer REG_SIMPLE(fnmatch), 485*f35ccf46SStefan Eßer { NULL, NULL }, 486*f35ccf46SStefan Eßer }; 487*f35ccf46SStefan Eßer 488405e3338SEd Maste static const struct luaL_Reg sys_statlib[] = { 489405e3338SEd Maste REG_SIMPLE(chmod), 490405e3338SEd Maste { NULL, NULL }, 491405e3338SEd Maste }; 492405e3338SEd Maste 4931726db7aSMark Johnston static const struct luaL_Reg sys_utsnamelib[] = { 4941726db7aSMark Johnston REG_SIMPLE(uname), 4951726db7aSMark Johnston { NULL, NULL }, 4961726db7aSMark Johnston }; 4971726db7aSMark Johnston 498c2caf3b3SKyle Evans static const struct luaL_Reg sys_waitlib[] = { 499c2caf3b3SKyle Evans REG_SIMPLE(wait), 500506f3640SKyle Evans {NULL, NULL}, 501506f3640SKyle Evans }; 502c2caf3b3SKyle Evans 503c2caf3b3SKyle Evans static const struct luaL_Reg unistdlib[] = { 504c2caf3b3SKyle Evans REG_SIMPLE(_exit), 505c2caf3b3SKyle Evans REG_SIMPLE(chown), 506c2caf3b3SKyle Evans REG_DEF(close, lua_pclose), 507c2caf3b3SKyle Evans REG_SIMPLE(fork), 508c2caf3b3SKyle Evans REG_SIMPLE(getpid), 509c2caf3b3SKyle Evans REG_SIMPLE(pipe), 510c2caf3b3SKyle Evans REG_SIMPLE(read), 511c2caf3b3SKyle Evans REG_SIMPLE(write), 512c2caf3b3SKyle Evans { NULL, NULL }, 513c2caf3b3SKyle Evans }; 514c2caf3b3SKyle Evans 515506f3640SKyle Evans #undef REG_SIMPLE 516c2caf3b3SKyle Evans #undef REG_DEF 517c2caf3b3SKyle Evans 518c2caf3b3SKyle Evans int 519c2caf3b3SKyle Evans luaopen_posix_libgen(lua_State *L) 520c2caf3b3SKyle Evans { 521c2caf3b3SKyle Evans luaL_newlib(L, libgenlib); 522c2caf3b3SKyle Evans return (1); 523c2caf3b3SKyle Evans } 524c2caf3b3SKyle Evans 525c2caf3b3SKyle Evans int 526c2caf3b3SKyle Evans luaopen_posix_stdlib(lua_State *L) 527c2caf3b3SKyle Evans { 528c2caf3b3SKyle Evans luaL_newlib(L, stdliblib); 529c2caf3b3SKyle Evans return (1); 530c2caf3b3SKyle Evans } 531506f3640SKyle Evans 532506f3640SKyle Evans int 533*f35ccf46SStefan Eßer luaopen_posix_fnmatch(lua_State *L) 534*f35ccf46SStefan Eßer { 535*f35ccf46SStefan Eßer luaL_newlib(L, fnmatchlib); 536*f35ccf46SStefan Eßer 537*f35ccf46SStefan Eßer #define setkv(f) do { \ 538*f35ccf46SStefan Eßer lua_pushinteger(L, f); \ 539*f35ccf46SStefan Eßer lua_setfield(L, -2, #f); \ 540*f35ccf46SStefan Eßer } while (0) 541*f35ccf46SStefan Eßer setkv(FNM_PATHNAME); 542*f35ccf46SStefan Eßer setkv(FNM_NOESCAPE); 543*f35ccf46SStefan Eßer setkv(FNM_NOMATCH); 544*f35ccf46SStefan Eßer setkv(FNM_PERIOD); 545*f35ccf46SStefan Eßer #undef setkv 546*f35ccf46SStefan Eßer 547*f35ccf46SStefan Eßer return 1; 548*f35ccf46SStefan Eßer } 549*f35ccf46SStefan Eßer 550*f35ccf46SStefan Eßer int 551405e3338SEd Maste luaopen_posix_sys_stat(lua_State *L) 552405e3338SEd Maste { 553405e3338SEd Maste luaL_newlib(L, sys_statlib); 554c2caf3b3SKyle Evans return (1); 555c2caf3b3SKyle Evans } 556c2caf3b3SKyle Evans 557c2caf3b3SKyle Evans int 558c2caf3b3SKyle Evans luaopen_posix_sys_wait(lua_State *L) 559c2caf3b3SKyle Evans { 560c2caf3b3SKyle Evans luaL_newlib(L, sys_waitlib); 561c2caf3b3SKyle Evans 562c2caf3b3SKyle Evans #define lua_pushflag(L, flag) do { \ 563c2caf3b3SKyle Evans lua_pushinteger(L, flag); \ 564c2caf3b3SKyle Evans lua_setfield(L, -2, #flag); \ 565c2caf3b3SKyle Evans } while(0) 566c2caf3b3SKyle Evans 567c2caf3b3SKyle Evans /* Only these two exported by lposix */ 568c2caf3b3SKyle Evans lua_pushflag(L, WNOHANG); 569c2caf3b3SKyle Evans lua_pushflag(L, WUNTRACED); 570c2caf3b3SKyle Evans 571c2caf3b3SKyle Evans lua_pushflag(L, WCONTINUED); 572c2caf3b3SKyle Evans lua_pushflag(L, WSTOPPED); 573aad50785SKyle Evans #ifdef WTRAPPED 574c2caf3b3SKyle Evans lua_pushflag(L, WTRAPPED); 575aad50785SKyle Evans #endif 576c2caf3b3SKyle Evans lua_pushflag(L, WEXITED); 577c2caf3b3SKyle Evans lua_pushflag(L, WNOWAIT); 578c2caf3b3SKyle Evans #undef lua_pushflag 579c2caf3b3SKyle Evans 580c2caf3b3SKyle Evans return (1); 581405e3338SEd Maste } 582405e3338SEd Maste 583405e3338SEd Maste int 5841726db7aSMark Johnston luaopen_posix_sys_utsname(lua_State *L) 5851726db7aSMark Johnston { 5861726db7aSMark Johnston luaL_newlib(L, sys_utsnamelib); 5871726db7aSMark Johnston return 1; 5881726db7aSMark Johnston } 5891726db7aSMark Johnston 5901726db7aSMark Johnston int 591506f3640SKyle Evans luaopen_posix_unistd(lua_State *L) 592506f3640SKyle Evans { 593506f3640SKyle Evans luaL_newlib(L, unistdlib); 594c2caf3b3SKyle Evans return (1); 595506f3640SKyle Evans } 596