summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-07-13 20:09:53 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-07-13 20:09:53 +0200
commit7d356b1ddab0150b7347a5952e3bff2a04704fd4 (patch)
treec26a5b9c45d970dda011f9923966233a4f70669b
parent7162c5eed91a8e22a4b768110011df28bfd86455 (diff)
downloadabaos-7d356b1ddab0150b7347a5952e3bff2a04704fd4.tar.gz
abaos-7d356b1ddab0150b7347a5952e3bff2a04704fd4.tar.bz2
added an exit function
added Linux syscall stubs for exit and write adapted all tests added a printf test made stdio work on Linux or AbaOs syscalls
-rw-r--r--doc/LINKS.TODO3
-rw-r--r--src/Makefile5
-rw-r--r--src/libc/stdio.c93
-rw-r--r--src/libc/stdio.h4
-rw-r--r--src/libc/stdlib.c20
-rw-r--r--src/libc/stdlib.h3
-rw-r--r--tests/libc/Makefile70
-rw-r--r--tests/libc/kernel_stub.asm48
-rw-r--r--tests/libc/kernel_stub.c8
-rw-r--r--tests/libc/kernel_stub.h27
-rw-r--r--tests/libc/test_abort.c6
-rw-r--r--tests/libc/test_itoa.c14
-rw-r--r--tests/libc/test_malloc.c6
-rw-r--r--tests/libc/test_printf.c15
-rw-r--r--tests/libc/test_strlcat.c11
-rw-r--r--tests/libc/test_strlcpy.c7
16 files changed, 274 insertions, 66 deletions
diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO
index 092c620..89f7ce8 100644
--- a/doc/LINKS.TODO
+++ b/doc/LINKS.TODO
@@ -99,3 +99,6 @@ http://webserver2.tecgraf.puc-rio.br/iup/
linker:
https://stackoverflow.com/questions/26143123/how-do-i-ensure-the-entry-function-at-a-fixed-address-of-bare-metal-arm
+
+Linux:
+https://blog.packagecloud.io/eng/2016/04/05/the-definitive-guide-to-linux-system-calls/
diff --git a/src/Makefile b/src/Makefile
index 4192fd1..b4ceff1 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,7 @@
CC := gcc
-INCLUDES = -DOS_ABAOS -I. -Ilibc -Ihardware -Idrivers -Idrivers/hdi -Idrivers/hdi/ps2 -Idrivers/video -Ikernel -Igui
-CFLAGS := -std=c99 -m32 -march=i486 -ffreestanding -O0 -g -Werror $(INCLUDES)
+DEFINES = -DOS_ABAOS
+INCLUDES = -I. -Ilibc -Ihardware -Idrivers -Idrivers/hdi -Idrivers/hdi/ps2 -Idrivers/video -Ikernel -Igui
+CFLAGS := -std=c99 -m32 -march=i486 -ffreestanding -O0 -g -Werror $(INCLUDES) $(DEFINES)
LD := ld
NASMFLAGS := -f elf32
NASM := nasm
diff --git a/src/libc/stdio.c b/src/libc/stdio.c
index 07a047e..631cfbb 100644
--- a/src/libc/stdio.c
+++ b/src/libc/stdio.c
@@ -3,17 +3,70 @@
#include "stdlib.h"
#include "string.h"
+#ifdef OS_ABAOS
+#include "kernel.h"
+#endif
+
+#ifdef OS_ABAOS
console_t *stdio_console = NULL;
+#endif
-int puts( const char *s )
+static void print_string( const char *s );
+static void print_char( const char c );
+static void print_newline( void );
+
+#ifdef OS_ABAOS
+static void print_string( const char *s )
{
if( stdio_console == NULL ) {
- return EOF;
+ kernel_panic( "stdio_console not set!" );
}
-
+
console_put_string( stdio_console, s );
+}
+
+static void print_char( const char c )
+{
+ if( stdio_console == NULL ) {
+ kernel_panic( "stdio_console not set!" );
+ }
+
+ console_put_char( stdio_console, c );
+}
+
+static void print_newline( void )
+{
+ if( stdio_console == NULL ) {
+ kernel_panic( "stdio_console not set!" );
+ }
+
console_put_newline( stdio_console );
-
+}
+#endif
+
+#ifdef OS_LINUX
+static void print_string( const char *s )
+{
+ syscall3( __NR_write, STDOUT_FILENO, (long)s, strlen( s ) );
+}
+
+static void print_char( const char c )
+{
+ char s[2]; s[0] = c;
+ syscall3( __NR_write, STDOUT_FILENO, (long)s, 1 );
+}
+
+static void print_newline( void )
+{
+ syscall3( __NR_write, STDOUT_FILENO, (long)"\n", 1 );
+}
+#endif
+
+int puts( const char *s )
+{
+ print_string( s );
+ print_newline( );
+
return 1;
}
@@ -32,35 +85,31 @@ int vprintf( const char *format, va_list args )
{
const char *s = format;
int n = 0;
-
- if( stdio_console == NULL ) {
- return -1;
- }
while( *s != '\0' ) {
switch( *s ) {
case '\n':
- console_put_newline( stdio_console );
+ print_newline( );
n++;
break;
case '%':
s++;
if( *s == '\0' ) {
- console_put_string( stdio_console, "<truncated % found at end of format string>" );
- console_put_newline( stdio_console );
+ print_string( "<truncated % found at end of format string>" );
+ print_newline( );
return -1;
}
switch( *s ) {
case '%':
- console_put_char( stdio_console, '%' );
+ print_char( '%' );
break;
case 'X': {
char buf[19];
itoa( va_arg( args, int ), (char *)buf, 16 );
- console_put_string( stdio_console, buf );
+ print_string( buf );
n += strlen( buf );
}
break;
@@ -68,30 +117,30 @@ int vprintf( const char *format, va_list args )
case 'd': {
char buf[19];
itoa( va_arg( args, int ), (char *)buf, 10 );
- console_put_string( stdio_console, buf );
+ print_string( buf );
n += strlen( buf );
}
break;
case 'c':
- console_put_char( stdio_console, va_arg( args, int ) );
+ print_char( va_arg( args, int ) );
break;
case 's':
- console_put_string( stdio_console, va_arg( args, const char * ) );
+ print_string( va_arg( args, const char * ) );
break;
default:
- console_put_string( stdio_console, "<illegal format string %" );
- console_put_char( stdio_console, *s );
- console_put_string( stdio_console, ">" );
- console_put_newline( stdio_console );
+ print_string( "<illegal format string %" );
+ print_char( *s );
+ print_string( ">" );
+ print_newline( );
}
break;
default:
- console_put_char( stdio_console, *s );
+ print_char( *s );
n++;
}
s++;
@@ -100,7 +149,9 @@ int vprintf( const char *format, va_list args )
return n;
}
+#ifdef OS_ABAOS
void __stdio_set_console( console_t *console )
{
stdio_console = console;
}
+#endif
diff --git a/src/libc/stdio.h b/src/libc/stdio.h
index 24632f6..33d7946 100644
--- a/src/libc/stdio.h
+++ b/src/libc/stdio.h
@@ -9,6 +9,10 @@
#include "console.h"
#endif
+#ifdef OS_LINUX
+#include "kernel_stub.h"
+#endif
+
#define EOF (-1)
int puts( const char *s );
diff --git a/src/libc/stdlib.c b/src/libc/stdlib.c
index d7d4331..b4c2d84 100644
--- a/src/libc/stdlib.c
+++ b/src/libc/stdlib.c
@@ -48,11 +48,29 @@ char *itoa( int v, char *s, int base )
return s;
}
-void abort( void )
+void __attribute__( ( noreturn ) ) exit( int status )
+{
+#ifdef OS_ABAOS
+ // TODO: this should be done on process level, terminating
+ // the process (by signalling SIGABRT for instance)
+ kernel_panic( "exited with exit code %d", status );
+#endif
+#ifdef OS_LINUX
+ syscall1( __NR_exit, status );
+#endif
+
+ // make gcc happy ("error: ‘noreturn’ function does return")
+ for( ;; );
+}
+
+void __attribute__( ( noreturn ) ) abort( void )
{
// TODO: this should be done on process level, terminating
// the process (by signalling SIGABRT for instance)
kernel_panic( "aborted" );
+
+ // make gcc happy ("error: ‘noreturn’ function does return")
+ for( ;; );
}
// TODO: we should have a global memory manager and one per
diff --git a/src/libc/stdlib.h b/src/libc/stdlib.h
index 9ff28a3..5b2521f 100644
--- a/src/libc/stdlib.h
+++ b/src/libc/stdlib.h
@@ -7,7 +7,8 @@
char *itoa( int v, char *s, int base );
-void abort( void );
+void __attribute__( (noreturn ) ) exit( int status );
+void __attribute__( (noreturn ) ) abort( void );
void *malloc( size_t size );
void free( void *p );
diff --git a/tests/libc/Makefile b/tests/libc/Makefile
index 43620d7..59fa715 100644
--- a/tests/libc/Makefile
+++ b/tests/libc/Makefile
@@ -1,53 +1,79 @@
CC := gcc
-CFLAGS := -std=c99 -m32 -ffreestanding -O0 -g -Wall -Werror
-INCLUDES = -I../../src/libc -I../../src/kernel
-LD := ld
+DEFINES = -DOS_LINUX
+INCLUDES = -I. -I../../src/libc -I../../src/kernel
+CFLAGS := -std=c99 -m32 -ffreestanding -O0 -g -Wall -Werror $(INCLUDES) $(DEFINES)
+# tcc misses crt1.o from gcc?! and fails with _start symbol missing on -nostdlib,
+# this seems very wrong..
+# TODO: for now test sanity of library tests with gcc and enabling -nostdlib
+#LDFLAGS := -nostdlib
+NASMFLAGS := -f elf32
+NASM := nasm
all: test
-test_strlcpy: test_strlcpy.o ../../src/libc/string.o
- $(CC) -o test_strlcpy test_strlcpy.o ../../src/libc/string.o
+test_strlcpy: test_strlcpy.o ../../src/libc/string.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
+ $(CC) -o test_strlcpy test_strlcpy.o ../../src/libc/string.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
test_strlcpy.o: test_strlcpy.c
- $(CC) $(CFLAGS) $(INCLUDES) -c -o test_strlcpy.o test_strlcpy.c
+ $(CC) $(CFLAGS) -c -o test_strlcpy.o test_strlcpy.c
-test_strlcat: test_strlcat.o ../../src/libc/string.o
- $(CC) -o test_strlcat test_strlcat.o ../../src/libc/string.o
+test_strlcat: test_strlcat.o ../../src/libc/string.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
+ $(CC) $(LDFLAGS) -o test_strlcat test_strlcat.o ../../src/libc/string.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
test_strlcat.o: test_strlcat.c
- $(CC) $(CFLAGS) $(INCLUDES) -c -o test_strlcat.o test_strlcat.c
+ $(CC) $(CFLAGS) -c -o test_strlcat.o test_strlcat.c
-test_itoa: test_itoa.o ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o
- $(CC) -o test_itoa test_itoa.o ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o
+test_itoa: test_itoa.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
+ $(CC) $(LDFLAGS) -o test_itoa test_itoa.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
test_itoa.o: test_itoa.c ../../src/libc/stdlib.h
- $(CC) $(CFLAGS) $(INCLUDES) -c -o test_itoa.o test_itoa.c
+ $(CC) $(CFLAGS) -c -o test_itoa.o test_itoa.c
-test_malloc: test_malloc.o ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o
- $(CC) -o test_malloc test_malloc.o ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o
+test_malloc: test_malloc.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
+ $(CC) $(LDFLAGS) -o test_malloc test_malloc.o ../../src/libc/stdio.o ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
test_malloc.o: test_malloc.c ../../src/libc/stdlib.h
- $(CC) $(CFLAGS) $(INCLUDES) -c -o test_malloc.o test_malloc.c
+ $(CC) $(CFLAGS) -c -o test_malloc.o test_malloc.c
+
+test_printf: test_printf.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
+ $(CC) $(LDFLAGS) -o test_printf test_printf.o ../../src/libc/stdio.o ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
+
+test_printf.o: test_printf.c ../../src/libc/stdlib.h
+ $(CC) $(CFLAGS) -c -o test_printf.o test_printf.c
+
+test_abort: test_abort.o ../../src/libc/stdlib.o ../../src/libc/stdio.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
+ $(CC) $(LDFLAGS) -o test_abort test_abort.o ../../src/libc/stdio.o ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o kernel_stub.o kernel_stub_asm.o
+
+test_abort.o: test_abort.c ../../src/libc/stdlib.h
+ $(CC) $(CFLAGS) -c -o test_abort.o test_abort.c
../../src/libc/string.o: ../../src/libc/string.c
- $(CC) $(CFLAGS) $(INCLUDES) -c -o ../../src/libc/string.o ../../src/libc/string.c
+ $(CC) $(CFLAGS) -c -o ../../src/libc/string.o ../../src/libc/string.c
../../src/libc/stdlib.o: ../../src/libc/stdlib.c
- $(CC) $(CFLAGS) $(INCLUDES) -c -o ../../src/libc/stdlib.o ../../src/libc/stdlib.c
+ $(CC) $(CFLAGS) -c -o ../../src/libc/stdlib.o ../../src/libc/stdlib.c
+
+../../src/libc/stdio.o: ../../src/libc/stdio.c
+ $(CC) $(CFLAGS) -c -o ../../src/libc/stdio.o ../../src/libc/stdio.c
../../src/kernel/memorymanagement.o: ../../src/kernel/memorymanagement.c
- $(CC) $(CFLAGS) $(INCLUDES) -c -o ../../src/kernel/memorymanagement.o ../../src/kernel/memorymanagement.c
+ $(CC) $(CFLAGS) -c -o ../../src/kernel/memorymanagement.o ../../src/kernel/memorymanagement.c
kernel_stub.o: kernel_stub.c
- $(CC) $(CFLAGS) $(INCLUDES) -c -o kernel_stub.o kernel_stub.c
+ $(CC) $(CFLAGS) -c -o kernel_stub.o kernel_stub.c
+
+kernel_stub_asm.o: kernel_stub.asm
+ $(NASM) kernel_stub.asm $(NASMFLAGS) -o kernel_stub_asm.o
-test: test_strlcpy test_strlcat test_itoa test_malloc
+test: test_strlcpy test_strlcat test_itoa test_malloc test_abort test_printf
./test_strlcpy
./test_strlcat
./test_itoa
./test_malloc
+ ./test_printf
+ -./test_abort
clean:
- -rm -f test_strlcpy test_strlcat test_itoa test_malloc
- -rm -f ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/kernel/memorymanagement.o
+ -rm -f test_strlcpy test_strlcat test_itoa test_malloc test_printf test_abort
+ -rm -f ../../src/libc/stdlib.o ../../src/libc/string.o ../../src/libc/stdio.o ../../src/kernel/memorymanagement.o
-rm -f *.o
diff --git a/tests/libc/kernel_stub.asm b/tests/libc/kernel_stub.asm
new file mode 100644
index 0000000..c9335a8
--- /dev/null
+++ b/tests/libc/kernel_stub.asm
@@ -0,0 +1,48 @@
+[bits 32]
+
+global syscall0
+global syscall1
+global syscall2
+global syscall3
+
+; long syscall1( long n );
+syscall0:
+ push ebp
+ mov ebp, esp
+ mov eax, [ebp+8]
+ int 0x80
+ leave
+ ret
+
+; long syscall1( long n, long a1 );
+syscall1:
+ push ebp
+ mov ebp, esp
+ mov eax, [ebp+8]
+ mov ebx, [ebp+12]
+ int 0x80
+ leave
+ ret
+
+; long syscall2( long n, long a1, long a2 );
+syscall2:
+ push ebp
+ mov ebp, esp
+ mov eax, [ebp+8]
+ mov ebx, [ebp+12]
+ mov ecx, [ebp+16]
+ int 0x80
+ leave
+ ret
+
+; long syscall3( long n, long a1, long a2, long a3 );
+syscall3:
+ push ebp
+ mov ebp, esp
+ mov eax, [ebp+8]
+ mov ebx, [ebp+12]
+ mov ecx, [ebp+16]
+ mov edx, [ebp+20]
+ int 0x80
+ leave
+ ret
diff --git a/tests/libc/kernel_stub.c b/tests/libc/kernel_stub.c
index c859be0..610c3d3 100644
--- a/tests/libc/kernel_stub.c
+++ b/tests/libc/kernel_stub.c
@@ -3,6 +3,12 @@
#include "stdio.h"
#include "stdlib.h"
+// abaos has a kernel_panic function
+// TODO: we should not need this stub, rather, libc functions should
+// use other means to abort the process (e.g. with abort), then the
+// kernel should catch this exception and issue the kernel_panic itself.
+// anyway: the kernel has to decide whether it dies in panic or it
+// kills the culprid child an merely goes his way..
void kernel_panic( const char *format, ... )
{
(void)printf( "\n*** KERNEL PANIC ***\n" );
@@ -13,6 +19,6 @@ void kernel_panic( const char *format, ... )
va_end( args );
puts( "" );
- abort( );
+ exit( 255 );
}
diff --git a/tests/libc/kernel_stub.h b/tests/libc/kernel_stub.h
new file mode 100644
index 0000000..467ad20
--- /dev/null
+++ b/tests/libc/kernel_stub.h
@@ -0,0 +1,27 @@
+#ifndef KERNEL_STUB_H
+#define KERNEL_STUB_H
+
+// abaos has a kernel_panic function
+// TODO: we should not need this stub, rather, libc functions should
+// use other means to abort the process (e.g. with abort), then the
+// kernel should catch this exception and issue the kernel_panic itself.
+// anyway: the kernel has to decide whether it dies in panic or it
+// kills the culprid child an merely goes his way..
+void kernel_panic( const char *format, ... );
+
+// definitions to emulate kernel functions by calling Linux kernel
+// syscalls directly (careful: works for 32-bit Intel only!)
+
+// those are defined in sys/syscall.h
+#define __NR_exit 1
+#define __NR_write 4
+
+// defined in unistd.h
+#define STDOUT_FILENO 1
+
+long syscall0( long n );
+long syscall1( long n, long a1 );
+long syscall2( long n, long a1, long a2 );
+long syscall3( long n, long a1, long a2, long a3 );
+
+#endif
diff --git a/tests/libc/test_abort.c b/tests/libc/test_abort.c
new file mode 100644
index 0000000..da5c0f2
--- /dev/null
+++ b/tests/libc/test_abort.c
@@ -0,0 +1,6 @@
+#include "stdlib.h"
+
+int main( void )
+{
+ abort( );
+}
diff --git a/tests/libc/test_itoa.c b/tests/libc/test_itoa.c
index 837b77a..837fd01 100644
--- a/tests/libc/test_itoa.c
+++ b/tests/libc/test_itoa.c
@@ -9,26 +9,26 @@ int main( void )
// simple conversion without sign
res = itoa( 568876, buf, 10 );
- if( strcmp( buf, "568876" ) ) return 1;
+ if( strcmp( buf, "568876" ) ) exit( 1 );
// test if the returned pointer points to the buffer
- if( strcmp( res, buf ) ) return 1;
+ if( strcmp( res, buf ) ) exit( 1 );
// conversion with sign
res = itoa( -568876, buf, 10 );
- if( strcmp( buf, "-568876" ) ) return 1;
+ if( strcmp( buf, "-568876" ) ) exit( 1 );
// convert upper limit
res = itoa( INT_MAX, buf, 10 );
- if( strcmp( buf, "2147483647" ) ) return 1;
+ if( strcmp( buf, "2147483647" ) ) exit( 1 );
// convert lower limit
res = itoa( INT_MIN+1, buf, 10 );
- if( strcmp( buf, "-2147483647" ) ) return 1;
+ if( strcmp( buf, "-2147483647" ) ) exit( 1 );
// convert to hex
res = itoa( 568876, buf, 16 );
- if( strcmp( buf, "8AE2C" ) ) return 1;
+ if( strcmp( buf, "8AE2C" ) ) exit( 1 );
- return 0;
+ exit( 0 );
}
diff --git a/tests/libc/test_malloc.c b/tests/libc/test_malloc.c
index 0f74fad..aaff2da 100644
--- a/tests/libc/test_malloc.c
+++ b/tests/libc/test_malloc.c
@@ -17,8 +17,8 @@ int main( void )
s = (char *)malloc( strlen( s1 ) + 1 );
size_t n = strlcpy( s, s1, strlen( s1 ) + 1 );
- if( n != 11 ) return 1;
- if( strcmp( s, s1 ) != 0 ) return 1;
+ if( n != 11 ) exit( 1 );
+ if( strcmp( s, s1 ) != 0 ) exit( 1 );
- return 0;
+ exit( 0 );
}
diff --git a/tests/libc/test_printf.c b/tests/libc/test_printf.c
new file mode 100644
index 0000000..d2fc849
--- /dev/null
+++ b/tests/libc/test_printf.c
@@ -0,0 +1,15 @@
+#include "string.h"
+#include "stdlib.h"
+#include "stdio.h"
+
+int main( void )
+{
+ char *s = "test_string";
+ int i = 47;
+ char c = 'X';
+
+ printf( "string '%s', decimal %d, hex 0x%X, character '%c'\n",
+ s, i, i, c );
+
+ exit( 0 );
+}
diff --git a/tests/libc/test_strlcat.c b/tests/libc/test_strlcat.c
index 074cb98..5a1bfc9 100644
--- a/tests/libc/test_strlcat.c
+++ b/tests/libc/test_strlcat.c
@@ -1,4 +1,5 @@
#include "string.h"
+#include "stdlib.h"
int main( void )
{
@@ -9,11 +10,11 @@ int main( void )
*d = '\0';
n = strlcat( d, s1, 15 );
- if( n != 11 ) return 1;
- if( strcmp( d, s1 ) != 0 ) return 1;
+ if( n != 11 ) exit( 1 );
+ if( strcmp( d, s1 ) != 0 ) exit( 1 );
n = strlcat( d, s2, 15 );
- if( n != 14 ) return 1;
- if( strcmp( d, "test_stringapp" ) != 0 ) return 1;
+ if( n != 14 ) exit( 1 );
+ if( strcmp( d, "test_stringapp" ) != 0 ) exit( 1 );
- return 0;
+ exit( 0 );
}
diff --git a/tests/libc/test_strlcpy.c b/tests/libc/test_strlcpy.c
index a23a5bc..ac7acf9 100644
--- a/tests/libc/test_strlcpy.c
+++ b/tests/libc/test_strlcpy.c
@@ -1,4 +1,5 @@
#include "string.h"
+#include "stdlib.h"
int main( void )
{
@@ -8,8 +9,8 @@ int main( void )
// copy into too small string
n = strlcpy( d, s, 4 );
- if( n != 11 ) return 1;
- if( strcmp( d, "tes" ) ) return 1;
+ if( n != 11 ) exit( 1 );
+ if( strcmp( d, "tes" ) ) exit( 1 );
- return 0;
+ exit( 0 );
}