TonicBoxOS · language reference

TBC standard library

There is no libc. Every program is compiled with this small built-in prelude of thin syscall wrappers, plus the raw __sys intrinsic underneath. That is the entire standard library - anything else you write yourself.

functions 48source the compiler prelude← TBC referencesyscall reference →

01I/O & terminal

write

int write(int fd, char* buf, int n)

Write n bytes from buf to file descriptor fd.

parammeaning
fddestination descriptor: 1 = stdout, 2 = stderr, 3+ = an open file
bufsource buffer
nnumber of bytes to write

Returns the number of bytes written (always n)   syscall 1

read

int read(int fd, char* buf, int n)

Read up to n bytes from file descriptor fd into buf. On the terminal (fd 0) a line-mode read stops at the newline; in raw mode (see set_raw) it returns keystrokes as they arrive. Blocks until input is available; returns 0 at end of input (Ctrl-D).

parammeaning
fdsource descriptor: 0 = stdin, 3+ = an open file
bufdestination buffer
nmaximum bytes to read

Returns the number of bytes read, or 0 at EOF   syscall 0

open

int open(char* p, int fl)

Open the file at path p and return a descriptor for it.

parammeaning
pabsolute or working-directory-relative path
flflags: 0 = read-only, O_WRONLY 1, O_RDWR 2, O_CREAT 0x40, O_TRUNC 0x200, O_APPEND 0x400 (or them together)

Returns a descriptor (>= 3) on success, or a negative errno (-2 no such file, -13 permission denied, -21 is a directory)   syscall 2

close

int close(int fd)

Close descriptor fd, releasing it for reuse.

parammeaning
fdthe descriptor to close

Returns 0   syscall 3

set_raw

int set_raw(int on)

Toggle raw terminal mode. In raw mode read(0, ...) returns individual keystrokes instead of buffering a whole line, which is what full-screen programs like vi need. A child process inherits line mode on exit.

parammeaning
onnonzero to enable raw mode, 0 to return to line mode

Returns 0   syscall 26

read_nb

int read_nb(int fd, char* buf, int len)

The non-blocking counterpart to read: pull up to len bytes that are already waiting into buf, without ever blocking. Reads the console stdin regardless of fd. Pair it with msleep to drive a responsive game or event loop that never stalls waiting for a key.

parammeaning
fdignored (the console is always the source)
bufdestination buffer
lenmaximum bytes to read

Returns the number of bytes read, or 0 if none are ready   syscall 78

ioctl

int ioctl(int fd, int req, char* arg)

Device control. On the console tty this queries or sets terminal parameters: req selects the operation (e.g. TIOCGWINSZ 0x5413 fills a winsize struct, TCGETS 0x5401 / TCSETS 0x5402 read/write a termios struct) and arg points to the operation's in/out buffer.

parammeaning
fdthe descriptor (0/1/2 = the console tty)
reqthe request code
argpointer to the request's argument buffer

Returns the driver-defined result, or -25 (ENOTTY) on a non-device   syscall 72

02System

msleep

int msleep(int ms)

Sleep for ms milliseconds of real time, then return. Millisecond pacing for animation and real-time loops; combine with read_nb for a loop that ticks on a fixed clock while still reacting to input.

parammeaning
msmilliseconds to sleep

Returns 0 once the interval has elapsed   syscall 73

getrandom

int getrandom(int* p, int n)

Fill p with n random bytes from the userland PRNG. Suitable for games and general randomness; it is not the cryptographic source behind ASLR.

parammeaning
pbuffer to fill
nnumber of bytes to write

Returns 0   syscall 28

03Filesystem

stat

int stat(char* p, char* buf)

Fill buf with metadata about path p: five little-endian int fields laid out as mode@0, uid@4, size@8, type@12 (1 = file, 2 = directory), gid@16.

parammeaning
ppath to inspect
bufa 20-byte buffer for the five fields

Returns 0 on success, or -2 if p does not exist   syscall 5

listdir

int listdir(char* p, char* b, int n)

List directory p, writing its entry names newline-separated into b.

parammeaning
pdirectory path
bdestination buffer
ncapacity of b in bytes

Returns the number of bytes written, or -2 if p is not a directory   syscall 7

getcwd

int getcwd(char* b, int n)

Copy the current working directory into b.

parammeaning
bdestination buffer
ncapacity of b in bytes

Returns the length copied   syscall 9

chdir

int chdir(char* p)

Change the current working directory to p.

parammeaning
ptarget directory

Returns 0 on success, or a negative errno   syscall 25

int unlink(char* p)

Remove the file at path p.

parammeaning
pfile to remove

Returns 0 on success, or a negative errno   syscall 15

mkdir

int mkdir(char* p, int m)

Create directory p with permission bits m.

parammeaning
pnew directory path
moctal permission bits, e.g. 0755

Returns 0 on success, or a negative errno   syscall 16

rmdir

int rmdir(char* p)

Remove the empty directory at path p.

parammeaning
pdirectory to remove

Returns 0 on success, or a negative errno   syscall 17

rename

int rename(char* a, char* b)

Rename path a to path b.

parammeaning
aexisting path
bnew path

Returns 0 on success, or a negative errno   syscall 18

chmod

int chmod(char* p, int m)

Set the permission bits of path p to m.

parammeaning
ppath to modify
moctal permission bits, e.g. 0644

Returns 0 on success, or a negative errno   syscall 19

chown

int chown(char* p, int u)

Set the owner user id of path p to u.

parammeaning
ppath to modify
unew owner uid

Returns 0 on success, or a negative errno   syscall 23

04Process

srun

int srun(int c, int v)

Run one already-expanded command as a foreground child and wait for it: a fused fork + exec + wait that returns the child's exit code. v is an array of char* argument addresses (v[0] is the path); set-user-ID / set-group-ID bits on the target are honored. It does no I/O plumbing of its own - real redirection uses fork + pipe + dup2 (all in this prelude); cc uses srun to invoke the assembler.

parammeaning
cargument count (argc)
vargument vector: the address of an array of char* (argv)

Returns the child's exit code   syscall 24

exit

void exit(int c)

Terminate the current process with status c. Does not return.

parammeaning
cexit status

syscall 11

05Identity

getuid

int getuid()

Return the real user id of the current process.

Returns the real uid   syscall 13

geteuid

int geteuid()

Return the effective user id, which differs from the real uid while a setuid program is running (this is what the guestbook exploit escalates).

Returns the effective uid   syscall 14

06Strings

strlen

int strlen(char* s)

Return the length of the NUL-terminated string s. This is the only prelude function that is pure TBC rather than a syscall wrapper.

parammeaning
sa NUL-terminated string

Returns the number of bytes before the terminating NUL

strcmp

int strcmp(char* a, char* b)

Compare two NUL-terminated strings. Returns 0 if equal, otherwise the signed difference of the first differing byte (compared as unsigned char).

parammeaning
afirst string
bsecond string

Returns 0 if equal, else first differing byte difference

strncmp

int strncmp(char* a, char* b, int n)

Like strcmp but compares at most n bytes.

parammeaning
afirst string
bsecond string
nmaximum number of bytes to compare

Returns 0 if equal within n bytes, else first differing byte difference

strcpy

char* strcpy(char* d, char* s)

Copy the NUL-terminated string s (including the terminator) into d. Returns d.

parammeaning
ddestination buffer (must be large enough)
ssource string

Returns d

strcat

char* strcat(char* d, char* s)

Append the NUL-terminated string s to the end of d. Returns d.

parammeaning
ddestination string (must have room for the result)
sstring to append

Returns d

strchr

char* strchr(char* s, int c)

Find the first occurrence of byte c in the NUL-terminated string s. Returns a pointer to it, or 0 if not found; searching for 0 returns the terminator.

parammeaning
sstring to search
cbyte to find (low 8 bits used)

Returns pointer to the first match, or 0

07Memory

memcpy

char* memcpy(char* d, char* s, int n)

Copy n bytes from s to d (the regions must not overlap). Returns d.

parammeaning
ddestination buffer
ssource buffer
nnumber of bytes to copy

Returns d

memset

char* memset(char* d, int c, int n)

Fill the first n bytes of d with the byte value c. Returns d.

parammeaning
ddestination buffer
cfill byte (low 8 bits used)
nnumber of bytes to set

Returns d

memcmp

int memcmp(char* a, char* b, int n)

Compare the first n bytes of a and b. Returns 0 if equal, otherwise the signed difference of the first differing byte (compared as unsigned char).

parammeaning
afirst buffer
bsecond buffer
nnumber of bytes to compare

Returns 0 if equal, else first differing byte difference

sbrk

char* sbrk(int d)

Grow (or query) the program break, the top of the heap. sbrk(0) returns the current break without moving it; a positive delta grows the heap upward and returns the *previous* break (the base of the freshly reserved region). The heap grows until it would collide with the stack, then returns (char*)-1.

parammeaning
dbytes to move the break by (0 to query)

Returns the previous break, or (char*)-1 on failure

malloc

char* malloc(int n)

Allocate n bytes from the heap and return a pointer to them, or 0 if the heap cannot grow far enough. Blocks carry a small header, are reused once freed, and adjacent free blocks are coalesced; the heap is grown on demand via sbrk only when no existing free block fits.

parammeaning
nnumber of bytes to allocate

Returns pointer to the allocation, or 0 on failure

free

void free(char* p)

Release a malloc'd allocation so its space can be reused. The block is marked free and merged with any adjacent free blocks on the next malloc. Passing 0 is a no-op.

parammeaning
pa pointer previously returned by malloc, or 0

mmap

int mmap(int a, int l, int p, int f, int d, int o)

Map len bytes into the address space and return the mapping's address. prot combines 1 read, 2 write, 4 exec; flags combines 0x10 MAP_FIXED and 0x20 MAP_ANON. An anonymous map (MAP_ANON, fd ignored) is demand-zero; a file-backed map fills pages from fd at off and needs the same read permission as opening the file. Pass addr only with MAP_FIXED.

parammeaning
arequested address (only with MAP_FIXED, else 0)
lbytes to map (rounded up to whole pages)
pprotection bits: 1 read | 2 write | 4 exec
fflags: 0x10 MAP_FIXED | 0x20 MAP_ANON
dfile descriptor for a file-backed map (else -1)
obyte offset into the file

Returns the mapping address, or a negative errno

munmap

int munmap(int a, int l)

Release a whole prior mmap mapping, freeing its pages. a and l must match the original mapping.

parammeaning
athe mapping's base address
lthe mapping's length

Returns 0, or -EINVAL if it does not match a mapping

mprotect

int mprotect(int a, int l, int p)

Change the protection of a whole mmap mapping (see mmap for the protection bits). A write to a page mapped without write permission faults.

parammeaning
athe mapping's base address
lthe mapping's length
pnew protection bits

Returns 0, or a negative errno

08Processes

fork

int fork()

Create a child process: a near-duplicate of the caller with its own copy of memory. Open file descriptors (and pipe ends) are inherited. fork returns twice - the new child's PID in the parent and 0 in the child - so the two branches can follow different paths.

Returns child PID to the parent, 0 to the child, or -EAGAIN if the table is full

getpid

int getpid()

The caller's own process id.

Returns the current PID

getppid

int getppid()

The parent's process id (the process that fork()ed this one, or 1 once an orphan has been reparented to init).

Returns the parent PID

waitpid

int waitpid(int pid, int st, int opt)

Wait for a child to change state and optionally collect its exit status. pid -1 waits for any child; a positive pid waits for that specific child. Pass the address of an int in st to receive the status word (or 0 to ignore it).

parammeaning
pidchild to wait for (-1 = any child)
staddress of an int to receive the status, or 0
optoption bits (1 = WNOHANG: don't block; 4 = WUNTRACED: also report stops)

Returns the reaped child's PID, 0 (WNOHANG and none ready), or -ECHILD

pipe

int pipe(int fds)

Create a unidirectional pipe. Fills the two-int array fds with a read end in fds[0] and a write end in fds[1]; bytes written to the write end are read back, in order, from the read end. With fork() + dup2() this wires one process's output into another's input.

parammeaning
fdsa two-int array that receives { read_fd, write_fd }

Returns 0 on success, or a negative error

dup

int dup(int fd)

Duplicate an open file descriptor onto the lowest free descriptor (>= 3). The copy shares the same open-file description - and thus the seek offset - as fd.

parammeaning
fdthe descriptor to duplicate

Returns the new descriptor, or a negative error

dup2

int dup2(int of, int nf)

Make nf refer to whatever of refers to, closing nf first if it was open. The classic way to point a child's stdin/stdout/stderr (fd 0/1/2) at a pipe or file just before exec.

parammeaning
ofthe source descriptor
nfthe descriptor to overwrite (commonly 0, 1, or 2)

Returns nf on success, or a negative error

execve

int execve(char* p)

Replace the current process image with the program at path p, keeping the caller's credentials and open descriptors. On success it does not return - the new program takes over the process.

parammeaning
ppath to the executable

Returns does not return on success; a negative error otherwise

execvp

int execvp(char* p, int v, int n)

Replace the current process image with program p, resolving a bare name against PATH and passing an explicit argument vector. Honors the target's set-user-ID / set-group-ID bits. On success it does not return.

parammeaning
ppath or command name to execute
vargv: an array of n string pointers (v[0] is the program name)
nthe number of arguments in v

Returns does not return on success; a negative error otherwise

kill

int kill(int pid, int sig)

Send signal sig to a process or process group. A positive pid targets that process, pid 0 the caller's group, and a negative pid the group -pid. Delivery obeys the usual permission rule (same user, or root).

parammeaning
pidtarget process (>0), the caller's group (0), or group -pid (<0)
sigthe signal number to deliver

Returns 0 on success, or a negative error (-EPERM / -ESRCH)

09Intrinsic

__sys

int __sys(int num, int a, int b, int c, int d, int e, int f)

The raw system-call intrinsic that every wrapper above is built on. num selects the call (loaded into r7); up to six arguments go in r1..r6 and the result comes back in r1. Use it to reach syscalls the prelude does not wrap - the syscall reference (linked above) lists every number and its signature.

parammeaning
numthe syscall number
a..fup to six integer/pointer arguments

Returns the syscall's result   intrinsic