commit 0f753c9c828d6073282bb05fac356d62899f029e
parent 2cd92f12d91100d15c76622a69f57d6ca0c76419
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 5 Mar 2024 10:59:45 +0100
unix: unify and normalize credentials
This merges all credentials-related Unix semantics into unix/*/creds.ha,
including getuid, setuid, getpid, and so on, adds unix::pid et al type
aliases, and updates everything accordingly.
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
38 files changed, 610 insertions(+), 408 deletions(-)
diff --git a/dirs/xdg.ha b/dirs/xdg.ha
@@ -91,7 +91,7 @@ export fn runtime() (str | fs::error) = {
};
const st = os::stat(path)?;
- const uid = unix::getuid();
+ const uid = unix::getuid(): uint;
if (st.uid != uid || fs::mode_perm(st.mode) != fs::mode::USER_RWX) {
return errors::noaccess;
};
diff --git a/makefiles/freebsd.aarch64.mk b/makefiles/freebsd.aarch64.mk
@@ -201,14 +201,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+freebsd/getpid.ha unix/+freebsd/getuid.ha unix/+freebsd/groups.ha unix/+freebsd/nice.ha unix/+freebsd/pipe.ha unix/+freebsd/setuid.ha unix/+freebsd/umask.ha
+unix_ha = unix/+freebsd/creds.ha unix/+freebsd/nice.ha unix/+freebsd/pipe.ha unix/+freebsd/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+freebsd.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/makefiles/freebsd.riscv64.mk b/makefiles/freebsd.riscv64.mk
@@ -201,14 +201,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+freebsd/getpid.ha unix/+freebsd/getuid.ha unix/+freebsd/groups.ha unix/+freebsd/nice.ha unix/+freebsd/pipe.ha unix/+freebsd/setuid.ha unix/+freebsd/umask.ha
+unix_ha = unix/+freebsd/creds.ha unix/+freebsd/nice.ha unix/+freebsd/pipe.ha unix/+freebsd/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+freebsd.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/makefiles/freebsd.x86_64.mk b/makefiles/freebsd.x86_64.mk
@@ -201,14 +201,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+freebsd/getpid.ha unix/+freebsd/getuid.ha unix/+freebsd/groups.ha unix/+freebsd/nice.ha unix/+freebsd/pipe.ha unix/+freebsd/setuid.ha unix/+freebsd/umask.ha
+unix_ha = unix/+freebsd/creds.ha unix/+freebsd/nice.ha unix/+freebsd/pipe.ha unix/+freebsd/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+freebsd.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/makefiles/linux.aarch64.mk b/makefiles/linux.aarch64.mk
@@ -219,14 +219,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+linux/getpid.ha unix/+linux/getuid.ha unix/+linux/groups.ha unix/+linux/nice.ha unix/+linux/pipe.ha unix/+linux/setuid.ha unix/+linux/umask.ha
+unix_ha = unix/+linux/creds.ha unix/+linux/nice.ha unix/+linux/pipe.ha unix/+linux/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+linux.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/errors.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/errors.td $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/makefiles/linux.riscv64.mk b/makefiles/linux.riscv64.mk
@@ -219,14 +219,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+linux/getpid.ha unix/+linux/getuid.ha unix/+linux/groups.ha unix/+linux/nice.ha unix/+linux/pipe.ha unix/+linux/setuid.ha unix/+linux/umask.ha
+unix_ha = unix/+linux/creds.ha unix/+linux/nice.ha unix/+linux/pipe.ha unix/+linux/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+linux.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/errors.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/errors.td $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/makefiles/linux.x86_64.mk b/makefiles/linux.x86_64.mk
@@ -219,14 +219,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+linux/getpid.ha unix/+linux/getuid.ha unix/+linux/groups.ha unix/+linux/nice.ha unix/+linux/pipe.ha unix/+linux/setuid.ha unix/+linux/umask.ha
+unix_ha = unix/+linux/creds.ha unix/+linux/nice.ha unix/+linux/pipe.ha unix/+linux/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+linux.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/errors.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/errors.td $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/makefiles/openbsd.aarch64.mk b/makefiles/openbsd.aarch64.mk
@@ -201,14 +201,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+openbsd/getpid.ha unix/+openbsd/getuid.ha unix/+openbsd/groups.ha unix/+openbsd/nice.ha unix/+openbsd/pipe.ha unix/+openbsd/setuid.ha unix/+openbsd/umask.ha
+unix_ha = unix/+openbsd/creds.ha unix/+openbsd/nice.ha unix/+openbsd/pipe.ha unix/+openbsd/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+openbsd.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/makefiles/openbsd.riscv64.mk b/makefiles/openbsd.riscv64.mk
@@ -201,14 +201,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+openbsd/getpid.ha unix/+openbsd/getuid.ha unix/+openbsd/groups.ha unix/+openbsd/nice.ha unix/+openbsd/pipe.ha unix/+openbsd/setuid.ha unix/+openbsd/umask.ha
+unix_ha = unix/+openbsd/creds.ha unix/+openbsd/nice.ha unix/+openbsd/pipe.ha unix/+openbsd/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+openbsd.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/makefiles/openbsd.x86_64.mk b/makefiles/openbsd.x86_64.mk
@@ -201,14 +201,14 @@ $(HARECACHE)/hare_module.ssa: $(hare_module_ha) $(HARECACHE)/ascii.td $(HARECACH
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/hare_module.td.tmp -N hare::module $(hare_module_ha)
-unix_ha = unix/+openbsd/getpid.ha unix/+openbsd/getuid.ha unix/+openbsd/groups.ha unix/+openbsd/nice.ha unix/+openbsd/pipe.ha unix/+openbsd/setuid.ha unix/+openbsd/umask.ha
+unix_ha = unix/+openbsd/creds.ha unix/+openbsd/nice.ha unix/+openbsd/pipe.ha unix/+openbsd/umask.ha
$(HARECACHE)/unix.ssa: $(unix_ha) $(HARECACHE)/errors.td $(HARECACHE)/fs.td $(HARECACHE)/io.td $(HARECACHE)/rt.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix.td.tmp -N unix $(unix_ha)
unix_signal_ha = unix/signal/+openbsd.ha unix/signal/types.ha
-$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td
+$(HARECACHE)/unix_signal.ssa: $(unix_signal_ha) $(HARECACHE)/io.td $(HARECACHE)/rt.td $(HARECACHE)/unix.td
@mkdir -p -- "$(HARECACHE)"
@printf 'HAREC\t%s\n' "$@"
@$(TDENV) $(HAREC) $(HARECFLAGS) -o $@ -t $(HARECACHE)/unix_signal.td.tmp -N unix::signal $(unix_signal_ha)
diff --git a/os/exec/+freebsd/exec.ha b/os/exec/+freebsd/exec.ha
@@ -14,7 +14,7 @@ export fn fork() (process | void | error) = {
match (rt::fork()) {
case let err: rt::errno =>
return errors::errno(err);
- case let i: int =>
+ case let i: rt::pid_t =>
return i: process;
case void =>
return void;
@@ -184,7 +184,7 @@ fn platform_start(cmd: *command) (process | errors::error) = {
match (rt::fork()) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
+ case let pid: rt::pid_t =>
rt::close(pipe[1])!;
defer rt::close(pipe[0])!;
let errno: int = 0;
diff --git a/os/exec/+freebsd/process.ha b/os/exec/+freebsd/process.ha
@@ -5,14 +5,15 @@ use errors;
use fmt;
use rt;
use time;
+use unix;
use unix::signal;
// Stores information about a child process.
-export type process = int;
+export type process = unix::pid;
// Returns the currently running [[process]].
export fn self() process = {
- return rt::getpid();
+ return unix::getpid();
};
// Stores information about an exited process.
@@ -73,7 +74,7 @@ export fn wait(proc: *process) (status | error) = {
case let err: rt::errno =>
return errors::errno(err);
case let pid: int =>
- assert(pid == *proc);
+ assert(pid == *proc: int);
};
rusage(&st, &ru);
return st;
@@ -89,7 +90,7 @@ export fn waitany() ((process, status) | error) = {
return errors::errno(err);
case let pid: int =>
rusage(&st, &ru);
- return (pid, st);
+ return (pid: process, st);
};
};
@@ -110,7 +111,7 @@ export fn waitall() (uint | error | !(process, exit_status)) = {
match (check(&st)) {
case void => void;
case let es: !exit_status =>
- return (pid, es);
+ return (pid: process, es);
};
};
};
@@ -128,7 +129,7 @@ export fn peek(proc: *process) (status | void | error) = {
case 0 =>
return;
case =>
- assert(pid == *proc);
+ assert(pid == *proc: int);
};
};
rusage(&st, &ru);
@@ -148,7 +149,7 @@ export fn peekany() ((process, status) | void | error) = {
case 0 =>
return;
case =>
- return (pid, st);
+ return (pid: process, st);
};
};
};
diff --git a/os/exec/+linux/exec.ha b/os/exec/+linux/exec.ha
@@ -14,7 +14,7 @@ export fn fork() (process | void | error) = {
match (rt::fork()) {
case let err: rt::errno =>
return errors::errno(err);
- case let i: int =>
+ case let i: rt::pid_t =>
return i: process;
case void =>
return void;
diff --git a/os/exec/+linux/process.ha b/os/exec/+linux/process.ha
@@ -5,14 +5,15 @@ use errors;
use fmt;
use rt;
use time;
+use unix;
use unix::signal;
// Stores information about a child process.
-export type process = int;
+export type process = unix::pid;
// Returns the currently running [[process]].
export fn self() process = {
- return rt::getpid();
+ return unix::getpid();
};
// Stores information about an exited process.
@@ -58,8 +59,8 @@ export fn wait(proc: *process) (status | error) = {
match (rt::wait4(*proc, &st.status, 0, &ru)) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
- assert(pid == *proc);
+ case let pid: rt::pid_t =>
+ assert(pid == *proc: rt::pid_t);
};
rusage(&st, &ru);
return st;
@@ -73,7 +74,7 @@ export fn waitany() ((process, status) | error) = {
match (rt::wait4(-1, &st.status, 0, &ru)) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
+ case let pid: rt::pid_t =>
rusage(&st, &ru);
return (pid, st);
};
@@ -91,7 +92,7 @@ export fn waitall() (uint | error | !(process, exit_status)) = {
return i;
};
return errors::errno(err);
- case let pid: int =>
+ case let pid: rt::pid_t =>
match (check(&st)) {
case void => void;
case let es: !exit_status =>
@@ -108,12 +109,12 @@ export fn peek(proc: *process) (status | void | error) = {
match (rt::wait4(*proc, &st.status, rt::WNOHANG, &ru)) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
+ case let pid: rt::pid_t =>
switch (pid) {
case 0 =>
return;
case =>
- assert(pid == *proc);
+ assert(pid == *proc: rt::pid_t);
};
};
rusage(&st, &ru);
@@ -128,7 +129,7 @@ export fn peekany() ((process, status) | void | error) = {
match (rt::wait4(-1, &st.status, rt::WNOHANG, &ru)) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
+ case let pid: rt::pid_t =>
switch (pid) {
case 0 =>
return;
diff --git a/os/exec/+openbsd/process.ha b/os/exec/+openbsd/process.ha
@@ -5,14 +5,15 @@ use errors;
use fmt;
use rt;
use time;
+use unix;
use unix::signal;
// Stores information about a child process.
-export type process = int;
+export type process = unix::pid;
// Returns the currently running [[process]].
export fn self() process = {
- return rt::getpid();
+ return unix::getpid();
};
// Stores information about an exited process.
@@ -72,9 +73,8 @@ export fn wait(proc: *process) (status | error) = {
match (rt::wait4(*proc, &st.status, 0, &ru)) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
- // TODO: Handle invalid pid?
- assert(pid == *proc);
+ case let pid: rt::pid_t =>
+ assert(pid == *proc: rt::pid_t);
};
rusage(&st, &ru);
return st;
@@ -88,9 +88,9 @@ export fn waitany() ((process, status) | error) = {
match (rt::wait4(rt::WAIT_ANY, &st.status, 0, &ru)) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
+ case let pid: rt::pid_t =>
rusage(&st, &ru);
- return (pid, st);
+ return (pid: process, st);
};
};
@@ -108,11 +108,11 @@ export fn waitall() (uint | error | !(process, exit_status)) = {
} else {
return errors::errno(err);
};
- case let pid: int =>
+ case let pid: rt::pid_t =>
match (check(&st)) {
case void => void;
case let es: !exit_status =>
- return (pid, es);
+ return (pid: process, es);
};
};
};
@@ -126,12 +126,12 @@ export fn peek(proc: *process) (status | void | error) = {
match (rt::wait4(*proc, &st.status, rt::WNOHANG, &ru)) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
+ case let pid: rt::pid_t =>
switch (pid) {
case 0 =>
return;
case =>
- assert(pid == *proc);
+ assert(pid == *proc: rt::pid_t);
};
};
rusage(&st, &ru);
@@ -146,12 +146,12 @@ export fn peekany() ((process, status) | void | error) = {
match (rt::wait4(rt::WAIT_ANY, &st.status, rt::WNOHANG, &ru)) {
case let err: rt::errno =>
return errors::errno(err);
- case let pid: int =>
+ case let pid: rt::pid_t =>
switch (pid) {
case 0 =>
return;
case =>
- return (pid, st);
+ return (pid: process, st);
};
};
};
diff --git a/rt/+freebsd/syscalls.ha b/rt/+freebsd/syscalls.ha
@@ -283,12 +283,12 @@ export fn exit(status: int) never = {
abort();
};
-export fn kill(pid: int, signal: int) (void | errno) = {
+export fn kill(pid: pid_t, signal: int) (void | errno) = {
wrap_return(syscall2(SYS_kill, pid: u64, signal: u64))?;
};
-export fn fork() (int | void | errno) = {
- let n = wrap_return(syscall0(SYS_fork))?: int;
+export fn fork() (pid_t | void | errno) = {
+ let n = wrap_return(syscall0(SYS_fork))?: pid_t;
switch (n) {
case 0 =>
return;
@@ -309,7 +309,7 @@ export fn fexecve(fd: int, argv: *[*]nullable *const u8,
};
export fn wait4(
- pid: int,
+ pid: pid_t,
wstatus: nullable *int,
options: int,
rusage: nullable *rusage,
@@ -326,7 +326,19 @@ export fn wtermsig(status: int) int = status & 0x7f;
export fn wifsignaled(status: int) bool =
wtermsig(status) != 0o177 && wtermsig(status) != 0 && status != 0x13;
-export fn getpid() int = syscall0(SYS_getpid): int;
+export fn getpid() pid_t = syscall0(SYS_getpid): pid_t;
+
+export fn getppid() pid_t = syscall0(SYS_getppid): pid_t;
+
+export fn getpgrp() pid_t = syscall0(SYS_getpgrp): pid_t;
+
+export fn getpgid(pid: pid_t) (pid_t | errno) = {
+ return wrap_return(syscall1(SYS_getpgid, pid))?: pid_t;
+};
+
+export fn getsid(pid: pid_t) (pid_t | errno) = {
+ return wrap_return(syscall1(SYS_getsid, pid))?: pid_t;
+};
export fn getpriority(which: int, who: id_t) (int | errno) = {
return wrap_return(syscall2(SYS_getpriority,
@@ -349,14 +361,14 @@ export fn setresgid(gid: gid_t, egid: gid_t, sgid: gid_t) (void | errno) = {
wrap_return(syscall3(SYS_setresgid, gid: u64, egid: u64, sgid: u64))?;
};
-export fn getgroups(gids: []uint) (uint | errno) = {
+export fn getgroups(gids: []gid_t) (uint | errno) = {
return wrap_return(syscall2(SYS_getgroups,
- len(gids): u64, gids: *[*]uint: uintptr: u64))?: uint;
+ len(gids): u64, gids: *[*]gid_t: uintptr: u64))?: uint;
};
-export fn setgroups(gids: []uint) (void | errno) = {
+export fn setgroups(gids: []gid_t) (void | errno) = {
wrap_return(syscall2(SYS_setgroups,
- len(gids): u64, gids: *[*]uint: uintptr: u64))?;
+ len(gids): u64, gids: *[*]gid_t: uintptr: u64))?;
};
export fn getresuid(uid: *uid_t, euid: *uid_t, suid: *uid_t) (void | errno) = {
diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha
@@ -263,23 +263,38 @@ export fn execve(path: path, argv: *[*]nullable *const u8,
// Returns the new PID to the parent, void to the child, or errno if something
// goes wrong.
-export fn fork() (int | void | errno) = clone(null, SIGCHLD, null, null, 0);
+export fn fork() (pid_t | void | errno) = {
+ match (clone(null, SIGCHLD, null, null, 0)?) {
+ case let id: int =>
+ return id: pid_t;
+ case void =>
+ return void;
+ };
+};
+
+export fn getpid() pid_t = syscall0(SYS_getpid): pid_t;
-export fn getpid() int = syscall0(SYS_getpid): int;
+export fn getppid() pid_t = syscall0(SYS_getppid): pid_t;
-export fn getpgid(pid: int) (int | errno) = {
- return wrap_return(syscall1(SYS_getpgid, pid: u64))?: int;
+export fn getpgrp() pid_t = syscall0(SYS_getpgrp): pid_t;
+
+export fn getpgid(pid: pid_t) (pid_t | errno) = {
+ return wrap_return(syscall1(SYS_getpgid, pid: u64))?: pid_t;
+};
+
+export fn setpgid(pid: pid_t, pgid: pid_t) (void | errno) = {
+ wrap_return(syscall2(SYS_setpgid, pid: u64, pgid: u64))?;
};
export fn wait4(
- pid: int,
+ pid: pid_t,
wstatus: nullable *int,
options: int,
rusage: nullable *rusage,
-) (int | errno) = {
+) (pid_t | errno) = {
return wrap_return(syscall4(SYS_wait4,
pid: u64, wstatus: uintptr: u64,
- options: u64, rusage: uintptr: u64))?: int;
+ options: u64, rusage: uintptr: u64))?: pid_t;
};
export fn sendfile(
@@ -295,7 +310,7 @@ export fn exit(status: int) never = {
abort();
};
-export fn kill(pid: int, signal: int) (void | errno) = {
+export fn kill(pid: pid_t, signal: int) (void | errno) = {
wrap_return(syscall2(SYS_kill, pid: u64, signal: u64))?;
};
@@ -731,14 +746,14 @@ export fn getresgid(gid: *gid_t, egid: *gid_t, sgid: *gid_t) (void | errno) = {
sgid: uintptr: u64))?;
};
-export fn getgroups(gids: []uint) (uint | errno) = {
+export fn getgroups(gids: []gid_t) (uint | errno) = {
return wrap_return(syscall2(SYS_getgroups,
- len(gids): u64, gids: *[*]uint: uintptr: u64))?: uint;
+ len(gids): u64, gids: *[*]gid_t: uintptr: u64))?: uint;
};
-export fn setgroups(gids: []uint) (void | errno) = {
+export fn setgroups(gids: []gid_t) (void | errno) = {
wrap_return(syscall2(SYS_setgroups,
- len(gids): u64, gids: *[*]uint: uintptr: u64))?;
+ len(gids): u64, gids: *[*]gid_t: uintptr: u64))?;
};
export fn getpriority(which: int, who: id_t) (int | errno) = {
@@ -841,8 +856,8 @@ export fn keyctl(
arg2, arg3, arg4, arg5))?: int;
};
-export fn getsid(pid: int) (int | errno) = {
- return wrap_return(syscall1(SYS_getsid, pid: u64))?: int;
+export fn getsid(pid: pid_t) (pid_t | errno) = {
+ return wrap_return(syscall1(SYS_getsid, pid: u64))?: pid_t;
};
export fn setsid() (void | errno) = {
@@ -869,7 +884,7 @@ export fn umount2(target: path, flags: int) (void | errno) = {
export fn ptrace(
request: int,
- pid: int,
+ pid: pid_t,
addr: uintptr,
data: uintptr,
) (u64 | errno) = {
@@ -970,7 +985,7 @@ export fn shmat(id: int, addr: *const opaque, flag: int) *opaque = {
};
export fn sched_getaffinity(
- pid: int,
+ pid: pid_t,
cpusetsize: size,
mask: *cpu_set,
) (void | errno) = {
@@ -979,7 +994,7 @@ export fn sched_getaffinity(
};
export fn sched_setaffinity(
- pid: int,
+ pid: pid_t,
cpusetsize: size,
mask: *const cpu_set,
) (void | errno) = {
diff --git a/rt/+openbsd/syscalls.ha b/rt/+openbsd/syscalls.ha
@@ -123,18 +123,18 @@ export fn close(fd: int) (void | errno) = {
// wait4
@symbol("wait4") fn libc_wait4(
- wpid: int,
+ wpid: pid_t,
status: nullable *int,
options: int,
rusage: nullable *rusage
-) int;
+) pid_t;
export fn wait4(
- pid: int,
+ pid: pid_t,
wstatus: nullable *int,
options: int,
rusage: nullable *rusage,
-) (int | errno) = {
+) (pid_t | errno) = {
let res = libc_wait4(pid, wstatus, options, rusage);
if (res == -1) {
return *__errno(): errno;
@@ -174,7 +174,7 @@ export fn fchdir(fd: int) (void | errno) = {
// getrusage
// getpid
-export @symbol("getpid") fn getpid() int;
+export @symbol("getpid") fn getpid() pid_t;
// mount
// unmount
@@ -315,7 +315,11 @@ export fn access(path: path, amode: int) (bool | errno) = {
// sync
// msyscall
// stat
+
// getppid
+
+export @symbol("getppid") fn getppid() pid_t;
+
// lstat
// dup
// fstatat
@@ -538,10 +542,10 @@ export fn munmap(addr: *opaque, len_: size) (void | errno) = {
// mquery
// getgroups
-@symbol("getgroups") fn libc_getgroups(gidsetlen: int, gidset: *[*]u32) int;
+@symbol("getgroups") fn libc_getgroups(gidsetlen: int, gidset: *[*]gid_t) int;
-export fn getgroups(gids: []uint) (uint | errno) = {
- let res = libc_getgroups(len(gids): int, gids: *[*]u32);
+export fn getgroups(gids: []gid_t) (uint | errno) = {
+ let res = libc_getgroups(len(gids): int, gids: *[*]gid_t);
if (res == -1) {
return *__errno(): errno;
};
@@ -552,18 +556,31 @@ export fn getgroups(gids: []uint) (uint | errno) = {
@symbol("setgroups") fn libc_setgroups(
ngroups: int,
- gidset: *[*]u32
+ gidset: *[*]gid_t,
) int;
-export fn setgroups(gids: []uint) (void | errno) = {
- let res = libc_setgroups(len(gids): int, gids: *[*]u32);
+export fn setgroups(gids: []gid_t) (void | errno) = {
+ let res = libc_setgroups(len(gids): int, gids: *[*]gid_t);
if (res == -1) {
return *__errno(): errno;
};
};
// getpgrp
+
+export @symbol("getpgrp") fn getpgrp() pid_t;
+
// setpgid
+
+@symbol("setpgid") fn libc_setpgid(pid: pid_t, pgrp: pid_t) int;
+
+export fn setpgid(pid: pid_t, pgrp: pid_t) (void | errno) = {
+ let res = libc_setpgid(pid, pgrp);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
// futex
// utimensat
// futimens
@@ -1027,7 +1044,18 @@ export fn socketpair(
// getthrname
// setthrname
// pinsyscall
+
// setsid
+
+@symbol("setsid") fn libc_setsid() pid_t;
+
+export fn setsid() (void | errno) = {
+ let res = libc_setsid();
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+};
+
// quotactl
// ypconnect
// nfssvc
@@ -1153,7 +1181,19 @@ export fn getpgid(pid: pid_t) (pid_t | errno) = {
// poll
// issetugid
// lchown
+
// getsid
+
+@symbol("getsid") fn libc_getsid(pid: pid_t) pid_t;
+
+export fn getsid(pid: pid_t) (pid_t | errno) = {
+ let res = libc_getsid(pid);
+ if (res == -1) {
+ return *__errno(): errno;
+ };
+ return res;
+};
+
// msync
// pipe
// fhopen
diff --git a/unix/+freebsd/creds.ha b/unix/+freebsd/creds.ha
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+// Unix credentials types & functions; ref credentials(7)
+
+use errors;
+use rt;
+
+// Process ID.
+export type pid = rt::pid_t;
+
+// User ID.
+export type uid = rt::uid_t;
+
+// Group ID.
+export type gid = rt::gid_t;
+
+// Returns the current process user ID.
+export fn getuid() uid = {
+ let uid = 0u, euid = 0u, suid = 0u;
+ rt::getresuid(&uid, &euid, &suid) as void;
+ return uid;
+};
+
+// Returns the current process effective user ID.
+export fn geteuid() uid = {
+ let uid = 0u, euid = 0u, suid = 0u;
+ rt::getresuid(&uid, &euid, &suid) as void;
+ return euid;
+};
+
+// Returns the current process group ID.
+export fn getgid() gid = {
+ let gid = 0u, egid = 0u, sgid = 0u;
+ rt::getresgid(&gid, &egid, &sgid) as void;
+ return gid;
+};
+
+// Returns the current process effective group ID.
+export fn getegid() gid = {
+ let gid = 0u, egid = 0u, sgid = 0u;
+ rt::getresgid(&gid, &egid, &sgid) as void;
+ return egid;
+};
+
+// Sets the caller's user ID to the specified value. This generally requires
+// elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setuid(uid: uid) void = rt::setresuid(uid, -1i: uint, -1i: uint)!;
+
+// Sets the caller's effective user ID to the specified value. This generally
+// requires elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from seteuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn seteuid(uid: uid) void = rt::setresuid(-1i: uint, uid, -1i: uint)!;
+
+// Sets the caller's group ID to the specified value. This generally requires
+// elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setgid(gid: gid) void = rt::setresgid(gid, -1i: uint, -1i: uint)!;
+
+// Sets the caller's effective group ID to the specified value. This generally
+// requires elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setegid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setegid(gid: gid) void = rt::setresgid(-1i: uint, gid, -1i: uint)!;
+
+// Returns a list of supplementary group IDs for the current process. The
+// returned slice is statically allocated.
+export fn getgroups() []gid = {
+ static let gids: [rt::NGROUPS_MAX]rt::gid_t = [0...];
+ const n = rt::getgroups(gids)!;
+ return gids[..n]: []gid;
+};
+
+// Sets the list of supplementary group IDs which apply to the current process.
+// This generally requires elevated permissions.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setgroups is a grave security issue in your program,
+// and therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setgroups(gids: []gid) void = rt::setgroups(gids: []rt::gid_t)!;
+
+// Returns the current process ID.
+export fn getpid() pid = rt::getpid();
+
+// Returns the parent process ID.
+export fn getppid() pid = rt::getppid();
+
+// Returns the current process group ID.
+export fn getpgrp() pid = rt::getpgrp();
+
+// Returns the current process's session ID.
+export fn getsid() pid = rt::getsid(0)!;
+
+// Returns the session ID associated with the given process.
+export fn getpsid(pid: pid) (pid | errors::noentry | errors::noaccess) = {
+ match (rt::getsid(pid)) {
+ case let pid: rt::pid_t =>
+ return pid;
+ case let err: rt::errno =>
+ assert(err == rt::ESRCH);
+ return errors::noentry;
+ };
+};
diff --git a/unix/+freebsd/getpid.ha b/unix/+freebsd/getpid.ha
@@ -1,7 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns the current process ID.
-export fn getpid() int = rt::getpid();
diff --git a/unix/+freebsd/getuid.ha b/unix/+freebsd/getuid.ha
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns the current process user ID.
-export fn getuid() uint = {
- let uid = 0u, euid = 0u, suid = 0u;
- rt::getresuid(&uid, &euid, &suid) as void;
- return uid;
-};
-
-// Returns the current process effective user ID.
-export fn geteuid() uint = {
- let uid = 0u, euid = 0u, suid = 0u;
- rt::getresuid(&uid, &euid, &suid) as void;
- return euid;
-};
-
-// Returns the current process group ID.
-export fn getgid() uint = {
- let gid = 0u, egid = 0u, sgid = 0u;
- rt::getresgid(&gid, &egid, &sgid) as void;
- return gid;
-};
-
-// Returns the current process effective group ID.
-export fn getegid() uint = {
- let gid = 0u, egid = 0u, sgid = 0u;
- rt::getresgid(&gid, &egid, &sgid) as void;
- return egid;
-};
diff --git a/unix/+freebsd/groups.ha b/unix/+freebsd/groups.ha
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns a list of supplementary group IDs for the current process. The
-// returned slice is statically allocated.
-export fn getgroups() []uint = {
- static let gids: [rt::NGROUPS_MAX]uint = [0...];
- const n = rt::getgroups(gids)!;
- return gids[..n];
-};
-
-// Sets the list of supplementary group IDs which apply to the current process.
-// This generally requires elevated permissions.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setgroups is a grave security issue in your program,
-// and therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setgroups(gids: []uint) void = rt::setgroups(gids)!;
diff --git a/unix/+freebsd/setuid.ha b/unix/+freebsd/setuid.ha
@@ -1,44 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Sets the caller's user ID to the specified value. This generally requires
-// elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setuid(uid: uint) void = rt::setresuid(uid, -1i: uint, -1i: uint)!;
-
-// Sets the caller's effective user ID to the specified value. This generally
-// requires elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from seteuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn seteuid(uid: uint) void = rt::setresuid(-1i: uint, uid, -1i: uint)!;
-
-// Sets the caller's group ID to the specified value. This generally requires
-// elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setgid(gid: uint) void = rt::setresgid(gid, -1i: uint, -1i: uint)!;
-
-// Sets the caller's effective group ID to the specified value. This generally
-// requires elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setegid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setegid(gid: uint) void = rt::setresgid(-1i: uint, gid, -1i: uint)!;
diff --git a/unix/+linux/creds.ha b/unix/+linux/creds.ha
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+// Unix credentials types & functions; ref credentials(7)
+
+use errors;
+use rt;
+
+// Process ID.
+export type pid = rt::pid_t;
+
+// User ID.
+export type uid = rt::uid_t;
+
+// Group ID.
+export type gid = rt::gid_t;
+
+// Returns the current process user ID.
+export fn getuid() uid = {
+ let uid = 0u, euid = 0u, suid = 0u;
+ rt::getresuid(&uid, &euid, &suid) as void;
+ return uid;
+};
+
+// Returns the current process effective user ID.
+export fn geteuid() uid = {
+ let uid = 0u, euid = 0u, suid = 0u;
+ rt::getresuid(&uid, &euid, &suid) as void;
+ return euid;
+};
+
+// Returns the current process group ID.
+export fn getgid() gid = {
+ let gid = 0u, egid = 0u, sgid = 0u;
+ rt::getresgid(&gid, &egid, &sgid) as void;
+ return gid;
+};
+
+// Returns the current process effective group ID.
+export fn getegid() gid = {
+ let gid = 0u, egid = 0u, sgid = 0u;
+ rt::getresgid(&gid, &egid, &sgid) as void;
+ return egid;
+};
+
+// Sets the caller's user ID to the specified value. This generally requires
+// elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setuid(uid: uid) void = rt::setresuid(uid, -1i: uint, -1i: uint)!;
+
+// Sets the caller's effective user ID to the specified value. This generally
+// requires elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from seteuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn seteuid(uid: uid) void = rt::setresuid(-1i: uint, uid, -1i: uint)!;
+
+// Sets the caller's group ID to the specified value. This generally requires
+// elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setgid(gid: gid) void = rt::setresgid(gid, -1i: uint, -1i: uint)!;
+
+// Sets the caller's effective group ID to the specified value. This generally
+// requires elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setegid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setegid(gid: gid) void = rt::setresgid(-1i: uint, gid, -1i: uint)!;
+
+// Returns a list of supplementary group IDs for the current process. The
+// returned slice is statically allocated.
+export fn getgroups() []gid = {
+ static let gids: [rt::NGROUPS_MAX]rt::gid_t = [0...];
+ const n = rt::getgroups(gids)!;
+ return gids[..n]: []gid;
+};
+
+// Sets the list of supplementary group IDs which apply to the current process.
+// This generally requires elevated permissions.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setgroups is a grave security issue in your program,
+// and therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setgroups(gids: []gid) void = rt::setgroups(gids: []rt::gid_t)!;
+
+// Returns the current process ID.
+export fn getpid() pid = rt::getpid();
+
+// Returns the parent process ID.
+export fn getppid() pid = rt::getppid();
+
+// Returns the current process group ID.
+export fn getpgrp() pid = rt::getpgrp();
+
+// Returns the process group associated with the given pid.
+export fn getpgid(pid: pid) (pid | errors::noentry) = {
+ match (rt::getpgid(pid)) {
+ case let pid: rt::pid_t =>
+ return pid;
+ case let err: rt::errno =>
+ assert(err == rt::ESRCH, "Unexpected getpgid return value");
+ return errors::noentry;
+ };
+};
+
+// Sets the process group ID of the specified process. This function is
+// error-prone; see the notes in the POSIX specification for its many caveats.
+export fn setpgid(targ: pid, pgid: pid) (void | errors::error) = {
+ match (rt::setpgid(targ, pgid)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case void =>
+ return;
+ };
+};
+
+// Returns the current process's session ID.
+export fn getsid() pid = rt::getsid(0)!;
+
+// Returns the session ID associated with the given process.
+export fn getpsid(pid: pid) (pid | errors::noentry | errors::noaccess) = {
+ match (rt::getsid(pid)) {
+ case let pid: rt::pid_t =>
+ return pid;
+ case let err: rt::errno =>
+ assert(err == rt::ESRCH, "Unexpected getsid return value");
+ return errors::noentry;
+ };
+};
+
+// Creates a new session and sets the current process to the session leader.
+// A new process group is also created with its process group ID equal to the
+// pid of the current process, and the current process is made the process group
+// leader.
+//
+// Upon return, the new session will have no controlling terminal. To establish
+// one, the caller must open a terminal file with [[fs::flag::CTTY]]; this
+// opt-in approach differs from the Unix norm where O_NOCTTY is required to
+// opt-out of establishing a controlling terminal.
+//
+// The current process cannot be a process group leader; this is a programmer
+// error and will cause a runtime assertion failure.
+export fn setsid() void = rt::setsid()!;
diff --git a/unix/+linux/getpid.ha b/unix/+linux/getpid.ha
@@ -1,7 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns the current process ID.
-export fn getpid() int = rt::getpid();
diff --git a/unix/+linux/getuid.ha b/unix/+linux/getuid.ha
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns the current process user ID.
-export fn getuid() uint = {
- let uid = 0u, euid = 0u, suid = 0u;
- rt::getresuid(&uid, &euid, &suid) as void;
- return uid;
-};
-
-// Returns the current process effective user ID.
-export fn geteuid() uint = {
- let uid = 0u, euid = 0u, suid = 0u;
- rt::getresuid(&uid, &euid, &suid) as void;
- return euid;
-};
-
-// Returns the current process group ID.
-export fn getgid() uint = {
- let gid = 0u, egid = 0u, sgid = 0u;
- rt::getresgid(&gid, &egid, &sgid) as void;
- return gid;
-};
-
-// Returns the current process effective group ID.
-export fn getegid() uint = {
- let gid = 0u, egid = 0u, sgid = 0u;
- rt::getresgid(&gid, &egid, &sgid) as void;
- return egid;
-};
diff --git a/unix/+linux/groups.ha b/unix/+linux/groups.ha
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns a list of supplementary group IDs for the current process. The
-// returned slice is statically allocated.
-export fn getgroups() []uint = {
- static let gids: [rt::NGROUPS_MAX]uint = [0...];
- const n = rt::getgroups(gids)!;
- return gids[..n];
-};
-
-// Sets the list of supplementary group IDs which apply to the current process.
-// This generally requires elevated permissions.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setgroups is a grave security issue in your program,
-// and therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setgroups(gids: []uint) void = rt::setgroups(gids)!;
diff --git a/unix/+linux/setuid.ha b/unix/+linux/setuid.ha
@@ -1,44 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Sets the caller's user ID to the specified value. This generally requires
-// elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setuid(uid: uint) void = rt::setresuid(uid, -1i: uint, -1i: uint)!;
-
-// Sets the caller's effective user ID to the specified value. This generally
-// requires elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from seteuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn seteuid(uid: uint) void = rt::setresuid(-1i: uint, uid, -1i: uint)!;
-
-// Sets the caller's group ID to the specified value. This generally requires
-// elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setgid(gid: uint) void = rt::setresgid(gid, -1i: uint, -1i: uint)!;
-
-// Sets the caller's effective group ID to the specified value. This generally
-// requires elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setegid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setegid(gid: uint) void = rt::setresgid(-1i: uint, gid, -1i: uint)!;
diff --git a/unix/+openbsd/creds.ha b/unix/+openbsd/creds.ha
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: MPL-2.0
+// (c) Hare authors <https://harelang.org>
+// Unix credentials types & functions; ref credentials(7)
+
+use errors;
+use rt;
+
+// Process ID.
+export type pid = rt::pid_t;
+
+// User ID.
+export type uid = rt::uid_t;
+
+// Group ID.
+export type gid = rt::gid_t;
+
+// Returns the current process user ID.
+export fn getuid() uid = rt::getuid();
+
+// Returns the current process effective user ID.
+export fn geteuid() uid = rt::geteuid();
+
+// Returns the current process group ID.
+export fn getgid() uid = rt::getgid();
+
+// Returns the current process effective group ID.
+export fn getegid() uid = rt::getegid();
+
+// Sets the caller's user ID to the specified value. This generally requires
+// elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]] yourself,
+// and take extreme care to handle errors correctly.
+export fn setuid(uid: uid) void = rt::setuid(uid)!;
+
+// Sets the caller's effective user ID to the specified value. This generally
+// requires elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from seteuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]] yourself,
+// and take extreme care to handle errors correctly.
+export fn seteuid(uid: uid) void = rt::seteuid(uid)!;
+
+// Sets the caller's group ID to the specified value. This generally requires
+// elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setuid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]] yourself,
+// and take extreme care to handle errors correctly.
+export fn setgid(gid: gid) void = rt::setgid(gid)!;
+
+// Sets the caller's effective group ID to the specified value. This generally
+// requires elevated permissions from the calling process.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setegid is a grave security issue in your program, and
+// therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]] yourself,
+// and take extreme care to handle errors correctly.
+export fn setegid(gid: gid) void = rt::setegid(gid)!;
+
+// Returns a list of supplementary group IDs for the current process. The
+// returned slice is statically allocated.
+export fn getgroups() []gid = {
+ static let gids: [rt::NGROUPS_MAX]rt::gid_t = [0...];
+ const n = rt::getgroups(gids)!;
+ return gids[..n]: []gid;
+};
+
+// Sets the list of supplementary group IDs which apply to the current process.
+// This generally requires elevated permissions.
+//
+// If the system returns an error, this function will abort the program. Failing
+// to handle errors from setgroups is a grave security issue in your program,
+// and therefore we require this function to succeed. If you need to handle the
+// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
+// yourself, and take extreme care to handle errors correctly.
+export fn setgroups(gids: []gid) void = rt::setgroups(gids: []rt::gid_t)!;
+
+// Returns the current process ID.
+export fn getpid() pid = rt::getpid();
+
+// Returns the parent process ID.
+export fn getppid() pid = rt::getppid();
+
+// Returns the current process group ID.
+export fn getpgrp() pid = rt::getpgrp();
+
+// Returns the process group associated with the given pid.
+export fn getpgid(pid: pid) (pid | errors::noentry) = {
+ match (rt::getpgid(pid)) {
+ case let pid: rt::pid_t =>
+ return pid;
+ case let err: rt::errno =>
+ assert(err == rt::ESRCH, "Unexpected getpgid return value");
+ return errors::noentry;
+ };
+};
+
+// Sets the process group ID of the specified process. This function is
+// error-prone; see the notes in the POSIX specification for its many caveats.
+export fn setpgid(targ: pid, pgid: pid) (void | errors::error) = {
+ match (rt::setpgid(targ, pgid)) {
+ case let err: rt::errno =>
+ return errors::errno(err);
+ case void =>
+ return;
+ };
+};
+
+// Returns the current process's session ID.
+export fn getsid() pid = rt::getsid(0)!;
+
+// Returns the session ID associated with the given process.
+export fn getpsid(pid: pid) (pid | errors::noentry | errors::noaccess) = {
+ match (rt::getsid(pid)) {
+ case let pid: rt::pid_t =>
+ return pid;
+ case let err: rt::errno =>
+ assert(err == rt::ESRCH, "Unexpected getsid return value");
+ return errors::noentry;
+ };
+};
+
+// Creates a new session and sets the current process to the session leader.
+// A new process group is also created with its process group ID equal to the
+// pid of the current process, and the current process is made the process group
+// leader.
+//
+// Upon return, the new session will have no controlling terminal. To establish
+// one, the caller must open a terminal file with [[fs::flag::CTTY]]; this
+// opt-in approach differs from the Unix norm where O_NOCTTY is required to
+// opt-out of establishing a controlling terminal.
+//
+// The current process cannot be a process group leader; this is a programmer
+// error and will cause a runtime assertion failure.
+export fn setsid() void = rt::setsid()!;
diff --git a/unix/+openbsd/getpid.ha b/unix/+openbsd/getpid.ha
@@ -1,7 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns the current process ID.
-export fn getpid() int = rt::getpid();
diff --git a/unix/+openbsd/getuid.ha b/unix/+openbsd/getuid.ha
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns the current process user ID.
-export fn getuid() uint = rt::getuid(): uint;
-
-// Returns the current process effective user ID.
-export fn geteuid() uint = rt::geteuid(): uint;
-
-// Returns the current process group ID.
-export fn getgid() uint = rt::getgid(): uint;
-
-// Returns the current process effective group ID.
-export fn getegid() uint = rt::getegid(): uint;
-\ No newline at end of file
diff --git a/unix/+openbsd/groups.ha b/unix/+openbsd/groups.ha
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Returns a list of supplementary group IDs for the current process. The
-// returned slice is statically allocated.
-export fn getgroups() []uint = {
- static let gids: [rt::NGROUPS_MAX]uint = [0...];
- const n = rt::getgroups(gids)!;
- return gids[..n];
-};
-
-// Sets the list of supplementary group IDs which apply to the current process.
-// This generally requires elevated permissions.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setgroups is a grave security issue in your program,
-// and therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]]
-// yourself, and take extreme care to handle errors correctly.
-export fn setgroups(gids: []uint) void = rt::setgroups(gids)!;
diff --git a/unix/+openbsd/setuid.ha b/unix/+openbsd/setuid.ha
@@ -1,44 +0,0 @@
-// SPDX-License-Identifier: MPL-2.0
-// (c) Hare authors <https://harelang.org>
-
-use rt;
-
-// Sets the caller's user ID to the specified value. This generally requires
-// elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]] yourself,
-// and take extreme care to handle errors correctly.
-export fn setuid(uid: uint) void = rt::setuid(uid: rt::uid_t)!;
-
-// Sets the caller's effective user ID to the specified value. This generally
-// requires elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from seteuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]] yourself,
-// and take extreme care to handle errors correctly.
-export fn seteuid(uid: uint) void = rt::seteuid(uid: rt::uid_t)!;
-
-// Sets the caller's group ID to the specified value. This generally requires
-// elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setuid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]] yourself,
-// and take extreme care to handle errors correctly.
-export fn setgid(gid: uint) void = rt::setgid(gid: rt::gid_t)!;
-
-// Sets the caller's effective group ID to the specified value. This generally
-// requires elevated permissions from the calling process.
-//
-// If the system returns an error, this function will abort the program. Failing
-// to handle errors from setegid is a grave security issue in your program, and
-// therefore we require this function to succeed. If you need to handle the
-// error case gracefully, call the appropriate syscall wrapper in [[rt::]] yourself,
-// and take extreme care to handle errors correctly.
-export fn setegid(gid: uint) void = rt::setegid(gid: rt::gid_t)!;
diff --git a/unix/passwd/group.ha b/unix/passwd/group.ha
@@ -7,6 +7,7 @@ use memio;
use os;
use strconv;
use strings;
+use unix;
// A Unix-like group file entry.
export type grent = struct {
@@ -15,7 +16,7 @@ export type grent = struct {
// Optional encrypted password
password: str,
// Numerical group ID
- gid: uint,
+ gid: unix::gid,
// List of usernames that are members of this group
userlist: []str,
};
@@ -43,9 +44,9 @@ export fn nextgr(in: io::handle) (grent | io::EOF | io::error | invalid) = {
return invalid;
};
- let gid = match (strconv::stou(fields[2])) {
- case let u: uint =>
- yield u;
+ let gid = match (strconv::stou64(fields[2])) {
+ case let u: u64 =>
+ yield u: unix::gid;
case =>
return invalid;
};
@@ -102,7 +103,7 @@ export fn getgroup(name: str) (grent | void) = {
// /etc/group. Aborts if that file doesn't exist or is not properly formatted.
//
// See [[nextgr]] for low-level parsing API.
-export fn getgid(gid: uint) (grent | void) = {
+export fn getgid(gid: unix::gid) (grent | void) = {
let file = match (os::open("/etc/group")) {
case let f: io::file =>
yield f;
diff --git a/unix/passwd/passwd.ha b/unix/passwd/passwd.ha
@@ -7,6 +7,7 @@ use memio;
use os;
use strconv;
use strings;
+use unix;
// A Unix-like password database entry.
export type pwent = struct {
@@ -15,9 +16,9 @@ export type pwent = struct {
// Optional encrypted password
password: str,
// Numerical user ID
- uid: uint,
+ uid: unix::uid,
// Numerical group ID
- gid: uint,
+ gid: unix::gid,
// User name or comment field
comment: str,
// User home directory
@@ -49,16 +50,16 @@ export fn nextpw(in: io::handle) (pwent | io::EOF | io::error | invalid) = {
return invalid;
};
- let uid = match (strconv::stou(fields[2])) {
- case let u: uint =>
- yield u;
+ let uid = match (strconv::stou64(fields[2])) {
+ case let u: u64 =>
+ yield u: unix::uid;
case =>
return invalid;
};
- let gid = match (strconv::stou(fields[3])) {
- case let u: uint =>
- yield u;
+ let gid = match (strconv::stou64(fields[3])) {
+ case let u: u64 =>
+ yield u: unix::gid;
case =>
return invalid;
};
@@ -122,7 +123,7 @@ export fn getuser(username: str) (pwent | void) = {
// properly formatted. The return value must be freed with [[pwent_finish]].
//
// See [[nextpw]] for low-level parsing API.
-export fn getuid(uid: uint) (pwent | void) = {
+export fn getuid(uid: unix::uid) (pwent | void) = {
let file = match (os::open("/etc/passwd")) {
case let f: io::file =>
yield f;
diff --git a/unix/signal/+freebsd.ha b/unix/signal/+freebsd.ha
@@ -3,6 +3,7 @@
use io;
use rt;
+use unix;
// Configures a new signal handler, returning the old details (which can be
// passed to [[restore]] to restore its behavior).
@@ -199,9 +200,9 @@ export type siginfo = union {
// The signal code, if any.
code: code,
// Process ID of the sender.
- pid: int,
+ pid: unix::pid,
// Real user ID of the sending process.
- uid: uint,
+ uid: unix::uid,
// Exit value or signal.
status: int,
// Address of the faulting instruction.
diff --git a/unix/signal/+linux.ha b/unix/signal/+linux.ha
@@ -4,6 +4,7 @@
use errors;
use io;
use rt;
+use unix;
// Configures a new signal handler, returning the old details (which can be
// passed to [[restore]] to restore its behavior).
@@ -204,9 +205,9 @@ export type siginfo = union {
union {
struct {
// Process ID of the sender.
- pid: int,
+ pid: unix::pid,
// Real user ID of the sending process.
- uid: uint,
+ uid: unix::uid,
// Exit value or signal.
status: int,
},
diff --git a/unix/signal/+openbsd.ha b/unix/signal/+openbsd.ha
@@ -3,6 +3,7 @@
use io;
use rt;
+use unix;
// Configures a new signal handler, returning the old details (which can be
// passed to [[restore]] to restore its behavior).
@@ -200,9 +201,9 @@ export type siginfo = struct {
union {
struct {
// Process ID of the sender.
- pid: int,
+ pid: unix::pid,
// Real user ID of the sending process.
- uid: uint,
+ uid: unix::uid,
},
struct {
// Address of the faulting instruction.