mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-02 02:32:27 +00:00
Add more documentation to redbean
This change also improves the unix module, adding a reboot() system call for fun and profit, fixing the execve() api, and a printimage release.
This commit is contained in:
parent
87396f43bc
commit
9bfa6ec06e
16 changed files with 498 additions and 133 deletions
|
@ -121,7 +121,7 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
|
||||||
if (rc == -1 && errno == EFAULT) {
|
if (rc == -1 && errno == EFAULT) {
|
||||||
STRACE("pwritev(%d, %p, %d, %'ld) → %'zd% m", fd, iov, iovlen, off, rc);
|
STRACE("pwritev(%d, %p, %d, %'ld) → %'zd% m", fd, iov, iovlen, off, rc);
|
||||||
} else {
|
} else {
|
||||||
kprintf(STRACE_PROLOGUE "readv(%d, ", fd);
|
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||||
kprintf(", %d, %'ld) → %'ld% m%n", iovlen, off, rc);
|
kprintf(", %d, %'ld) → %'ld% m%n", iovlen, off, rc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||||
if (rc == -1 && errno == EFAULT) {
|
if (rc == -1 && errno == EFAULT) {
|
||||||
STRACE("writev(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
STRACE("writev(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||||
} else {
|
} else {
|
||||||
kprintf(STRACE_PROLOGUE "readv(%d, ", fd);
|
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
|
||||||
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
|
||||||
kprintf(", %d) → %'ld% m%n", iovlen, rc);
|
kprintf(", %d) → %'ld% m%n", iovlen, rc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon reboot,RB_DISABLE_CAD,0,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
|
.syscon reboot,RB_DISABLE_CAD,0,-1,-1,-1,-1,-1
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon reboot,RB_ENABLE_CAD,0x89abcdef,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
|
.syscon reboot,RB_ENABLE_CAD,0x89abcdef,-1,-1,-1,-1,-1
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon reboot,RB_KEXEC,0x45584543,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
|
.syscon reboot,RB_KEXEC,0x45584543,-1,-1,-1,-1,-1
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon reboot,RB_POWERDOWN,0x4321fedc,0xffffffff,0x4000,0x1000,0x808,8
|
.syscon reboot,RB_POWERDOWN,0x4321fedc,-1,0x4000,0x1000,0x808,8
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon reboot,RB_POWEROFF,0x4321fedc,0xffffffff,0x4000,0x1000,0x808,8
|
.syscon reboot,RB_POWEROFF,0x4321fedc,-1,0x4000,0x1000,0x808,8
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon reboot,RB_POWER_OFF,0x4321fedc,0xffffffff,0x4000,0x1000,0x808,8
|
.syscon reboot,RB_POWER_OFF,0x4321fedc,-1,0x4000,0x1000,0x808,8
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#include "libc/sysv/consts/syscon.internal.h"
|
#include "libc/sysv/consts/syscon.internal.h"
|
||||||
.syscon reboot,RB_SW_SUSPEND,0xd000fce2,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xd000fce2
|
.syscon reboot,RB_SW_SUSPEND,0xd000fce2,-1,-1,-1,-1,0xd000fce2
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
extern const uint32_t RB_AUTOBOOT;
|
extern const int RB_AUTOBOOT;
|
||||||
extern const uint32_t RB_POWER_OFF;
|
extern const int RB_POWER_OFF;
|
||||||
extern const uint32_t RB_POWERDOWN;
|
extern const int RB_POWERDOWN;
|
||||||
extern const uint32_t RB_POWEROFF;
|
extern const int RB_POWEROFF;
|
||||||
extern const uint32_t RB_HALT_SYSTEM;
|
extern const int RB_HALT_SYSTEM;
|
||||||
extern const uint32_t RB_HALT;
|
extern const int RB_HALT;
|
||||||
extern const uint32_t RB_SW_SUSPEND;
|
extern const int RB_SW_SUSPEND;
|
||||||
extern const uint32_t RB_KEXEC;
|
extern const int RB_KEXEC;
|
||||||
extern const uint32_t RB_ENABLE_CAD;
|
extern const int RB_ENABLE_CAD;
|
||||||
extern const uint32_t RB_DISABLE_CAD;
|
extern const int RB_DISABLE_CAD;
|
||||||
extern const uint32_t RB_NOSYNC;
|
extern const int RB_NOSYNC;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
26
tool/net/demo/unix2.lua
Normal file
26
tool/net/demo/unix2.lua
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
-- example of how to run the ls command
|
||||||
|
-- and pipe its output to the http user
|
||||||
|
local unix = require "unix"
|
||||||
|
ls = unix.commandv("ls")
|
||||||
|
reader, writer = unix.pipe()
|
||||||
|
if unix.fork() == 0 then
|
||||||
|
unix.close(1)
|
||||||
|
unix.dup(writer)
|
||||||
|
unix.close(writer)
|
||||||
|
unix.close(reader)
|
||||||
|
unix.execve(ls, {ls, "-Shal"})
|
||||||
|
unix.exit(127)
|
||||||
|
else
|
||||||
|
unix.close(writer)
|
||||||
|
SetHeader('Content-Type', 'text/plain')
|
||||||
|
while true do
|
||||||
|
data = unix.read(reader)
|
||||||
|
if data ~= "" then
|
||||||
|
Write(data)
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
unix.close(reader)
|
||||||
|
unix.wait(-1)
|
||||||
|
end
|
|
@ -24,6 +24,17 @@ OVERVIEW
|
||||||
itself is written as a single .c file. It embeds the Lua programming
|
itself is written as a single .c file. It embeds the Lua programming
|
||||||
language and SQLite which let you write dynamic pages.
|
language and SQLite which let you write dynamic pages.
|
||||||
|
|
||||||
|
FEATURES
|
||||||
|
|
||||||
|
- Lua v5.4
|
||||||
|
- SQLite 3.35.5
|
||||||
|
- TLS v1.2 / v1.1 / v1.0
|
||||||
|
- HTTP v1.1 / v1.0 / v0.9
|
||||||
|
- Chromium-Zlib Compression
|
||||||
|
- Statusz Monitoring Statistics
|
||||||
|
- Self-Modifying PKZIP Object Store
|
||||||
|
- Linux + Windows + Mac + FreeBSD + OpenBSD + NetBSD
|
||||||
|
|
||||||
FLAGS
|
FLAGS
|
||||||
|
|
||||||
-h or -? help
|
-h or -? help
|
||||||
|
@ -65,16 +76,53 @@ FLAGS
|
||||||
--strace enables system call tracing
|
--strace enables system call tracing
|
||||||
--ftrace enables function call tracing
|
--ftrace enables function call tracing
|
||||||
|
|
||||||
FEATURES
|
KEYBOARD
|
||||||
|
|
||||||
- Lua v5.4
|
CTRL-D EXIT
|
||||||
- SQLite 3.35.5
|
CTRL-C CTRL-C EXIT
|
||||||
- TLS v1.2 / v1.1 / v1.0
|
CTRL-E END
|
||||||
- HTTP v1.1 / v1.0 / v0.9
|
CTRL-A START
|
||||||
- Chromium-Zlib Compression
|
CTRL-B BACK
|
||||||
- Statusz Monitoring Statistics
|
CTRL-F FORWARD
|
||||||
- Self-Modifying PKZIP Object Store
|
CTRL-L CLEAR
|
||||||
- Linux + Windows + Mac + FreeBSD + OpenBSD + NetBSD
|
CTRL-H BACKSPACE
|
||||||
|
CTRL-D DELETE
|
||||||
|
CTRL-N NEXT HISTORY
|
||||||
|
CTRL-P PREVIOUS HISTORY
|
||||||
|
CTRL-R SEARCH HISTORY
|
||||||
|
CTRL-G CANCEL SEARCH
|
||||||
|
ALT-< BEGINNING OF HISTORY
|
||||||
|
ALT-> END OF HISTORY
|
||||||
|
ALT-F FORWARD WORD
|
||||||
|
ALT-B BACKWARD WORD
|
||||||
|
CTRL-K KILL LINE FORWARDS
|
||||||
|
CTRL-U KILL LINE BACKWARDS
|
||||||
|
ALT-H KILL WORD BACKWARDS
|
||||||
|
CTRL-W KILL WORD BACKWARDS
|
||||||
|
CTRL-ALT-H KILL WORD BACKWARDS
|
||||||
|
ALT-D KILL WORD FORWARDS
|
||||||
|
CTRL-Y YANK
|
||||||
|
ALT-Y ROTATE KILL RING AND YANK AGAIN
|
||||||
|
CTRL-T TRANSPOSE
|
||||||
|
ALT-T TRANSPOSE WORD
|
||||||
|
ALT-U UPPERCASE WORD
|
||||||
|
ALT-L LOWERCASE WORD
|
||||||
|
ALT-C CAPITALIZE WORD
|
||||||
|
CTRL-\ QUIT PROCESS
|
||||||
|
CTRL-S PAUSE OUTPUT
|
||||||
|
CTRL-Q UNPAUSE OUTPUT (IF PAUSED)
|
||||||
|
CTRL-Q ESCAPED INSERT
|
||||||
|
CTRL-ALT-F FORWARD EXPR
|
||||||
|
CTRL-ALT-B BACKWARD EXPR
|
||||||
|
ALT-RIGHT FORWARD EXPR
|
||||||
|
ALT-LEFT BACKWARD EXPR
|
||||||
|
ALT-SHIFT-B BARF EXPR
|
||||||
|
ALT-SHIFT-S SLURP EXPR
|
||||||
|
CTRL-SPACE SET MARK
|
||||||
|
CTRL-X CTRL-X GOTO MARK
|
||||||
|
CTRL-Z SUSPEND PROCESS
|
||||||
|
ALT-\ SQUEEZE ADJACENT WHITESPACE
|
||||||
|
PROTIP REMAP CAPS LOCK TO CTRL
|
||||||
|
|
||||||
USAGE
|
USAGE
|
||||||
|
|
||||||
|
@ -1303,23 +1351,139 @@ UNIX MODULE
|
||||||
`prog` contains slashes then it's not path searched either and
|
`prog` contains slashes then it's not path searched either and
|
||||||
will be returned if it exists.
|
will be returned if it exists.
|
||||||
|
|
||||||
unix.realpath(filename:str) → abspath:str[, errno:int]
|
unix.execve(prog:str[, args:List<*>, env:Map<str,*>]) → errno:int
|
||||||
|
|
||||||
Returns absolute path of filename, with `.` and `..` components
|
|
||||||
removed, and symlinks will be resolved.
|
|
||||||
|
|
||||||
unix.execve(prog, argv[, envp]) → errno
|
|
||||||
|
|
||||||
Exits current process, replacing it with a new instance of the
|
Exits current process, replacing it with a new instance of the
|
||||||
specified program. `prog` needs to be an absolute path, see
|
specified program. `prog` needs to be an absolute path, see
|
||||||
commandv(). `envp` defaults to to the current `environ`. Both
|
commandv(). `env` defaults to to the current `environ`. Here's
|
||||||
`prog` and `envp` are arrays of strings.
|
a basic usage example:
|
||||||
|
|
||||||
unix.execve("/bin/ls", {"/bin/ls", "-hal"})
|
unix.execve("/bin/ls", {"/bin/ls", "-hal"}, {PATH="/bin"})
|
||||||
unix.exit(127)
|
unix.exit(127)
|
||||||
|
|
||||||
The first element in `argv` should be `prog`. This function is
|
`prog` needs to be the resolved pathname of your executable. You
|
||||||
normally called after forking.
|
can use commandv() to search your `PATH`.
|
||||||
|
|
||||||
|
`args` is a string list table. The first element in `args`
|
||||||
|
should be `prog`. Values are coerced to strings. This parameter
|
||||||
|
defaults to `{prog}`.
|
||||||
|
|
||||||
|
`env` is a key/value table. Keys that aren't strings are
|
||||||
|
ignored. Values are coerced to strings. This parameter defaults
|
||||||
|
to environ() in a way that avoids copying.
|
||||||
|
|
||||||
|
execve() function is normally called after fork() returns 0. If
|
||||||
|
that isn't the case, then your redbean worker will be destroyed.
|
||||||
|
|
||||||
|
This function never returns on success.
|
||||||
|
|
||||||
|
`EAGAIN` is returned if you've enforced a max number of
|
||||||
|
processes using `setrlimit(RLIMIT_NPROC)`.
|
||||||
|
|
||||||
|
unix.dup(oldfd:int[, newfd:int[, flags:int]]) → newfd:int, errno:int
|
||||||
|
|
||||||
|
Duplicates file descriptor.
|
||||||
|
|
||||||
|
`newfd` defaults to the lowest number available file descriptor.
|
||||||
|
If the new number is specified and it's already open, then it'll
|
||||||
|
be silently closed before the duplication happens.
|
||||||
|
|
||||||
|
`flags` can have `O_CLOEXEC` which means the returned file
|
||||||
|
descriptors will be automatically closed upon execve().
|
||||||
|
|
||||||
|
unix.pipe([flags]) → reader, writer, errno:int
|
||||||
|
|
||||||
|
Creates fifo which enables communication between processes.
|
||||||
|
Returns two file descriptors: one for reading and one for
|
||||||
|
writing. `flags` can have `O_CLOEXEC`. On error, `reader` and
|
||||||
|
`writer` will be `nil` and `errno` will be set to non-nil.
|
||||||
|
|
||||||
|
Here's an example of how pipe(), fork(), dup(), etc. may be used
|
||||||
|
to serve an HTTP response containing the output of a subprocess.
|
||||||
|
|
||||||
|
local unix = require "unix"
|
||||||
|
ls = unix.commandv("ls")
|
||||||
|
reader, writer = unix.pipe()
|
||||||
|
if unix.fork() == 0 then
|
||||||
|
unix.close(1)
|
||||||
|
unix.dup(writer)
|
||||||
|
unix.close(writer)
|
||||||
|
unix.close(reader)
|
||||||
|
unix.execve(ls, {ls, "-Shal"})
|
||||||
|
unix.exit(127)
|
||||||
|
else
|
||||||
|
unix.close(writer)
|
||||||
|
SetHeader('Content-Type', 'text/plain')
|
||||||
|
while true do
|
||||||
|
data = unix.read(reader)
|
||||||
|
if data ~= "" then
|
||||||
|
Write(data)
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
unix.close(reader)
|
||||||
|
unix.wait(-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
unix.wait([pid:int, options:int])
|
||||||
|
→ pid:int, wstatus:int, nil, errno:int
|
||||||
|
|
||||||
|
Waits for subprocess to terminate.
|
||||||
|
|
||||||
|
`pid` defaults to `-1` which means any child process. Setting
|
||||||
|
`pid` to `0` is equivalent to `-getpid()`. If `pid < -1` then
|
||||||
|
that means wait for any pid in the process group `-pid`. Then
|
||||||
|
lastly if `pid > 0` then this waits for a specific process id
|
||||||
|
|
||||||
|
Options may have `WNOHANG` which means don't block, check for
|
||||||
|
the existence of processes that are already dead (technically
|
||||||
|
speaking zombies) and if so harvest them immediately.
|
||||||
|
|
||||||
|
Returns the process id of the child that terminated. In other
|
||||||
|
cases, the returned `pid` is nil and `errno` is non-nil.
|
||||||
|
|
||||||
|
The returned `wstatus` contains information about the process
|
||||||
|
exit status. It's a complicated integer and there's functions
|
||||||
|
that can help interpret it. For example:
|
||||||
|
|
||||||
|
-- wait for zombies
|
||||||
|
-- traditional technique for SIGCHLD handlers
|
||||||
|
while true do
|
||||||
|
pid, wstatus, errno = unix.wait(-1, unix.WNOHANG)
|
||||||
|
if pid then
|
||||||
|
if unix.WIFEXITED(wstatus) then
|
||||||
|
print('child', pid, 'exited with',
|
||||||
|
unix.WEXITSTATUS(wstatus))
|
||||||
|
elseif unix.WIFSIGNALED(wstatus) then
|
||||||
|
print('child', pid, 'crashed with',
|
||||||
|
unix.strsignal(unix.WTERMSIG(wstatus)))
|
||||||
|
end
|
||||||
|
elseif errno == unix.ECHILD then
|
||||||
|
print('no more zombies')
|
||||||
|
break
|
||||||
|
elseif errno == unix.ECHILD then
|
||||||
|
print('wait failed', unix.strerror(errno))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
unix.getpid() → pid
|
||||||
|
|
||||||
|
Returns process id of current process.
|
||||||
|
|
||||||
|
unix.getppid() → pid
|
||||||
|
|
||||||
|
Returns process id of parent process.
|
||||||
|
|
||||||
|
unix.kill(pid, sig) → rc:int[, errno:int]
|
||||||
|
|
||||||
|
Returns process id of current process.
|
||||||
|
|
||||||
|
unix.raise(sig) → rc:int[, errno:int]
|
||||||
|
|
||||||
|
Triggers signal in current process.
|
||||||
|
This is pretty much the same as `kill(getpid(), sig)`.
|
||||||
|
|
||||||
unix.access(path:str, how) → rc:int[, errno:int]
|
unix.access(path:str, how) → rc:int[, errno:int]
|
||||||
|
|
||||||
|
@ -1347,17 +1511,6 @@ UNIX MODULE
|
||||||
|
|
||||||
Changes root directory. Raises `ENOSYS` on Windows.
|
Changes root directory. Raises `ENOSYS` on Windows.
|
||||||
|
|
||||||
unix.dup(oldfd[, newfd[, flags]]) → newfd:int, errno:int
|
|
||||||
|
|
||||||
Duplicates file descriptor. `flags` can have `O_CLOEXEC`.
|
|
||||||
|
|
||||||
unix.pipe([flags]) → reader, writer, errno:int
|
|
||||||
|
|
||||||
Creates fifo which enables communication between processes.
|
|
||||||
Returns two file descriptors: one for reading and one for
|
|
||||||
writing. `flags` can have `O_CLOEXEC`. On error, `reader` and
|
|
||||||
`writer` will be `nil` and `errno` will be set to non-nil.
|
|
||||||
|
|
||||||
unix.rename(oldpath:str, newpath:str) → rc:int[, errno:int]
|
unix.rename(oldpath:str, newpath:str) → rc:int[, errno:int]
|
||||||
|
|
||||||
Renames file.
|
Renames file.
|
||||||
|
@ -1370,28 +1523,79 @@ UNIX MODULE
|
||||||
|
|
||||||
Creates soft link, or a symbolic link.
|
Creates soft link, or a symbolic link.
|
||||||
|
|
||||||
|
unix.realpath(filename:str) → abspath:str[, errno:int]
|
||||||
|
|
||||||
|
Returns absolute path of filename, with `.` and `..` components
|
||||||
|
removed, and symlinks will be resolved.
|
||||||
|
|
||||||
unix.chown(path:str, uid, gid) → rc:int[, errno:int]
|
unix.chown(path:str, uid, gid) → rc:int[, errno:int]
|
||||||
|
|
||||||
Changes user and gorup on file.
|
Changes user and gorup on file.
|
||||||
|
|
||||||
unix.chmod(path:str, mode) → rc:int[, errno:int]
|
unix.chmod(path:str, mode) → rc:int[, errno:int]
|
||||||
|
|
||||||
|
Changes mode bits on file.
|
||||||
|
|
||||||
unix.getcwd(path:str, mode) → rc:int[, errno:int]
|
unix.getcwd(path:str, mode) → rc:int[, errno:int]
|
||||||
unix.getpid() → pid
|
|
||||||
unix.getppid() → pid
|
Returns current working directory.
|
||||||
unix.kill(pid, sig) → rc:int[, errno:int]
|
|
||||||
unix.raise(sig) → rc:int[, errno:int]
|
unix.fcntl(fd:int, cmd:int[, arg:int]) → rc:int[, errno:int]
|
||||||
unix.wait(pid[, options]) → pid, wstatus, nil, errno:int
|
|
||||||
unix.fcntl(fd:int, cmd[, arg]) → rc:int[, errno:int]
|
Manipulates file descriptor.
|
||||||
|
|
||||||
|
Setting `cmd` to `F_GETFD`, `F_SETFD`, `F_GETFL` or `F_SETFL`
|
||||||
|
lets you query and/or change the status of file descriptors. For
|
||||||
|
example, it's possible using this to change `FD_CLOEXEC`.
|
||||||
|
|
||||||
|
POSIX advisory locks can be controlled by setting `cmd` to
|
||||||
|
`F_UNLCK`, `F_RDLCK`, `F_WRLCK`, `F_SETLK`, or `F_SETLKW`.
|
||||||
|
|
||||||
unix.getsid(pid) → sid, errno:int
|
unix.getsid(pid) → sid, errno:int
|
||||||
|
|
||||||
|
Gets session id.
|
||||||
|
|
||||||
unix.getpgrp() → pgid, errno:int
|
unix.getpgrp() → pgid, errno:int
|
||||||
unix.getpgid(pid) → pgid, errno:int
|
|
||||||
|
Gets process group id.
|
||||||
|
|
||||||
|
unix.setpgrp() → pgid, errno:int
|
||||||
|
|
||||||
|
Sets process group id. This is the same as `setpgid(0,0)`.
|
||||||
|
|
||||||
unix.setpgid(pid, pgid) → pgid, errno:int
|
unix.setpgid(pid, pgid) → pgid, errno:int
|
||||||
|
|
||||||
|
Sets process group id the modern way.
|
||||||
|
|
||||||
|
unix.getpgid(pid) → pgid, errno:int
|
||||||
|
|
||||||
|
Gets process group id the modern wayp.
|
||||||
|
|
||||||
unix.setsid() → sid, errno:int
|
unix.setsid() → sid, errno:int
|
||||||
unix.getuid() → uid, errno:int
|
|
||||||
|
Sets session id.
|
||||||
|
|
||||||
|
This function can be used to create daemons.
|
||||||
|
|
||||||
|
unix.getuid() → uid:int
|
||||||
|
|
||||||
|
Gets user id.
|
||||||
|
|
||||||
|
unix.getgid() → gid:int
|
||||||
|
|
||||||
|
Sets group id.
|
||||||
|
|
||||||
unix.setuid(uid:int) → rc:int[, errno:int]
|
unix.setuid(uid:int) → rc:int[, errno:int]
|
||||||
unix.getgid() → gid, errno:int
|
|
||||||
|
Sets user id.
|
||||||
|
|
||||||
unix.setgid(gid:int) → rc:int[, errno:int]
|
unix.setgid(gid:int) → rc:int[, errno:int]
|
||||||
unix.umask(mask) → rc:int[, errno:int]
|
|
||||||
|
Sets group id.
|
||||||
|
|
||||||
|
unix.umask(mask) → oldmask:int
|
||||||
|
|
||||||
|
Sets file permission mask and returns the old one.
|
||||||
|
|
||||||
unix.syslog(priority:int, msg:str)
|
unix.syslog(priority:int, msg:str)
|
||||||
|
|
||||||
|
@ -1455,17 +1659,42 @@ UNIX MODULE
|
||||||
`type` defaults to `SOCK_STREAM`
|
`type` defaults to `SOCK_STREAM`
|
||||||
`protocol` defaults to `IPPROTO_TCP`
|
`protocol` defaults to `IPPROTO_TCP`
|
||||||
|
|
||||||
unix.bind(fd:int, ip, port) → rc:int[, errno:int]
|
unix.bind(fd:int[, ip:uint32, port:uint16]) → rc:int[, errno:int]
|
||||||
|
|
||||||
unix.connect(fd:int, ip, port) → rc:int[, errno:int]
|
Binds socket.
|
||||||
|
|
||||||
|
`ip` and `port` are in host endian order. For example, if you
|
||||||
|
wanted to listen on `10.0.0.1:31337` you could do:
|
||||||
|
|
||||||
|
unix.bind(sock, 10 << 24 | 0 << 16 | 0 << 8 | 1, 31337)
|
||||||
|
|
||||||
|
By default, `ip` and `port` are set to zero, which means to
|
||||||
|
listen on all interfaces with a kernel-assigned port number that
|
||||||
|
can be retrieved and used as follows:
|
||||||
|
|
||||||
|
local sock = unix.socket()
|
||||||
|
unix.bind(sock)
|
||||||
|
ip, port = unix.getsockname(sock)
|
||||||
|
print("listening on ip", FormatIp(ip), "port", port)
|
||||||
|
unix.listen(sock)
|
||||||
|
unix.accept(sock)
|
||||||
|
while true do
|
||||||
|
client, clientip, clientport = unix.accept(sock)
|
||||||
|
print("got client ip", FormatIp(clientip), "port", clientport)
|
||||||
|
unix.close(client)
|
||||||
|
end
|
||||||
|
|
||||||
unix.listen(fd:int[, backlog]) → rc:int[, errno:int]
|
unix.listen(fd:int[, backlog]) → rc:int[, errno:int]
|
||||||
|
|
||||||
unix.getsockname(fd:int) → ip, port, errno:int
|
Listens for incoming connections on bound socket.
|
||||||
|
|
||||||
unix.getpeername(fd:int) → ip, port, errno:int
|
unix.accept(serverfd) → clientfd:int, ip:uint32, port:uint16[, errno:int]
|
||||||
|
|
||||||
unix.accept(serverfd) → clientfd, ip, port, errno:int
|
unix.connect(fd:int, ip:uint32, port:uint16) → rc:int[, errno:int]
|
||||||
|
|
||||||
|
unix.getsockname(fd:int) → ip:uint32, port:uint16[, errno:int]
|
||||||
|
|
||||||
|
unix.getpeername(fd:int) → ip:uint32, port:uint16[, errno:int]
|
||||||
|
|
||||||
unix.recv(fd:int[, bufsiz[, flags]]) → data, errno:int
|
unix.recv(fd:int[, bufsiz[, flags]]) → data, errno:int
|
||||||
|
|
||||||
|
@ -1496,7 +1725,8 @@ UNIX MODULE
|
||||||
|
|
||||||
`how` can be `SIG_BLOCK`, `SIG_UNBLOCK`, `SIG_SETMASK`
|
`how` can be `SIG_BLOCK`, `SIG_UNBLOCK`, `SIG_SETMASK`
|
||||||
|
|
||||||
unix.sigaction(sig[, handler[, flags[, mask]]]) → handler, flags, mask, errno:int
|
unix.sigaction(sig:int[, handler:func|int[, flags:int[, mask:int]]])
|
||||||
|
→ oldhandler:func|int, flags:int, mask:int, errno:int
|
||||||
|
|
||||||
`handler` can be `SIG_IGN`, `SIG_DFL`, `intptr_t`, or a Lua
|
`handler` can be `SIG_IGN`, `SIG_DFL`, `intptr_t`, or a Lua
|
||||||
function. `sig` can be `SIGINT`, `SIGQUIT`, `SIGTERM`, etc.
|
function. `sig` can be `SIGINT`, `SIGQUIT`, `SIGTERM`, etc.
|
||||||
|
@ -1539,6 +1769,20 @@ UNIX MODULE
|
||||||
unix.sigaction(unix.SIGALRM, MyOnSigAlrm, unix.SA_RESETHAND)
|
unix.sigaction(unix.SIGALRM, MyOnSigAlrm, unix.SA_RESETHAND)
|
||||||
unix.setitimer(unix.ITIMER_REAL, 0, 0, 1, 0)
|
unix.setitimer(unix.ITIMER_REAL, 0, 0, 1, 0)
|
||||||
|
|
||||||
|
unix.reboot(how:int) → str
|
||||||
|
|
||||||
|
Changes power status of system.
|
||||||
|
|
||||||
|
`how` may be `RB_AUTOBOOT` to reboot, `RB_POWER_OFF` to power
|
||||||
|
down, `RB_HALT_SYSTEM` to literally just stop the processor, or
|
||||||
|
`RB_SW_SUSPEND` to put the machine into a suspend state. These
|
||||||
|
magnums will be set to -1 if the method isn't supported on the
|
||||||
|
host platform.
|
||||||
|
|
||||||
|
By default, an implicit sync() is performed. That's to help
|
||||||
|
prevent you from losing data. If you don't want to shutdown
|
||||||
|
gracefully, then you can bitwise or `RB_NOSYNC` into `how`.
|
||||||
|
|
||||||
unix.strerrno(errno:int) → str
|
unix.strerrno(errno:int) → str
|
||||||
|
|
||||||
Turns `errno` code into its symbolic name, e.g. `"EINTR"`.
|
Turns `errno` code into its symbolic name, e.g. `"EINTR"`.
|
||||||
|
|
175
tool/net/lunix.c
175
tool/net/lunix.c
|
@ -52,6 +52,7 @@
|
||||||
#include "libc/sysv/consts/nr.h"
|
#include "libc/sysv/consts/nr.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/ok.h"
|
#include "libc/sysv/consts/ok.h"
|
||||||
|
#include "libc/sysv/consts/reboot.h"
|
||||||
#include "libc/sysv/consts/rlimit.h"
|
#include "libc/sysv/consts/rlimit.h"
|
||||||
#include "libc/sysv/consts/sa.h"
|
#include "libc/sysv/consts/sa.h"
|
||||||
#include "libc/sysv/consts/shut.h"
|
#include "libc/sysv/consts/shut.h"
|
||||||
|
@ -92,6 +93,11 @@ static dontinline int ReturnInteger(lua_State *L, lua_Integer x) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dontinline int ReturnString(lua_State *L, const char *x) {
|
||||||
|
lua_pushstring(L, x);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static dontinline int ReturnTimespec(lua_State *L, struct timespec *ts) {
|
static dontinline int ReturnTimespec(lua_State *L, struct timespec *ts) {
|
||||||
lua_pushinteger(L, ts->tv_sec);
|
lua_pushinteger(L, ts->tv_sec);
|
||||||
lua_pushinteger(L, ts->tv_nsec);
|
lua_pushinteger(L, ts->tv_nsec);
|
||||||
|
@ -132,6 +138,23 @@ static char **ConvertLuaArrayToStringList(lua_State *L, int i) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char **ConvertLuaTableToEnvList(lua_State *L, int i) {
|
||||||
|
int j, n;
|
||||||
|
char **p, *s;
|
||||||
|
luaL_checktype(L, i, LUA_TTABLE);
|
||||||
|
p = xcalloc((n = 0) + 1, sizeof(char *));
|
||||||
|
lua_pushnil(L);
|
||||||
|
for (n = 0; lua_next(L, i);) {
|
||||||
|
if (lua_type(L, -2) == LUA_TSTRING) {
|
||||||
|
p = xrealloc(p, (++n + 1) * sizeof(char *));
|
||||||
|
p[n - 1] = xasprintf("%s=%s", lua_tostring(L, -2), lua_tostring(L, -1));
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
p[n] = 0;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
static void FreeStringList(char **p) {
|
static void FreeStringList(char **p) {
|
||||||
int i;
|
int i;
|
||||||
if (p) {
|
if (p) {
|
||||||
|
@ -145,6 +168,31 @@ static void FreeStringList(char **p) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// System Calls
|
// System Calls
|
||||||
|
|
||||||
|
// unix.getpid() → pid:int
|
||||||
|
static int LuaUnixGetpid(lua_State *L) {
|
||||||
|
return ReturnInteger(L, getpid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix.getppid() → pid:int
|
||||||
|
static int LuaUnixGetppid(lua_State *L) {
|
||||||
|
return ReturnInteger(L, getppid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix.getuid() → uid:int
|
||||||
|
static int LuaUnixGetuid(lua_State *L) {
|
||||||
|
return ReturnInteger(L, getuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix.getgid() → gid:int
|
||||||
|
static int LuaUnixGetgid(lua_State *L) {
|
||||||
|
return ReturnInteger(L, getgid());
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix.umask(mask:int) → oldmask:int
|
||||||
|
static int LuaUnixUmask(lua_State *L) {
|
||||||
|
return ReturnInteger(L, umask(luaL_checkinteger(L, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
// unix.exit([exitcode:int]) → ⊥
|
// unix.exit([exitcode:int]) → ⊥
|
||||||
static wontreturn int LuaUnixExit(lua_State *L) {
|
static wontreturn int LuaUnixExit(lua_State *L) {
|
||||||
_Exit(luaL_optinteger(L, 1, 0));
|
_Exit(luaL_optinteger(L, 1, 0));
|
||||||
|
@ -290,12 +338,11 @@ static int LuaUnixFork(lua_State *L) {
|
||||||
return ReturnRc(L, rc, olderr);
|
return ReturnRc(L, rc, olderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.execve(prog, argv[, envp]) → errno
|
// unix.execve(prog:str[, args:List<*>, env:Map<str,*>]) → errno:int
|
||||||
// unix.exit(127)
|
|
||||||
//
|
//
|
||||||
// unix = require "unix"
|
// unix = require "unix"
|
||||||
// prog = unix.commandv("ls")
|
// prog = unix.commandv("ls")
|
||||||
// unix.execve(prog, {prog, "-hal", "."})
|
// unix.execve(prog, {prog, "-hal", "."}, {PATH="/bin"})
|
||||||
// unix.exit(127)
|
// unix.exit(127)
|
||||||
//
|
//
|
||||||
// prog needs to be absolute, see commandv()
|
// prog needs to be absolute, see commandv()
|
||||||
|
@ -303,20 +350,30 @@ static int LuaUnixFork(lua_State *L) {
|
||||||
static int LuaUnixExecve(lua_State *L) {
|
static int LuaUnixExecve(lua_State *L) {
|
||||||
int olderr;
|
int olderr;
|
||||||
const char *prog;
|
const char *prog;
|
||||||
char **argv, **envp, **freeme;
|
char **argv, **envp, **freeme1, **freeme2, *ezargs[2];
|
||||||
olderr = errno;
|
olderr = errno;
|
||||||
prog = luaL_checkstring(L, 1);
|
prog = luaL_checkstring(L, 1);
|
||||||
argv = ConvertLuaArrayToStringList(L, 2);
|
if (!lua_isnoneornil(L, 2)) {
|
||||||
if (!lua_isnoneornil(L, 3)) {
|
argv = ConvertLuaArrayToStringList(L, 2);
|
||||||
envp = ConvertLuaArrayToStringList(L, 3);
|
freeme1 = argv;
|
||||||
freeme = envp;
|
if (!lua_isnoneornil(L, 3)) {
|
||||||
|
envp = ConvertLuaTableToEnvList(L, 3);
|
||||||
|
freeme2 = envp;
|
||||||
|
} else {
|
||||||
|
envp = environ;
|
||||||
|
freeme2 = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
ezargs[0] = prog;
|
||||||
|
ezargs[1] = 0;
|
||||||
|
argv = ezargs;
|
||||||
envp = environ;
|
envp = environ;
|
||||||
freeme = 0;
|
freeme1 = 0;
|
||||||
|
freeme2 = 0;
|
||||||
}
|
}
|
||||||
execve(prog, argv, envp);
|
execve(prog, argv, envp);
|
||||||
FreeStringList(freeme);
|
FreeStringList(freeme1);
|
||||||
FreeStringList(argv);
|
FreeStringList(freeme2);
|
||||||
lua_pushinteger(L, errno);
|
lua_pushinteger(L, errno);
|
||||||
errno = olderr;
|
errno = olderr;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -401,18 +458,6 @@ static int LuaUnixGetrlimit(lua_State *L) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.getpid() → pid:int
|
|
||||||
static int LuaUnixGetpid(lua_State *L) {
|
|
||||||
lua_pushinteger(L, getpid());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unix.getppid() → pid:int
|
|
||||||
static int LuaUnixGetppid(lua_State *L) {
|
|
||||||
lua_pushinteger(L, getppid());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unix.kill(pid, sig) → rc:int[, errno:int]
|
// unix.kill(pid, sig) → rc:int[, errno:int]
|
||||||
static int LuaUnixKill(lua_State *L) {
|
static int LuaUnixKill(lua_State *L) {
|
||||||
int rc, pid, sig, olderr;
|
int rc, pid, sig, olderr;
|
||||||
|
@ -432,11 +477,11 @@ static int LuaUnixRaise(lua_State *L) {
|
||||||
return ReturnRc(L, rc, olderr);
|
return ReturnRc(L, rc, olderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.wait(pid[, options]) → pid, wstatus, nil, errno
|
// unix.wait([pid, options]) → pid, wstatus, nil, errno
|
||||||
static int LuaUnixWait(lua_State *L) {
|
static int LuaUnixWait(lua_State *L) {
|
||||||
int rc, pid, olderr, options, wstatus;
|
int rc, pid, olderr, options, wstatus;
|
||||||
olderr = errno;
|
olderr = errno;
|
||||||
pid = luaL_checkinteger(L, 1);
|
pid = luaL_optinteger(L, 1, -1);
|
||||||
options = luaL_optinteger(L, 2, 0);
|
options = luaL_optinteger(L, 2, 0);
|
||||||
rc = wait4(pid, &wstatus, options, 0);
|
rc = wait4(pid, &wstatus, options, 0);
|
||||||
if (rc != -1) {
|
if (rc != -1) {
|
||||||
|
@ -517,15 +562,6 @@ static int LuaUnixGetpgid(lua_State *L) {
|
||||||
return ReturnRc(L, rc, olderr);
|
return ReturnRc(L, rc, olderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.umask(mask:int) → rc:int[, errno:int]
|
|
||||||
static int LuaUnixUmask(lua_State *L) {
|
|
||||||
int rc, mask, olderr;
|
|
||||||
olderr = errno;
|
|
||||||
mask = luaL_checkinteger(L, 1);
|
|
||||||
rc = umask(mask);
|
|
||||||
return ReturnRc(L, rc, olderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// unix.setpgid(pid:int, pgid:int) → pgid:int[, errno:int]
|
// unix.setpgid(pid:int, pgid:int) → pgid:int[, errno:int]
|
||||||
static int LuaUnixSetpgid(lua_State *L) {
|
static int LuaUnixSetpgid(lua_State *L) {
|
||||||
int rc, pid, pgid, olderr;
|
int rc, pid, pgid, olderr;
|
||||||
|
@ -554,28 +590,12 @@ static int LuaUnixSetsid(lua_State *L) {
|
||||||
return ReturnRc(L, rc, olderr);
|
return ReturnRc(L, rc, olderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.getuid() → uid[, errno]
|
|
||||||
static int LuaUnixGetuid(lua_State *L) {
|
|
||||||
int rc, olderr;
|
|
||||||
olderr = errno;
|
|
||||||
rc = getuid();
|
|
||||||
return ReturnRc(L, rc, olderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// unix.setuid(uid:int) → rc:int[, errno:int]
|
// unix.setuid(uid:int) → rc:int[, errno:int]
|
||||||
static int LuaUnixSetuid(lua_State *L) {
|
static int LuaUnixSetuid(lua_State *L) {
|
||||||
int olderr = errno;
|
int olderr = errno;
|
||||||
return ReturnRc(L, setuid(luaL_checkinteger(L, 1)), olderr);
|
return ReturnRc(L, setuid(luaL_checkinteger(L, 1)), olderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.getgid() → gid:int[, errno:int]
|
|
||||||
static int LuaUnixGetgid(lua_State *L) {
|
|
||||||
int rc, olderr;
|
|
||||||
olderr = errno;
|
|
||||||
rc = getgid();
|
|
||||||
return ReturnRc(L, rc, olderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// unix.setgid(gid:int) → rc:int[, errno:int]
|
// unix.setgid(gid:int) → rc:int[, errno:int]
|
||||||
static int LuaUnixSetgid(lua_State *L) {
|
static int LuaUnixSetgid(lua_State *L) {
|
||||||
int olderr = errno;
|
int olderr = errno;
|
||||||
|
@ -848,7 +868,7 @@ static int LuaUnixSocketpair(lua_State *L) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.bind(fd, ip, port) → rc:int[, errno:int]
|
// unix.bind(fd[, ip, port]) → rc:int[, errno:int]
|
||||||
// SOCK_CLOEXEC may be or'd into type
|
// SOCK_CLOEXEC may be or'd into type
|
||||||
// family defaults to AF_INET
|
// family defaults to AF_INET
|
||||||
// type defaults to SOCK_STREAM
|
// type defaults to SOCK_STREAM
|
||||||
|
@ -859,8 +879,8 @@ static int LuaUnixBind(lua_State *L) {
|
||||||
bzero(&sa, sizeof(sa));
|
bzero(&sa, sizeof(sa));
|
||||||
olderr = errno;
|
olderr = errno;
|
||||||
fd = luaL_checkinteger(L, 1);
|
fd = luaL_checkinteger(L, 1);
|
||||||
sa.sin_addr.s_addr = htonl(luaL_checkinteger(L, 2));
|
sa.sin_addr.s_addr = htonl(luaL_optinteger(L, 2, 0));
|
||||||
sa.sin_port = htons(luaL_checkinteger(L, 3));
|
sa.sin_port = htons(luaL_optinteger(L, 3, 0));
|
||||||
rc = bind(fd, &sa, sizeof(sa));
|
rc = bind(fd, &sa, sizeof(sa));
|
||||||
return ReturnRc(L, rc, olderr);
|
return ReturnRc(L, rc, olderr);
|
||||||
}
|
}
|
||||||
|
@ -928,7 +948,7 @@ static int LuaUnixGetpeername(lua_State *L) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.accept(serverfd) → clientfd, ip, port, errno
|
// unix.accept(serverfd:int) → clientfd:int, ip:uint32, port:uint16, errno
|
||||||
static int LuaUnixAccept(lua_State *L) {
|
static int LuaUnixAccept(lua_State *L) {
|
||||||
uint32_t addrsize;
|
uint32_t addrsize;
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
|
@ -1237,20 +1257,42 @@ static int LuaUnixSetitimer(lua_State *L) {
|
||||||
|
|
||||||
// unix.strerror(errno) → str
|
// unix.strerror(errno) → str
|
||||||
static int LuaUnixStrerror(lua_State *L) {
|
static int LuaUnixStrerror(lua_State *L) {
|
||||||
lua_pushstring(L, strerror(luaL_checkinteger(L, 1)));
|
return ReturnString(L, strerror(luaL_checkinteger(L, 1)));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.strerrno(errno) → str
|
// unix.strerrno(errno) → str
|
||||||
static int LuaUnixStrerrno(lua_State *L) {
|
static int LuaUnixStrerrno(lua_State *L) {
|
||||||
lua_pushstring(L, strerror_short(luaL_checkinteger(L, 1)));
|
return ReturnString(L, strerror_short(luaL_checkinteger(L, 1)));
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unix.strsignal(sig) → str
|
// unix.strsignal(sig) → str
|
||||||
static int LuaUnixStrsignal(lua_State *L) {
|
static int LuaUnixStrsignal(lua_State *L) {
|
||||||
lua_pushstring(L, strsignal(luaL_checkinteger(L, 1)));
|
return ReturnString(L, strsignal(luaL_checkinteger(L, 1)));
|
||||||
return 1;
|
}
|
||||||
|
|
||||||
|
// unix.WIFEXITED(wstatus) → int
|
||||||
|
static int LuaUnixWifexited(lua_State *L) {
|
||||||
|
return ReturnInteger(L, WIFEXITED(luaL_checkinteger(L, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix.WEXITSTATUS(wstatus) → int
|
||||||
|
static int LuaUnixWexitstatus(lua_State *L) {
|
||||||
|
return ReturnInteger(L, WEXITSTATUS(luaL_checkinteger(L, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix.WIFSIGNALED(wstatus) → int
|
||||||
|
static int LuaUnixWifsignaled(lua_State *L) {
|
||||||
|
return ReturnInteger(L, WIFSIGNALED(luaL_checkinteger(L, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix.WTERMSIG(wstatus) → int
|
||||||
|
static int LuaUnixWtermsig(lua_State *L) {
|
||||||
|
return ReturnInteger(L, WTERMSIG(luaL_checkinteger(L, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// unix.reboot(how:int) → rc:int[, errno:int]
|
||||||
|
static int LuaUnixReboot(lua_State *L) {
|
||||||
|
return ReturnInteger(L, reboot(luaL_checkinteger(L, 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -1549,9 +1591,14 @@ static const luaL_Reg kLuaUnix[] = {
|
||||||
{"sigprocmask", LuaUnixSigprocmask}, // change signal mask
|
{"sigprocmask", LuaUnixSigprocmask}, // change signal mask
|
||||||
{"sigsuspend", LuaUnixSigsuspend}, // wait for signal
|
{"sigsuspend", LuaUnixSigsuspend}, // wait for signal
|
||||||
{"setitimer", LuaUnixSetitimer}, // set alarm clock
|
{"setitimer", LuaUnixSetitimer}, // set alarm clock
|
||||||
|
{"reboot", LuaUnixReboot}, // reboots system
|
||||||
{"strerror", LuaUnixStrerror}, // turn errno into string
|
{"strerror", LuaUnixStrerror}, // turn errno into string
|
||||||
{"strerrno", LuaUnixStrerrno}, // turn errno into string
|
{"strerrno", LuaUnixStrerrno}, // turn errno into string
|
||||||
{"strsignal", LuaUnixStrsignal}, // turn signal into string
|
{"strsignal", LuaUnixStrsignal}, // turn signal into string
|
||||||
|
{"WIFEXITED", LuaUnixWifexited}, // gets exit code from wait status
|
||||||
|
{"WEXITSTATUS", LuaUnixWexitstatus}, // gets exit status from wait status
|
||||||
|
{"WIFSIGNALED", LuaUnixWifsignaled}, // determines if died due to signal
|
||||||
|
{"WTERMSIG", LuaUnixWtermsig}, // gets the signal code
|
||||||
{0}, //
|
{0}, //
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1643,6 +1690,7 @@ int LuaUnix(lua_State *L) {
|
||||||
|
|
||||||
// wait() options
|
// wait() options
|
||||||
LuaSetIntField(L, "WNOHANG", WNOHANG);
|
LuaSetIntField(L, "WNOHANG", WNOHANG);
|
||||||
|
LuaSetIntField(L, "WNOHANG", WNOHANG);
|
||||||
|
|
||||||
// gettime() clocks
|
// gettime() clocks
|
||||||
LuaSetIntField(L, "CLOCK_REALTIME", CLOCK_REALTIME); // portable
|
LuaSetIntField(L, "CLOCK_REALTIME", CLOCK_REALTIME); // portable
|
||||||
|
@ -1721,5 +1769,12 @@ int LuaUnix(lua_State *L) {
|
||||||
LuaSetIntField(L, "LOG_INFO", LOG_INFO);
|
LuaSetIntField(L, "LOG_INFO", LOG_INFO);
|
||||||
LuaSetIntField(L, "LOG_DEBUG", LOG_DEBUG);
|
LuaSetIntField(L, "LOG_DEBUG", LOG_DEBUG);
|
||||||
|
|
||||||
|
// reboot() howto
|
||||||
|
LuaSetIntField(L, "RB_AUTOBOOT", RB_AUTOBOOT);
|
||||||
|
LuaSetIntField(L, "RB_POWER_OFF", RB_POWER_OFF);
|
||||||
|
LuaSetIntField(L, "RB_HALT_SYSTEM", RB_HALT_SYSTEM);
|
||||||
|
LuaSetIntField(L, "RB_SW_SUSPEND", RB_SW_SUSPEND);
|
||||||
|
LuaSetIntField(L, "RB_NOSYNC", RB_NOSYNC);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,7 @@ o/$(MODE)/tool/net/redbean-demo.com.dbg: \
|
||||||
o/$(MODE)/tool/net/net.pkg \
|
o/$(MODE)/tool/net/net.pkg \
|
||||||
o/$(MODE)/tool/net/demo/sql.lua.zip.o \
|
o/$(MODE)/tool/net/demo/sql.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/unix.lua.zip.o \
|
o/$(MODE)/tool/net/demo/unix.lua.zip.o \
|
||||||
|
o/$(MODE)/tool/net/demo/unix2.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/fetch.lua.zip.o \
|
o/$(MODE)/tool/net/demo/fetch.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/hello.lua.zip.o \
|
o/$(MODE)/tool/net/demo/hello.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/demo/redbean.lua.zip.o \
|
o/$(MODE)/tool/net/demo/redbean.lua.zip.o \
|
||||||
|
|
|
@ -53,12 +53,15 @@
|
||||||
#include "third_party/stb/stb_image.h"
|
#include "third_party/stb/stb_image.h"
|
||||||
#include "tool/viz/lib/graphic.h"
|
#include "tool/viz/lib/graphic.h"
|
||||||
|
|
||||||
|
STATIC_YOINK("__zipos_get");
|
||||||
|
|
||||||
static struct Flags {
|
static struct Flags {
|
||||||
const char *out;
|
const char *out;
|
||||||
bool subpixel;
|
bool subpixel;
|
||||||
bool unsharp;
|
bool unsharp;
|
||||||
bool dither;
|
bool dither;
|
||||||
bool ruler;
|
bool ruler;
|
||||||
|
bool magikarp;
|
||||||
bool trailingnewline;
|
bool trailingnewline;
|
||||||
long half;
|
long half;
|
||||||
bool full;
|
bool full;
|
||||||
|
@ -85,6 +88,7 @@ FLAGS\n\
|
||||||
-f display full size\n\
|
-f display full size\n\
|
||||||
-s unsharp sharpening\n\
|
-s unsharp sharpening\n\
|
||||||
-x xterm256 color mode\n\
|
-x xterm256 color mode\n\
|
||||||
|
-m use magikarp scaling\n\
|
||||||
-d hilbert curve dithering\n\
|
-d hilbert curve dithering\n\
|
||||||
-r display pixel ruler on sides\n\
|
-r display pixel ruler on sides\n\
|
||||||
-p convert to subpixel layout\n\
|
-p convert to subpixel layout\n\
|
||||||
|
@ -94,7 +98,6 @@ FLAGS\n\
|
||||||
EXAMPLES\n\
|
EXAMPLES\n\
|
||||||
\n\
|
\n\
|
||||||
printimage.com -sxd lemurs.jpg # 256-color dither unsharp\n\
|
printimage.com -sxd lemurs.jpg # 256-color dither unsharp\n\
|
||||||
\n\
|
|
||||||
\n");
|
\n");
|
||||||
exit(rc);
|
exit(rc);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +121,7 @@ static void GetOpts(int *argc, char *argv[]) {
|
||||||
(strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-help") == 0)) {
|
(strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-help") == 0)) {
|
||||||
PrintUsage(EXIT_SUCCESS, stdout);
|
PrintUsage(EXIT_SUCCESS, stdout);
|
||||||
}
|
}
|
||||||
while ((opt = getopt(*argc, argv, "?vpfrtxads234o:w:h:")) != -1) {
|
while ((opt = getopt(*argc, argv, "?vpmfrtxads234o:w:h:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'o':
|
case 'o':
|
||||||
g_flags.out = optarg;
|
g_flags.out = optarg;
|
||||||
|
@ -146,6 +149,9 @@ static void GetOpts(int *argc, char *argv[]) {
|
||||||
case 'r':
|
case 'r':
|
||||||
g_flags.ruler = true;
|
g_flags.ruler = true;
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
g_flags.magikarp = true;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
g_flags.subpixel = true;
|
g_flags.subpixel = true;
|
||||||
break;
|
break;
|
||||||
|
@ -173,10 +179,6 @@ static void GetOpts(int *argc, char *argv[]) {
|
||||||
PrintUsage(EX_USAGE, stderr);
|
PrintUsage(EX_USAGE, stderr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (optind == *argc) {
|
|
||||||
if (!g_flags.out) g_flags.out = "-";
|
|
||||||
argv[(*argc)++] = "-";
|
|
||||||
}
|
|
||||||
if (!g_flags.full && (!g_flags.width || !g_flags.width)) {
|
if (!g_flags.full && (!g_flags.width || !g_flags.width)) {
|
||||||
ws.ws_col = 80;
|
ws.ws_col = 80;
|
||||||
ws.ws_row = 24;
|
ws.ws_row = 24;
|
||||||
|
@ -398,6 +400,22 @@ void WithImageFile(const char *path,
|
||||||
sxn = xn;
|
sxn = xn;
|
||||||
dyn = g_flags.height;
|
dyn = g_flags.height;
|
||||||
dxn = g_flags.width;
|
dxn = g_flags.width;
|
||||||
|
if (g_flags.magikarp) {
|
||||||
|
while (HALF(syn) > dyn || HALF(sxn) > dxn) {
|
||||||
|
if (HALF(sxn) > dxn) {
|
||||||
|
Magikarp2xX(yn, xn, data, syn, sxn);
|
||||||
|
Magikarp2xX(yn, xn, (char *)data + yn * xn, syn, sxn);
|
||||||
|
Magikarp2xX(yn, xn, (char *)data + yn * xn * 2, syn, sxn);
|
||||||
|
sxn = HALF(sxn);
|
||||||
|
}
|
||||||
|
if (HALF(syn) > dyn) {
|
||||||
|
Magikarp2xY(yn, xn, data, syn, sxn);
|
||||||
|
Magikarp2xY(yn, xn, (char *)data + yn * xn, syn, sxn);
|
||||||
|
Magikarp2xY(yn, xn, (char *)data + yn * xn * 2, syn, sxn);
|
||||||
|
syn = HALF(syn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
data = EzGyarados(3, dyn, dxn, gc(memalign(32, dyn * dxn * 3)), cn, yn, xn,
|
data = EzGyarados(3, dyn, dxn, gc(memalign(32, dyn * dxn * 3)), cn, yn, xn,
|
||||||
data, 0, cn, dyn, dxn, syn, sxn, 0, 0, 0, 0);
|
data, 0, cn, dyn, dxn, syn, sxn, 0, 0, 0, 0);
|
||||||
yn = dyn;
|
yn = dyn;
|
||||||
|
@ -410,6 +428,7 @@ int main(int argc, char *argv[]) {
|
||||||
int i;
|
int i;
|
||||||
ShowCrashReports();
|
ShowCrashReports();
|
||||||
GetOpts(&argc, argv);
|
GetOpts(&argc, argv);
|
||||||
|
if (optind == argc) PrintUsage(0, stdout);
|
||||||
stbi_set_unpremultiply_on_load(true);
|
stbi_set_unpremultiply_on_load(true);
|
||||||
for (i = optind; i < argc; ++i) {
|
for (i = optind; i < argc; ++i) {
|
||||||
WithImageFile(argv[i], ProcessImage);
|
WithImageFile(argv[i], ProcessImage);
|
||||||
|
|
|
@ -45,6 +45,7 @@ TOOL_VIZ_DIRECTDEPS = \
|
||||||
LIBC_TINYMATH \
|
LIBC_TINYMATH \
|
||||||
LIBC_UNICODE \
|
LIBC_UNICODE \
|
||||||
LIBC_X \
|
LIBC_X \
|
||||||
|
LIBC_ZIPOS \
|
||||||
NET_HTTP \
|
NET_HTTP \
|
||||||
THIRD_PARTY_DLMALLOC \
|
THIRD_PARTY_DLMALLOC \
|
||||||
THIRD_PARTY_GDTOA \
|
THIRD_PARTY_GDTOA \
|
||||||
|
@ -71,6 +72,25 @@ o/$(MODE)/tool/viz/%.com.dbg: \
|
||||||
$(APE)
|
$(APE)
|
||||||
@$(APELINK)
|
@$(APELINK)
|
||||||
|
|
||||||
|
o/$(MODE)/tool/viz/printimage.com.dbg: \
|
||||||
|
$(TOOL_VIZ_DEPS) \
|
||||||
|
o/$(MODE)/tool/viz/printimage.o \
|
||||||
|
o/$(MODE)/tool/viz/viz.pkg \
|
||||||
|
o/$(MODE)/LICENSE.zip.o \
|
||||||
|
$(CRT) \
|
||||||
|
$(APE_NO_MODIFY_SELF)
|
||||||
|
@$(APELINK)
|
||||||
|
|
||||||
|
o/$(MODE)/tool/viz/printimage.com: \
|
||||||
|
o/$(MODE)/tool/viz/printimage.com.dbg \
|
||||||
|
o/$(MODE)/third_party/zip/zip.com \
|
||||||
|
o/$(MODE)/tool/build/symtab.com
|
||||||
|
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
|
||||||
|
@$(COMPILE) -ASYMTAB o/$(MODE)/tool/build/symtab.com \
|
||||||
|
-o o/$(MODE)/tool/viz/.printimage/.symtab $<
|
||||||
|
@$(COMPILE) -AZIP -T$@ o/$(MODE)/third_party/zip/zip.com -9qj $@ \
|
||||||
|
o/$(MODE)/tool/viz/.printimage/.symtab
|
||||||
|
|
||||||
o/$(MODE)/tool/viz/printvideo.com: \
|
o/$(MODE)/tool/viz/printvideo.com: \
|
||||||
o/$(MODE)/tool/viz/printvideo.com.dbg \
|
o/$(MODE)/tool/viz/printvideo.com.dbg \
|
||||||
o/$(MODE)/third_party/zip/zip.com \
|
o/$(MODE)/third_party/zip/zip.com \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue