Lunix
Lua Unix Module.
Install / Use
/learn @wahern/LunixREADME
About
lunix is a Lua bindings library module to common Unix system APIs. The
module is regularly tested on recent versions of AIX, FreeBSD, Linux/glibc,
Linux/musl, NetBSD, OpenBSD, OS X, and Solaris. The best way to describe it
is in contradistinction to luaposix, the most popular bindings module for
Unix APIs in Lua.
Thread-safety
Unlike luaposix, it strives to be as thread-safe as possible on the host
platform. Interfaces like strerror_r and O_CLOEXEC are used throughout
where appropriate. The module even includes a novel solution for the
inherently non-thread-safe umask system call, where calling umask from
one thread might result in another thread creating a file with unsafe or
unexpected permissions.
POSIX Extensions
Unlike luaposix, the library does not restrict itself to POSIX, and where
possible emulates an interface when not available natively on a supported
platform. For example, the library provides arc4random (absent on Linux
and older Solaris releases), clock_gettime (absent on older macOS
releases), and a thread-safe timegm (absent on Solaris).
Leak-safety
Unlike luaposix, the library prefers dealing with FILE handles rather than
raw integer descriptors. This helps to mitigate and prevent leaks or
double-close bugs---a common source of problems in, e.g., asynchronous
applications where a descriptor is closed that has already been reassigned
to another resource. Routines like chdir, stat, and opendir
transparently accept string paths, FILE handles, DIR handles, and raw
integer descriptors.
Lua Versions
lunix supports the Lua 5.1, 5.2, and 5.3 APIs. lunix supports LuaJIT wth
the caveat that when creating custom FILE handles using fdopen (directly
or indirectly through, e.g., fdup) the process must have read access to an
existing filesystem resource (presently . or /dev/null) in order to
create a LUA_FILEHANDLE object in the VM. This might not work in some
sandboxed environments.
Installation
The usual GNU-style flags are supported, such as CC, CPPFLAGS, CFLAGS,
LDFLAGS, SOFLAGS, and LIBS. ...
TODO. See lunix Userguide PDF
API
Conventions
Namespace
Unlike recent versions of luaposix, interfaces are not grouped into
submodules. (But see unix.unsafe submodule.)
Both Unix and POSIX evolved organically over time and neither
consistently group interfaces, either by header or any other singular
convention. And while theoretically it could done de novo I feel that
might add confusion and is otherwise wasted effort. In C the interfaces
exist in a single namespace. While from a C source language perspective a
small handful of interfaces technically have naming conflicts depending on
which standard is selected at compile-time, in 2016 this is largely a
theoretical problem. Where it does exist (e.g. GNU strerror_r vs POSIX
strerror_r) this can easily be smoothed over transparently by lunix.
f prefix.
Following the example of fopen, lunix implements a sister interface for
some routines to atomically wrap a descriptor within a FILE handle. This
cannot be easily accomplished from Lua script because of the possibility of
memory allocation failure. (Despite a widespread myth, this can easily
happen even on systems like Linux in the presence of process resource
limits, regardless of allocation size.) For example, the lunix routine
fdup behaves just like dup but returns a FILE handle instead of an
integer descriptor. Note that both dup and fdup will accept either an
integer descriptor or FILE handle.
Errors
Generally, errors with argument type or format are thrown using lua_error.
System errors are returned directly using the idiomatic 3-tuple Lua
convention---nil or boolean false, error string description, error integer
code.
Some internal allocation errors are returned as-if they were system errors,
particularly where they arise in the C portion of an emulated routine. In
such a case the call may return with ENOMEM even through neither the local
system nor the POSIX specification specify such an error. Other allocation
errors are thrown, particularly where they occur within the Lua/C preamble
of a binding.
Arithmetic Overflow
The module takes great care to detect arithmetic overflow, including
undefined arithmetic conversions between lua_Integer, lua_Number, and
the relevant system types. When detected arithemtic overflow is generally
treated as a type error and thrown (see Errors, above).
Constants
TODO. See lunix Userguide PDF.
Routines
All of the following routines are implemented though they may not yet be documented. Descriptions for some interfaces may be in the original PDF userguide.
accept
access
alarm
arc4random
arc4random : () -> (integer)
Returns a cryptographically strong, uniformly random 32-bit integer as a Lua
number. On Linux the RANDOM_UUID sysctl feature is used to seed the
generator if available; or on more recent Linux and Solaris kernels the
getrandom interface.[^sysctl_uuid] This avoids fiddling with file
descriptors, and also works in a chroot jail. On other platforms without a
native arc4random interface, such as Solaris 11.2 or earlier, the
implementation must resort to /dev/urandom for seeding.
Note that unlike the original implementation on OpenBSD, arc4random on some older platforms (e.g. FreeBSD prior to 10.10) seeds itself from /dev/urandom. This could cause problems in chroot jails.
[^sysctl_uuid]: Some Linux distributions, such as Red Hat, disable
sysctl(2).
arc4random_buf
arc4random_buf : (n:integer) -> (string)
Returns a string of length $n$ containing cryptographically strong random
octets using the same CSPRNG underlying arc4random.
arc4random_stir
arc4random_stir : () -> (true)
Stir the arc4random entropy pool using the best available resources. This normally should be unnecessary and is a noop on some systems.
arc4random_uniform
arc4random_uniform : (n:integer?) -> (integer)
Returns a cryptographically strong uniform random integer in the interval
$[0, n-1]$ where $n \leq 2^{32}$. If $n$ is omitted the interval is
$[0, 2^{32}-1]$ and effectively behaves like arc4random.
bind
bitand
bitor
chdir
chdir : (path:string|file|fd:integer) -> (true) | (false, string, integer)
If $dir$ is a string, attempts to change the current working directory using
chdir(2). Otherwise, if $dir$ is a FILE handle referencing a
directory, or an integer file descriptor referencing a directory, attempts
to change the current working directory using fchdir(2).
Returns true on success, otherwise returns false, an error string, and
an integer system error.
chmod
chown
chown : (path:string|file|fd:integer, uid?, gid?) -> (true) | (false, string, integer)
$file$ may either be a string path for use with chown(2), or a FILE handle
or integer file descriptor for use with fchown(2). $uid$ and $gid$ may be
integer values or symbolic string names.
Returns true on success, otherwise returns false, an error string, and
an integer system error.
chroot
chroot : (path:string) -> (true) | (false, string, integer)
Attempt to chroot to the specified string $path$.
Returns true on success, otherwise returns false, an error string, and
an integer system error.
clearerr
clock_gettime
clock_gettime : (id:string|id:number) -> (integer) | (nil, string, integer)
$id$ should be the string "realtime" or "monotonic", or the integer
constant CLOCK_REALTIME or CLOCK_MONOTONIC.
Returns a time value as a Lua floating point number, otherwise returns nil,
an error string, and an integer system error.
close
closedir
closedir : (DIR) -> (true) | (false, string, integer)
Closes the DIR handle, releasing the underlying file descriptor.
closelog
compl
connect
dup
dup2
dup3
execve
execve : (path:string, {string*}, {string*}) -> (false, string, integer)
Executes $path$, replacing the existing process image. $path$ should be an
absolute pathname as the $PATH environment variable is not used. $argv$ is
a table or ipairs--iterable object specifying the argument vector to pass to
the new process image. Traditionally the first such argument should be the
basename of $path$, but this is not enforced. If absent or empty the new
process image will be passed an empty argument vector. $env$ is a table or
ipairs--iterable object specifying the new environment. If absent or empty
the new process image will contain an empty environment.
On success never returns. On failure returns false, an error string, and
an integer system error.
execl
execl : (path:string, string*) -> (false, string, integer)
Executes $path$, replacing the existing process image. The $PATH
environment variable is not used. Any subsequent arguments are passed to the
new process image. The new process image inherits the current environment
table.
On success never returns. On failure returns false, an error string, and
an integer system error.
execlp
execlp : (file:string, string*) -> (false, string, integer)
Executes $file$, replacing the existing process image. The $PATH
environment variable is used to search for $file$. Any subsequent arguments
are passed to the new process image. The new process image inherits the
current environment table.
On success never returns. On failure returns false, an error string, and
an integer system error.
execvp
execvp : (file:string, string*) -> (false, string, integer)
Executes $file$, replacing the existing process image. The $PATH
environment variable is used to search for $file$. An
Related Skills
node-connect
343.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
90.0kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
343.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
343.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
