hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

syscalls.ha (16959B)


      1 // License: MPL-2.0
      2 // (c) 2021 Drew DeVault <sir@cmpwn.com>
      3 // (c) 2021 Ember Sawady <ecs@d2evs.net>
      4 // (c) 2021 Thomas Bracht Laumann Jespersen <t@laumann.xyz>
      5 
      6 fn syscall0(u64) u64;
      7 fn syscall1(u64, u64) u64;
      8 fn syscall2(u64, u64, u64) u64;
      9 fn syscall3(u64, u64, u64, u64) u64;
     10 fn syscall4(u64, u64, u64, u64, u64) u64;
     11 fn syscall5(u64, u64, u64, u64, u64, u64) u64;
     12 fn syscall6(u64, u64, u64, u64, u64, u64, u64) u64;
     13 
     14 export def PATH_MAX: size = 1024z;
     15 export type path = (str | []u8 | *const u8);
     16 let pathbuf: [PATH_MAX + 1]u8 = [0...];
     17 
     18 fn copy_kpath(path: path, buf: []u8) (*const u8 | errno) = {
     19 	let path = match (path) {
     20 	case let c: *const u8 =>
     21 		return c;
     22 	case let s: str =>
     23 		let ptr = &s: *struct {
     24 			buf: *[*]u8,
     25 			length: size,
     26 			capacity: size,
     27 		};
     28 		yield ptr.buf[..ptr.length];
     29 	case let b: []u8 =>
     30 		yield b;
     31 	};
     32 	if (len(path) + 1 >= len(pathbuf)) {
     33 		return ENAMETOOLONG;
     34 	};
     35 	memcpy(buf: *[*]u8, path: *[*]u8, len(path));
     36 	buf[len(path)] = 0;
     37 	return buf: *[*]u8: *const u8;
     38 };
     39 
     40 // NUL terminates a string and stores it in a static buffer of PATH_MAX+1 bytes
     41 // in length.
     42 fn kpath(path: path) (*const u8 | errno) = {
     43 	return copy_kpath(path, pathbuf);
     44 };
     45 
     46 export fn read(fd: int, buf: *void, count: size) (size | errno) = {
     47 	return wrap_return(syscall3(SYS_read,
     48 		fd: u64, buf: uintptr: u64, count: u64))?: size;
     49 };
     50 
     51 export fn write(fd: int, buf: *const void, count: size) (size | errno) = {
     52 	return wrap_return(syscall3(SYS_write,
     53 		fd: u64, buf: uintptr: u64, count: u64))?: size;
     54 };
     55 
     56 export fn readv(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
     57 	return wrap_return(syscall3(SYS_readv,
     58 		fd: u64, iov: uintptr: u64, iovcnt: u64))?: size;
     59 };
     60 
     61 export fn writev(fd: int, iov: const *[*]iovec, iovcnt: int) (size | errno) = {
     62 	return wrap_return(syscall3(SYS_writev,
     63 		fd: u64, iov: uintptr: u64, iovcnt: u64))?: size;
     64 };
     65 
     66 export fn close(fd: int) (void | errno) = {
     67 	wrap_return(syscall1(SYS_close, fd: u64))?;
     68 };
     69 
     70 export fn lseek(fd: int, off: i64, whence: int) (i64 | errno) = {
     71 	return wrap_return(syscall3(SYS_lseek,
     72 		fd: u64, off: u64, whence: u64))?: i64;
     73 };
     74 
     75 export fn ftruncate(fd: int, ln: off_t) (void | errno) = {
     76 	wrap_return(syscall2(SYS_ftruncate, fd: u64, ln: u32))?;
     77 };
     78 
     79 export fn pipe2(pipefd: *[2]int, flags: int) (void | errno) = {
     80 	wrap_return(syscall2(SYS_pipe2, pipefd: uintptr: u64, flags: u64))?;
     81 };
     82 
     83 export fn ioctl(fd: int, req: u64, arg: nullable *void) (int | errno) = {
     84 	return wrap_return(syscall3(SYS_ioctl, fd: u64,
     85 		req, arg: uintptr: u64))?: int;
     86 };
     87 
     88 export fn openat(
     89 	dirfd: int,
     90 	path: path,
     91 	flags: int,
     92 	mode: uint,
     93 ) (int | errno) = {
     94 	let path = kpath(path)?;
     95 	return wrap_return(syscall4(SYS_openat, dirfd: u64,
     96 		path: uintptr: u64, flags: u64, mode: u64))?: int;
     97 };
     98 
     99 export fn open(path: str, flags: int, mode: uint) (int | errno) = {
    100 	return openat(AT_FDCWD, path, flags, mode);
    101 };
    102 
    103 export fn unlink(path: path) (void | errno) = {
    104 	let path = kpath(path)?;
    105 	wrap_return(syscall3(SYS_unlinkat,
    106 		AT_FDCWD: u64, path: uintptr: u64, 0u64))?;
    107 };
    108 
    109 export fn renameat(
    110 	olddirfd: int,
    111 	oldpath: str,
    112 	newdirfd: int,
    113 	newpath: str,
    114 ) (void | errno) = {
    115 	let oldpath = kpath(oldpath)?;
    116 	static let newpathbuf: [PATH_MAX + 1]u8 = [0...];
    117 	let newpath = copy_kpath(newpath, newpathbuf)?;
    118 	wrap_return(syscall4(SYS_renameat,
    119 		olddirfd: u64, oldpath: uintptr: u64,
    120 		newdirfd: u64, newpath: uintptr: u64))?;
    121 };
    122 
    123 export fn unlinkat(dirfd: int, path: path, flags: int) (void | errno) = {
    124 	let path = kpath(path)?;
    125 	wrap_return(syscall3(SYS_unlinkat,
    126 		dirfd: u64, path: uintptr: u64, flags: u64))?;
    127 };
    128 
    129 export fn fstatat(fd: int, path: path, stat: *st, flag: int) (void | errno) = {
    130 	let path = kpath(path)?;
    131 	let fbstat = freebsd11_stat { ... };
    132 	wrap_return(syscall4(SYS_freebsd11_fstatat, fd: u64,
    133 		path: uintptr: u64, &fbstat: uintptr: u64, flag: u64))?;
    134 	stat.dev = fbstat.st_dev;
    135 	stat.ino = fbstat.st_ino;
    136 	stat.mode = fbstat.st_mode;
    137 	stat.nlink = fbstat.st_nlink;
    138 	stat.uid = fbstat.st_uid;
    139 	stat.gid = fbstat.st_gid;
    140 	stat.rdev = fbstat.st_rdev;
    141 	stat.atime.tv_sec = fbstat.st_atim.tv_sec;
    142 	stat.atime.tv_nsec = fbstat.st_atim.tv_nsec: i64;
    143 	stat.mtime.tv_sec = fbstat.st_mtim.tv_sec;
    144 	stat.mtime.tv_nsec = fbstat.st_mtim.tv_nsec: i64;
    145 	stat.ctime.tv_sec = fbstat.st_ctim.tv_sec;
    146 	stat.ctime.tv_nsec = fbstat.st_ctim.tv_nsec: i64;
    147 	stat.btime.tv_sec = fbstat.st_birthtim.tv_sec;
    148 	stat.btime.tv_nsec = fbstat.st_birthtim.tv_nsec: i64;
    149 	stat.sz = fbstat.st_size;
    150 	stat.blocks = fbstat.st_blocks;
    151 	stat.blksz = fbstat.st_blksize;
    152 	stat.flags = fbstat.st_flags;
    153 };
    154 
    155 export fn readlinkat(
    156 	dirfd: int,
    157 	path: path,
    158 	buf: []u8,
    159 ) (size | errno) = {
    160 	let path = kpath(path)?;
    161 	return wrap_return(syscall4(SYS_readlinkat,
    162 		dirfd: u64, path: uintptr: u64,
    163 		buf: *[*]u8: uintptr: u64,
    164 		len(buf): u64))?: size;
    165 };
    166 
    167 export fn mkdirat(dirfd: int, path: path, mode: uint) (void | errno) = {
    168 	let path = kpath(path)?;
    169 	wrap_return(syscall3(SYS_mkdirat,
    170 		dirfd: u64, path: uintptr: u64, mode: u64))?;
    171 };
    172 
    173 export fn fchmodat(dirfd: int, path: path, mode: uint, flags: int) (void | errno) = {
    174 	let path = kpath(path)?;
    175 	wrap_return(syscall4(SYS_fchmodat,
    176 		dirfd: u64, path: uintptr: u64, mode: u64, flags: u64))?;
    177 };
    178 
    179 export fn fchownat(dirfd: int, path: path, uid: uint, gid: uint, flags: int) (void | errno) = {
    180 	let path = kpath(path)?;
    181 	wrap_return(syscall5(SYS_fchownat,
    182 		dirfd: u64, path: uintptr: u64, uid: u32, gid: u32, flags: u64))?;
    183 };
    184 
    185 export fn faccessat(
    186 	dirfd: int,
    187 	path: path,
    188 	mode: int,
    189 	flags: int,
    190 ) (bool | errno) = {
    191 	let path = kpath(path)?;
    192 	match (wrap_return(syscall4(SYS_faccessat, dirfd: u64,
    193 		path: uintptr: u64, mode: u64, flags: u64))) {
    194 	case let err: errno =>
    195 		switch (err) {
    196 		case EACCES =>
    197 			return false;
    198 		case =>
    199 			return err;
    200 		};
    201 	case let n: u64 =>
    202 		assert(n == 0);
    203 		return true;
    204 	};
    205 };
    206 
    207 // The use of this function is discouraged, as it can create race conditions.
    208 // TOCTOU is preferred: attempt to simply use the resource you need and handle
    209 // any access errors which occur.
    210 export fn access(path: path, mode: int) (bool | errno) =
    211 	faccessat(AT_FDCWD, path, mode, 0);
    212 
    213 // TODO: Consider updating this to use SYS_freebsd11_getdirentries
    214 export fn getdents(dirfd: int, buf: *void, nbytes: size) (size | errno) = {
    215 	return wrap_return(syscall3(SYS_freebsd11_getdents, dirfd: u64,
    216 		buf: uintptr: u64, nbytes: u64))?: size;
    217 };
    218 
    219 // The return value is statically allocated and must be duplicated before
    220 // calling getcwd again.
    221 export fn getcwd() (*const u8 | errno) = {
    222 	static let pathbuf: [PATH_MAX + 1]u8 = [0...];
    223 	wrap_return(syscall2(SYS___getcwd,
    224 		&pathbuf: *[*]u8: uintptr: u64,
    225 		PATH_MAX + 1))?;
    226 	return &pathbuf: *const u8;
    227 };
    228 
    229 export fn fchdir(fd: int) (void | errno) = {
    230 	wrap_return(syscall1(SYS_fchdir, fd: u64))?;
    231 };
    232 
    233 export fn chdir(path: path) (void | errno) = {
    234 	let path = kpath(path)?;
    235 	wrap_return(syscall1(SYS_chdir, path: uintptr: u64))?;
    236 };
    237 
    238 export fn chroot(path: path) (void | errno) = {
    239 	let path = kpath(path)?;
    240 	wrap_return(syscall1(SYS_chroot, path: uintptr: u64))?;
    241 };
    242 
    243 export fn mmap(
    244 	addr: nullable *void,
    245 	length: size,
    246 	prot: uint,
    247 	flags: uint,
    248 	fd: int,
    249 	offs: size
    250 ) (errno | *void) = {
    251 	return wrap_return(syscall6(SYS_mmap, addr: uintptr: u64,
    252 		length: u64, prot: u64, flags: u64,
    253 		fd: u64, offs: u64))?: uintptr: *void;
    254 };
    255 
    256 export fn munmap(addr: *void, length: size) (void | errno) = {
    257 	wrap_return(syscall2(SYS_munmap, addr: uintptr: u64, length: u64))?;
    258 };
    259 
    260 export @noreturn fn exit(status: int) void = {
    261 	syscall1(SYS_exit, status: u64);
    262 };
    263 
    264 export fn kill(pid: int, signal: int) (void | errno) = {
    265 	wrap_return(syscall2(SYS_kill, pid: u64, signal: u64))?;
    266 };
    267 
    268 export fn fork() (int | void | errno) = {
    269 	let n = wrap_return(syscall0(SYS_fork))?: int;
    270 	switch (n) {
    271 	case 0 =>
    272 		return;
    273 	case =>
    274 		return n;
    275 	};
    276 };
    277 
    278 export fn fexecve(fd: int, argv: *[*]nullable *const u8,
    279 		envp: *[*]nullable *const u8) errno = {
    280 	return match (wrap_return(syscall3(SYS_fexecve, fd: u64,
    281 		argv: uintptr: u64, envp: uintptr: u64))) {
    282 	case let err: errno =>
    283 		yield err;
    284 	case u64 =>
    285 		abort("unreachable");
    286 	};
    287 };
    288 
    289 export fn wait4(
    290 	pid: int,
    291 	wstatus: nullable *int,
    292 	options: int,
    293 	rusage: nullable *rusage,
    294 ) (int | errno) = {
    295 	return wrap_return(syscall4(SYS_wait4,
    296 		pid: u64, wstatus: uintptr: u64,
    297 		options: u64, rusage: uintptr: u64))?: int;
    298 };
    299 
    300 export fn wifexited(status: int) bool = wtermsig(status) == 0;
    301 export fn wexitstatus(status: int) int = (status & 0xff00) >> 8;
    302 
    303 export fn wtermsig(status: int) int = status & 0x7f;
    304 export fn wifsignaled(status: int) bool =
    305 	wtermsig(status) != 0o177 && wtermsig(status) != 0 && status != 0x13;
    306 
    307 export fn getpid() int = syscall0(SYS_getpid): int;
    308 
    309 export fn getpriority(which: int, who: id_t) (int | errno) = {
    310 	return wrap_return(syscall2(SYS_setpriority,
    311 		which: u64, who: u64))?: int;
    312 };
    313 
    314 export fn setpriority(which: int, who: id_t, prio: int) (void | errno) = {
    315 	wrap_return(syscall3(SYS_setpriority, which: u64, who: u64, prio: u64))?;
    316 };
    317 
    318 export fn umask(mode: mode_t) (mode_t | errno) = {
    319 	return wrap_return(syscall1(SYS_umask, mode: u64))?: mode_t;
    320 };
    321 
    322 export fn setresuid(uid: uid_t, euid: uid_t, suid: uid_t) (void | errno) = {
    323 	wrap_return(syscall3(SYS_setresuid, uid: u64, euid: u64, suid: u64))?;
    324 };
    325 
    326 export fn setresgid(gid: gid_t, egid: gid_t, sgid: gid_t) (void | errno) = {
    327 	wrap_return(syscall3(SYS_setresgid, gid: u64, egid: u64, sgid: u64))?;
    328 };
    329 
    330 export fn getgroups(gids: []uint) (uint | errno) = {
    331 	return wrap_return(syscall2(SYS_getgroups,
    332 		len(gids): u64, gids: *[*]uint: uintptr: u64))?: uint;
    333 };
    334 
    335 export fn setgroups(gids: []uint) (void | errno) = {
    336 	wrap_return(syscall2(SYS_setgroups,
    337 		len(gids): u64, gids: *[*]uint: uintptr: u64))?;
    338 };
    339 
    340 export fn getresuid(uid: *uid_t, euid: *uid_t, suid: *uid_t) (void | errno) = {
    341 	wrap_return(syscall3(SYS_getresuid,
    342 		uid: uintptr: u64,
    343 		euid: uintptr: u64,
    344 		suid: uintptr: u64))?;
    345 };
    346 
    347 export fn getresgid(gid: *gid_t, egid: *gid_t, sgid: *gid_t) (void | errno) = {
    348 	wrap_return(syscall3(SYS_getresgid,
    349 		gid: uintptr: u64,
    350 		egid: uintptr: u64,
    351 		sgid: uintptr: u64))?;
    352 };
    353 
    354 export fn clock_gettime(clock_id: int, tp: *timespec) (void | errno) = {
    355 	wrap_return(syscall2(SYS_clock_gettime,
    356 		clock_id: u64, tp: uintptr: u64))?;
    357 };
    358 
    359 export fn nanosleep(req: *const timespec, rem: *timespec) (void | errno) = {
    360 	wrap_return(syscall2(SYS_nanosleep,
    361 		req: uintptr: u64, rem: uintptr: u64))?;
    362 };
    363 
    364 export fn getrandom(buf: *void, bufln: size, flags: uint) (size | errno) = {
    365 	return wrap_return(syscall3(SYS_getrandom,
    366 		buf: uintptr: u64, bufln: u64, flags: u64))?: size;
    367 };
    368 
    369 export type fcntl_arg = (void | int | *st_flock | *u64);
    370 
    371 export fn fcntl(fd: int, cmd: int, arg: fcntl_arg) (int | errno) = {
    372 	let _fd = fd: u64, _cmd = cmd: u64;
    373 	return wrap_return(match (arg) {
    374 	case void =>
    375 		yield syscall2(SYS_fcntl, _fd, _cmd);
    376 	case let i: int =>
    377 		yield syscall3(SYS_fcntl, _fd, _cmd, i: u64);
    378 	case let l: *st_flock =>
    379 		yield syscall3(SYS_fcntl, _fd, _cmd, l: uintptr: u64);
    380 	case let u: *u64 =>
    381 		yield syscall3(SYS_fcntl, _fd, _cmd, u: uintptr: u64);
    382 	})?: int;
    383 };
    384 
    385 export fn ppoll(
    386 	fds: *[*]pollfd,
    387 	nfds: nfds_t,
    388 	timeout: const nullable *timespec,
    389 	sigmask: const nullable *sigset,
    390 ) (int | errno) = {
    391 	return wrap_return(syscall4(SYS_ppoll, fds: uintptr: u64, nfds: u64,
    392 		timeout: uintptr: u64, sigmask: uintptr: u64))?: int;
    393 };
    394 
    395 export fn poll(fds: *[*]pollfd, nfds: nfds_t, timeout: int) (int | errno) = {
    396 	const ts = timespec {
    397 		tv_sec = timeout % 1000,
    398 		tv_nsec = timeout * 1000000,
    399 	};
    400 	return ppoll(fds, nfds, (if (timeout != -1) &ts else null), null);
    401 };
    402 
    403 export fn socket(domain: int, type_: int, protocol: int) (int | errno) = {
    404 	return wrap_return(syscall3(SYS_socket,
    405 		domain: u64, type_: u64, protocol: u64))?: int;
    406 };
    407 
    408 export fn socketpair(
    409 	domain: int,
    410 	type_: int,
    411 	protocol: int,
    412 	sv: *[*]int,
    413 ) (int | errno) = {
    414 	return wrap_return(syscall4(SYS_socketpair, domain: u64,
    415 		type_: u64, protocol: u64, sv: uintptr : u64))?: int;
    416 };
    417 
    418 export fn connect(sockfd: int, addr: *const sockaddr, addrlen: u32) (int | errno) = {
    419 	return wrap_return(syscall3(SYS_connect,
    420 		sockfd: u64, addr: uintptr: u64, addrlen: u64))?: int;
    421 };
    422 
    423 export fn bind(sockfd: int, addr: *const sockaddr, addrlen: u32) (int | errno) = {
    424 	return wrap_return(syscall3(SYS_bind,
    425 		sockfd: u64, addr: uintptr: u64, addrlen: u64))?: int;
    426 };
    427 
    428 export fn listen(sockfd: int, backlog: u32) (int | errno) = {
    429 	return wrap_return(syscall2(SYS_listen,
    430 		sockfd: u64, backlog: u64))?: int;
    431 };
    432 
    433 export fn accept(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = {
    434 	return wrap_return(syscall3(SYS_accept,
    435 		sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int;
    436 };
    437 
    438 export fn accept4(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32, flags: int) (int | errno) = {
    439 	return wrap_return(syscall4(SYS_accept4,
    440 		sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64, flags: u64))?: int;
    441 };
    442 
    443 export fn recvfrom(sockfd: int, buf: *void, len_: size, flags: int,
    444 	src_addr: nullable *sockaddr, addrlen: nullable *u32
    445 ) (size | errno) = {
    446 	return wrap_return(syscall6(SYS_recvfrom,
    447 		sockfd: u64, buf: uintptr: u64, len_: u64, flags: u64,
    448 		src_addr: uintptr: u64, addrlen: uintptr: u64))?: size;
    449 };
    450 
    451 export fn sendto(sockfd: int, buf: *void, len_: size, flags: int,
    452 	dest_addr: nullable *sockaddr, addrlen: u32
    453 ) (size | errno) = {
    454 	return wrap_return(syscall6(SYS_sendto,
    455 		sockfd: u64, buf: uintptr: u64, len_: u64, flags: u64,
    456 		dest_addr: uintptr: u64, addrlen: u64))?: size;
    457 };
    458 
    459 export fn recv(sockfd: int, buf: *void, len_: size, flags: int) (size | errno) = {
    460 	return recvfrom(sockfd, buf, len_, flags, null, null);
    461 };
    462 
    463 export fn send(sockfd: int, buf: *void, len_: size, flags: int) (size | errno) = {
    464 	return sendto(sockfd, buf, len_, flags, null, 0);
    465 };
    466 
    467 export fn sendmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = {
    468 	return wrap_return(syscall3(SYS_sendmsg,
    469 		fd: u64, msg: uintptr: u64, flags: u64))?: int;
    470 };
    471 
    472 export fn recvmsg(fd: int, msg: *const msghdr, flags: int) (int | errno) = {
    473 	return wrap_return(syscall3(SYS_recvmsg,
    474 		fd: u64, msg: uintptr: u64, flags: u64))?: int;
    475 };
    476 
    477 export fn getsockopt(sockfd: int, level: int, optname: int, optval: nullable *void, optlen: nullable *u32) (int | errno) = {
    478 	return wrap_return(syscall5(SYS_getsockopt,
    479 		sockfd: u64, level: u64, optname: u64,
    480 		optval: uintptr: u64, optlen: uintptr: u64))?: int;
    481 };
    482 
    483 export fn setsockopt(sockfd: int, level: int, optname: int, optval: *void, optlen: u32) (int | errno) = {
    484 	return wrap_return(syscall5(SYS_setsockopt,
    485 		sockfd: u64, level: u64, optname: u64,
    486 		optval: uintptr: u64, optlen: u64))?: int;
    487 };
    488 
    489 export fn getsockname(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = {
    490 	return wrap_return(syscall3(SYS_getsockname,
    491 		sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int;
    492 };
    493 
    494 export fn getpeername(sockfd: int, addr: nullable *sockaddr, addrlen: nullable *u32) (int | errno) = {
    495 	return wrap_return(syscall3(SYS_getpeername,
    496 		sockfd: u64, addr: uintptr: u64, addrlen: uintptr: u64))?: int;
    497 };
    498 
    499 export fn sysctlbyname(name: str, oldp: nullable *void, oldlenp: nullable *size,
    500 		newp: nullable *const void, newlen: size) (void | errno) = {
    501 	let kname = kpath(name)?;
    502 	wrap_return(syscall6(SYS___sysctlbyname,
    503 		kname: uintptr: u64, len(name): u64,
    504 		oldp: uintptr: u64, oldlenp: uintptr: u64,
    505 		newp: uintptr: u64, newlen: u64))?;
    506 };
    507 
    508 export fn dup2(oldfd: int, newfd: int) (int | errno) = {
    509 	return wrap_return(syscall2(SYS_dup2, oldfd: u64, newfd: u64))?: int;
    510 };
    511 
    512 export fn posix_openpt(flags: int) (int | errno) = {
    513 	return wrap_return(syscall1(SYS_posix_openpt, flags: u64))?: int;
    514 };
    515 
    516 export fn posix_fallocate(fd: int, off: i64, ln: i64) (void | errno) = {
    517 	wrap_return(syscall3(SYS_posix_fallocate,
    518 		fd: u64, off: u64, ln: u64))?;
    519 };
    520 
    521 export fn flock(fd: int, op: int) (void | errno) = {
    522 	wrap_return(syscall2(SYS_flock,
    523 		fd: u64, op: u64))?;
    524 };
    525 
    526 export fn shmat(id: int, addr: *const void, flag: int) *void = {
    527 	return syscall3(SYS_shmat, id: u64, addr: uintptr: u64,
    528 		flag: u64): uintptr: *void;
    529 };
    530 
    531 export fn getrlimit(resource: int, rlim: *rlimit) (void | errno) = {
    532 	wrap_return(syscall2(SYS_getrlimit,
    533 		resource: u64, rlim: uintptr: u64))?;
    534 };
    535 
    536 export fn setrlimit(resource: int, rlim: *const rlimit) (void | errno) = {
    537 	wrap_return(syscall2(SYS_setrlimit,
    538 		resource: u64, rlim: uintptr: u64))?;
    539 };
    540 
    541 export fn sigprocmask(
    542 	how: int,
    543 	set: nullable *const sigset,
    544 	old: nullable *sigset,
    545 ) (int | errno) = {
    546 	return wrap_return(syscall3(SYS_sigprocmask,
    547 		how: u64, set: uintptr: u64, old: uintptr: u64))?: int;
    548 };
    549 
    550 export fn sigaction(
    551 	signum: int,
    552 	act: *const sigact,
    553 	old: nullable *sigact,
    554 ) (int | errno) = {
    555 	return wrap_return(syscall3(SYS_sigaction,
    556 		signum: u64, act: uintptr: u64, old: uintptr: u64))?: int;
    557 };
    558 
    559 export fn shutdown(sockfd: int, how: int) (void | errno) = {
    560 	wrap_return(syscall2(SYS_shutdown,
    561 		sockfd: u64, how: u64))?;
    562 };