sys() — Direct Syscalls
Nitpick provides direct syscall access at three safety levels to balance developer control with process integrity.
| Function | Tier | Syscalls Available | Return Type | TOS Layer |
|---|---|---|---|---|
sys(CONST, args...) |
Safe | 72 curated whitelist | Result<int64> or Result<string> |
Layer 1 |
sys!!(CONST, args...) |
Full | All syscalls | Result<int64> or Result<string> |
Layer 2 |
sys!!!(expr, args...) |
Raw | Any int64 expression | int64 (bare) |
Layer 3 |
Safe Tier — sys()
The safe tier uses a curated whitelist of 72 syscalls. This tier guarantees that process integrity cannot be compromised (e.g., you cannot accidentally fork or kill a process).
Note: The compiler requires a named constant as the first argument to
sys(). These builtin constants (e.g.,WRITE,OPEN) do not have theSYS_prefix. TheSYS_prefixed constants are exported bystdlib/sys.npkfor use in the raw tier. ```nitpick // Builtin safe tier usage: sys(WRITE, ...)// Raw tier usage using stdlib constants: int64:nr = SYS_WRITE; sys!!!(nr, ...) ```
Safe Syscall Whitelist
| Category | Syscalls | Count |
|---|---|---|
| File I/O | READ, WRITE, OPEN, CLOSE, LSEEK, PREAD64, PWRITE64, OPENAT, READV, WRITEV |
10 |
| File Metadata | FSTAT, NEWFSTATAT, FCHMOD, FCHOWN, UTIMENSAT, FACCESSAT |
6 |
| Memory | MMAP, MUNMAP, MPROTECT, BRK, MREMAP |
5 |
| Directory & Links | GETDENTS64, GETCWD, CHDIR, MKDIR, RMDIR, RENAME, RENAMEAT2, UNLINK, UNLINKAT, SYMLINK, READLINK |
11 |
| Process Info | GETPID, GETPPID, GETTID, GETUID, GETGID, GETEUID, GETEGID |
7 |
| Time | CLOCK_GETTIME, CLOCK_NANOSLEEP, NANOSLEEP |
3 |
| Networking | SOCKET, BIND, LISTEN, ACCEPT4, CONNECT, SEND, RECV, SENDTO, RECVFROM, SETSOCKOPT, GETSOCKOPT, SHUTDOWN |
12 |
| Polling | POLL, PPOLL, EPOLL_CREATE1, EPOLL_CTL, EPOLL_WAIT, SELECT, PSELECT6 |
7 |
| Pipe / IPC | PIPE2, DUP, DUP2, DUP3, EVENTFD2 |
5 |
| Misc Safe | IOCTL, FCNTL, FLOCK, FSYNC, FDATASYNC, GETRANDOM |
6 |
| Total | 72 |
Inclusion Rationale
- I/O & File Ops: These are fundamental operations required for typical programming that do not cause privilege escalation.
- Process Info: Read-only queries that have no side effects on the process state.
- Networking: Standard operations safe for user-level network programming.
- Memory: Safe when properly typed, though care is required.
Exclusion Rationale (Moved to Full Tier)
FORK/CLONE: Process creation is complex and easy to misuse, potentially breaking the application model.KILL: Signal delivery can maliciously or accidentally terminate other processes.PTRACE: Debugging syscalls allow arbitrary inspection and modification of processes.SETUID/SETGID: Privilege changes are highly security-critical operations.
Typed Returns
Some syscalls return structured data instead of a plain integer. The compiler automatically handles the buffer management.
Result — GETCWD, READLINK
// GETCWD: returns the current working directory as a string
Result<string>:cwd = sys(GETCWD);
string:dir = cwd ? "/unknown";
println(dir);
// READLINK: resolves a symbolic link target
Result<string>:target = sys(READLINK, "/proc/self/exe");
string:path = target ? "";
These syscalls internally:
1. Allocate a temporary 4096-byte buffer via mmap.
2. Execute the syscall writing into the buffer.
3. Copy the result into a managed Nitpick string.
4. Release the temporary buffer via munmap.
Variants:
- sys(GETCWD) — uses the default 4096-byte buffer.
- sys(GETCWD, size) — uses the specified buffer size in bytes.
Full Tier — sys!!()
All syscalls are available in this tier, including dangerous ones, but it still wraps the return value in a Result type:
int64:result = sys!!(SETUID, 0i64) ? -1i64;
Raw Tier Usage Guidelines
The sys!!!() tier accepts any int64 expression as the syscall number and returns a bare int64 (no Result wrapper).
When to use sys!!!:
- Only for truly exotic syscalls not in any constant table.
- For performance-critical hot paths where the Result wrapper overhead matters.
- Calling a newer kernel syscall not yet present in Nitpick's builtin tables.
Risks:
- No errno wrapping.
- No compile-time argument validation.
Raw Tier Error Handling:
The raw tier returns the exact kernel return value, which means errors are returned as negative errno values.
int64:ret = sys!!!(1i64, 1i64, "hello\n", 6i64); // raw WRITE
if (ret < 0i64) {
// ret is -errno (e.g., -9 = EBADF)
int64:errno = 0i64 - ret;
println("Error!");
}
Known Issue
⚠️ Known Issue: String literals passed directly to
sys()may fail to compile correctly due to an IR conversion issue.Store the string in a variable first: ```nitpick // WRONG: // sys(WRITE, 1i64, "hello\n", 6i64);
// RIGHT: string:msg = "hello\n"; sys(WRITE, 1i64, msg, 6i64); ``` Note: This is tracked for a future fix and is not blocking.
Related
- file_io.md — higher-level file operations
- control_flow/error_flow.md — error handling tiers
aria-syscalls(7)— man page reference