API reference
pledge (name...)
Grants or checks a permission. Returns true if the permission was granted,
false if it was denied or the state is sealed.
The name arguments specify the permissions to grant or check.
Special permissions: "all" grants all permissions (CLI only),
"seal" prevents future permission changes. The ~ prefix
rejects a permission permanently.
pledge("fs") -- grant filesystem access
pledge("fs:read=/tmp") -- grant read access to /tmp only
pledge("~network") -- reject network permission
pledge("seal") -- lock permissions lus_PledgeRequest
typedef struct lus_PledgeRequest {
const char *base; /* "fs", "network", etc. */
const char *sub; /* "read", "tcp", or NULL */
const char *value; /* requested value, or NULL */
const char *current; /* current stored value during iteration */
int status; /* LUS_PLEDGE_GRANT, UPDATE, or CHECK */
int count; /* number of stored values */
int has_base; /* 1 if base permission already granted */
} lus_PledgeRequest; Request structure passed to granter callbacks. Contains all information about the permission being granted or checked.
status indicates the operation: LUS_PLEDGE_GRANT for new
grants,
LUS_PLEDGE_UPDATE for updates, LUS_PLEDGE_CHECK for access
checks.
lus_PledgeGranter
typedef void (*lus_PledgeGranter)(lua_State *L, lus_PledgeRequest *p); Callback type for permission granters. Libraries register granters to handle their own permission validation logic.
Granters should call lus_setpledge to confirm valid permissions. Unprocessed
requests are automatically denied. For invalid subpermissions, use luaL_error to report an error.
Status Constants
#define LUS_PLEDGE_GRANT 0 /* New permission request */
#define LUS_PLEDGE_UPDATE 1 /* Updating existing permission */
#define LUS_PLEDGE_CHECK 2 /* Read-only permission check */
Values for lus_PledgeRequest.status. Granters should handle
GRANT/UPDATE for permission grants and CHECK for access checks.
lus_initpledge
void lus_initpledge(lua_State *L, lus_PledgeRequest *p, const char *base); Initializes a pledge request for C-side grants. This bypasses granters and is used for direct permission grants from C code.
lus_PledgeRequest p;
lus_initpledge(L, &p, "fs");
lus_setpledge(L, &p, "read", "/tmp/*"); lus_nextpledge
int lus_nextpledge(lua_State *L, lus_PledgeRequest *p);
Iterates through stored values for a permission. Sets p->current
to the next stored value.
Returns 1 if there are more values, 0 when done.
while (lus_nextpledge(L, p)) {
if (match(p->current, p->value))
lus_setpledge(L, p, p->sub, NULL);
} lus_setpledge
void lus_setpledge(lua_State *L, lus_PledgeRequest *p,
const char *sub, const char *value); Confirms or sets a pledge value. Marks the request as processed, preventing automatic denial. Must be called by granters to approve a permission.
sub is the subpermission (e.g., "read") or NULL for base.
value is the value to store (e.g., path) or NULL for unrestricted.
lus_rejectrequest
void lus_rejectrequest(lua_State *L, lus_PledgeRequest *p); Permanently rejects a permission using the request struct. Future attempts to grant this permission will fail.
lus_pledgeerror
void lus_pledgeerror(lua_State *L, lus_PledgeRequest *p, const char *msg); Sets a denial error message for user-facing feedback. Called by granters to explain why a permission was denied.
lus_pledge
int lus_pledge(lua_State *L, const char *name, const char *value);
Grants a permission to the Lua state. Triggers the granter callback for
validation. Returns 1 on success, 0 if denied or sealed.
Throws an error if the permission name is not recognized (no granter registered).
lus_haspledge
int lus_haspledge(lua_State *L, const char *name, const char *value);
Checks if a permission has been granted. The value argument specifies
the resource being accessed (e.g., a file path).
Returns 1 if access is allowed, 0 if denied.
lus_registerpledge
void lus_registerpledge(lua_State *L, const char *base, lus_PledgeGranter fn);
Registers a granter callback for a permission namespace. Call this in your
library's luaopen_* function.
static void my_granter(lua_State *L, lus_PledgeRequest *p) {
if (p->status == LUS_PLEDGE_CHECK) {
lus_setpledge(L, p, p->sub, NULL); /* allow */
} else {
lus_setpledge(L, p, p->sub, p->value); /* grant */
}
}
LUAMOD_API int luaopen_mylib(lua_State *L) {
lus_registerpledge(L, "mylib", my_granter);
/* ... */
} lus_rejectpledge
int lus_rejectpledge(lua_State *L, const char *name);
Permanently rejects a permission by name (string-based version). Returns 1 on success, 0 if sealed.
lus_revokepledge
int lus_revokepledge(lua_State *L, const char *name);
Revokes a previously granted permission. Clears all stored values for the
permission. Returns 1 on success, 0 if sealed or not found.
lus_issealed
int lus_issealed(lua_State *L);
Returns 1 if the permission state is sealed, 0 otherwise.
When sealed, no new permissions can be granted or rejected.
lus_checkfsperm
int lus_checkfsperm(lua_State *L, const char *perm, const char *path);
Convenience function for filesystem permission checks. Checks if perm
(e.g., "fs:read") is granted for path. Raises an error if denied.
lus_checkfsperm(L, "fs:read", "/etc/passwd"); /* error if denied */ worker.create (path, ...)
Spawns a new worker running the script at path. Optional varargs
are serialized and can be received by the worker via worker.peek(). Returns a worker handle. Requires load and fs:read pledges.
local w = worker.create("worker.lus", "hello", 42)
-- worker can receive "hello" and 42 via worker.peek() worker.status (w)
Returns the status of worker w: "running" if the worker
is still executing, or "dead" if it has finished or errored.
worker.receive (w1, ...)
Blocking select-style receive from one or more workers. Blocks until at least
one worker has a message. Returns one value per worker: the message if
available, or nil if that worker has no message. Propagates worker
errors.
local msg = worker.receive(w)
-- or multi-worker select:
local m1, m2 = worker.receive(w1, w2) worker.send (w, value)
Sends value to worker w's inbox. The worker can
receive it via worker.peek(). Values are deep-copied.
worker.message (value)
(Worker-side only) Sends value to the worker's outbox for
the parent to receive via worker.receive().
worker.peek ()
(Worker-side only) Blocking receive from the worker's inbox. Blocks until
a message from the parent (via worker.send()) is available.
lus_WorkerSetup
typedef void (*lus_WorkerSetup)(lua_State *parent, lua_State *worker); Callback type for worker state initialization. Called when a new worker is created, allowing embedders to configure the worker's Lua state (e.g., open libraries).
lus_onworker
void lus_onworker(lua_State *L, lus_WorkerSetup fn); Registers a callback to be invoked when new worker states are created. Typically used to open libraries in worker states.
static void worker_setup(lua_State *parent, lua_State *worker) {
luaL_openlibs(worker);
}
lus_onworker(L, worker_setup); lus_worker_pool_init
void lus_worker_pool_init(lua_State *L);
Initializes the global worker thread pool. Called automatically on first
worker.create(). M = number of CPU cores (capped at 32).
lus_worker_pool_shutdown
void lus_worker_pool_shutdown(void); Shuts down the worker thread pool. Waits for all threads to complete.
luaopen_worker
int luaopen_worker(lua_State *L);
Opens the worker library. Called automatically by luaL_openlibs.
debug.parse (code, [chunkname])
Parses a Lus source string and returns its AST (Abstract Syntax Tree) as a
nested table structure. Returns nil if parsing fails.
The optional chunkname argument specifies the name used in error messages
(defaults to "=(parse)").
local ast = debug.parse("local x = 1 + 2")
-- Returns: {type = "chunk", line = 1, children = {...}}
-- With custom chunk name
local ast = debug.parse(code, "myfile.lus")
Each AST node is a table with at minimum type (node type string) and
line (source line number). Additional fields depend on node type. See
Acquis 12 for details.
vector.create (capacity [, fast])
Creates a new vector with the given capacity in bytes. If fast
is true, the buffer is not zero-initialized (faster but contents are undefined).
local v = vector.create(1024) -- zero-initialized
local v = vector.create(1024, true) -- fast, uninitialized vector.pack (v, offset, fmt, ...)
Packs values into the vector v starting at offset.
Uses the same format string as string.pack.
local v = vector.create(16)
vector.pack(v, 0, "I4I4I4", 1, 2, 3) vector.unpack (v, offset, fmt)
Unpacks values from the vector v starting at offset.
Uses the same format string as string.unpack. Returns unpacked values
followed by the next offset.
local a, b, c, nextpos = vector.unpack(v, 0, "I4I4I4") vector.clone (v)
Creates a copy of the vector v.
vector.size (v)
Returns the size of the vector in bytes. Equivalent to #v.
vector.resize (v, newsize)
Resizes the vector to newsize bytes. New bytes are zero-initialized.
Existing data within the new size is preserved.
vector.unpackmany (v, offset, fmt [, count])
Returns an iterator that repeatedly unpacks values from v using the format
fmt. Optional count limits the number of iterations.
for a, b in vector.unpackmany(v, 0, "I4I4") do
print(a, b)
end table.clone (t [, deep])
Creates a copy of the table t. If deep is true, nested tables
are recursively cloned. Deep copies preserve circular references.
local x = table.clone(t) -- shallow copy
local y = table.clone(t, true) -- deep copy
-- Circular references preserved
local t = {}
t.a = t
local c = table.clone(t, true)
assert(c.a == c) __slice
The __slice metamethod is called when the slice operator is used on a table.
It receives the table, start index, and end index (which may be nil).
local mt = {
__slice = function(self, start, finish)
return {start = start, finish = finish}
end
}
local x = setmetatable({}, mt)
local result = x[5, 10] -- calls __slice(x, 5, 10)