Index: uspace/lib/c/generic/libc.c
===================================================================
--- uspace/lib/c/generic/libc.c	(revision 379db9efebb974024006a4fe8299aa4a4f9ca63c)
+++ uspace/lib/c/generic/libc.c	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
@@ -130,5 +130,5 @@
 }
 
-void exit(int status)
+void __libc_exit(int status)
 {
 	if (env_setup) {
@@ -145,5 +145,5 @@
 }
 
-void abort(void)
+void __libc_abort(void)
 {
 	__SYSCALL1(SYS_TASK_EXIT, true);
Index: uspace/lib/c/generic/private/libc.h
===================================================================
--- uspace/lib/c/generic/private/libc.h	(revision 379db9efebb974024006a4fe8299aa4a4f9ca63c)
+++ uspace/lib/c/generic/private/libc.h	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
@@ -38,4 +38,6 @@
 extern unsigned char _end[];
 extern void __libc_main(void *) __attribute__((noreturn));
+extern void __libc_exit(int) __attribute__((noreturn));
+extern void __libc_abort(void) __attribute__((noreturn));
 extern int main(int, char *[]);
 
Index: uspace/lib/c/generic/private/stdlib.h
===================================================================
--- uspace/lib/c/generic/private/stdlib.h	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
+++ uspace/lib/c/generic/private/stdlib.h	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup libc
+ * @{
+ */
+/** @file
+ */
+
+#ifndef LIBC_PRIVATE_STDLIB_H_
+#define LIBC_PRIVATE_STDLIB_H_
+
+#include <adt/list.h>
+
+/** Exit handler list entry */
+typedef struct {
+	/** Link to exit handler list */
+	link_t llist;
+	/** Exit handler function */
+	void (*func)(void);
+} __exit_handler_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/c/generic/stdlib.c
===================================================================
--- uspace/lib/c/generic/stdlib.c	(revision 379db9efebb974024006a4fe8299aa4a4f9ca63c)
+++ uspace/lib/c/generic/stdlib.c	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2006 Ondrej Palkovsky
+ * Copyright (c) 2018 Jiri Svoboda
  * All rights reserved.
  *
@@ -33,8 +34,19 @@
  */
 
+#include <adt/list.h>
+#include <fibril_synch.h>
 #include <stdlib.h>
+#include "private/libc.h"
+#include "private/stdlib.h"
 
 static int glbl_seed = 1;
 
+static LIST_INITIALIZE(exit_handlers);
+static FIBRIL_MUTEX_INITIALIZE(exit_handlers_lock);
+
+static LIST_INITIALIZE(quick_exit_handlers);
+static FIBRIL_MUTEX_INITIALIZE(quick_exit_handlers_lock);
+
+
 int rand(void)
 {
@@ -46,4 +58,110 @@
 	glbl_seed = seed % RAND_MAX;
 }
+
+/** Register exit handler.
+ *
+ * @param func Function to be called during program terimnation
+ * @return Zero on success, nonzero on failure
+ */
+int atexit(void (*func)(void))
+{
+	__exit_handler_t *entry;
+
+	entry = malloc(sizeof(__exit_handler_t));
+	if (entry == NULL)
+		return -1;
+
+	entry->func = func;
+
+	fibril_mutex_lock(&exit_handlers_lock);
+	list_prepend(&entry->llist, &exit_handlers);
+	fibril_mutex_unlock(&exit_handlers_lock);
+	return 0;
+}
+
+/** Terminate program with exit status.
+ *
+ * @param status Exit status
+ */
+void exit(int status)
+{
+	link_t *link;
+	__exit_handler_t *eh;
+
+	/* Call exit handlers */
+	fibril_mutex_lock(&exit_handlers_lock);
+	while (!list_empty(&exit_handlers)) {
+		link = list_first(&exit_handlers);
+		list_remove(link);
+		fibril_mutex_unlock(&exit_handlers_lock);
+
+		eh = list_get_instance(link, __exit_handler_t, llist);
+		eh->func();
+		fibril_mutex_lock(&exit_handlers_lock);
+	}
+
+	fibril_mutex_unlock(&exit_handlers_lock);
+
+	_Exit(status);
+}
+
+/** Register quick exit handler.
+ *
+ * @param func Function to be called during quick program terimnation
+ * @return Zero on success, nonzero on failure
+ */
+int at_quick_exit(void (*func)(void))
+{
+	__exit_handler_t *entry;
+
+	entry = malloc(sizeof(__exit_handler_t));
+	if (entry == NULL)
+		return -1;
+
+	entry->func = func;
+
+	fibril_mutex_lock(&exit_handlers_lock);
+	list_prepend(&entry->llist, &exit_handlers);
+	fibril_mutex_unlock(&exit_handlers_lock);
+	return 0;
+}
+
+/** Quickly terminate program with exit status.
+ *
+ * @param status Exit status
+ */
+void quick_exit(int status)
+{
+	link_t *link;
+	__exit_handler_t *eh;
+
+	/* Call quick exit handlers */
+	fibril_mutex_lock(&quick_exit_handlers_lock);
+	while (!list_empty(&quick_exit_handlers)) {
+		link = list_first(&quick_exit_handlers);
+		list_remove(link);
+		fibril_mutex_unlock(&quick_exit_handlers_lock);
+
+		eh = list_get_instance(link, __exit_handler_t, llist);
+		eh->func();
+		fibril_mutex_lock(&quick_exit_handlers_lock);
+	}
+
+	fibril_mutex_unlock(&quick_exit_handlers_lock);
+
+	_Exit(status);
+}
+
+void _Exit(int status)
+{
+	__libc_exit(status);
+}
+
+/** Abnormal program termination */
+void abort(void)
+{
+	__libc_abort();
+}
+
 
 /** Compute quotient and remainder of int division.
Index: uspace/lib/c/include/stdlib.h
===================================================================
--- uspace/lib/c/include/stdlib.h	(revision 379db9efebb974024006a4fe8299aa4a4f9ca63c)
+++ uspace/lib/c/include/stdlib.h	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
@@ -77,5 +77,9 @@
 
 extern void abort(void) __attribute__((noreturn));
+extern int atexit(void (*)(void));
 extern void exit(int) __attribute__((noreturn));
+extern void _Exit(int) __attribute__((noreturn));
+extern int at_quick_exit(void (*)(void));
+extern void quick_exit(int);
 
 extern int atoi(const char *);
Index: uspace/lib/c/test/stdlib.c
===================================================================
--- uspace/lib/c/test/stdlib.c	(revision 379db9efebb974024006a4fe8299aa4a4f9ca63c)
+++ uspace/lib/c/test/stdlib.c	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
@@ -63,4 +63,223 @@
 }
 
+/** atoi function */
+PCUT_TEST(atoi)
+{
+	int i;
+
+	i = atoi(" \t42");
+	PCUT_ASSERT_TRUE(i == 42);
+}
+
+/** atol function */
+PCUT_TEST(atol)
+{
+	long li;
+
+	li = atol(" \t42");
+	PCUT_ASSERT_TRUE(li == 42);
+}
+
+/** atoll function */
+PCUT_TEST(atoll)
+{
+	long long lli;
+
+	lli = atoll(" \t42");
+	PCUT_ASSERT_TRUE(lli == 42);
+}
+
+/** strtol function */
+PCUT_TEST(strtol)
+{
+	long li;
+	char *ep;
+
+	li = strtol(" \t42x", &ep, 10);
+	PCUT_ASSERT_TRUE(li == 42);
+	PCUT_ASSERT_TRUE(*ep == 'x');
+}
+
+/** strtol function with auto-detected base 10 */
+PCUT_TEST(strtol_dec_auto)
+{
+	long li;
+	char *ep;
+
+	li = strtol(" \t42x", &ep, 0);
+	PCUT_ASSERT_TRUE(li == 42);
+	PCUT_ASSERT_TRUE(*ep == 'x');
+}
+
+/** strtol function with octal number */
+PCUT_TEST(strtol_oct)
+{
+	long li;
+	char *ep;
+
+	li = strtol(" \t052x", &ep, 8);
+	PCUT_ASSERT_TRUE(li == 052);
+	PCUT_ASSERT_TRUE(*ep == 'x');
+}
+
+/** strtol function with octal number with prefix */
+#include <stdio.h>
+PCUT_TEST(strtol_oct_prefix)
+{
+	long li;
+	char *ep;
+
+	li = strtol(" \t052x", &ep, 0);
+	printf("li=%ld (0%lo)\n", li, li);
+	PCUT_ASSERT_TRUE(li == 052);
+	PCUT_ASSERT_TRUE(*ep == 'x');
+}
+
+/** strtol function with hex number */
+PCUT_TEST(strtol_hex)
+{
+	long li;
+	char *ep;
+
+	li = strtol(" \t2ax", &ep, 16);
+	PCUT_ASSERT_TRUE(li == 0x2a);
+	PCUT_ASSERT_TRUE(*ep == 'x');
+}
+
+/** strtol function with hex number with hex prefix */
+PCUT_TEST(strtol_hex_prefixed)
+{
+	long li;
+	char *ep;
+
+	li = strtol(" \t0x2ax", &ep, 0);
+	PCUT_ASSERT_TRUE(li == 0x2a);
+	PCUT_ASSERT_TRUE(*ep == 'x');
+}
+
+/** strtol function with base 16 and number with 0x prefix */
+PCUT_TEST(strtol_base16_prefix)
+{
+	long li;
+	char *ep;
+
+	li = strtol(" \t0x1y", &ep, 16);
+	printf("li=%ld\n", li);
+	PCUT_ASSERT_TRUE(li == 1);
+	PCUT_ASSERT_TRUE(*ep == 'y');
+}
+
+/** strtol function with base 36 number */
+PCUT_TEST(strtol_base36)
+{
+	long li;
+	char *ep;
+
+	li = strtol(" \tz1.", &ep, 36);
+	PCUT_ASSERT_TRUE(li == 35 * 36 + 1);
+	PCUT_ASSERT_TRUE(*ep == '.');
+}
+
+/** rand function */
+PCUT_TEST(rand)
+{
+	int i;
+	int r;
+
+	for (i = 0; i < 100; i++) {
+		r = rand();
+		PCUT_ASSERT_TRUE(r >= 0);
+		PCUT_ASSERT_TRUE(r <= RAND_MAX);
+	}
+
+	PCUT_ASSERT_TRUE(RAND_MAX >= 32767);
+}
+
+/** srand function */
+PCUT_TEST(srand)
+{
+	int r1;
+	int r2;
+
+	srand(1);
+	r1 = rand();
+	srand(1);
+	r2 = rand();
+
+	PCUT_ASSERT_INT_EQUALS(r2, r1);
+
+	srand(42);
+	r1 = rand();
+	srand(42);
+	r2 = rand();
+
+	PCUT_ASSERT_INT_EQUALS(r2, r1);
+}
+
+/** Just make sure we have memory allocation function prototypes */
+PCUT_TEST(malloc)
+{
+	void *p;
+
+#if 0
+	// TODO
+	p = aligned_alloc(4, 8);
+	PCUT_ASSERT_NOT_NULL(p);
+	free(p);
+#endif
+	p = calloc(4, 4);
+	PCUT_ASSERT_NOT_NULL(p);
+	free(p);
+
+	p = malloc(4);
+	PCUT_ASSERT_NOT_NULL(p);
+	p = realloc(p, 2);
+	PCUT_ASSERT_NOT_NULL(p);
+	free(p);
+}
+
+/** Just check abort() is defined */
+PCUT_TEST(abort)
+{
+	if (0)
+		abort();
+}
+
+static void dummy_exit_handler(void)
+{
+}
+
+/** atexit function */
+PCUT_TEST(atexit)
+{
+	int rc;
+
+	rc = atexit(dummy_exit_handler);
+	PCUT_ASSERT_INT_EQUALS(0, rc);
+}
+
+/** exit function -- just make sure it is declared */
+PCUT_TEST(exit)
+{
+	if (0)
+		exit(0);
+}
+
+/** at_quick_exit function */
+PCUT_TEST(at_quick_exit)
+{
+	int rc;
+
+	rc = at_quick_exit(dummy_exit_handler);
+	PCUT_ASSERT_INT_EQUALS(0, rc);
+}
+
+/** quick_exit function -- just make sure it is declared */
+PCUT_TEST(quick_exit)
+{
+	if (0)
+		quick_exit(0);
+}
+
 /** Integer division */
 PCUT_TEST(div_func)
Index: uspace/lib/posix/include/posix/stdlib.h
===================================================================
--- uspace/lib/posix/include/posix/stdlib.h	(revision 379db9efebb974024006a4fe8299aa4a4f9ca63c)
+++ uspace/lib/posix/include/posix/stdlib.h	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
@@ -42,9 +42,4 @@
 #include <_bits/NULL.h>
 
-/* Process Termination */
-#define _Exit exit
-
-extern int atexit(void (*func)(void));
-
 /* Absolute Value */
 extern int abs(int i);
Index: uspace/lib/posix/src/stdlib.c
===================================================================
--- uspace/lib/posix/src/stdlib.c	(revision 379db9efebb974024006a4fe8299aa4a4f9ca63c)
+++ uspace/lib/posix/src/stdlib.c	(revision 099c834df962a90df5b478e1622ba3b91f162a84)
@@ -49,18 +49,4 @@
 #include "libc/vfs/vfs.h"
 #include "libc/stats.h"
-
-/**
- *
- * @param array
- * @param count
- * @param size
- * @param compare
- */
-int atexit(void (*func)(void))
-{
-	// TODO: low priority, just a compile-time dependency of binutils
-	not_implemented();
-	return 0;
-}
 
 /**
