diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs
index aa7eef7c00bdd2bdd4f323eb190e28a757fb3be6..daff60cb5760fde81bd0776f39f94af6f3fd73ea 100644
--- a/src/platform/src/linux/mod.rs
+++ b/src/platform/src/linux/mod.rs
@@ -116,7 +116,7 @@ pub fn getuid() -> uid_t {
 }
 
 pub fn link(path1: *const c_char, path2: *const c_char) -> c_int {
-    e(unsafe { syscall!(LINKAT, AT_FDCWD, path1, path2) }) as c_int
+    e(unsafe { syscall!(LINKAT, AT_FDCWD, path1, AT_FDCWD, path2, 0) }) as c_int
 }
 
 pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int {
@@ -139,6 +139,22 @@ pub fn rmdir(path: *const c_char) -> c_int {
     e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, AT_REMOVEDIR) }) as c_int
 }
 
+pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
+    e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int
+}
+
+pub fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
+    e(unsafe { syscall!(SETREGID, rgid, egid) }) as c_int
+}
+
+pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
+    e(unsafe { syscall!(SETREUID, ruid, euid) }) as c_int
+}
+
+pub fn unlink(path: *const c_char) -> c_int {
+    e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, 0) }) as c_int
+}
+
 pub fn write(fildes: c_int, buf: &[u8]) -> ssize_t {
     e(unsafe { syscall!(WRITE, fildes, buf.as_ptr(), buf.len()) }) as ssize_t
 }
diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs
index 264042d79ce12f965c363cd3b9cc7d9208a3fa71..0ea4bda2073454a74f9968f0c351413b5471f741 100644
--- a/src/platform/src/redox/mod.rs
+++ b/src/platform/src/redox/mod.rs
@@ -157,6 +157,23 @@ pub fn rmdir(path: *const c_char) -> c_int {
     e(syscall::rmdir(path)) as c_int
 }
 
+pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
+    e(syscall::setpgid(pid as usize, pgid as usize)) as c_int
+}
+
+pub fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
+    e(syscall::setregid(rgid as usize, egid as usize)) as c_int
+}
+
+pub fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
+    e(syscall::setreuid(ruid as usize, euid as usize)) as c_int
+}
+
+pub fn unlink(path: *const c_char) -> c_int {
+    let path = unsafe { c_str(path) };
+    e(syscall::unlink(path)) as c_int
+}
+
 pub fn write(fd: c_int, buf: &[u8]) -> ssize_t {
     e(syscall::write(fd as usize, buf)) as ssize_t
 }
diff --git a/src/unistd/src/lib.rs b/src/unistd/src/lib.rs
index e83c8a8280f66f38f3c4645d9c597db65841e40a..8a1d149f887b8aad5ab05f60d54d8c3607a60f31 100644
--- a/src/unistd/src/lib.rs
+++ b/src/unistd/src/lib.rs
@@ -225,7 +225,7 @@ pub extern "C" fn getpgid(pid: pid_t) -> pid_t {
 
 #[no_mangle]
 pub extern "C" fn getpgrp() -> pid_t {
-    unimplemented!();
+    platform::getpgid(platform::getpid())
 }
 
 #[no_mangle]
@@ -351,7 +351,7 @@ pub extern "C" fn setgid(gid: gid_t) -> c_int {
 
 #[no_mangle]
 pub extern "C" fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
-    unimplemented!();
+    platform::setpgid(pid, pgid)
 }
 
 #[no_mangle]
@@ -361,12 +361,12 @@ pub extern "C" fn setpgrp() -> pid_t {
 
 #[no_mangle]
 pub extern "C" fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
-    unimplemented!();
+    platform::setregid(rgid, egid)
 }
 
 #[no_mangle]
 pub extern "C" fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
-    unimplemented!();
+    platform::setreuid(ruid, euid)
 }
 
 #[no_mangle]
@@ -436,7 +436,7 @@ pub extern "C" fn ualarm(useconds: useconds_t, interval: useconds_t) -> useconds
 
 #[no_mangle]
 pub extern "C" fn unlink(path: *const c_char) -> c_int {
-    unimplemented!();
+    platform::unlink(path)
 }
 
 #[no_mangle]
diff --git a/tests/.gitignore b/tests/.gitignore
index 5e35eadf6c6a60435f337ce970df0445cb12a649..42fe4750c666a6810fd66def2384df6045e3cc7c 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -23,5 +23,7 @@
 /pipe
 /printf
 /rmdir
+/setid
+/unlink
 /stdlib/strtol
 /write
diff --git a/tests/Makefile b/tests/Makefile
index d1c3d111cb572bb29071f8f3624dcf2150be7f24..18f8e1911f9cbaf4eb49bd7d9adff3229884beda 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -16,9 +16,11 @@ BINS=\
 	getid \
 	link \
 	math \
-	rmdir \
 	pipe \
-	printf \
+	printf \ 
+	rmdir \
+	setid \
+	unlink \
 	stdlib/strtol \
 	write
 
diff --git a/tests/link.c b/tests/link.c
index 3e36df81fbfd72fb472c5245aad3db84c05c5c6d..383575e8ce60e3a7d7fd57b71e2cb9b7d41f7c8e 100644
--- a/tests/link.c
+++ b/tests/link.c
@@ -1,5 +1,6 @@
 #include <unistd.h>
 
 int main(int argc, char** argv) {
-    int status = link("link.c", "link.out");
+    link("./link.c", "./link.out");
+    perror("link");
 }
diff --git a/tests/setid.c b/tests/setid.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce2b42ea93e4ba464faaf9341ea38fd2da171f11
--- /dev/null
+++ b/tests/setid.c
@@ -0,0 +1,26 @@
+/*
+ * The process joins process group 0.
+ */
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+int main( void )
+  {
+    if( setpgid( getpid(), 0 ) == -1 ) {
+        perror( "setpgid" );
+    }
+    printf( "%d belongs to process group %d\n",
+         getpid(), getpgrp() );
+
+    if( setregid(-1, -1) == -1 ) {
+        perror( "setregid" );
+    }
+    printf("%d has egid %d and gid %d\n", getpid(), getegid(), getgid());
+
+    if( setreuid(-1, -1) == -1 ) {
+        perror( "setreuid" );
+    }
+    printf("%d has euid %d and uid %d\n", getpid(), geteuid(), getuid());
+  }
diff --git a/tests/unlink.c b/tests/unlink.c
new file mode 100644
index 0000000000000000000000000000000000000000..0eceae0ac2891215ab2f531157476b6188952444
--- /dev/null
+++ b/tests/unlink.c
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include <stdio.h>
+
+int main(int argc, char** argv) {
+    link("./unlink.c", "./unlink.out");
+    perror("unlink");
+}