[klibc] Core klibc code The actual klibc library. Signed-off-by: H. Peter Anvin --- commit 4aa604eeb8354e1154464f2107ce0731300592f1 tree b772d96e5d93427e8957feb6e941216927908306 parent 0b445e6b5c59116ad94ac997586c0f9aebf29599 author H. Peter Anvin Sun, 02 Jul 2006 12:25:06 -0700 committer H. Peter Anvin Sun, 02 Jul 2006 12:25:06 -0700 usr/include/Kbuild | 11 + usr/include/alloca.h | 12 + usr/include/arpa/inet.h | 22 + usr/include/assert.h | 22 + usr/include/bits32/bitsize.h | 3 usr/include/bits32/bitsize/limits.h | 14 + usr/include/bits32/bitsize/stddef.h | 18 + usr/include/bits32/bitsize/stdint.h | 34 ++ usr/include/bits32/bitsize/stdintconst.h | 18 + usr/include/bits32/bitsize/stdintlimits.h | 22 + usr/include/bits64/bitsize.h | 3 usr/include/bits64/bitsize/limits.h | 14 + usr/include/bits64/bitsize/stddef.h | 13 + usr/include/bits64/bitsize/stdint.h | 34 ++ usr/include/bits64/bitsize/stdintconst.h | 18 + usr/include/bits64/bitsize/stdintlimits.h | 22 + usr/include/byteswap.h | 15 + usr/include/ctype.h | 140 ++++++++ usr/include/dirent.h | 33 ++ usr/include/elf.h | 11 + usr/include/endian.h | 15 + usr/include/errno.h | 13 + usr/include/fcntl.h | 47 +++ usr/include/grp.h | 13 + usr/include/inttypes.h | 226 +++++++++++++ usr/include/klibc/compiler.h | 123 +++++++ usr/include/klibc/diverr.h | 15 + usr/include/klibc/endian.h | 39 ++ usr/include/klibc/extern.h | 16 + usr/include/klibc/stathelp.h | 24 + usr/include/klibc/sysconfig.h | 166 ++++++++++ usr/include/limits.h | 40 ++ usr/include/malloc.h | 21 + usr/include/net/if.h | 7 usr/include/net/if_arp.h | 1 usr/include/net/if_packet.h | 1 usr/include/net/route.h | 1 usr/include/netinet/if_ether.h | 1 usr/include/netinet/in.h | 39 ++ usr/include/netinet/in6.h | 10 + usr/include/netinet/ip.h | 13 + usr/include/netinet/tcp.h | 11 + usr/include/netinet/udp.h | 19 + usr/include/netpacket/packet.h | 1 usr/include/paths.h | 74 ++++ usr/include/poll.h | 1 usr/include/sched.h | 36 ++ usr/include/setjmp.h | 43 +++ usr/include/signal.h | 97 ++++++ usr/include/stdarg.h | 14 + usr/include/stddef.h | 24 + usr/include/stdint.h | 116 +++++++ usr/include/stdio.h | 128 ++++++++ usr/include/stdlib.h | 94 ++++++ usr/include/string.h | 47 +++ usr/include/sys/dirent.h | 32 ++ usr/include/sys/elf32.h | 113 +++++++ usr/include/sys/elf64.h | 113 +++++++ usr/include/sys/elfcommon.h | 187 +++++++++++ usr/include/sys/fsuid.h | 14 + usr/include/sys/inotify.h | 16 + usr/include/sys/ioctl.h | 14 + usr/include/sys/klog.h | 24 + usr/include/sys/md.h | 32 ++ usr/include/sys/mman.h | 24 + usr/include/sys/mount.h | 71 ++++ usr/include/sys/param.h | 11 + usr/include/sys/poll.h | 20 + usr/include/sys/reboot.h | 25 + usr/include/sys/resource.h | 15 + usr/include/sys/select.h | 17 + usr/include/sys/sendfile.h | 14 + usr/include/sys/socket.h | 44 +++ usr/include/sys/socketcalls.h | 28 ++ usr/include/sys/splice.h | 19 + usr/include/sys/stat.h | 33 ++ usr/include/sys/statfs.h | 1 usr/include/sys/syscall.h | 13 + usr/include/sys/sysinfo.h | 12 + usr/include/sys/sysmacros.h | 34 ++ usr/include/sys/time.h | 18 + usr/include/sys/times.h | 14 + usr/include/sys/types.h | 111 +++++++ usr/include/sys/uio.h | 15 + usr/include/sys/un.h | 10 + usr/include/sys/utime.h | 10 + usr/include/sys/utsname.h | 23 + usr/include/sys/vfs.h | 115 +++++++ usr/include/sys/wait.h | 28 ++ usr/include/syslog.h | 62 ++++ usr/include/termios.h | 91 +++++ usr/include/time.h | 18 + usr/include/unistd.h | 159 +++++++++ usr/include/utime.h | 14 + usr/klibc/CAVEATS | 60 ++++ usr/klibc/Kbuild | 186 +++++++++++ usr/klibc/LICENSE | 73 ++++ usr/klibc/README | 80 +++++ usr/klibc/SOCKETCALLS.def | 21 + usr/klibc/SYSCALLS.def | 260 +++++++++++++++ usr/klibc/__put_env.c | 74 ++++ usr/klibc/__shared_init.c | 2 usr/klibc/__signal.c | 20 + usr/klibc/__static_init.c | 2 usr/klibc/abort.c | 18 + usr/klibc/alarm.c | 25 + usr/klibc/arch/README | 81 +++++ usr/klibc/asprintf.c | 30 ++ usr/klibc/assert.c | 14 + usr/klibc/atexit.c | 10 + usr/klibc/atexit.h | 18 + usr/klibc/atoi.c | 3 usr/klibc/atol.c | 3 usr/klibc/atoll.c | 3 usr/klibc/atox.c | 14 + usr/klibc/brk.c | 24 + usr/klibc/bsd_signal.c | 11 + usr/klibc/bsearch.c | 26 ++ usr/klibc/calloc.c | 20 + usr/klibc/clearenv.c | 17 + usr/klibc/closelog.c | 18 + usr/klibc/creat.c | 12 + usr/klibc/ctype/ctypefunc.h | 13 + usr/klibc/ctype/isalnum.c | 2 usr/klibc/ctype/isalpha.c | 2 usr/klibc/ctype/isascii.c | 2 usr/klibc/ctype/isblank.c | 2 usr/klibc/ctype/iscntrl.c | 2 usr/klibc/ctype/isdigit.c | 2 usr/klibc/ctype/isgraph.c | 2 usr/klibc/ctype/islower.c | 2 usr/klibc/ctype/isprint.c | 2 usr/klibc/ctype/ispunct.c | 2 usr/klibc/ctype/isspace.c | 2 usr/klibc/ctype/isupper.c | 2 usr/klibc/ctype/isxdigit.c | 2 usr/klibc/ctype/tolower.c | 2 usr/klibc/ctype/toupper.c | 2 usr/klibc/ctypes.c | 284 +++++++++++++++++ usr/klibc/daemon.c | 35 ++ usr/klibc/env.h | 10 + usr/klibc/exec_l.c | 59 ++++ usr/klibc/execl.c | 8 usr/klibc/execle.c | 8 usr/klibc/execlp.c | 8 usr/klibc/execlpe.c | 8 usr/klibc/execv.c | 11 + usr/klibc/execvp.c | 11 + usr/klibc/execvpe.c | 75 ++++ usr/klibc/exit.c | 30 ++ usr/klibc/fgetc.c | 19 + usr/klibc/fgets.c | 31 ++ usr/klibc/fopen.c | 39 ++ usr/klibc/fork.c | 21 + usr/klibc/fprintf.c | 19 + usr/klibc/fputc.c | 14 + usr/klibc/fputs.c | 15 + usr/klibc/fread.c | 33 ++ usr/klibc/fread2.c | 13 + usr/klibc/fstatfs.c | 19 + usr/klibc/fwrite.c | 33 ++ usr/klibc/fwrite2.c | 13 + usr/klibc/getcwd.c | 15 + usr/klibc/getdomainname.c | 25 + usr/klibc/getenv.c | 24 + usr/klibc/gethostname.c | 25 + usr/klibc/getopt.c | 97 ++++++ usr/klibc/getpgrp.c | 10 + usr/klibc/getpriority.c | 23 + usr/klibc/getpt.c | 17 + usr/klibc/globals.c | 10 + usr/klibc/inet/bindresvport.c | 46 +++ usr/klibc/inet/inet_addr.c | 14 + usr/klibc/inet/inet_aton.c | 22 + usr/klibc/inet/inet_ntoa.c | 16 + usr/klibc/inet/inet_ntop.c | 53 +++ usr/klibc/inet/inet_pton.c | 78 +++++ usr/klibc/interp.S | 13 + usr/klibc/isatty.c | 20 + usr/klibc/jrand48.c | 24 + usr/klibc/libc_init.c | 107 ++++++ usr/klibc/libgcc/__ashldi3.c | 23 + usr/klibc/libgcc/__ashrdi3.c | 23 + usr/klibc/libgcc/__clzsi2.c | 36 ++ usr/klibc/libgcc/__divdi3.c | 29 ++ usr/klibc/libgcc/__divsi3.c | 29 ++ usr/klibc/libgcc/__lshrdi3.c | 23 + usr/klibc/libgcc/__moddi3.c | 29 ++ usr/klibc/libgcc/__modsi3.c | 29 ++ usr/klibc/libgcc/__udivdi3.c | 13 + usr/klibc/libgcc/__udivmoddi4.c | 32 ++ usr/klibc/libgcc/__udivmodsi4.c | 32 ++ usr/klibc/libgcc/__udivsi3.c | 13 + usr/klibc/libgcc/__umoddi3.c | 16 + usr/klibc/libgcc/__umodsi3.c | 16 + usr/klibc/llseek.c | 30 ++ usr/klibc/lrand48.c | 13 + usr/klibc/makeerrlist.pl | 98 ++++++ usr/klibc/malloc.c | 200 ++++++++++++ usr/klibc/malloc.h | 47 +++ usr/klibc/memccpy.c | 23 + usr/klibc/memchr.c | 19 + usr/klibc/memcmp.c | 19 + usr/klibc/memcpy.c | 29 ++ usr/klibc/memmem.c | 52 +++ usr/klibc/memmove.c | 36 ++ usr/klibc/memrchr.c | 19 + usr/klibc/memset.c | 30 ++ usr/klibc/memswap.c | 24 + usr/klibc/mmap.c | 40 ++ usr/klibc/mrand48.c | 13 + usr/klibc/nice.c | 19 + usr/klibc/nrand48.c | 11 + usr/klibc/nullenv.c | 8 usr/klibc/onexit.c | 23 + usr/klibc/open.c | 22 + usr/klibc/openat.c | 22 + usr/klibc/pause.c | 17 + usr/klibc/perror.c | 13 + usr/klibc/ppoll.c | 19 + usr/klibc/printf.c | 19 + usr/klibc/pselect.c | 42 ++ usr/klibc/pty.c | 31 ++ usr/klibc/putchar.c | 15 + usr/klibc/putenv.c | 37 ++ usr/klibc/puts.c | 13 + usr/klibc/qsort.c | 42 ++ usr/klibc/raise.c | 11 + usr/klibc/readdir.c | 57 +++ usr/klibc/realloc.c | 48 +++ usr/klibc/reboot.c | 15 + usr/klibc/recv.c | 11 + usr/klibc/remove.c | 18 + usr/klibc/sbrk.c | 45 +++ usr/klibc/seed48.c | 18 + usr/klibc/send.c | 11 + usr/klibc/setegid.c | 10 + usr/klibc/setenv.c | 42 ++ usr/klibc/seteuid.c | 10 + usr/klibc/setpgrp.c | 10 + usr/klibc/sha1hash.c | 317 +++++++++++++++++++ usr/klibc/sigabbrev.c | 121 +++++++ usr/klibc/sigaction.c | 60 ++++ usr/klibc/siglist.c | 121 +++++++ usr/klibc/siglongjmp.c | 15 + usr/klibc/sigpending.c | 18 + usr/klibc/sigprocmask.c | 18 + usr/klibc/sigsuspend.c | 18 + usr/klibc/sleep.c | 20 + usr/klibc/snprintf.c | 16 + usr/klibc/socketcalls.pl | 88 +++++ usr/klibc/socketcalls/Kbuild | 50 +++ usr/klibc/socketcalls/socketcommon.h | 16 + usr/klibc/sprintf.c | 18 + usr/klibc/srand48.c | 15 + usr/klibc/sscanf.c | 17 + usr/klibc/statfs.c | 19 + usr/klibc/strcasecmp.c | 24 + usr/klibc/strcat.c | 11 + usr/klibc/strchr.c | 19 + usr/klibc/strcmp.c | 21 + usr/klibc/strcpy.c | 20 + usr/klibc/strcspn.c | 10 + usr/klibc/strdup.c | 17 + usr/klibc/strerror.c | 33 ++ usr/klibc/strlcat.c | 31 ++ usr/klibc/strlcpy.c | 27 ++ usr/klibc/strlen.c | 13 + usr/klibc/strncasecmp.c | 24 + usr/klibc/strncat.c | 22 + usr/klibc/strncmp.c | 21 + usr/klibc/strncpy.c | 24 + usr/klibc/strndup.c | 17 + usr/klibc/strnlen.c | 18 + usr/klibc/strntoimax.c | 13 + usr/klibc/strntoumax.c | 76 +++++ usr/klibc/strpbrk.c | 12 + usr/klibc/strrchr.c | 21 + usr/klibc/strsep.c | 21 + usr/klibc/strsignal.c | 26 ++ usr/klibc/strspn.c | 10 + usr/klibc/strstr.c | 11 + usr/klibc/strtoimax.c | 3 usr/klibc/strtok.c | 15 + usr/klibc/strtol.c | 3 usr/klibc/strtoll.c | 3 usr/klibc/strtotimespec.c | 5 usr/klibc/strtotimeval.c | 5 usr/klibc/strtotimex.c | 39 ++ usr/klibc/strtoul.c | 3 usr/klibc/strtoull.c | 3 usr/klibc/strtoumax.c | 3 usr/klibc/strtox.c | 13 + usr/klibc/strxspn.c | 29 ++ usr/klibc/strxspn.h | 12 + usr/klibc/syscalls.pl | 286 +++++++++++++++++ usr/klibc/syscalls/Kbuild | 94 ++++++ usr/klibc/syscalls/syscommon.h | 33 ++ usr/klibc/syslog.c | 89 +++++ usr/klibc/system.c | 61 ++++ usr/klibc/sysv_signal.c | 11 + usr/klibc/time.c | 23 + usr/klibc/umount.c | 12 + usr/klibc/unsetenv.c | 44 +++ usr/klibc/usleep.c | 15 + usr/klibc/utime.c | 24 + usr/klibc/vasprintf.c | 25 + usr/klibc/version | 1 usr/klibc/vfork.c | 13 + usr/klibc/vfprintf.c | 26 ++ usr/klibc/vprintf.c | 11 + usr/klibc/vsnprintf.c | 488 +++++++++++++++++++++++++++++ usr/klibc/vsprintf.c | 11 + usr/klibc/vsscanf.c | 378 ++++++++++++++++++++++ usr/klibc/wait.c | 12 + usr/klibc/wait3.c | 12 + usr/klibc/waitpid.c | 12 + 317 files changed, 11252 insertions(+), 0 deletions(-) diff --git a/usr/include/Kbuild b/usr/include/Kbuild new file mode 100644 index 0000000..3f20026 --- /dev/null +++ b/usr/include/Kbuild @@ -0,0 +1,11 @@ +always := asm + +$(obj)/asm: + @echo ' SYMLINK $@ -> include/asm-$(KLIBCASMARCH)' + $(Q)if [ '$(KLIBCKERNELSRC).' -ef '$(obj)/../..' ]; then \ + ln -fsn ../../include/asm-$(KLIBCASMARCH) $@; \ + else \ + ln -fsn $(KLIBCKERNELSRC)./include/asm-$(KLIBCASMARCH) $@; \ + fi + +clean-files := asm diff --git a/usr/include/alloca.h b/usr/include/alloca.h new file mode 100644 index 0000000..91ef4c0 --- /dev/null +++ b/usr/include/alloca.h @@ -0,0 +1,12 @@ +/* + * alloca.h + * + * Just call the builtin alloca() function + */ + +#ifndef _ALLOCA_H +#define _ALLOCA_H + +#define alloca(size) __builtin_alloca(size) + +#endif /* _ALLOCA_H */ diff --git a/usr/include/arpa/inet.h b/usr/include/arpa/inet.h new file mode 100644 index 0000000..8532f67 --- /dev/null +++ b/usr/include/arpa/inet.h @@ -0,0 +1,22 @@ +/* + * arpa/inet.h + */ + +#ifndef _ARPA_INET_H +#define _ARPA_INET_H + +#include +#include +#include +#include +#include + +__extern uint32_t inet_addr(const char *); +__extern int inet_aton(const char *, struct in_addr *); +__extern char *inet_ntoa(struct in_addr); +__extern int inet_pton(int, const char *, void *); +__extern const char *inet_ntop(int, const void *, char *, size_t); +__extern unsigned int inet_nsap_addr(const char *, unsigned char *, int); +__extern char *inet_nsap_ntoa(int, const unsigned char *, char *); + +#endif /* _ARPA_INET_H */ diff --git a/usr/include/assert.h b/usr/include/assert.h new file mode 100644 index 0000000..d89e082 --- /dev/null +++ b/usr/include/assert.h @@ -0,0 +1,22 @@ +/* + * assert.h + */ + +#ifndef _ASSERT_H +#define _ASSERT_H + +#include + +#ifdef NDEBUG + +#define assert(x) ((void)(x)) + +#else + +extern __noreturn __assert_fail(const char *, const char *, unsigned int); + +#define assert(x) ((x) ? (void)0 : __assert_fail(#x, __FILE__, __LINE__)) + +#endif + +#endif /* _ASSERT_H */ diff --git a/usr/include/bits32/bitsize.h b/usr/include/bits32/bitsize.h new file mode 100644 index 0000000..06cc885 --- /dev/null +++ b/usr/include/bits32/bitsize.h @@ -0,0 +1,3 @@ +#ifndef _BITSIZE +#define _BITSIZE 32 +#endif diff --git a/usr/include/bits32/bitsize/limits.h b/usr/include/bits32/bitsize/limits.h new file mode 100644 index 0000000..8eb97d6 --- /dev/null +++ b/usr/include/bits32/bitsize/limits.h @@ -0,0 +1,14 @@ +/* + * bits32/limits.h + */ + +#ifndef _BITSIZE_LIMITS_H +#define _BITSIZE_LIMITS_H + +#define LONG_BIT 32 + +#define LONG_MIN (-2147483647L-1) +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL + +#endif /* _BITSIZE_LIMITS_H */ diff --git a/usr/include/bits32/bitsize/stddef.h b/usr/include/bits32/bitsize/stddef.h new file mode 100644 index 0000000..43d733c --- /dev/null +++ b/usr/include/bits32/bitsize/stddef.h @@ -0,0 +1,18 @@ +/* + * bits32/stddef.h + */ + +#ifndef _BITSIZE_STDDEF_H +#define _BITSIZE_STDDEF_H + +#define _SIZE_T +#if defined(__s390__) || defined(__cris__) +typedef unsigned long size_t; +#else +typedef unsigned int size_t; +#endif + +#define _PTRDIFF_T +typedef signed int ptrdiff_t; + +#endif /* _BITSIZE_STDDEF_H */ diff --git a/usr/include/bits32/bitsize/stdint.h b/usr/include/bits32/bitsize/stdint.h new file mode 100644 index 0000000..8e444b6 --- /dev/null +++ b/usr/include/bits32/bitsize/stdint.h @@ -0,0 +1,34 @@ +/* + * bits32/stdint.h + */ + +#ifndef _BITSIZE_STDINT_H +#define _BITSIZE_STDINT_H + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long long int int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long int uint64_t; + +typedef int int_fast16_t; +typedef int int_fast32_t; + +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; + +typedef int intptr_t; +typedef unsigned int uintptr_t; + +#define __INT64_C(c) c ## LL +#define __UINT64_C(c) c ## ULL + +#define __PRI64_RANK "ll" +#define __PRIFAST_RANK "" +#define __PRIPTR_RANK "" + +#endif /* _BITSIZE_STDINT_H */ diff --git a/usr/include/bits32/bitsize/stdintconst.h b/usr/include/bits32/bitsize/stdintconst.h new file mode 100644 index 0000000..7db63bd --- /dev/null +++ b/usr/include/bits32/bitsize/stdintconst.h @@ -0,0 +1,18 @@ +/* + * bits32/stdintconst.h + */ + +#ifndef _BITSIZE_STDINTCONST_H +#define _BITSIZE_STDINTCONST_H + +#define INT_FAST16_C(c) INT32_C(c) +#define INT_FAST32_C(c) INT32_C(c) + +#define UINT_FAST16_C(c) UINT32_C(c) +#define UINT_FAST32_C(c) UINT32_C(c) + +#define INTPTR_C(c) INT32_C(c) +#define UINTPTR_C(c) UINT32_C(c) +#define PTRDIFF_C(c) INT32_C(c) + +#endif /* _BITSIZE_STDINTCONST_H */ diff --git a/usr/include/bits32/bitsize/stdintlimits.h b/usr/include/bits32/bitsize/stdintlimits.h new file mode 100644 index 0000000..d85094d --- /dev/null +++ b/usr/include/bits32/bitsize/stdintlimits.h @@ -0,0 +1,22 @@ +/* + * bits32/stdintlimits.h + */ + +#ifndef _BITSIZE_STDINTLIMITS_H +#define _BITSIZE_STDINTLIMITS_H + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INTPTR_MIN INT32_MIN +#define INTPTR_MAX INT32_MAX +#define UINTPTR_MAX UINT32_MAX + +#define PTRDIFF_MIN INT32_MIN +#define PTRDIFF_MAX INT32_MAX + +#endif /* _BITSIZE_STDINTLIMITS_H */ diff --git a/usr/include/bits64/bitsize.h b/usr/include/bits64/bitsize.h new file mode 100644 index 0000000..54696fd --- /dev/null +++ b/usr/include/bits64/bitsize.h @@ -0,0 +1,3 @@ +#ifndef _BITSIZE +#define _BITSIZE 64 +#endif diff --git a/usr/include/bits64/bitsize/limits.h b/usr/include/bits64/bitsize/limits.h new file mode 100644 index 0000000..f5bbf83 --- /dev/null +++ b/usr/include/bits64/bitsize/limits.h @@ -0,0 +1,14 @@ +/* + * bits64/limits.h + */ + +#ifndef _BITSIZE_LIMITS_H +#define _BITSIZE_LIMITS_H + +#define LONG_BIT 64 + +#define LONG_MIN (-9223372036854775807L-1) +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL + +#endif /* _BITSIZE_LIMITS_H */ diff --git a/usr/include/bits64/bitsize/stddef.h b/usr/include/bits64/bitsize/stddef.h new file mode 100644 index 0000000..1e942a1 --- /dev/null +++ b/usr/include/bits64/bitsize/stddef.h @@ -0,0 +1,13 @@ +/* + * bits64/stddef.h + */ + +#ifndef _BITSIZE_STDDEF_H +#define _BITSIZE_STDDEF_H + +#define _SIZE_T +typedef unsigned long size_t; +#define _PTRDIFF_T +typedef signed long ptrdiff_t; + +#endif /* _BITSIZE_STDDEF_H */ diff --git a/usr/include/bits64/bitsize/stdint.h b/usr/include/bits64/bitsize/stdint.h new file mode 100644 index 0000000..988e639 --- /dev/null +++ b/usr/include/bits64/bitsize/stdint.h @@ -0,0 +1,34 @@ +/* + * bits64/stdint.h + */ + +#ifndef _BITSIZE_STDINT_H +#define _BITSIZE_STDINT_H + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef long int int64_t; + +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long int uint64_t; + +typedef long int int_fast16_t; +typedef long int int_fast32_t; + +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; + +typedef long int intptr_t; +typedef unsigned long int uintptr_t; + +#define __INT64_C(c) c ## L +#define __UINT64_C(c) c ## UL + +#define __PRI64_RANK "l" +#define __PRIFAST_RANK "l" +#define __PRIPTR_RANK "l" + +#endif /* _BITSIZE_STDINT_H */ diff --git a/usr/include/bits64/bitsize/stdintconst.h b/usr/include/bits64/bitsize/stdintconst.h new file mode 100644 index 0000000..24e8eb6 --- /dev/null +++ b/usr/include/bits64/bitsize/stdintconst.h @@ -0,0 +1,18 @@ +/* + * bits64/stdintconst.h + */ + +#ifndef _BITSIZE_STDINTCONST_H +#define _BITSIZE_STDINTCONST_H + +#define INT_FAST16_C(c) INT64_C(c) +#define INT_FAST32_C(c) INT64_C(c) + +#define UINT_FAST16_C(c) UINT64_C(c) +#define UINT_FAST32_C(c) UINT64_C(c) + +#define INTPTR_C(c) INT64_C(c) +#define UINTPTR_C(c) UINT64_C(c) +#define PTRDIFF_C(c) INT64_C(c) + +#endif /* _BITSIZE_STDINTCONST_H */ diff --git a/usr/include/bits64/bitsize/stdintlimits.h b/usr/include/bits64/bitsize/stdintlimits.h new file mode 100644 index 0000000..805d5b8 --- /dev/null +++ b/usr/include/bits64/bitsize/stdintlimits.h @@ -0,0 +1,22 @@ +/* + * bits64/stdintlimits.h + */ + +#ifndef _BITSIZE_STDINTLIMITS_H +#define _BITSIZE_STDINTLIMITS_H + +#define INT_FAST16_MIN INT64_MIN +#define INT_FAST32_MIN INT64_MIN +#define INT_FAST16_MAX INT64_MAX +#define INT_FAST32_MAX INT64_MAX +#define UINT_FAST16_MAX UINT64_MAX +#define UINT_FAST32_MAX UINT64_MAX + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX + +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX + +#endif /* _BITSIZE_STDINTLIMITS_H */ diff --git a/usr/include/byteswap.h b/usr/include/byteswap.h new file mode 100644 index 0000000..6f41a28 --- /dev/null +++ b/usr/include/byteswap.h @@ -0,0 +1,15 @@ +/* + * byteswap.h + */ + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H + +#include +#include + +#define bswap_16(x) __swab16(x) +#define bswap_32(x) __swab32(x) +#define bswap_64(x) __swab64(x) + +#endif /* _BYTESWAP_H */ diff --git a/usr/include/ctype.h b/usr/include/ctype.h new file mode 100644 index 0000000..670aec9 --- /dev/null +++ b/usr/include/ctype.h @@ -0,0 +1,140 @@ +/* + * ctype.h + * + * This assumes ISO 8859-1, being a reasonable superset of ASCII. + */ + +#ifndef _CTYPE_H +#define _CTYPE_H + +#include + +/* + * This relies on the following definitions: + * + * cntrl = !print + * alpha = upper|lower + * graph = punct|alpha|digit + * blank = '\t' || ' ' (per POSIX requirement) + */ +enum { + __ctype_upper = (1 << 0), + __ctype_lower = (1 << 1), + __ctype_digit = (1 << 2), + __ctype_xdigit = (1 << 3), + __ctype_space = (1 << 4), + __ctype_print = (1 << 5), + __ctype_punct = (1 << 6), + __ctype_cntrl = (1 << 7), +}; + +extern const unsigned char __ctypes[]; + +static inline int __ctype_isalnum(int __c) +{ + return __ctypes[__c + 1] & + (__ctype_upper | __ctype_lower | __ctype_digit); +} + +static inline int __ctype_isalpha(int __c) +{ + return __ctypes[__c + 1] & (__ctype_upper | __ctype_lower); +} + +static inline int __ctype_isascii(int __c) +{ + return !(__c & ~0x7f); +} + +static inline int __ctype_isblank(int __c) +{ + return (__c == '\t') || (__c == ' '); +} + +static inline int __ctype_iscntrl(int __c) +{ + return __ctypes[__c + 1] & __ctype_cntrl; +} + +static inline int __ctype_isdigit(int __c) +{ + return ((unsigned)__c - '0') <= 9; +} + +static inline int __ctype_isgraph(int __c) +{ + return __ctypes[__c + 1] & + (__ctype_upper | __ctype_lower | __ctype_digit | __ctype_punct); +} + +static inline int __ctype_islower(int __c) +{ + return __ctypes[__c + 1] & __ctype_lower; +} + +static inline int __ctype_isprint(int __c) +{ + return __ctypes[__c + 1] & __ctype_print; +} + +static inline int __ctype_ispunct(int __c) +{ + return __ctypes[__c + 1] & __ctype_punct; +} + +static inline int __ctype_isspace(int __c) +{ + return __ctypes[__c + 1] & __ctype_space; +} + +static inline int __ctype_isupper(int __c) +{ + return __ctypes[__c + 1] & __ctype_upper; +} + +static inline int __ctype_isxdigit(int __c) +{ + return __ctypes[__c + 1] & __ctype_xdigit; +} + +/* Note: this is decimal, not hex, to avoid accidental promotion to unsigned */ +#define _toupper(__c) ((__c) & ~32) +#define _tolower(__c) ((__c) | 32) + +static inline int __ctype_toupper(int __c) +{ + return __ctype_islower(__c) ? _toupper(__c) : __c; +} + +static inline int __ctype_tolower(int __c) +{ + return __ctype_isupper(__c) ? _tolower(__c) : __c; +} + +#ifdef __CTYPE_NO_INLINE +# define __CTYPEFUNC(X) \ + __extern int X(int); +#else +#define __CTYPEFUNC(X) \ + __extern inline int X(int __c) \ + { \ + return __ctype_##X(__c); \ + } +#endif + +__CTYPEFUNC(isalnum) + __CTYPEFUNC(isalpha) + __CTYPEFUNC(isascii) + __CTYPEFUNC(isblank) + __CTYPEFUNC(iscntrl) + __CTYPEFUNC(isdigit) + __CTYPEFUNC(isgraph) + __CTYPEFUNC(islower) + __CTYPEFUNC(isprint) + __CTYPEFUNC(ispunct) + __CTYPEFUNC(isspace) + __CTYPEFUNC(isupper) + __CTYPEFUNC(isxdigit) + __CTYPEFUNC(toupper) + __CTYPEFUNC(tolower) +#endif /* _CTYPE_H */ diff --git a/usr/include/dirent.h b/usr/include/dirent.h new file mode 100644 index 0000000..e324474 --- /dev/null +++ b/usr/include/dirent.h @@ -0,0 +1,33 @@ +/* + * dirent.h + */ + +#ifndef _DIRENT_H +#define _DIRENT_H + +#include +#include + +struct _IO_dir { + int __fd; + +#ifdef __KLIBC_DIRENT_INTERNALS + /* These fields for internal use only */ + + size_t bytes_left; + struct dirent *next; + /* Declaring this as an array of struct enforces correct alignment */ + struct dirent buffer[15]; /* 15 times max dirent size =~ 4K */ +#endif +}; +typedef struct _IO_dir DIR; + +__extern DIR *opendir(const char *); +__extern struct dirent *readdir(DIR *); +__extern int closedir(DIR *); +static __inline__ int dirfd(DIR * __d) +{ + return __d->__fd; +} + +#endif /* _DIRENT_H */ diff --git a/usr/include/elf.h b/usr/include/elf.h new file mode 100644 index 0000000..c543a81 --- /dev/null +++ b/usr/include/elf.h @@ -0,0 +1,11 @@ +/* + * elf.h + */ + +#ifndef _ELF_H +#define _ELF_H + +#include +#include + +#endif /* _ELF_H */ diff --git a/usr/include/endian.h b/usr/include/endian.h new file mode 100644 index 0000000..a6cd6d9 --- /dev/null +++ b/usr/include/endian.h @@ -0,0 +1,15 @@ +/* + * endian.h + */ + +#ifndef _ENDIAN_H +#define _ENDIAN_H + +#include + +#define LITTLE_ENDIAN __LITTLE_ENDIAN +#define BIG_ENDIAN __BIG_ENDIAN +#define PDP_ENDIAN __PDP_ENDIAN +#define BYTE_ORDER __BYTE_ORDER + +#endif /* _ENDIAN_H */ diff --git a/usr/include/errno.h b/usr/include/errno.h new file mode 100644 index 0000000..d8e20bd --- /dev/null +++ b/usr/include/errno.h @@ -0,0 +1,13 @@ +/* + * errno.h + */ + +#ifndef _ERRNO_H +#define _ERRNO_H + +#include +#include + +__extern int errno; + +#endif /* _ERRNO_H */ diff --git a/usr/include/fcntl.h b/usr/include/fcntl.h new file mode 100644 index 0000000..64dcb04 --- /dev/null +++ b/usr/include/fcntl.h @@ -0,0 +1,47 @@ +/* + * fcntl.h + */ + +#ifndef _FCNTL_H +#define _FCNTL_H + +#include +#include +#include +#if defined(__mips__) && !defined(__mips64__) +# include +#endif +#include + +/* This is ugly, but "struct flock" has actually been defined with + a long off_t, so it's really "struct flock64". It just happens + to work. Gag. Barf. + + This happens to work on all 32-bit architectures except MIPS. */ + +#ifdef F_GETLK64 +# undef F_GETLK +# define F_GETLK F_GETLK64 +#endif + +#ifdef F_SETLK64 +# undef F_SETLK +# define F_SETLK F_SETLK64 +#endif + +#ifdef F_SETLKW64 +# undef F_SETLKW +# define F_SETLKW F_SETLKW64 +#endif + +/* This is defined here as well as in since old-style code + would still include when using open(), and open() being + a varadic function changes its calling convention on some architectures. */ +#ifndef _KLIBC_IN_OPEN_C +__extern int open(const char *, int, ...); +__extern int openat(int, const char *, int, ...); +#endif + +__extern int fcntl(int, int, ...); + +#endif /* _FCNTL_H */ diff --git a/usr/include/grp.h b/usr/include/grp.h new file mode 100644 index 0000000..19b1828 --- /dev/null +++ b/usr/include/grp.h @@ -0,0 +1,13 @@ +/* + * grp.h + */ + +#ifndef _GRP_H +#define _GRP_H + +#include +#include + +__extern int setgroups(size_t, const gid_t *); + +#endif /* _GRP_H */ diff --git a/usr/include/inttypes.h b/usr/include/inttypes.h new file mode 100644 index 0000000..29311fe --- /dev/null +++ b/usr/include/inttypes.h @@ -0,0 +1,226 @@ +/* + * inttypes.h + */ + +#ifndef _INTTYPES_H +#define _INTTYPES_H + +#include +#include +#include + +static __inline__ intmax_t imaxabs(intmax_t __n) +{ + return (__n < (intmax_t) 0) ? -__n : __n; +} + +__extern intmax_t strtoimax(const char *, char **, int); +__extern uintmax_t strtoumax(const char *, char **, int); + +/* extensions */ +__extern intmax_t strntoimax(const char *, char **, int, size_t); +__extern uintmax_t strntoumax(const char *, char **, int, size_t); + +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) + +#define PRId8 "d" +#define PRId16 "d" +#define PRId32 "d" +#define PRId64 __PRI64_RANK "d" + +#define PRIdLEAST8 "d" +#define PRIdLEAST16 "d" +#define PRIdLEAST32 "d" +#define PRIdLEAST64 __PRI64_RANK "d" + +#define PRIdFAST8 "d" +#define PRIdFAST16 __PRIFAST_RANK "d" +#define PRIdFAST32 __PRIFAST_RANK "d" +#define PRIdFAST64 __PRI64_RANK "d" + +#define PRIdMAX __PRI64_RANK "d" +#define PRIdPTR __PRIPTR_RANK "d" + +#define PRIi8 "i" +#define PRIi16 "i" +#define PRIi32 "i" +#define PRIi64 __PRI64_RANK "i" + +#define PRIiLEAST8 "i" +#define PRIiLEAST16 "i" +#define PRIiLEAST32 "i" +#define PRIiLEAST64 __PRI64_RANK "i" + +#define PRIiFAST8 "i" +#define PRIiFAST16 __PRIFAST_RANK "i" +#define PRIiFAST32 __PRIFAST_RANK "i" +#define PRIiFAST64 __PRI64_RANK "i" + +#define PRIiMAX __PRI64_RANK "i" +#define PRIiPTR __PRIPTR_RANK "i" + +#define PRIo8 "o" +#define PRIo16 "o" +#define PRIo32 "o" +#define PRIo64 __PRI64_RANK "o" + +#define PRIoLEAST8 "o" +#define PRIoLEAST16 "o" +#define PRIoLEAST32 "o" +#define PRIoLEAST64 __PRI64_RANK "o" + +#define PRIoFAST8 "o" +#define PRIoFAST16 __PRIFAST_RANK "o" +#define PRIoFAST32 __PRIFAST_RANK "o" +#define PRIoFAST64 __PRI64_RANK "o" + +#define PRIoMAX __PRI64_RANK "o" +#define PRIoPTR __PRIPTR_RANK "o" + +#define PRIu8 "u" +#define PRIu16 "u" +#define PRIu32 "u" +#define PRIu64 __PRI64_RANK "u" + +#define PRIuLEAST8 "u" +#define PRIuLEAST16 "u" +#define PRIuLEAST32 "u" +#define PRIuLEAST64 __PRI64_RANK "u" + +#define PRIuFAST8 "u" +#define PRIuFAST16 __PRIFAST_RANK "u" +#define PRIuFAST32 __PRIFAST_RANK "u" +#define PRIuFAST64 __PRI64_RANK "u" + +#define PRIuMAX __PRI64_RANK "u" +#define PRIuPTR __PRIPTR_RANK "u" + +#define PRIx8 "x" +#define PRIx16 "x" +#define PRIx32 "x" +#define PRIx64 __PRI64_RANK "x" + +#define PRIxLEAST8 "x" +#define PRIxLEAST16 "x" +#define PRIxLEAST32 "x" +#define PRIxLEAST64 __PRI64_RANK "x" + +#define PRIxFAST8 "x" +#define PRIxFAST16 __PRIFAST_RANK "x" +#define PRIxFAST32 __PRIFAST_RANK "x" +#define PRIxFAST64 __PRI64_RANK "x" + +#define PRIxMAX __PRI64_RANK "x" +#define PRIxPTR __PRIPTR_RANK "x" + +#define PRIX8 "X" +#define PRIX16 "X" +#define PRIX32 "X" +#define PRIX64 __PRI64_RANK "X" + +#define PRIXLEAST8 "X" +#define PRIXLEAST16 "X" +#define PRIXLEAST32 "X" +#define PRIXLEAST64 __PRI64_RANK "X" + +#define PRIXFAST8 "X" +#define PRIXFAST16 __PRIFAST_RANK "X" +#define PRIXFAST32 __PRIFAST_RANK "X" +#define PRIXFAST64 __PRI64_RANK "X" + +#define PRIXMAX __PRI64_RANK "X" +#define PRIXPTR __PRIPTR_RANK "X" + +#define SCNd8 "hhd" +#define SCNd16 "hd" +#define SCNd32 "d" +#define SCNd64 __PRI64_RANK "d" + +#define SCNdLEAST8 "hhd" +#define SCNdLEAST16 "hd" +#define SCNdLEAST32 "d" +#define SCNdLEAST64 __PRI64_RANK "d" + +#define SCNdFAST8 "hhd" +#define SCNdFAST16 __PRIFAST_RANK "d" +#define SCNdFAST32 __PRIFAST_RANK "d" +#define SCNdFAST64 __PRI64_RANK "d" + +#define SCNdMAX __PRI64_RANK "d" +#define SCNdPTR __PRIPTR_RANK "d" + +#define SCNi8 "hhi" +#define SCNi16 "hi" +#define SCNi32 "i" +#define SCNi64 __PRI64_RANK "i" + +#define SCNiLEAST8 "hhi" +#define SCNiLEAST16 "hi" +#define SCNiLEAST32 "i" +#define SCNiLEAST64 __PRI64_RANK "i" + +#define SCNiFAST8 "hhi" +#define SCNiFAST16 __PRIFAST_RANK "i" +#define SCNiFAST32 __PRIFAST_RANK "i" +#define SCNiFAST64 __PRI64_RANK "i" + +#define SCNiMAX __PRI64_RANK "i" +#define SCNiPTR __PRIPTR_RANK "i" + +#define SCNo8 "hho" +#define SCNo16 "ho" +#define SCNo32 "o" +#define SCNo64 __PRI64_RANK "o" + +#define SCNoLEAST8 "hho" +#define SCNoLEAST16 "ho" +#define SCNoLEAST32 "o" +#define SCNoLEAST64 __PRI64_RANK "o" + +#define SCNoFAST8 "hho" +#define SCNoFAST16 __PRIFAST_RANK "o" +#define SCNoFAST32 __PRIFAST_RANK "o" +#define SCNoFAST64 __PRI64_RANK "o" + +#define SCNoMAX __PRI64_RANK "o" +#define SCNoPTR __PRIPTR_RANK "o" + +#define SCNu8 "hhu" +#define SCNu16 "hu" +#define SCNu32 "u" +#define SCNu64 __PRI64_RANK "u" + +#define SCNuLEAST8 "hhu" +#define SCNuLEAST16 "hu" +#define SCNuLEAST32 "u" +#define SCNuLEAST64 __PRI64_RANK "u" + +#define SCNuFAST8 "hhu" +#define SCNuFAST16 __PRIFAST_RANK "u" +#define SCNuFAST32 __PRIFAST_RANK "u" +#define SCNuFAST64 __PRI64_RANK "u" + +#define SCNuMAX __PRI64_RANK "u" +#define SCNuPTR __PRIPTR_RANK "u" + +#define SCNx8 "hhx" +#define SCNx16 "hx" +#define SCNx32 "x" +#define SCNx64 __PRI64_RANK "x" + +#define SCNxLEAST8 "hhx" +#define SCNxLEAST16 "hx" +#define SCNxLEAST32 "x" +#define SCNxLEAST64 __PRI64_RANK "x" + +#define SCNxFAST8 "hhx" +#define SCNxFAST16 __PRIFAST_RANK "x" +#define SCNxFAST32 __PRIFAST_RANK "x" +#define SCNxFAST64 __PRI64_RANK "x" + +#define SCNxMAX __PRI64_RANK "x" +#define SCNxPTR __PRIPTR_RANK "x" + +#endif + +#endif /* _INTTYPES_H */ diff --git a/usr/include/klibc/compiler.h b/usr/include/klibc/compiler.h new file mode 100644 index 0000000..893f8a9 --- /dev/null +++ b/usr/include/klibc/compiler.h @@ -0,0 +1,123 @@ +/* + * klibc/compiler.h + * + * Various compiler features + */ + +#ifndef _KLIBC_COMPILER_H +#define _KLIBC_COMPILER_H + +/* Specific calling conventions */ +/* __cdecl is used when we want varadic and non-varadic functions to have + the same binary calling convention. */ +#ifdef __i386__ +# ifdef __GNUC__ +# define __cdecl __attribute__((cdecl,regparm(0))) +# else + /* Most other C compilers have __cdecl as a keyword */ +# endif +#else +# define __cdecl /* Meaningless on non-i386 */ +#endif + +/* How to declare a function that *must* be inlined */ +#ifdef __GNUC__ +# if __GNUC__ >= 3 +# define __must_inline static __inline__ __attribute__((always_inline)) +# else +# define __must_inline extern __inline__ +# endif +#else +# define __must_inline inline /* Just hope this works... */ +#endif + +/* How to declare a function that does not return */ +#ifdef __GNUC__ +# define __noreturn void __attribute__((noreturn)) +#else +# define __noreturn void +#endif + +/* "const" function: + + Many functions do not examine any values except their arguments, + and have no effects except the return value. Basically this is + just slightly more strict class than the `pure' attribute above, + since function is not allowed to read global memory. + + Note that a function that has pointer arguments and examines the + data pointed to must _not_ be declared `const'. Likewise, a + function that calls a non-`const' function usually must not be + `const'. It does not make sense for a `const' function to return + `void'. +*/ +#ifdef __GNUC__ +# define __constfunc __attribute__((const)) +#else +# define __constfunc +#endif +#undef __attribute_const__ +#define __attribute_const__ __constfunc + +/* "pure" function: + + Many functions have no effects except the return value and their + return value depends only on the parameters and/or global + variables. Such a function can be subject to common subexpression + elimination and loop optimization just as an arithmetic operator + would be. These functions should be declared with the attribute + `pure'. +*/ +#ifdef __GNUC__ +# define __purefunc __attribute__((pure)) +#else +# define __purefunc +#endif +#undef __attribute_pure__ +#define __attribute_pure__ __purefunc + +/* Format attribute */ +#ifdef __GNUC__ +# define __formatfunc(t,f,a) __attribute__((format(t,f,a))) +#else +# define __formatfunc(t,f,a) +#endif + +/* malloc() function (returns unaliased pointer) */ +#if defined(__GNUC__) && (__GNUC__ >= 3) +# define __mallocfunc __attribute__((malloc)) +#else +# define __mallocfunc +#endif + +/* likely/unlikely */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) +# define __likely(x) __builtin_expect((x), 1) +# define __unlikely(x) __builtin_expect((x), 0) +#else +# define __likely(x) (x) +# define __unlikely(x) (x) +#endif + +/* Possibly unused function */ +#ifdef __GNUC__ +# define __unusedfunc __attribute__((unused)) +#else +# define __unusedfunc +#endif + +/* It's all user space... */ +#define __user + +/* The bitwise attribute: disallow arithmetric operations */ +#ifdef __CHECKER__ /* sparse only */ +# define __bitwise __attribute__((bitwise)) +#else +# define __bitwise +#endif + +/* Compiler pragma to make an alias symbol */ +#define __ALIAS(__t, __f, __p, __a) \ + __t __f __p __attribute__((weak, alias(#__a))); + +#endif diff --git a/usr/include/klibc/diverr.h b/usr/include/klibc/diverr.h new file mode 100644 index 0000000..e70887e --- /dev/null +++ b/usr/include/klibc/diverr.h @@ -0,0 +1,15 @@ +/* + * klibc/diverr.h + */ + +#ifndef _KLIBC_DIVERR_H +#define _KLIBC_DIVERR_H + +#include + +static __inline__ void __divide_error(void) +{ + raise(SIGFPE); +} + +#endif /* _KLIBC_DIVERR_H */ diff --git a/usr/include/klibc/endian.h b/usr/include/klibc/endian.h new file mode 100644 index 0000000..99563de --- /dev/null +++ b/usr/include/klibc/endian.h @@ -0,0 +1,39 @@ +/* + * klibc/endian.h + * + * Like , but export only double-underscore symbols + */ + +#ifndef _KLIBC_ENDIAN_H +#define _KLIBC_ENDIAN_H + +#include +#include + +/* Linux' asm/byteorder.h defines either __LITTLE_ENDIAN or + __BIG_ENDIAN, but the glibc/BSD-ish macros expect both to be + defined with __BYTE_ORDER defining which is actually used... */ + +#if defined(__LITTLE_ENDIAN) +# undef __LITTLE_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __LITTLE_ENDIAN +#elif defined(__BIG_ENDIAN) +# undef __BIG_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __BIG_ENDIAN +#elif defined(__PDP_ENDIAN) +# undef __PDP_ENDIAN +# define __LITTLE_ENDIAN 1234 +# define __BIG_ENDIAN 4321 +# define __PDP_ENDIAN 3412 +# define __BYTE_ORDER __PDP_ENDIAN +#else +# error "Unknown byte order!" +#endif + +#endif /* _KLIBC_ENDIAN_H */ diff --git a/usr/include/klibc/extern.h b/usr/include/klibc/extern.h new file mode 100644 index 0000000..7d7c7b8 --- /dev/null +++ b/usr/include/klibc/extern.h @@ -0,0 +1,16 @@ +/* + * klibc/extern.h + */ + +#ifndef _KLIBC_EXTERN_H +#define _KLIBC_EXTERN_H + +#ifdef __cplusplus +#define __extern extern "C" +#else +#define __extern extern +#endif + +#define __alias(x) __attribute__((weak, alias(x))) + +#endif /* _KLIBC_EXTERN_H */ diff --git a/usr/include/klibc/stathelp.h b/usr/include/klibc/stathelp.h new file mode 100644 index 0000000..9520dad --- /dev/null +++ b/usr/include/klibc/stathelp.h @@ -0,0 +1,24 @@ +/* + * stathelp.h + * + * Helper macros for + */ + +#ifndef _KLIBC_STATHELP_H +#define _KLIBC_STATHELP_H + +#include + +/* + * Most architectures have a 64-bit field for st_dev and st_rdev, + * but dev_t is 32 bits (uint32_t == unsigned int), so make a + * macro we can use across all architectures. + */ + +#if __BYTE_ORDER == __BIG_ENDIAN +# define __stdev64(x) unsigned int __##x, x; +#else +# define __stdev64(x) unsigned int x, __##x; +#endif + +#endif /* _KLIBC_STATHELP_H */ diff --git a/usr/include/klibc/sysconfig.h b/usr/include/klibc/sysconfig.h new file mode 100644 index 0000000..f3ae915 --- /dev/null +++ b/usr/include/klibc/sysconfig.h @@ -0,0 +1,166 @@ +/* + * klibc/sysconfig.h + * + * Allows for definitions of some things which may be system-dependent + * NOTE: this file must not result in any output from the preprocessor. + */ + +#ifndef _KLIBC_SYSCONFIG_H +#define _KLIBC_SYSCONFIG_H + +#include +#include + +/* + * These are the variables that can be defined in . + * For boolean options, #define to 0 to disable, #define to 1 to enable. + * + * If undefined, they will be given defaults here. + */ + + +/* + * _KLIBC_NO_MMU: + * + * Indicates this architecture doesn't have an MMU, and therefore + * does not have the sys_fork and sys_brk system calls. + */ +/* Default to having an MMU if we can find the fork system call */ +#ifndef _KLIBC_NO_MMU +# if defined(__NR_fork) +# define _KLIBC_NO_MMU 0 +# else +# define _KLIBC_NO_MMU 1 +# endif +#endif + + +/* + * _KLIBC_REAL_VFORK: + * + * Indicates that this architecture has a real vfork() system call. + * This is the default if sys_vfork exists; if there is an + * architecture-dependent implementation of vfork(), define this + * symbol. + */ +#ifndef _KLIBC_REAL_VFORK +# if defined(__NR_vfork) +# define _KLIBC_REAL_VFORK 1 +# else +# define _KLIBC_REAL_VFORK 0 +# endif +#endif + + +/* + * _KLIBC_USE_MMAP2: + * + * Indicates that this architecture should use sys_mmap2 instead + * of sys_mmap. This is the default on 32-bit architectures, assuming + * sys_mmap2 exists. + */ +#ifndef _KLIBC_USE_MMAP2 +# if (_BITSIZE == 32 && defined(__NR_mmap2)) || \ + (_BITSIZE == 64 && !defined(__NR_mmap)) +# define _KLIBC_USE_MMAP2 1 +# else +# define _KLIBC_USE_MMAP2 0 +# endif +#endif + + +/* + * _KLIBC_MMAP2_SHIFT: + * + * Indicate the shift of the offset parameter in sys_mmap2. + * On most architectures, this is always 12, but on some + * architectures it can be a different number, or the current + * page size. If this is dependent on the page size, define + * this to an expression which includes __getpageshift(). + */ +#ifndef _KLIBC_MMAP2_SHIFT +# define _KLIBC_MMAP2_SHIFT 12 +#endif + + +/* + * _KLIBC_MALLOC_USES_SBRK: + * + * Indicates that malloc() should use sbrk() to obtain raw memory + * from the system, rather than mmap(). + */ +/* Default to get memory using mmap() */ +#ifndef _KLIBC_MALLOC_USES_SBRK +# define _KLIBC_MALLOC_USES_SBRK 0 +#endif + + +/* + * _KLIBC_MALLOC_CHUNK_SIZE: + * This is the minimum chunk size we will ask the kernel for using + * malloc(); this should be a multiple of the page size and must + * be a power of 2. + */ +#ifndef _KLIBC_MALLOC_CHUNK_SIZE +# define _KLIBC_MALLOC_CHUNK_SIZE 65536 +#endif + + +/* + * _KLIBC_SBRK_ALIGNMENT: + * + * This is the minimum alignment for the memory returned by + * sbrk(). It must be a power of 2. If _KLIBC_MALLOC_USES_SBRK + * is set it should be no smaller than the size of struct + * arena_header in malloc.h (== 4 pointers.) + */ +#ifndef _KLIBC_SBRK_ALIGNMENT +# define _KLIBC_SBRK_ALIGNMENT 32 +#endif + + +/* + * _KLIBC_USE_RT_SIG: + * + * Indicates that this architecture should use the rt_sig*() + * family of system calls, even if the older system calls are + * provided. This requires that is correct for + * using with the rt_sig*() system calls. This is the default if + * the older system calls are undefined in . + * + */ +#ifndef _KLIBC_USE_RT_SIG +# ifdef __NR_sigaction +# define _KLIBC_USE_RT_SIG 0 +# else +# define _KLIBC_USE_RT_SIG 1 +# endif +#endif + + +/* + * _KLIBC_NEEDS_SA_RESTORER: + * + * Some architectures, like x86-64 and some i386 Fedora kernels, + * do not provide a default sigreturn, and therefore must have + * SA_RESTORER set. + */ +#ifndef _KLIBC_NEEDS_SA_RESTORER +# define _KLIBC_NEEDS_SA_RESTORER 0 +#endif + + +/* + * _KLIBC_STATFS_F_TYPE_64: + * + * This indicates that the f_type, f_bsize, f_namelen, + * f_frsize, and f_spare fields of struct statfs are + * 64 bits long. This is normally the case for 64-bit + * platforms, and so is the default for those. See + * usr/include/sys/vfs.h for the exact details. + */ +#ifndef _KLIBC_STATFS_F_TYPE_64 +# define _KLIBC_STATFS_F_TYPE_64 (_BITSIZE == 64) +#endif + +#endif /* _KLIBC_SYSCONFIG_H */ diff --git a/usr/include/limits.h b/usr/include/limits.h new file mode 100644 index 0000000..942f005 --- /dev/null +++ b/usr/include/limits.h @@ -0,0 +1,40 @@ +/* + * limits.h + */ + +#ifndef _LIMITS_H +#define _LIMITS_H + +#define CHAR_BIT 8 +#define SHRT_BIT 16 +#define INT_BIT 32 +#define LONGLONG_BIT 64 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 + +#ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 +# define CHAR_MAX UCHAR_MAX +#else +# define CHAR_MIN SCHAR_MIN +# define CHAR_MAX SCHAR_MAX +#endif + +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 +#define USHRT_MAX 65535 + +#define INT_MIN (-2147483647-1) +#define INT_MAX 2147483647 +#define UINT_MAX 4294967295U + +#define LONGLONG_MIN (-9223372036854775807LL-1) +#define LONGLONG_MAX 9223372036854775807LL +#define ULONGLONG_MAX 18446744073709551615ULL + +#include +#include + +#endif /* _LIMITS_H */ diff --git a/usr/include/malloc.h b/usr/include/malloc.h new file mode 100644 index 0000000..2773167 --- /dev/null +++ b/usr/include/malloc.h @@ -0,0 +1,21 @@ +/* + * malloc.h + * + * Apparently people haven't caught on to use , which is the + * standard place for this crap since the 1980's... + */ + +#ifndef _MALLOC_H +#define _MALLOC_H + +#include +#include +#include + +__extern void free(void *); + +__extern __mallocfunc void *malloc(size_t); +__extern __mallocfunc void *calloc(size_t, size_t); +__extern __mallocfunc void *realloc(void *, size_t); + +#endif /* _MALLOC_H */ diff --git a/usr/include/net/if.h b/usr/include/net/if.h new file mode 100644 index 0000000..f6aa0c0 --- /dev/null +++ b/usr/include/net/if.h @@ -0,0 +1,7 @@ +#ifndef _NET_IF_H +#define _NET_IF_H + +#include +#include + +#endif /* _NET_IF_H */ diff --git a/usr/include/net/if_arp.h b/usr/include/net/if_arp.h new file mode 100644 index 0000000..a25f1b4 --- /dev/null +++ b/usr/include/net/if_arp.h @@ -0,0 +1 @@ +#include diff --git a/usr/include/net/if_packet.h b/usr/include/net/if_packet.h new file mode 100644 index 0000000..b5e8e0e --- /dev/null +++ b/usr/include/net/if_packet.h @@ -0,0 +1 @@ +#include diff --git a/usr/include/net/route.h b/usr/include/net/route.h new file mode 100644 index 0000000..a60df24 --- /dev/null +++ b/usr/include/net/route.h @@ -0,0 +1 @@ +#include diff --git a/usr/include/netinet/if_ether.h b/usr/include/netinet/if_ether.h new file mode 100644 index 0000000..060ef22 --- /dev/null +++ b/usr/include/netinet/if_ether.h @@ -0,0 +1 @@ +#include diff --git a/usr/include/netinet/in.h b/usr/include/netinet/in.h new file mode 100644 index 0000000..4ab7c24 --- /dev/null +++ b/usr/include/netinet/in.h @@ -0,0 +1,39 @@ +/* + * netinet/in.h + */ + +#ifndef _NETINET_IN_H +#define _NETINET_IN_H + +/* added this include by Mats Petersson */ +#include + +#include +#include +#include /* Must be included *before* */ +#include + +#ifndef htons +# define htons(x) __cpu_to_be16(x) +#endif +#ifndef ntohs +# define ntohs(x) __be16_to_cpu(x) +#endif +#ifndef htonl +# define htonl(x) __cpu_to_be32(x) +#endif +#ifndef ntohl +# define ntohl(x) __be32_to_cpu(x) +#endif +#ifndef htonq +# define htonq(x) __cpu_to_be64(x) +#endif +#ifndef ntohq +# define ntohq(x) __be64_to_cpu(x) +#endif + +#define IPPORT_RESERVED 1024 + +__extern int bindresvport(int sd, struct sockaddr_in *sin); + +#endif /* _NETINET_IN_H */ diff --git a/usr/include/netinet/in6.h b/usr/include/netinet/in6.h new file mode 100644 index 0000000..7e6da92 --- /dev/null +++ b/usr/include/netinet/in6.h @@ -0,0 +1,10 @@ +/* + * netinet/in6.h + */ + +#ifndef _NETINET_IN6_H +#define _NETINET_IN6_H + +#include + +#endif /* _NETINET_IN6_H */ diff --git a/usr/include/netinet/ip.h b/usr/include/netinet/ip.h new file mode 100644 index 0000000..4684bfd --- /dev/null +++ b/usr/include/netinet/ip.h @@ -0,0 +1,13 @@ +/* + * netinet/ip.h + */ + +#ifndef _NETINET_IP_H +#define _NETINET_IP_H + +#include +#include + +#define IP_DF 0x4000 /* Flag: "Don't Fragment" */ + +#endif /* _NETINET_IP_H */ diff --git a/usr/include/netinet/tcp.h b/usr/include/netinet/tcp.h new file mode 100644 index 0000000..7fc4729 --- /dev/null +++ b/usr/include/netinet/tcp.h @@ -0,0 +1,11 @@ +/* + * netinet/tcp.h + */ + +#ifndef _NETINET_TCP_H +#define _NETINET_TCP_H + +#include /* Include *before* linux/tcp.h */ +#include + +#endif /* _NETINET_TCP_H */ diff --git a/usr/include/netinet/udp.h b/usr/include/netinet/udp.h new file mode 100644 index 0000000..036f588 --- /dev/null +++ b/usr/include/netinet/udp.h @@ -0,0 +1,19 @@ +/* + * netinet/udp.h + */ + +#ifndef _NETINET_UDP_H +#define _NETINET_UDP_H + +/* + * We would include linux/udp.h, but it brings in too much other stuff + */ + +struct udphdr { + __u16 source; + __u16 dest; + __u16 len; + __u16 check; +}; + +#endif /* _NETINET_UDP_H */ diff --git a/usr/include/netpacket/packet.h b/usr/include/netpacket/packet.h new file mode 100644 index 0000000..b5e8e0e --- /dev/null +++ b/usr/include/netpacket/packet.h @@ -0,0 +1 @@ +#include diff --git a/usr/include/paths.h b/usr/include/paths.h new file mode 100644 index 0000000..29ef301 --- /dev/null +++ b/usr/include/paths.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + * + * @(#)paths.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PATHS_H_ +#define _PATHS_H_ + +/* Default search path. */ +#define _PATH_DEFPATH "/usr/bin:/bin" +/* All standard utilities path. */ +#define _PATH_STDPATH \ + "/usr/bin:/bin:/usr/sbin:/sbin" + +#define _PATH_BSHELL "/bin/sh" +#define _PATH_CONSOLE "/dev/console" +#define _PATH_CSHELL "/bin/csh" +#define _PATH_DEVDB "/var/run/dev.db" +#define _PATH_DEVNULL "/dev/null" +#define _PATH_DRUM "/dev/drum" +#define _PATH_KLOG "/proc/kmsg" +#define _PATH_KMEM "/dev/kmem" +#define _PATH_LASTLOG "/var/log/lastlog" +#define _PATH_MAILDIR "/var/mail" +#define _PATH_MAN "/usr/share/man" +#define _PATH_MEM "/dev/mem" +#define _PATH_MNTTAB "/etc/fstab" +#define _PATH_MOUNTED "/etc/mtab" +#define _PATH_NOLOGIN "/etc/nologin" +#define _PATH_PRESERVE "/var/lib" +#define _PATH_RWHODIR "/var/spool/rwho" +#define _PATH_SENDMAIL "/usr/sbin/sendmail" +#define _PATH_SHADOW "/etc/shadow" +#define _PATH_SHELLS "/etc/shells" +#define _PATH_TTY "/dev/tty" +#define _PATH_UNIX "/boot/vmlinux" +#define _PATH_UTMP "/var/run/utmp" +#define _PATH_VI "/bin/vi" +#define _PATH_WTMP "/var/log/wtmp" + +/* Provide trailing slash, since mostly used for building pathnames. */ +#define _PATH_DEV "/dev/" +#define _PATH_TMP "/tmp/" +#define _PATH_VARDB "/var/db/" +#define _PATH_VARRUN "/var/run/" +#define _PATH_VARTMP "/var/tmp/" + +#endif /* !_PATHS_H_ */ diff --git a/usr/include/poll.h b/usr/include/poll.h new file mode 100644 index 0000000..06fb41a --- /dev/null +++ b/usr/include/poll.h @@ -0,0 +1 @@ +#include diff --git a/usr/include/sched.h b/usr/include/sched.h new file mode 100644 index 0000000..fb4da8d --- /dev/null +++ b/usr/include/sched.h @@ -0,0 +1,36 @@ +/* + * sched.h + */ + +#ifndef _SCHED_H +#define _SCHED_H + +#include + +/* linux/sched.h is unusable; put the declarations we need here... */ + +#define SCHED_NORMAL 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 + +struct sched_param { + int sched_priority; +}; + +__extern int sched_setscheduler(pid_t, int, const struct sched_param *); +__extern int sched_yield(void); + +/* Raw interfaces to clone(2); only actually usable for non-VM-cloning */ +#ifdef __ia64__ +__extern pid_t __clone2(int, void *, void *); +static __inline__ pid_t __clone(int _f, void *_sp) +{ + /* If this is used with _sp != 0 it will have the effect of the sp + and rsp growing away from a single point in opposite directions. */ + return __clone2(_f, _sp, _sp); +} +#else +__extern pid_t __clone(int, void *); +#endif + +#endif /* _SCHED_H */ diff --git a/usr/include/setjmp.h b/usr/include/setjmp.h new file mode 100644 index 0000000..abebccd --- /dev/null +++ b/usr/include/setjmp.h @@ -0,0 +1,43 @@ +/* + * setjmp.h + */ + +#ifndef _SETJMP_H +#define _SETJMP_H + +#include +#include +#include +#include + +#include + +__extern int setjmp(jmp_buf); +__extern __noreturn longjmp(jmp_buf, int); + +/* + Whose bright idea was it to add unrelated functionality to just about + the only function in the standard C library (setjmp) which cannot be + wrapped by an ordinary function wrapper? Anyway, the damage is done, + and therefore, this wrapper *must* be inline. However, gcc will + complain if this is an inline function for unknown reason, and + therefore sigsetjmp() needs to be a macro. +*/ + +struct __sigjmp_buf { + jmp_buf __jmpbuf; + sigset_t __sigs; +}; + +typedef struct __sigjmp_buf sigjmp_buf[1]; + +#define sigsetjmp(__env, __save) \ +({ \ + struct __sigjmp_buf *__e = (__env); \ + sigprocmask(0, NULL, &__e->__sigs); \ + setjmp(__e->__jmpbuf); \ +}) + +__extern __noreturn siglongjmp(sigjmp_buf, int); + +#endif /* _SETJMP_H */ diff --git a/usr/include/signal.h b/usr/include/signal.h new file mode 100644 index 0000000..4751b78 --- /dev/null +++ b/usr/include/signal.h @@ -0,0 +1,97 @@ +/* + * signal.h + */ + +#ifndef _SIGNAL_H +#define _SIGNAL_H + +#include +#include +#include /* For memset() */ +#include /* For LONG_BIT */ +#include + +#include /* Includes if appropriate */ + +/* glibc seems to use sig_atomic_t as "int" pretty much on all architectures. + Do the same, but allow the architecture to override. */ +#ifndef _KLIBC_HAS_ARCH_SIG_ATOMIC_T +typedef int sig_atomic_t; +#endif + +/* Some architectures don't define these */ +#ifndef SA_RESETHAND +# define SA_RESETHAND SA_ONESHOT +#endif +#ifndef SA_NODEFER +# define SA_NODEFER SA_NOMASK +#endif +/* Some architectures define NSIG and not _NSIG or vice versa */ +#ifndef NSIG +# define NSIG _NSIG +#endif +#ifndef _NSIG +# define _NSIG NSIG +#endif + +/* If we don't have any real-time signals available to userspace, + hide them all */ +#if SIGRTMAX <= SIGRTMIN +# undef SIGRTMIN +# undef SIGRTMAX +#endif + +/* The kernel header files are inconsistent whether or not + SIGRTMAX is inclusive or exclusive. POSIX seems to state that + it's inclusive, however. */ +#if SIGRTMAX >= _NSIG +# undef SIGRTMAX +# define SIGRTMAX (_NSIG-1) +#endif + +__extern const char *const sys_siglist[_NSIG]; +__extern const char *const sys_sigabbrev[_NSIG]; + +/* This assumes sigset_t is either an unsigned long or an array of such, + and that _NSIG_BPW in the kernel is always LONG_BIT */ + +static __inline__ int sigemptyset(sigset_t * __set) +{ + memset(__set, 0, sizeof *__set); + return 0; +} +static __inline__ int sigfillset(sigset_t * __set) +{ + memset(__set, ~0, sizeof *__set); + return 0; +} +static __inline__ int sigaddset(sigset_t * __set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + __lset[__signum / LONG_BIT] |= 1UL << (__signum % LONG_BIT); + return 0; +} +static __inline__ int sigdelset(sigset_t * __set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + __lset[__signum / LONG_BIT] &= ~(1UL << (__signum % LONG_BIT)); + return 0; +} +static __inline__ int sigismember(sigset_t * __set, int __signum) +{ + unsigned long *__lset = (unsigned long *)__set; + return (int)((__lset[__signum / LONG_BIT] >> (__signum % LONG_BIT)) & + 1); +} + +__extern __sighandler_t __signal(int, __sighandler_t, int); +__extern __sighandler_t sysv_signal(int, __sighandler_t); +__extern __sighandler_t bsd_signal(int, __sighandler_t); +__extern int sigaction(int, const struct sigaction *, struct sigaction *); +__extern int sigprocmask(int, const sigset_t *, sigset_t *); +__extern int sigpending(sigset_t *); +__extern int sigsuspend(const sigset_t *); +__extern int raise(int); +__extern int kill(pid_t, int); + +#endif /* _SIGNAL_H */ diff --git a/usr/include/stdarg.h b/usr/include/stdarg.h new file mode 100644 index 0000000..cc324b8 --- /dev/null +++ b/usr/include/stdarg.h @@ -0,0 +1,14 @@ +/* + * stdarg.h + * + * This is just a wrapper for the gcc one, but defines va_copy() + * even if gcc doesn't. + */ + +/* Note: the _STDARG_H macro belongs to the gcc header... */ +#include_next + +/* Older gcc considers this an extension, so it's double underbar only */ +#ifndef va_copy +#define va_copy(d,s) __va_copy(d,s) +#endif diff --git a/usr/include/stddef.h b/usr/include/stddef.h new file mode 100644 index 0000000..f1529a4 --- /dev/null +++ b/usr/include/stddef.h @@ -0,0 +1,24 @@ +/* + * stddef.h + */ + +#ifndef _STDDEF_H +#define _STDDEF_H + +#ifndef __KLIBC__ +# error "__KLIBC__ not defined, compiler invocation error!" +#endif + +#include + +#undef NULL +#ifdef __cplusplus +# define NULL 0 +#else +# define NULL ((void *)0) +#endif + +#undef offsetof +#define offsetof(t,m) ((size_t)&((t *)0)->m) + +#endif /* _STDDEF_H */ diff --git a/usr/include/stdint.h b/usr/include/stdint.h new file mode 100644 index 0000000..f64f027 --- /dev/null +++ b/usr/include/stdint.h @@ -0,0 +1,116 @@ +/* + * stdint.h + */ + +#ifndef _STDINT_H +#define _STDINT_H + +#include + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +typedef int8_t int_fast8_t; +typedef int64_t int_fast64_t; + +typedef uint8_t uint_fast8_t; +typedef uint64_t uint_fast64_t; + +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) + +#define INT8_MIN (-128) +#define INT16_MIN (-32768) +#define INT32_MIN (-2147483647-1) +#define INT64_MIN (__INT64_C(-9223372036854775807)-1) + +#define INT8_MAX (127) +#define INT16_MAX (32767) +#define INT32_MAX (2147483647) +#define INT64_MAX (__INT64_C(9223372036854775807)) + +#define UINT8_MAX (255U) +#define UINT16_MAX (65535U) +#define UINT32_MAX (4294967295U) +#define UINT64_MAX (__UINT64_C(18446744073709551615)) + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#include + +#endif + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) + +#define INT8_C(c) c +#define INT16_C(c) c +#define INT32_C(c) c +#define INT64_C(c) __INT64_C(c) + +#define UINT8_C(c) c ## U +#define UINT16_C(c) c ## U +#define UINT32_C(c) c ## U +#define UINT64_C(c) __UINT64_C(c) + +#define INT_LEAST8_C(c) INT8_C(c) +#define INT_LEAST16_C(c) INT16_C(c) +#define INT_LEAST32_C(c) INT32_C(c) +#define INT_LEAST64_C(c) INT64_C(c) + +#define UINT_LEAST8_C(c) UINT8_C(c) +#define UINT_LEAST16_C(c) UINT16_C(c) +#define UINT_LEAST32_C(c) UINT32_C(c) +#define UINT_LEAST64_C(c) UINT64_C(c) + +#define INT_FAST8_C(c) INT8_C(c) +#define INT_FAST64_C(c) INT64_C(c) + +#define UINT_FAST8_C(c) UINT8_C(c) +#define UINT_FAST64_C(c) UINT64_C(c) + +#define INTMAX_C(c) INT64_C(c) +#define UINTMAX_C(c) UINT64_C(c) + +#include + +#endif + +/* Keep the kernel from trying to define these types... */ +#define __BIT_TYPES_DEFINED__ + +#endif /* _STDINT_H */ diff --git a/usr/include/stdio.h b/usr/include/stdio.h new file mode 100644 index 0000000..1462f5b --- /dev/null +++ b/usr/include/stdio.h @@ -0,0 +1,128 @@ +/* + * stdio.h + */ + +#ifndef _STDIO_H +#define _STDIO_H + +#include +#include +#include +#include + +/* This structure doesn't really exist, but it gives us something + to define FILE * with */ +struct _IO_file; +typedef struct _IO_file FILE; + +#ifndef EOF +# define EOF (-1) +#endif + +#ifndef BUFSIZ +# define BUFSIZ 4096 +#endif + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +/* + * Convert between a FILE * and a file descriptor. We don't actually + * have any in-memory data, so we just abuse the pointer itself to + * hold the data. Note, however, that for file descriptors, -1 is + * error and 0 is a valid value; for FILE *, NULL (0) is error and + * non-NULL are valid. + */ +static __inline__ int fileno(FILE * __f) +{ + /* This should really be intptr_t, but size_t should be the same size */ + return (int)(size_t) __f - 1; +} + +/* This is a macro so it can be used as initializer */ +#define __create_file(__fd) ((FILE *)(size_t)((__fd) + 1)) + +#define stdin __create_file(0) +#define stdout __create_file(1) +#define stderr __create_file(2) + +__extern FILE *fopen(const char *, const char *); + +static __inline__ FILE *fdopen(int __fd, const char *__m) +{ + (void)__m; + return __create_file(__fd); +} +static __inline__ int fclose(FILE * __f) +{ + extern int close(int); + return close(fileno(__f)); +} +static __inline__ int fseek(FILE * __f, off_t __o, int __w) +{ + extern off_t lseek(int, off_t, int); + return (lseek(fileno(__f), __o, __w) == (off_t) - 1) ? -1 : 0; +} +static __inline__ off_t ftell(FILE * __f) +{ + extern off_t lseek(int, off_t, int); + return lseek(fileno(__f), 0, SEEK_CUR); +} + +__extern int fputs(const char *, FILE *); +__extern int puts(const char *); +__extern int fputc(int, FILE *); +#define putc(c,f) fputc((c),(f)) +#define putchar(c) fputc((c),stdout) + +__extern int fgetc(FILE *); +__extern char *fgets(char *, int, FILE *); +#define getc(f) fgetc(f) +#define getchar() fgetc(stdin) + +__extern size_t _fread(void *, size_t, FILE *); +__extern size_t _fwrite(const void *, size_t, FILE *); + +#ifndef __NO_FREAD_FWRITE_INLINES +extern __inline__ size_t fread(void *__p, size_t __s, size_t __n, FILE * __f) +{ + return _fread(__p, __s * __n, __f) / __s; +} + +extern __inline__ size_t +fwrite(const void *__p, size_t __s, size_t __n, FILE * __f) +{ + return _fwrite(__p, __s * __n, __f) / __s; +} +#endif + +__extern int printf(const char *, ...); +__extern int vprintf(const char *, va_list); +__extern int fprintf(FILE *, const char *, ...); +__extern int vfprintf(FILE *, const char *, va_list); +__extern int sprintf(char *, const char *, ...); +__extern int vsprintf(char *, const char *, va_list); +__extern int snprintf(char *, size_t n, const char *, ...); +__extern int vsnprintf(char *, size_t n, const char *, va_list); +__extern int asprintf(char **, const char *, ...); +__extern int vasprintf(char **, const char *, va_list); + +/* No buffering, so no flushing needed */ +extern __inline__ int fflush(FILE * __f) +{ + (void)__f; + return 0; +} + +__extern int sscanf(const char *, const char *, ...); +__extern int vsscanf(const char *, const char *, va_list); + +__extern void perror(const char *); + +__extern int rename(const char *, const char *); +__extern int renameat(int, const char *, int, const char *); + +__extern int remove(const char *); + +#endif /* _STDIO_H */ diff --git a/usr/include/stdlib.h b/usr/include/stdlib.h new file mode 100644 index 0000000..24cc226 --- /dev/null +++ b/usr/include/stdlib.h @@ -0,0 +1,94 @@ +/* + * stdlib.h + */ + +#ifndef _STDLIB_H +#define _STDLIB_H + +#include +#include +#include + +#include + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +__extern __noreturn abort(void); +static __inline__ int abs(int __n) +{ + return (__n < 0) ? -__n : __n; +} +__extern int system(const char *string); +__extern int atexit(void (*)(void)); +__extern int on_exit(void (*)(int, void *), void *); +__extern int atoi(const char *); +__extern long atol(const char *); +__extern long long atoll(const char *); +__extern __noreturn exit(int); +__extern __noreturn _exit(int); +#define _Exit _exit +static __inline__ long labs(long __n) +{ + return (__n < 0L) ? -__n : __n; +} + +static __inline__ long long llabs(long long __n) +{ + return (__n < 0LL) ? -__n : __n; +} + +__extern long strtol(const char *, char **, int); +__extern long long strtoll(const char *, char **, int); +__extern unsigned long strtoul(const char *, char **, int); +__extern unsigned long long strtoull(const char *, char **, int); + +__extern char *getenv(const char *); +__extern int putenv(const char *); +__extern int setenv(const char *, const char *, int); +__extern int unsetenv(const char *); +__extern int clearenv(void); + +typedef int (*__comparefunc_t) (const void *, const void *); +__extern void *bsearch(const void *, const void *, size_t, size_t, + __comparefunc_t); +__extern void qsort(void *, size_t, size_t, __comparefunc_t); + +__extern long jrand48(unsigned short *); +__extern long mrand48(void); +__extern long nrand48(unsigned short *); +__extern long lrand48(void); +__extern unsigned short *seed48(const unsigned short *); +__extern void srand48(long); + +#define RAND_MAX 0x7fffffff +static __inline__ int rand(void) +{ + return (int)lrand48(); +} +static __inline__ void srand(unsigned int __s) +{ + srand48(__s); +} +static __inline__ long random(void) +{ + return lrand48(); +} +static __inline__ void srandom(unsigned int __s) +{ + srand48(__s); +} + +/* Basic PTY functions. These only work if devpts is mounted! */ + +__extern int unlockpt(int); +__extern char *ptsname(int); +__extern int getpt(void); + +static __inline__ int grantpt(int __fd) +{ + (void)__fd; + return 0; /* devpts does this all for us! */ +} + +#endif /* _STDLIB_H */ diff --git a/usr/include/string.h b/usr/include/string.h new file mode 100644 index 0000000..1a6072c --- /dev/null +++ b/usr/include/string.h @@ -0,0 +1,47 @@ +/* + * string.h + */ + +#ifndef _STRING_H +#define _STRING_H + +#include +#include + +__extern void *memccpy(void *, const void *, int, size_t); +__extern void *memchr(const void *, int, size_t); +__extern void *memrchr(const void *, int, size_t); +__extern int memcmp(const void *, const void *, size_t); +__extern void *memcpy(void *, const void *, size_t); +__extern void *memmove(void *, const void *, size_t); +__extern void *memset(void *, int, size_t); +__extern void *memmem(const void *, size_t, const void *, size_t); +__extern void memswap(void *, void *, size_t); +__extern int strcasecmp(const char *, const char *); +__extern int strncasecmp(const char *, const char *, size_t); +__extern char *strcat(char *, const char *); +__extern char *strchr(const char *, int); +__extern char *index(const char *, int); +__extern char *strrchr(const char *, int); +__extern char *rindex(const char *, int); +__extern int strcmp(const char *, const char *); +__extern char *strcpy(char *, const char *); +__extern size_t strcspn(const char *, const char *); +__extern char *strdup(const char *); +__extern char *strndup(const char *, size_t); +__extern char *strerror(int); +__extern char *strsignal(int); +__extern size_t strlen(const char *); +__extern size_t strnlen(const char *, size_t); +__extern char *strncat(char *, const char *, size_t); +__extern size_t strlcat(char *, const char *, size_t); +__extern int strncmp(const char *, const char *, size_t); +__extern char *strncpy(char *, const char *, size_t); +__extern size_t strlcpy(char *, const char *, size_t); +__extern char *strpbrk(const char *, const char *); +__extern char *strsep(char **, const char *); +__extern size_t strspn(const char *, const char *); +__extern char *strstr(const char *, const char *); +__extern char *strtok(char *, const char *); + +#endif /* _STRING_H */ diff --git a/usr/include/sys/dirent.h b/usr/include/sys/dirent.h new file mode 100644 index 0000000..18b7a33 --- /dev/null +++ b/usr/include/sys/dirent.h @@ -0,0 +1,32 @@ +/* + * sys/dirent.h + */ + +#ifndef _SYS_DIRENT_H +#define _SYS_DIRENT_H + +#include + +/* The kernel calls this struct dirent64 */ +struct dirent { + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +/* File types to use for d_type */ +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + +__extern int getdents(unsigned int, struct dirent *, unsigned int); + +#endif /* _SYS_DIRENT_H */ diff --git a/usr/include/sys/elf32.h b/usr/include/sys/elf32.h new file mode 100644 index 0000000..e4df8ce --- /dev/null +++ b/usr/include/sys/elf32.h @@ -0,0 +1,113 @@ +/* + * sys/elf32.h + */ + +#ifndef _SYS_ELF32_H +#define _SYS_ELF32_H + +#include + +/* ELF standard typedefs (yet more proof that was way overdue) */ +typedef uint16_t Elf32_Half; +typedef int16_t Elf32_SHalf; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; + +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Section; + +/* Dynamic header */ + +typedef struct elf32_dyn { + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +/* Relocations */ + +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf32_rela { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +/* Symbol */ + +typedef struct elf32_sym { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +/* Main file header */ + +typedef struct elf32_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +/* Program header */ + +typedef struct elf32_phdr { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +/* Section header */ + +typedef struct elf32_shdr { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +/* Note header */ +typedef struct elf32_note { + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +#endif /* _SYS_ELF32_H */ diff --git a/usr/include/sys/elf64.h b/usr/include/sys/elf64.h new file mode 100644 index 0000000..0b486ac --- /dev/null +++ b/usr/include/sys/elf64.h @@ -0,0 +1,113 @@ +/* + * sys/elf64.h + */ + +#ifndef _SYS_ELF64_H +#define _SYS_ELF64_H + +#include + +/* ELF standard typedefs (yet more proof that was way overdue) */ +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +typedef uint64_t Elf64_Off; +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Section; + +/* Dynamic header */ + +typedef struct elf64_dyn { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* Relocations */ + +#define ELF64_R_SYM(x) ((x) >> 32) +#define ELF64_R_TYPE(x) ((x) & 0xffffffff) + +typedef struct elf64_rel { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +/* Symbol */ + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +/* Main file header */ + +typedef struct elf64_hdr { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* Program header */ + +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +/* Section header */ + +typedef struct elf64_shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +/* Note header */ +typedef struct elf64_note { + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; + +#endif /* _SYS_ELF64_H */ diff --git a/usr/include/sys/elfcommon.h b/usr/include/sys/elfcommon.h new file mode 100644 index 0000000..0d81db5 --- /dev/null +++ b/usr/include/sys/elfcommon.h @@ -0,0 +1,187 @@ +/* + * sys/elfcommon.h + */ + +#ifndef _SYS_ELFCOMMON_H +#define _SYS_ELFCOMMON_H + +#include + +/* Segment types */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 /* Extension, eh? */ + +/* ELF file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* ELF machine types */ +#define EM_NONE 0 +#define EM_M32 1 +#define EM_SPARC 2 +#define EM_386 3 +#define EM_68K 4 +#define EM_88K 5 +#define EM_486 6 /* Not used in Linux at least */ +#define EM_860 7 +#define EM_MIPS 8 /* R3k, bigendian(?) */ +#define EM_MIPS_RS4_BE 10 /* R4k BE */ +#define EM_PARISC 15 +#define EM_SPARC32PLUS 18 +#define EM_PPC 20 +#define EM_PPC64 21 +#define EM_S390 22 +#define EM_SH 42 +#define EM_SPARCV9 43 /* v9 = SPARC64 */ +#define EM_H8_300H 47 +#define EM_H8S 48 +#define EM_IA_64 50 /* Itanic */ +#define EM_X86_64 62 +#define EM_CRIS 76 +#define EM_V850 87 +#define EM_ALPHA 0x9026 /* Interrim Alpha that stuck around */ +#define EM_CYGNUS_V850 0x9080 /* Old v850 ID used by Cygnus */ +#define EM_S390_OLD 0xA390 /* Obsolete interrim value for S/390 */ + +/* Dynamic type values */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* Auxilliary table entries */ +#define AT_NULL 0 /* end of vector */ +#define AT_IGNORE 1 /* entry should be ignored */ +#define AT_EXECFD 2 /* file descriptor of program */ +#define AT_PHDR 3 /* program headers for program */ +#define AT_PHENT 4 /* size of program header entry */ +#define AT_PHNUM 5 /* number of program headers */ +#define AT_PAGESZ 6 /* system page size */ +#define AT_BASE 7 /* base address of interpreter */ +#define AT_FLAGS 8 /* flags */ +#define AT_ENTRY 9 /* entry point of program */ +#define AT_NOTELF 10 /* program is not ELF */ +#define AT_UID 11 /* real uid */ +#define AT_EUID 12 /* effective uid */ +#define AT_GID 13 /* real gid */ +#define AT_EGID 14 /* effective gid */ +#define AT_PLATFORM 15 /* string identifying CPU for optimizations */ +#define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ +#define AT_CLKTCK 17 /* frequency at which times() increments */ +/* 18..22 = ? */ +#define AT_SECURE 23 /* secure mode boolean */ + +/* Program header permission flags */ +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 + +/* Section header types */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* Section header flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* Special section numbers */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +/* Lenght of magic at the start of a file */ +#define EI_NIDENT 16 + +/* Magic number constants... */ +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#endif /* _SYS_ELFCOMMON_H */ diff --git a/usr/include/sys/fsuid.h b/usr/include/sys/fsuid.h new file mode 100644 index 0000000..d64e28b --- /dev/null +++ b/usr/include/sys/fsuid.h @@ -0,0 +1,14 @@ +/* + * sys/fsuid.h + */ + +#ifndef _SYS_FSUID_H +#define _SYS_FSUID_H + +#include +#include + +__extern int setfsuid(uid_t); +__extern int setfsgid(gid_t); + +#endif /* _SYS_FSUID_H */ diff --git a/usr/include/sys/inotify.h b/usr/include/sys/inotify.h new file mode 100644 index 0000000..e08cb05 --- /dev/null +++ b/usr/include/sys/inotify.h @@ -0,0 +1,16 @@ +/* + * sys/inotify.h + */ + +#ifndef _SYS_INOTIFY_H +#define _SYS_INOTIFY_H + +#include +#include +#include + +__extern int inotify_init(void); +__extern int inotify_add_watch(int, const char *, __u32); +__extern int inotify_rm_watch(int, __u32); + +#endif /* _SYS_INOTIFY_H */ diff --git a/usr/include/sys/ioctl.h b/usr/include/sys/ioctl.h new file mode 100644 index 0000000..559f111 --- /dev/null +++ b/usr/include/sys/ioctl.h @@ -0,0 +1,14 @@ +/* + * sys/ioctl.h + */ + +#ifndef _SYS_IOCTL_H +#define _SYS_IOCTL_H + +#include +#include +#include + +__extern int ioctl(int, int, void *); + +#endif /* _SYS_IOCTL_H */ diff --git a/usr/include/sys/klog.h b/usr/include/sys/klog.h new file mode 100644 index 0000000..02c7217 --- /dev/null +++ b/usr/include/sys/klog.h @@ -0,0 +1,24 @@ +/* + * sys/klog.h + */ + +#ifndef _SYS_KLOG_H +#define _SYS_KLOG_H + +#include + +#define KLOG_CLOSE 0 +#define KLOG_OPEN 1 +#define KLOG_READ 2 +#define KLOG_READ_ALL 3 +#define KLOG_READ_CLEAR 4 +#define KLOG_CLEAR 5 +#define KLOG_DISABLE 6 +#define KLOG_ENABLE 7 +#define KLOG_SETLEVEL 8 +#define KLOG_UNREADSIZE 9 +#define KLOG_WRITE 10 + +__extern int klogctl(int, char *, int); + +#endif /* _SYS_KLOG_H */ diff --git a/usr/include/sys/md.h b/usr/include/sys/md.h new file mode 100644 index 0000000..184e4aa --- /dev/null +++ b/usr/include/sys/md.h @@ -0,0 +1,32 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2006 H. Peter Anvin - All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * sys/md.h + * + * Defines for the Linux md functionality. Some of this stuff is + * userspace-visible but lives in md_k.h, which is user-space unsafe. + * Sigh. + */ + +#ifndef _SYS_MD_H +#define _SYS_MD_H + +#define LEVEL_MULTIPATH (-4) +#define LEVEL_LINEAR (-1) +#define LEVEL_FAULTY (-5) +#define MAX_MD_DEVS 256 /* Max number of md dev */ + +#include +#include + +#endif /* _SYS_MD_H */ diff --git a/usr/include/sys/mman.h b/usr/include/sys/mman.h new file mode 100644 index 0000000..c146ec8 --- /dev/null +++ b/usr/include/sys/mman.h @@ -0,0 +1,24 @@ +/* + * sys/mman.h + */ + +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H + +#include +#include +#include + +#define MAP_FAILED ((void *)-1) + +__extern void *mmap(void *, size_t, int, int, int, off_t); +__extern int munmap(void *, size_t); +__extern void *mremap(void *, size_t, size_t, unsigned long); +__extern int msync(const void *, size_t, int); +__extern int mprotect(const void *, size_t, int); +__extern int mlockall(int); +__extern int munlockall(void); +__extern int mlock(const void *, size_t); +__extern int munlock(const void *, size_t); + +#endif /* _SYS_MMAN_H */ diff --git a/usr/include/sys/mount.h b/usr/include/sys/mount.h new file mode 100644 index 0000000..9d6b0ee --- /dev/null +++ b/usr/include/sys/mount.h @@ -0,0 +1,71 @@ +/* + * sys/mount.h + */ + +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H + +#include +#include + +/* + * These are the fs-independent mount-flags: up to 32 flags are supported + */ +#define MS_RDONLY 0x0001 /* Mount read-only */ +#define MS_NOSUID 0x0002 /* Ignore suid and sgid bits */ +#define MS_NODEV 0x0004 /* Disallow access to device special files */ +#define MS_NOEXEC 0x0008 /* Disallow program execution */ +#define MS_SYNCHRONOUS 0x0010 /* Writes are synced at once */ +#define MS_REMOUNT 0x0020 /* Alter flags of a mounted FS */ +#define MS_MANDLOCK 0x0040 /* Allow mandatory locks on an FS */ +#define MS_DIRSYNC 0x0080 /* Directory modifications are synchronous */ +#define MS_NOATIME 0x0400 /* Do not update access times. */ +#define MS_NODIRATIME 0x0800 /* Do not update directory access times */ +#define MS_BIND 0x1000 +#define MS_MOVE 0x2000 +#define MS_REC 0x4000 +#define MS_VERBOSE 0x8000 +#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ +#define MS_ONE_SECOND (1<<17) /* fs has 1 sec a/m/ctime resolution */ +#define MS_ACTIVE (1<<30) +#define MS_NOUSER (1<<31) + +/* + * Superblock flags that can be altered by MS_REMOUNT + */ +#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME|MS_NODIRATIME) + +/* + * Old magic mount flag and mask + */ +#define MS_MGC_VAL 0xC0ED0000 +#define MS_MGC_MSK 0xffff0000 + +/* + * umount2() flags + */ +#define MNT_FORCE 1 /* Forcibly unmount */ +#define MNT_DETACH 2 /* Detach from tree only */ +#define MNT_EXPIRE 4 /* Mark for expiry */ + +/* + * Block device ioctls + */ +#define BLKROSET _IO(0x12, 93) /* Set device read-only (0 = read-write). */ +#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */ +#define BLKRRPART _IO(0x12, 95) /* Re-read partition table. */ +#define BLKGETSIZE _IO(0x12, 96) /* Return device size. */ +#define BLKFLSBUF _IO(0x12, 97) /* Flush buffer cache. */ +#define BLKRASET _IO(0x12, 98) /* Set read ahead for block device. */ +#define BLKRAGET _IO(0x12, 99) /* Get current read ahead setting. */ + +/* + * Prototypes + */ +__extern int mount(const char *, const char *, + const char *, unsigned long, const void *); +__extern int umount(const char *); +__extern int umount2(const char *, int); +__extern int pivot_root(const char *, const char *); + +#endif /* _SYS_MOUNT_H */ diff --git a/usr/include/sys/param.h b/usr/include/sys/param.h new file mode 100644 index 0000000..fb3b2e4 --- /dev/null +++ b/usr/include/sys/param.h @@ -0,0 +1,11 @@ +/* + * sys/param.h + */ + +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H + +#include +#include + +#endif /* _SYS_PARAM_H */ diff --git a/usr/include/sys/poll.h b/usr/include/sys/poll.h new file mode 100644 index 0000000..f0c60c2 --- /dev/null +++ b/usr/include/sys/poll.h @@ -0,0 +1,20 @@ +/* + * poll.h + */ + +#ifndef _POLL_H +#define _POLL_H + +#include +#include +#include +#include + +/* POSIX specifies "int" for the timeout, Linux seems to use long... */ + +typedef unsigned int nfds_t; +__extern int poll(struct pollfd *, nfds_t, long); +__extern int ppoll(struct pollfd *, nfds_t, struct timespec *, + const sigset_t *); + +#endif /* _POLL_H */ diff --git a/usr/include/sys/reboot.h b/usr/include/sys/reboot.h new file mode 100644 index 0000000..3337d27 --- /dev/null +++ b/usr/include/sys/reboot.h @@ -0,0 +1,25 @@ +/* + * sys/reboot.h + */ + +#ifndef _SYS_REBOOT_H +#define _SYS_REBOOT_H + +#include +#include + +/* glibc names these constants differently; allow both versions */ + +#define RB_AUTOBOOT LINUX_REBOOT_CMD_RESTART +#define RB_HALT_SYSTEM LINUX_REBOOT_CMD_HALT +#define RB_ENABLE_CAD LINUX_REBOOT_CMD_CAD_ON +#define RB_DISABLE_CAD LINUX_REBOOT_CMD_CAD_OFF +#define RB_POWER_OFF LINUX_REBOOT_CMD_POWER_OFF + +/* glibc-ish one-argument version */ +__extern int reboot(int); + +/* Native four-argument system call */ +__extern int __reboot(int, int, int, void *); + +#endif /* _SYS_REBOOT_H */ diff --git a/usr/include/sys/resource.h b/usr/include/sys/resource.h new file mode 100644 index 0000000..41cefb4 --- /dev/null +++ b/usr/include/sys/resource.h @@ -0,0 +1,15 @@ +/* + * sys/resource.h + */ + +#ifndef _SYS_RESOURCE_H +#define _SYS_RESOURCE_H + +#include +#include /* MUST be included before linux/resource.h */ +#include + +__extern int getpriority(int, int); +__extern int setpriority(int, int, int); + +#endif /* _SYS_RESOURCE_H */ diff --git a/usr/include/sys/select.h b/usr/include/sys/select.h new file mode 100644 index 0000000..cc4e00e --- /dev/null +++ b/usr/include/sys/select.h @@ -0,0 +1,17 @@ +/* + * sys/select.h + */ + +#ifndef _SYS_SELECT_H +#define _SYS_SELECT_H + +#include +#include +#include +#include + +__extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); +__extern int pselect(int, fd_set *, fd_set *, fd_set *, + const struct timespec *, const sigset_t *); + +#endif /* _SYS_SELECT_H */ diff --git a/usr/include/sys/sendfile.h b/usr/include/sys/sendfile.h new file mode 100644 index 0000000..a745f10 --- /dev/null +++ b/usr/include/sys/sendfile.h @@ -0,0 +1,14 @@ +/* + * sys/sendfile.h + */ + +#ifndef _SYS_SENDFILE_H +#define _SYS_SENDFILE_H + +#include +#include +#include + +__extern ssize_t sendfile(int, int, off_t *, size_t, off_t); + +#endif /* _SYS_SENDFILE_H */ diff --git a/usr/include/sys/socket.h b/usr/include/sys/socket.h new file mode 100644 index 0000000..2de1d6a --- /dev/null +++ b/usr/include/sys/socket.h @@ -0,0 +1,44 @@ +/* + * sys/socket.h + */ + +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H + +#include +#include +#include + +/* For some reason these may be protected by __KERNEL__ in asm/socket.h */ +#ifndef SOCK_STREAM +# define SOCK_STREAM 1 +# define SOCK_DGRAM 2 +# define SOCK_RAW 3 +# define SOCK_RDM 4 +# define SOCK_SEQPACKET 5 +# define SOCK_PACKET 10 +#endif + +typedef int socklen_t; + +__extern int socket(int, int, int); +__extern int bind(int, struct sockaddr *, int); +__extern int connect(int, struct sockaddr *, socklen_t); +__extern int listen(int, int); +__extern int accept(int, struct sockaddr *, socklen_t *); +__extern int getsockname(int, struct sockaddr *, socklen_t *); +__extern int getpeername(int, struct sockaddr *, socklen_t *); +__extern int socketpair(int, int, int, int *); +__extern int send(int, const void *, size_t, unsigned int); +__extern int sendto(int, const void *, size_t, int, const struct sockaddr *, + socklen_t); +__extern int recv(int, void *, size_t, unsigned int); +__extern int recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, + socklen_t *); +__extern int shutdown(int, int); +__extern int setsockopt(int, int, int, const void *, socklen_t); +__extern int getsockopt(int, int, int, void *, socklen_t *); +__extern int sendmsg(int, const struct msghdr *, unsigned int); +__extern int recvmsg(int, struct msghdr *, unsigned int); + +#endif /* _SYS_SOCKET_H */ diff --git a/usr/include/sys/socketcalls.h b/usr/include/sys/socketcalls.h new file mode 100644 index 0000000..1c4367d --- /dev/null +++ b/usr/include/sys/socketcalls.h @@ -0,0 +1,28 @@ +/* + * sys/socketcalls.h + */ + +#ifndef _SYS_SOCKETCALLS_H +#define _SYS_SOCKETCALLS_H + +/* socketcalls by number, since isn't usable for assembly */ + +#define SYS_SOCKET 1 /* sys_socket(2) */ +#define SYS_BIND 2 /* sys_bind(2) */ +#define SYS_CONNECT 3 /* sys_connect(2) */ +#define SYS_LISTEN 4 /* sys_listen(2) */ +#define SYS_ACCEPT 5 /* sys_accept(2) */ +#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */ +#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */ +#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */ +#define SYS_SEND 9 /* sys_send(2) */ +#define SYS_RECV 10 /* sys_recv(2) */ +#define SYS_SENDTO 11 /* sys_sendto(2) */ +#define SYS_RECVFROM 12 /* sys_recvfrom(2) */ +#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ +#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ +#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ +#define SYS_SENDMSG 16 /* sys_sendmsg(2) */ +#define SYS_RECVMSG 17 /* sys_recvmsg(2) */ + +#endif /* _SYS_SOCKETCALLS_H */ diff --git a/usr/include/sys/splice.h b/usr/include/sys/splice.h new file mode 100644 index 0000000..1fa26d9 --- /dev/null +++ b/usr/include/sys/splice.h @@ -0,0 +1,19 @@ +/* + * sys/splice.h + */ + +#ifndef _SYS_SPLICE_H +#define _SYS_SPLICE_H + +/* move pages instead of copying */ +#define SPLICE_F_MOVE 1 +/* don't block on the pipe splicing (but we may still block on the fd + we splice from/to, of course */ +#define SPLICE_F_NONBLOCK 2 +/* expect more data */ +#define SPLICE_F_MORE 4 + +__extern int splice(int, off_t *, int, off_t *, size_t, unsigned int); +__extern int tee(int, int, size_t, unsigned int); + +#endif /* _SYS_SPLICE_H */ diff --git a/usr/include/sys/stat.h b/usr/include/sys/stat.h new file mode 100644 index 0000000..3226133 --- /dev/null +++ b/usr/include/sys/stat.h @@ -0,0 +1,33 @@ +/* + * sys/stat.h + */ + +#ifndef _SYS_STAT_H +#define _SYS_STAT_H + +#include +#include +#include /* For struct timespec */ +#include +#include + +#ifdef _STATBUF_ST_NSEC + /* struct stat has struct timespec instead of time_t */ +# define st_atime st_atim.tv_sec +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#endif + +__extern int stat(const char *, struct stat *); +__extern int fstat(int, struct stat *); +__extern int fstatat(int, const char *, struct stat *, int); +__extern int lstat(const char *, struct stat *); +__extern mode_t umask(mode_t); +__extern int mknod(const char *, mode_t, dev_t); +__extern int mknodat(int, const char *, const char *, mode_t, dev_t); +static __inline__ int mkfifo(const char *__p, mode_t __m) +{ + return mknod(__p, (__m & ~S_IFMT) | S_IFIFO, (dev_t) 0); +} + +#endif /* _SYS_STAT_H */ diff --git a/usr/include/sys/statfs.h b/usr/include/sys/statfs.h new file mode 100644 index 0000000..53b3b5e --- /dev/null +++ b/usr/include/sys/statfs.h @@ -0,0 +1 @@ +#include diff --git a/usr/include/sys/syscall.h b/usr/include/sys/syscall.h new file mode 100644 index 0000000..8fe0142 --- /dev/null +++ b/usr/include/sys/syscall.h @@ -0,0 +1,13 @@ +/* + * sys/syscall.h + * + * Generic system call interface macros + */ +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#include +#include +#include + +#endif /* _SYS_SYSCALL_H */ diff --git a/usr/include/sys/sysinfo.h b/usr/include/sys/sysinfo.h new file mode 100644 index 0000000..dba68dc --- /dev/null +++ b/usr/include/sys/sysinfo.h @@ -0,0 +1,12 @@ +/* + * sys/sysinfo.h + */ + +#ifndef _SYS_SYSINFO_H +#define _SYS_SYSINFO_H + +#include + +extern int sysinfo(struct sysinfo *info); + +#endif /* _SYS_SYSINFO_H */ diff --git a/usr/include/sys/sysmacros.h b/usr/include/sys/sysmacros.h new file mode 100644 index 0000000..c344339 --- /dev/null +++ b/usr/include/sys/sysmacros.h @@ -0,0 +1,34 @@ +/* + * sys/sysmacros.h + * + * Constructs to create and pick apart dev_t. The double-underscore + * versions are macros so they can be used as constants. + */ + +#ifndef _SYS_SYSMACROS_H +#define _SYS_SYSMACROS_H + +#ifndef _SYS_TYPES_H +# include +#endif + +#define __major(__d) (((__d) >> 8) & 0xfff) +static __inline__ int major(dev_t __d) +{ + return __major(__d); +} + +#define __minor(__d) (((__d) & 0xff)|(((__d) >> 12) & 0xfff00)) +static __inline__ int minor(dev_t __d) +{ + return __minor(__d); +} + +#define __makedev(__ma, __mi) \ + ((((__ma) & 0xfff) << 8)|((__mi) & 0xff)|(((__mi) & 0xfff00) << 12)) +static __inline__ dev_t makedev(int __ma, int __mi) +{ + return __makedev(__ma, __mi); +} + +#endif /* _SYS_SYSMACROS_H */ diff --git a/usr/include/sys/time.h b/usr/include/sys/time.h new file mode 100644 index 0000000..65115b5 --- /dev/null +++ b/usr/include/sys/time.h @@ -0,0 +1,18 @@ +/* + * sys/time.h + */ + +#ifndef _SYS_TIME_H +#define _SYS_TIME_H + +#include +#include +#include + +__extern int gettimeofday(struct timeval *, struct timezone *); +__extern int settimeofday(const struct timeval *, const struct timezone *); +__extern int getitimer(int, struct itimerval *); +__extern int setitimer(int, const struct itimerval *, struct itimerval *); +__extern int utimes(const char *, const struct timeval *); + +#endif /* _SYS_TIME_H */ diff --git a/usr/include/sys/times.h b/usr/include/sys/times.h new file mode 100644 index 0000000..16be69a --- /dev/null +++ b/usr/include/sys/times.h @@ -0,0 +1,14 @@ +/* + * sys/times.h + */ + +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H + +#include +#include +#include + +__extern clock_t times(struct tms *); + +#endif /* _SYS_TIMES_H */ diff --git a/usr/include/sys/types.h b/usr/include/sys/types.h new file mode 100644 index 0000000..41cc634 --- /dev/null +++ b/usr/include/sys/types.h @@ -0,0 +1,111 @@ +/* + * sys/types.h + */ + +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H + +#include +#include +#include + +#define _SSIZE_T +typedef ptrdiff_t ssize_t; + +#include +#include + +/* Keeps linux/types.h from getting included elsewhere */ +#define _LINUX_TYPES_H + +typedef __kernel_fd_set fd_set; +typedef uint32_t dev_t; +typedef __kernel_ino_t ino_t; +typedef __kernel_mode_t mode_t; +typedef __kernel_nlink_t nlink_t; +typedef __kernel_loff_t off_t; +typedef __kernel_loff_t loff_t; +typedef __kernel_pid_t pid_t; +typedef __kernel_daddr_t daddr_t; +typedef __kernel_key_t key_t; +typedef __kernel_suseconds_t suseconds_t; +/* typedef __kernel_timer_t timer_t; */ +typedef int timer_t; + +typedef __kernel_uid32_t uid_t; +typedef __kernel_gid32_t gid_t; + +typedef __kernel_fsid_t fsid_t; + +/* + * The following typedefs are also protected by individual ifdefs for + * historical reasons: + */ +#ifndef _SIZE_T +#define _SIZE_T +typedef __kernel_size_t size_t; +#endif + +#ifndef _SSIZE_T +#define _SSIZE_T +typedef __kernel_ssize_t ssize_t; +#endif + +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef __kernel_ptrdiff_t ptrdiff_t; +#endif + +#ifndef _TIME_T +#define _TIME_T +typedef __kernel_time_t time_t; +#endif + +#ifndef _CLOCK_T +#define _CLOCK_T +typedef __kernel_clock_t clock_t; +#endif + +#ifndef _CADDR_T +#define _CADDR_T +typedef __kernel_caddr_t caddr_t; +#endif + +/* BSD */ +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +/* SysV */ +typedef unsigned char unchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +/* More BSD */ +typedef uint8_t u_int8_t; +typedef uint16_t u_int16_t; +typedef uint32_t u_int32_t; +typedef uint64_t u_int64_t; + +typedef uint16_t __bitwise __le16; +typedef uint16_t __bitwise __be16; +typedef uint32_t __bitwise __le32; +typedef uint32_t __bitwise __be32; +typedef uint64_t __bitwise __le64; +typedef uint64_t __bitwise __be64; + +/* + * Some headers seem to require this... + */ +#ifndef BITS_PER_LONG +# define BITS_PER_LONG _BITSIZE +#endif + +/* + * Some apps want this in + */ +#include + +#endif diff --git a/usr/include/sys/uio.h b/usr/include/sys/uio.h new file mode 100644 index 0000000..ee341fb --- /dev/null +++ b/usr/include/sys/uio.h @@ -0,0 +1,15 @@ +/* + * sys/uio.h + */ + +#ifndef _SYS_UIO_H +#define _SYS_UIO_H + +#include +#include +#include + +__extern int readv(int, const struct iovec *, int); +__extern int writev(int, const struct iovec *, int); + +#endif /* _SYS_UIO_H */ diff --git a/usr/include/sys/un.h b/usr/include/sys/un.h new file mode 100644 index 0000000..252d87b --- /dev/null +++ b/usr/include/sys/un.h @@ -0,0 +1,10 @@ +/* + * + */ + +#ifndef _SYS_UN_H +#define _SYS_UN_H + +#include + +#endif /* _SYS_UN_H */ diff --git a/usr/include/sys/utime.h b/usr/include/sys/utime.h new file mode 100644 index 0000000..56288a8 --- /dev/null +++ b/usr/include/sys/utime.h @@ -0,0 +1,10 @@ +/* + * sys/utime.h + */ + +#ifndef _SYS_UTIME_H +#define _SYS_UTIME_H + +#include + +#endif /* _SYS_UTIME_H */ diff --git a/usr/include/sys/utsname.h b/usr/include/sys/utsname.h new file mode 100644 index 0000000..fd55c0b --- /dev/null +++ b/usr/include/sys/utsname.h @@ -0,0 +1,23 @@ +/* + * sys/utsname.h + */ + +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H + +#include + +#define SYS_NMLN 65 + +struct utsname { + char sysname[SYS_NMLN]; + char nodename[SYS_NMLN]; + char release[SYS_NMLN]; + char version[SYS_NMLN]; + char machine[SYS_NMLN]; + char domainname[SYS_NMLN]; +}; + +__extern int uname(struct utsname *); + +#endif /* _SYS_UTSNAME_H */ diff --git a/usr/include/sys/vfs.h b/usr/include/sys/vfs.h new file mode 100644 index 0000000..33b1026 --- /dev/null +++ b/usr/include/sys/vfs.h @@ -0,0 +1,115 @@ +/* + * sys/vfs.h + */ + +#ifndef _SYS_VFS_H +#define _SYS_VFS_H + +#include +#include +#include +#include +#include + +/* struct statfs64 -- there seems to be two standards - + one for 32 and one for 64 bits, and they're incompatible. + Worse, some 64-bit platforms seem to use the 32-bit layout. + Of course, there is no includable header that does this well. */ + +#if _KLIBC_STATFS_F_TYPE_64 + +struct statfs { + uint64_t f_type; + uint64_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + __kernel_fsid_t f_fsid; + uint64_t f_namelen; + uint64_t f_frsize; + uint64_t f_spare[5]; +}; + +#else /* not _KLIBC_STATFS_F_TYPE_64 */ + +struct statfs { + uint32_t f_type; + uint32_t f_bsize; + uint64_t f_blocks; + uint64_t f_bfree; + uint64_t f_bavail; + uint64_t f_files; + uint64_t f_ffree; + __kernel_fsid_t f_fsid; + uint32_t f_namelen; + uint32_t f_frsize; + uint32_t f_spare[5]; +}; + +#endif /* _KLIBC_STATFS_F_TYPE_64 */ + +__extern int statfs(const char *, struct statfs *); +__extern int fstatfs(int, struct statfs *); + +/* Various filesystem types */ +#define ADFS_SUPER_MAGIC 0xadf5 +#define AFFS_SUPER_MAGIC 0xadff +#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ +#define AUTOFS_SUPER_MAGIC 0x0187 +#define BFS_MAGIC 0x1BADFACE +#define CAPIFS_SUPER_MAGIC 0x434e +#define CIFS_MAGIC_NUMBER 0xFF534D42 +#define CODA_SUPER_MAGIC 0x73757245 +#define CRAMFS_MAGIC 0x28cd3d45 +#define DEVFS_SUPER_MAGIC 0x1373 +#define DEVPTS_SUPER_MAGIC 0x1cd1 +#define EFS_SUPER_MAGIC 0x414A53 +#define EVENTPOLLFS_MAGIC 0x03111965 +#define EXT2_SUPER_MAGIC 0xEF53 +#define EXT3_SUPER_MAGIC 0xEF53 +#define GADGETFS_MAGIC 0xaee71ee7 +#define HFSPLUS_SUPER_MAGIC 0x482b +#define HFS_MFS_SUPER_MAGIC 0xD2D7 /* MFS MDB (super block) */ +#define HFS_SUPER_MAGIC 0x4244 /* "BD": HFS MDB (super block) */ +#define HPFS_SUPER_MAGIC 0xf995e849 +#define HUGETLBFS_MAGIC 0x958458f6 +#define HWGFS_MAGIC 0x12061983 +#define IBMASMFS_MAGIC 0x66726f67 +#define ISOFS_SUPER_MAGIC 0x9660 +#define JFFS2_SUPER_MAGIC 0x72b6 +#define JFFS_MAGIC_BITMASK 0x34383931 /* "1984" */ +#define JFFS_MAGIC_SB_BITMASK 0x07c0 /* 1984 */ +#define JFS_SUPER_MAGIC 0x3153464a /* "JFS1" */ +#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ +#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ +#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ +#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ +#define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ +#define NCP_SUPER_MAGIC 0x564c +#define NFS_SUPER_MAGIC 0x6969 +#define NFS_SUPER_MAGIC 0x6969 +#define OPENPROM_SUPER_MAGIC 0x9fa1 +#define OPROFILEFS_MAGIC 0x6f70726f +#define PFMFS_MAGIC 0xa0b4d889 +#define PIPEFS_MAGIC 0x50495045 +#define PROC_SUPER_MAGIC 0x9fa0 +#define QNX4_SUPER_MAGIC 0x002f /* qnx4 fs detection */ +#define RAMFS_MAGIC 0x858458f6 +#define REISERFS_SUPER_MAGIC 0x52654973 +#define ROMFS_MAGIC 0x7275 +#define SMB_SUPER_MAGIC 0x517B +#define SOCKFS_MAGIC 0x534F434B +#define SYSFS_MAGIC 0x62656572 +#define TMPFS_MAGIC 0x01021994 +#define UDF_SUPER_MAGIC 0x15013346 +#define UFS_MAGIC 0x00011954 +#define UFS_MAGIC_4GB 0x05231994 /* fs > 4 GB && fs_featurebits */ +#define UFS_MAGIC_FEA 0x00195612 /* fs_featurebits supported */ +#define UFS_MAGIC_LFN 0x00095014 /* fs supports filenames > 14 chars */ +#define UFS_MAGIC_SEC 0x00612195 /* B1 security fs */ +#define USBDEVICE_SUPER_MAGIC 0x9fa2 +#define VXFS_SUPER_MAGIC 0xa501FCF5 + +#endif /* _SYS_VFS_H */ diff --git a/usr/include/sys/wait.h b/usr/include/sys/wait.h new file mode 100644 index 0000000..0f5efaf --- /dev/null +++ b/usr/include/sys/wait.h @@ -0,0 +1,28 @@ +/* + * sys/wait.h + */ + +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H + +#include +#include +#include + +#include + +#define WEXITSTATUS(s) (((s) & 0xff00) >> 8) +#define WTERMSIG(s) ((s) & 0x7f) +#define WIFEXITED(s) (WTERMSIG(s) == 0) +#define WIFSTOPPED(s) (WTERMSIG(s) == 0x7f) +/* Ugly hack to avoid multiple evaluation of "s" */ +#define WIFSIGNALED(s) (WTERMSIG((s)+1) >= 2) +#define WCOREDUMP(s) ((s) & 0x80) +#define WSTOPSIG(s) WEXITSTATUS(s) + +__extern pid_t wait(int *); +__extern pid_t waitpid(pid_t, int *, int); +__extern pid_t wait3(int *, int, struct rusage *); +__extern pid_t wait4(pid_t, int *, int, struct rusage *); + +#endif /* _SYS_WAIT_H */ diff --git a/usr/include/syslog.h b/usr/include/syslog.h new file mode 100644 index 0000000..71a17e0 --- /dev/null +++ b/usr/include/syslog.h @@ -0,0 +1,62 @@ +/* + * syslog.h + */ + +#ifndef _SYSLOG_H +#define _SYSLOG_H + +#include +#include + +/* Alert levels */ +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 + +#define LOG_PRIMASK 7 +#define LOG_PRI(x) ((x) & LOG_PRIMASK) + +/* Facilities; not actually used */ +#define LOG_KERN 0000 +#define LOG_USER 0010 +#define LOG_MAIL 0020 +#define LOG_DAEMON 0030 +#define LOG_AUTH 0040 +#define LOG_SYSLOG 0050 +#define LOG_LPR 0060 +#define LOG_NEWS 0070 +#define LOG_UUCP 0100 +#define LOG_CRON 0110 +#define LOG_AUTHPRIV 0120 +#define LOG_FTP 0130 +#define LOG_LOCAL0 0200 +#define LOG_LOCAL1 0210 +#define LOG_LOCAL2 0220 +#define LOG_LOCAL3 0230 +#define LOG_LOCAL4 0240 +#define LOG_LOCAL5 0250 +#define LOG_LOCAL6 0260 +#define LOG_LOCAL7 0270 + +#define LOG_FACMASK 01770 +#define LOG_FAC(x) (((x) >> 3) & (LOG_FACMASK >> 3)) + +/* openlog() flags; only LOG_PID and LOG_PERROR supported */ +#define LOG_PID 0x01 /* include pid with message */ +#define LOG_CONS 0x02 /* write to console on logger error */ +#define LOG_ODELAY 0x04 /* delay connection until syslog() */ +#define LOG_NDELAY 0x08 /* open connection immediately */ +#define LOG_NOWAIT 0x10 /* wait for child processes (unused on linux) */ +#define LOG_PERROR 0x20 /* additional logging to stderr */ + +__extern void openlog(const char *, int, int); +__extern void syslog(int, const char *, ...); +__extern void vsyslog(int, const char *, va_list); +__extern void closelog(void); + +#endif /* _SYSLOG_H */ diff --git a/usr/include/termios.h b/usr/include/termios.h new file mode 100644 index 0000000..59d9859 --- /dev/null +++ b/usr/include/termios.h @@ -0,0 +1,91 @@ +/* + * termios.h + */ + +#ifndef _TERMIOS_H +#define _TERMIOS_H + +#include +#include +#include +#include +#include + +/* Redefine these so the magic constants == the ioctl number to use. */ +#undef TCSANOW +#undef TCSADRAIN +#undef TCSAFLUSH +#define TCSANOW TCSETS +#define TCSADRAIN TCSETSW +#define TCSAFLUSH TCSETSF + +static __inline__ int tcgetattr(int __fd, struct termios *__s) +{ + return ioctl(__fd, TCGETS, __s); +} + +static __inline__ int tcsetattr(int __fd, int __opt, const struct termios *__s) +{ + return ioctl(__fd, __opt, (void *)__s); +} + +static __inline__ int tcflow(int __fd, int __action) +{ + return ioctl(__fd, TCXONC, (void *)(intptr_t) __action); +} + +static __inline__ int tcflush(int __fd, int __queue) +{ + return ioctl(__fd, TCFLSH, (void *)(intptr_t) __queue); +} + +static __inline__ int tcdrain(int __fd) +{ + return ioctl(__fd, TCSBRK, (void *)1L); +} + +static __inline__ pid_t tcgetpgrp(int __fd) +{ + pid_t __p; + return ioctl(__fd, TIOCGPGRP, &__p) ? (pid_t) - 1 : __p; +} + +static __inline__ pid_t tcgetsid(int __fd) +{ + pid_t __p; + return ioctl(__fd, TIOCGSID, &__p) ? (pid_t) - 1 : __p; +} + +static __inline__ int tcsendbreak(int __fd, int __duration) +{ + return ioctl(__fd, TCSBRKP, (void *)(uintptr_t) __duration); +} + +static __inline__ int tcsetpgrp(int __fd, pid_t __p) +{ + return ioctl(__fd, TIOCSPGRP, &__p); +} + +static __inline__ speed_t cfgetospeed(const struct termios *__s) +{ + return (speed_t) (__s->c_cflag & CBAUD); +} + +static __inline__ speed_t cfgetispeed(const struct termios *__s) +{ + return (speed_t) (__s->c_cflag & CBAUD); +} + +static __inline__ int cfsetospeed(struct termios *__s, speed_t __v) +{ + __s->c_cflag = (__s->c_cflag & ~CBAUD) | (__v & CBAUD); + return 0; +} + +static __inline__ int cfsetispeed(struct termios *__s, speed_t __v) +{ + __s->c_cflag = (__s->c_cflag & ~CBAUD) | (__v & CBAUD); + return 0; +} + +#endif /* _TERMIOS_H */ diff --git a/usr/include/time.h b/usr/include/time.h new file mode 100644 index 0000000..72b2993 --- /dev/null +++ b/usr/include/time.h @@ -0,0 +1,18 @@ +/* + * time.h + */ + +#ifndef _TIME_H +#define _TIME_H + +#include +#include + +__extern time_t time(time_t *); +__extern int nanosleep(const struct timespec *, struct timespec *); + +/* klibc-specific but useful since we don't have floating point */ +__extern char *strtotimeval(const char *str, struct timeval *tv); +__extern char *strtotimespec(const char *str, struct timespec *tv); + +#endif /* _TIME_H */ diff --git a/usr/include/unistd.h b/usr/include/unistd.h new file mode 100644 index 0000000..dadb63d --- /dev/null +++ b/usr/include/unistd.h @@ -0,0 +1,159 @@ +/* + * unistd.h + */ + +#ifndef _UNISTD_H +#define _UNISTD_H + +#include +#include +#include +#include +#include + +__extern char **environ; +__extern __noreturn _exit(int); + +__extern pid_t fork(void); +__extern pid_t vfork(void); +__extern pid_t getpid(void); +__extern pid_t getpgid(pid_t); +__extern int setpgid(pid_t, pid_t); +__extern pid_t getppid(void); +__extern pid_t getpgrp(void); +__extern int setpgrp(void); +__extern pid_t setsid(void); +__extern pid_t getsid(pid_t); +__extern int execv(const char *, char *const *); +__extern int execvp(const char *, char *const *); +__extern int execve(const char *, char *const *, char *const *); +__extern int execvpe(const char *, char *const *, char *const *); +__extern int execl(const char *, const char *, ...); +__extern int execlp(const char *, const char *, ...); +__extern int execle(const char *, const char *, ...); +__extern int execlpe(const char *, const char *, ...); + +__extern int setuid(uid_t); +__extern uid_t getuid(void); +__extern int seteuid(uid_t); +__extern uid_t geteuid(void); +__extern int setgid(gid_t); +__extern gid_t getgid(void); +__extern int setegid(gid_t); +__extern gid_t getegid(void); +__extern int getgroups(int, gid_t *); +__extern int setgroups(size_t, const gid_t *); +__extern int setreuid(uid_t, uid_t); +__extern int setregid(gid_t, gid_t); +__extern int setresuid(uid_t, uid_t, uid_t); +__extern int setresgid(gid_t, gid_t, gid_t); +__extern int getfsuid(uid_t); +__extern int setfsuid(uid_t); + +/* Macros for access() */ +#define R_OK 4 /* Read */ +#define W_OK 2 /* Write */ +#define X_OK 1 /* Execute */ +#define F_OK 0 /* Existence */ + +__extern int access(const char *, int); +__extern int faccessat(int, const char *, int); +__extern int link(const char *, const char *); +__extern int linkat(int, const char *, int, const char *); +__extern int unlink(const char *); +__extern int unlinkat(int, const char *); +__extern int chdir(const char *); +__extern int fchdir(int); +__extern int chmod(const char *, mode_t); +__extern int fchmod(int, mode_t); +__extern int fchmodat(int, const char *, mode_t); +__extern int mkdir(const char *, mode_t); +__extern int mkdirat(int, const char *, const char *, mode_t); +__extern int rmdir(const char *); +__extern int pipe(int *); +__extern int chroot(const char *); +__extern int symlink(const char *, const char *); +__extern int symlinkat(int, const char *, const char *); +__extern int readlink(const char *, char *, size_t); +__extern int readlinkat(int, const char *, char *, size_t); +__extern int chown(const char *, uid_t, gid_t); +__extern int fchown(int, uid_t, gid_t); +__extern int lchown(const char *, uid_t, gid_t); +__extern char *getcwd(char *, size_t); + +/* Also in */ +#ifndef _KLIBC_IN_OPEN_C +__extern int open(const char *, int, ...); +__extern int openat(int, const char *, int, ...); +#endif +__extern int close(int); +__extern off_t lseek(int, off_t, int); +/* off_t is 64 bits now even on 32-bit platforms; see llseek.c */ +static __inline__ off_t llseek(int __f, off_t __o, int __w) +{ + return lseek(__f, __o, __w); +} + +__extern ssize_t read(int, void *, size_t); +__extern ssize_t write(int, const void *, size_t); +__extern ssize_t pread(int, void *, size_t, off_t); +__extern ssize_t pwrite(int, void *, size_t, off_t); + +__extern int dup(int); +__extern int dup2(int, int); +__extern int fcntl(int, int, ...); +__extern int ioctl(int, int, void *); +__extern int flock(int, int); +__extern int ftruncate(int, off_t); + +/* + * Macros for sync_file_range() + */ +#define SYNC_FILE_RANGE_WAIT_BEFORE 1 +#define SYNC_FILE_RANGE_WRITE 2 +#define SYNC_FILE_RANGE_WAIT_AFTER 4 + +__extern int sync(void); +__extern int fsync(int); +__extern int fdatasync(int); +__extern int sync_file_range(int, off_t, off_t, unsigned int); + +__extern int pause(void); +__extern unsigned int alarm(unsigned int); +__extern unsigned int sleep(unsigned int); +__extern void usleep(unsigned long); + +__extern int gethostname(char *, size_t); +__extern int sethostname(const char *, size_t); +__extern int getdomainname(char *, size_t); +__extern int setdomainname(const char *, size_t); + +__extern void *__brk(void *); +__extern int brk(void *); +__extern void *sbrk(ptrdiff_t); + +__extern int getopt(int, char *const *, const char *); +__extern char *optarg; +__extern int optind, opterr, optopt; + +__extern int isatty(int); + +static __inline__ int getpagesize(void) +{ + extern unsigned int __page_size; + return __page_size; +} +static __inline__ int __getpageshift(void) +{ + extern unsigned int __page_shift; + return __page_shift; +} + +__extern int daemon(int, int); + +/* Standard file descriptor numbers. */ +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#endif /* _UNISTD_H */ diff --git a/usr/include/utime.h b/usr/include/utime.h new file mode 100644 index 0000000..fa00604 --- /dev/null +++ b/usr/include/utime.h @@ -0,0 +1,14 @@ +/* + * utime.h + */ + +#ifndef _UTIME_H +#define _UTIME_H + +#include +#include +#include + +__extern int utime(const char *, const struct utimbuf *); + +#endif /* _UTIME_H */ diff --git a/usr/klibc/CAVEATS b/usr/klibc/CAVEATS new file mode 100644 index 0000000..02b9b9e --- /dev/null +++ b/usr/klibc/CAVEATS @@ -0,0 +1,60 @@ + ------------------------------------------------- + Please note the following caveats to using klibc: + ------------------------------------------------- + +optimization: +------------- + +Compiling with -O0 is not supported. It may or may not work; please +use -O1 if you want to do maximize debuggability. + +Compiling with -O0 is more likely to work on gcc 3. + + +setjmp()/longjmp(): +------------------- + +setjmp() and longjmp() *do not* save signal state. sigsetjmp() and +siglongjmp() *do* save the signal mask -- regardless of the value of +the extra argument. + +The standards actually state that if you pass longjmp() a final value +of zero the library should change that to a 1! Presumably the reason +is so people who write broken code can get away with writing +longjmp(buf); or something equally bad. If you pass longjmp() a final +value of 0 you get what you deserve -- setjmp() will happily return 0. + + +stdio: +------ + +Only a small subset of the stdio functions are implemented. Those +that are implemented do not buffer, although they *do* trap EINTR or +short read/writes and iterate. + +_fread() and _fwrite(), which take only one size argument (like +read/write), but do handle EINTR/short return are also available. + + +namespaces: +----------- + +klibc frequently includes headers in other headers in a way that +exposes more symbols than POSIX says they should. "Live with it." + + +theading: +--------- + +klibc is not thread-safe. Consequently, clone() or any of the +pthreads functions are not included. + + +bsd_signal vs sysv_signal: +-------------------------- + +There is no signal() call, because you never know if you want +Linux/SysV semantics (SA_RESETHAND) or GNU/BSD semantics (SA_RESTART). +The best, in *any* circumstances, is to never use signal() and instead +use sigaction(), but in order to simplify porting you can use either +sysv_signal() or bsd_signal(), depending on what you actually want. diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild new file mode 100644 index 0000000..a1e8763 --- /dev/null +++ b/usr/klibc/Kbuild @@ -0,0 +1,186 @@ +# +# Kbuild file for klibc +# + +# Tell that we are building klibc +klibc-build := y + +libc-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \ + asprintf.o vasprintf.o \ + vsscanf.o sscanf.o ctypes.o \ + strntoumax.o strntoimax.o \ + atoi.o atol.o atoll.o \ + strtol.o strtoll.o strtoul.o strtoull.o \ + strtoimax.o strtoumax.o \ + globals.o exit.o atexit.o onexit.o \ + execl.o execle.o execv.o execvpe.o execvp.o execlp.o execlpe.o \ + fork.o vfork.o wait.o wait3.o waitpid.o system.o \ + setpgrp.o getpgrp.o daemon.o \ + printf.o vprintf.o fprintf.o vfprintf.o perror.o \ + statfs.o fstatfs.o umount.o \ + open.o openat.o fopen.o fread.o fread2.o fgetc.o fgets.o \ + fwrite.o fwrite2.o fputc.o fputs.o puts.o putchar.o \ + sleep.o usleep.o strtotimespec.o strtotimeval.o \ + raise.o abort.o assert.o alarm.o pause.o \ + __signal.o sysv_signal.o bsd_signal.o siglist.o sigabbrev.o \ + siglongjmp.o \ + sigaction.o sigpending.o sigprocmask.o sigsuspend.o \ + pselect.o ppoll.o \ + brk.o sbrk.o malloc.o realloc.o calloc.o mmap.o \ + memcpy.o memcmp.o memset.o memccpy.o memmem.o memswap.o \ + memmove.o memchr.o memrchr.o \ + strcasecmp.o strncasecmp.o strndup.o strerror.o strsignal.o \ + strcat.o strchr.o strcmp.o strcpy.o strdup.o strlen.o strnlen.o \ + strncat.o strlcpy.o strlcat.o \ + strstr.o strncmp.o strncpy.o strrchr.o \ + strxspn.o strspn.o strcspn.o strpbrk.o strsep.o strtok.o \ + gethostname.o getdomainname.o getcwd.o \ + seteuid.o setegid.o \ + getenv.o setenv.o putenv.o __put_env.o unsetenv.o \ + clearenv.o nullenv.o \ + getopt.o readdir.o remove.o \ + syslog.o closelog.o pty.o getpt.o isatty.o reboot.o \ + time.o utime.o llseek.o nice.o getpriority.o \ + qsort.o bsearch.o \ + lrand48.o jrand48.o mrand48.o nrand48.o srand48.o seed48.o \ + inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \ + inet/inet_ntop.o inet/inet_pton.o inet/bindresvport.o \ + send.o recv.o \ + ctype/isalnum.o ctype/isalpha.o ctype/isascii.o \ + ctype/isblank.o ctype/iscntrl.o ctype/isdigit.o \ + ctype/isgraph.o ctype/islower.o ctype/isprint.o \ + ctype/ispunct.o ctype/isspace.o ctype/isupper.o \ + ctype/isxdigit.o ctype/tolower.o ctype/toupper.o + +libc-$(CONFIG_KLIBC_ERRLIST) += errlist.o + +ifeq ($(CONFIG_KLIBC_ERRLIST),y) +KLIBCCFLAGS_strerror.o += -DWITH_ERRLIST +endif + +libc-$(CONFIG_KLIBC_ZLIB) += \ + zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/gzio.o \ + zlib/uncompr.o zlib/deflate.o zlib/trees.o zlib/zutil.o \ + zlib/inflate.o zlib/infback.o zlib/inftrees.o zlib/inffast.o + +# zlib specific flag +KLIBCCFLAGS += -DDYNAMIC_CRC_TABLE + +##### +# Add any architecture-specific rules +include $(obj)/arch/$(KLIBCARCHDIR)/Makefile.inc + +##### +# Shared definitions +LIB := libc.a +SOLIB := libc.so +SOHASH := klibc.so +CRT0 := arch/$(KLIBCARCHDIR)/crt0.o +INTERP_O := interp.o + +always := $(CRT0) $(LIB) $(SOLIB) $(SOHASH) $(INTERP_O) +LIB := $(call objectify,$(LIB)) +SOLIB := $(call objectify,$(SOLIB)) +SOHASH := $(call objectify,$(SOHASH)) +CRT0 := $(call objectify,$(CRT0)) +INTERP_O := $(call objectify,$(INTERP_O)) + +SOLIBHASH = $(shell cat $(SOLIB).hash) + +targets += arch/$(KLIBCARCHDIR)/crt0.o +targets += $(libc-y) $(KLIBCARCHOBJS) + +# Generate syscall stubs +subdir-y += syscalls +# Generate socket calls stubs +subdir-y += socketcalls + +# Tell make to descend before building libs +$(obj)/syscalls/syscalls.list: $(obj)/syscalls +$(obj)/socketcalls/socketcalls.list: $(obj)/socketcalls + +##### +# Readable errormessages extracted from src.. +targets += errlist.c +quiet_cmd_errlist = GEN $@ + cmd_errlist = $(PERL) $< $(KLIBCCPPFLAGS) -errlist > $@ || rm -f $@ + +$(obj)/errlist.c: $(srctree)/$(src)/makeerrlist.pl + $(call cmd,errlist) + +# full list of dependencies for klibc +libc-deps = $(call objectify, $(libc-y) $(KLIBCARCHOBJS)) \ + $(call objectify, syscalls/syscalls.list socketcalls/socketcalls.list) + +###### +# Build static library: libc.a +targets += libc.a __static_init.o +quiet_cmd_libc = KLIBCAR $@ + cmd_libc = rm -f $@; \ + $(KLIBCAR) cq $@ \ + $(patsubst %.list,`cat %.list`,$(filter-out FORCE,$^)); \ + $(KLIBCRANLIB) $@ + +$(LIB): $(call objectify,__static_init.o) $(libc-deps) FORCE + $(call if_changed,libc) + +###### +# Build shared library +targets += libc.so __shared_init.o + +quiet_cmd_libcso = KLIBCLD $@ + cmd_libcso = $(KLIBCLD) $(KLIBCLDFLAGS) $(KLIBCSHAREDFLAGS) -o $@ \ + --start-group \ + $(patsubst %.list,`cat %.list`,$(filter-out FORCE,$^)) \ + $(KLIBCLIBGCC) \ + --end-group + +$(SOLIB): $(CRT0) $(call objectify,__shared_init.o) $(libc-deps) FORCE + $(call if_changed,libcso) + + +##### +# Build sha1 hash values +targets += klibc.so libc.so.hash +hostprogs-y := sha1hash +clean-files += klibc-???????????????????????????.so + +quiet_cmd_solibhash = HASH $@ + cmd_solibhash = $(KLIBCNM) $< | egrep '^[0-9a-fA-F]+ [ADRTW] ' | \ + sort | $(obj)/sha1hash > $@ +$(SOLIB).hash: $(SOLIB) $(obj)/sha1hash FORCE + $(call if_changed,solibhash) + +quiet_cmd_sohash = GEN $@ + cmd_sohash = cat $< > $@; \ + $(KLIBCSTRIP) $(KLIBCSTRIPFLAGS) $@; \ + rm -f $(obj)/klibc-???????????????????????????.so; \ + ln -f $@ $(obj)/klibc-$(SOLIBHASH).so +$(SOHASH): $(SOLIB) $(SOLIB).hash + $(call cmd,sohash) + + +##### +# build interp.o +targets += interp.o + +quiet_cmd_interp = BUILD $@ + cmd_interp = $(KLIBCCC) $(klibccflags) -D__ASSEMBLY__ \ + -DLIBDIR=\"$(SHLIBDIR)\" \ + -DSOHASH=\"$(SOLIBHASH)\" \ + -c -o $@ $< + +$(INTERP_O): $(obj)/interp.S $(SOLIB).hash + $(call if_changed,interp) + +##### +# Install klibc +install-rule: + @echo " INSTALL klibc to $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)lib" + $(Q)$(foreach f, $(LIB) $(SOLIB) $(CRT0) $(INTERP_O), \ + $(shell $(install-data) $(f) \ + $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)lib)) + $(Q)$(install-lib) $(obj)/klibc-$(SOLIBHASH).so \ + $(INSTALLROOT)$(INSTALLDIR)/$(KLIBCCROSS)lib + $(Q)$(install-lib) $(obj)/klibc-$(SOLIBHASH).so \ + $(INSTALLROOT)$(SHLIBDIR) diff --git a/usr/klibc/LICENSE b/usr/klibc/LICENSE new file mode 100644 index 0000000..aa6d7a7 --- /dev/null +++ b/usr/klibc/LICENSE @@ -0,0 +1,73 @@ +This license applies to all files in directory and its subdirectories, +unless otherwise noted in individual files. + + +Some files are derived from files derived from the include/ directory +of the Linux kernel, and are licensed under the terms of the GNU +General Public License, version 2, as released by the Free Software +Foundation, Inc.; incorporated herein by reference. + + ----- + +Some files are derived from files copyrighted by the Regents of The +University of California, and are available under the following +license: + +Note: The advertising clause in the license appearing on BSD Unix +files was officially rescinded by the Director of the Office of +Technology Licensing of the University of California on July 22 +1999. He states that clause 3 is "hereby deleted in its entirety." + + * Copyright (c) + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. + + ----- + +For all remaining files, the following license applies: + + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * Any copyright notice(s) and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/usr/klibc/README b/usr/klibc/README new file mode 100644 index 0000000..5dc2ce2 --- /dev/null +++ b/usr/klibc/README @@ -0,0 +1,80 @@ +This is klibc, what is intended to be a minimalistic libc subset for +use with initramfs. It is deliberately written for small size, +minimal entaglement, and portability, not speed. It is definitely a +work in progress, and a lot of things are still missing. + + +The build procedure is not very polished yet, but it should work like +this: + +a) In the source root directory (the directory above the one in which + this file is found) create a symlink called "linux" pointing to a + reasonably recent Linux kernel tree (2.4 or 2.6 should be OK.) + This tree must have the include/asm symlink set up for the + architecture you're compiling for, and include/linux/autoconf.h + must exist. The easiest way to make sure of all of these is to do + a "make config" or any of its variants on the kernel tree is + question, followed by a "make dep" (2.4) or "make prepare" (2.6). + +b) If you're cross-compiling, you need to set KLIBCARCH to the + appropriate architecture, and set CROSS_COMPILE to your toolchain + prefix. + + IMPORTANT: if you're on a 64-bit machine with a 32-bit userland + (ia64, mips64, ppc64 sparc64, s390x or x86_64), and you want to + build the 32-bit version: you need to set KLIBCARCH to the 32-bit + architecture as well as set up the linux/include/asm symlink to + point to the 32-bit architecture. Building the 32-bit architecture + usually (but not always) produces smaller binaries, and is likely + to be better tested. + + If you are on ARM, and want to build a thumb version of the library + (this is supported), change OPTFLAGS in arch/arm/MCONFIG to build + thumb code. + + The following is the last known status of various architectures: + + alpha: Working + arm-thumb: Untested + arm: Working + arm26: Not yet ported + cris: Working + h8300: Not yet ported + i386: Working + ia64: Working + m32r: Untested + m68k: Untested + m68knommu: Not yet ported + mips: Working + mips64: Not yet ported + parisc: Working + parisc64: Not yet ported + ppc: Working + ppc64: Working + s390: Working static, shared untested + s390x: Working + sh: Untested + sh64: Not yet ported + sparc: Working + sparc64: Untested + v850: Not yet ported + x86-64: Working + xtensa: Not yet ported + + Shared library support requires recent binutils on many + architectures. + + Note that even the "working" ones likely have bugs. Please report + them if you run into them. + +c) Type "make" and pray... + +d) Try the test programs in the tests/ directory. They should run... + +Contact the klibc mailing list: + + http://www.zytor.com/mailman/listinfo/klibc + +... for more info. + + -hpa diff --git a/usr/klibc/SOCKETCALLS.def b/usr/klibc/SOCKETCALLS.def new file mode 100644 index 0000000..70d478f --- /dev/null +++ b/usr/klibc/SOCKETCALLS.def @@ -0,0 +1,21 @@ +/* -*- c -*- + * + * These are calls that are invoked via the socketcall mechanism + * Note that on most architectures this is simply #included into + * SYSCALLS.def. + */ + int socket(int, int, int); + int bind(int, struct sockaddr *, int); + int connect(int, struct sockaddr *, socklen_t); + int listen(int, int); + int accept(int, struct sockaddr *, socklen_t *); + int getsockname(int, struct sockaddr *, socklen_t *); + int getpeername(int, struct sockaddr *, socklen_t *); + int socketpair(int, int, int, int *); + int sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t); + int recvfrom(int, void *, size_t, unsigned int, struct sockaddr *, socklen_t *); + int shutdown(int, int); + int setsockopt(int, int, int, const void *, socklen_t); + int getsockopt(int, int, int, void *, socklen_t *); + int sendmsg(int, const struct msghdr *, unsigned int); + int recvmsg(int, struct msghdr *, unsigned int); diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def new file mode 100644 index 0000000..64b92be --- /dev/null +++ b/usr/klibc/SYSCALLS.def @@ -0,0 +1,260 @@ +/* -*- c -*- + * + * This is a list of system calls we invoke "directly". These + * are generated into syscall stubs in their own files, so the + * linker can do its job properly. + * + * The full description of a line is: + * [<[?][!]arch,...>] type [sysname,...][@systype][::funcname](args); + * + * ? means only instantiate this system call if present in asm/unistd.h + */ + +#include +#include +#include + +/* + * Process-related syscalls + */ +void _exit,exit::_exit(int); + pid_t clone::__clone(unsigned long, void *); + pid_t clone::__clone2(unsigned long, void *, void *); +# if ! _KLIBC_NO_MMU + pid_t fork(); + pid_t fork@forkish(); +#endif +#if _KLIBC_REAL_VFORK +/* + * A lot of architectures need architecture-specific vfork + * stubs, due to the no-stack requirement. These are the + * architectures which do not. + */ + pid_t vfork(); + pid_t vfork@forkish(); +#endif + pid_t getpid(); + pid_t getxpid@dual0::getpid(); +int setpgid(pid_t, pid_t); +pid_t getpgid(pid_t); + pid_t getppid(); + pid_t getxpid@dual1::getppid(); +pid_t setsid(); +pid_t getsid(pid_t); +pid_t wait4(pid_t, int *, int, struct rusage *); +int execve(const char *, char * const *, char * const *); + int nice(int); + int getpriority(int, int); + int getpriority::__getpriority(int, int); +int setpriority(int, int, int); +int sched_setscheduler(pid_t, int, const struct sched_param *); +int sched_yield(); + +/* + * User and group IDs + */ +int setuid32,setuid::setuid(uid_t); +int setgid32,setgid::setgid(gid_t); + uid_t getuid32,getuid::getuid(); + uid_t getxuid@dual0::getuid(); + gid_t getgid32,getgid::getgid(); + gid_t getxgid@dual0::getgid(); + uid_t geteuid32,geteuid::geteuid(); + uid_t getxuid@dual1::geteuid(); + gid_t getegid32,getegid::getegid(); + gid_t getxgid@dual1::getegid(); +int getgroups32,getgroups::getgroups(int, gid_t *); +int setgroups32,setgroups::setgroups(size_t, const gid_t *); +int setreuid32,setreuid::setreuid(uid_t, uid_t); +int setregid32,setregid::setregid(gid_t, gid_t); +int setfsuid32,setfsuid::setfsuid(uid_t); +int setfsgid32,setfsgid::setfsgid(gid_t); +int setresuid32,setresuid::setresuid(int, uid_t, uid_t, uid_t); + +/* + * Filesystem-related system calls + */ +int mount(const char *, const char *, const char *, unsigned long, const void *); + int umount2(const char *, int); + int umount::umount2(const char *, int); + int pivot_root(const char *, const char *); +int sync(); +#ifdef __NR_statfs64 +int statfs64::__statfs64(const char *, size_t, struct statfs *); +#else +int statfs(const char *, struct statfs *); +#endif +#ifdef __NR_fstatfs64 +int fstatfs64::__fstatfs64(int, size_t, struct statfs *); +#else +int fstatfs(int, struct statfs *); +#endif +int swapon(const char *, int); +int swapoff(const char *); + +/* + * Inode-related system calls + */ +int access(const char *, int); + int faccessat(int, const char *, int); +int link(const char *, const char *); + int linkat(int, const char *, int, const char *); +int unlink(const char *); + int unlinkat(int, const char *); +int chdir(const char *); +int fchdir(int); +int rename(const char *, const char *); + int renameat(int, const char *, int, const char *); +int mknod(const char *, mode_t, dev_t); + int mknodat(int, const char *, const char *, mode_t, dev_t); +int chmod(const char *, mode_t); +int fchmod(int, mode_t); + int fchmodat(int, const char *, mode_t); +int mkdir(const char *, mode_t); + int mkdirat(int, const char *, const char *, mode_t); +int rmdir(const char *); + int pipe(int *); +mode_t umask(mode_t); +int chroot(const char *); +int symlink(const char *, const char *); + int symlinkat(const char *, int, const char *); +int readlink(const char *, char *, size_t); + int readlinkat(int, const char *, char *, int); + int stat64,stat::stat(const char *, struct stat *); + int lstat64,lstat::lstat(const char *, struct stat *); + int fstat64,fstat::fstat(int, struct stat *); + int stat::stat(const char *, struct stat *); + int lstat::lstat(const char *, struct stat *); + int fstat::fstat(int, struct stat *); +/* XXX: Is this right?! */ + int fstatat64,newstatat,fstatat::fstatat(int, const char *, struct stat *, int); +int getdents64,getdents::getdents(unsigned int, struct dirent *, unsigned int); +int chown32,chown::chown(const char *, uid_t, gid_t); +int fchown32,fchown::fchown(int, uid_t, gid_t); + int fchownat(int, const char *, uid_t, gid_t, int); +int lchown32,lchown::lchown(const char *, uid_t, gid_t); +int getcwd::__getcwd(char *, size_t); + int utime(const char *, const struct utimbuf *); + int utimes(const char *, const struct timeval *); + int futimesat(int, const char *, const struct timeval *); + int inotify_init(); + int inotify_add_watch(int, const char *, __u32); + int inotify_rm_watch(int, __u32); + +/* + * I/O operations + */ + int open::__open(const char *, int, mode_t); + int openat::__openat(int, const char *, int, mode_t); +<64> int open(const char *, int, mode_t); +ssize_t read(int, void *, size_t); +ssize_t write(int, const void *, size_t); +int close(int); +<64> off_t lseek(int, off_t, int); +<32> int _llseek::__llseek(int, unsigned long, unsigned long, off_t *, int); +int dup(int); +int dup2(int, int); + int fcntl64@varadic::fcntl(int, int, unsigned long); + int fcntl(int, int, unsigned long); + int fcntl64,fcntl::fcntl(int, int, unsigned long); +int ioctl(int, int, void *); +int flock(int, int); +int _newselect,select::select(int, fd_set *, fd_set *, fd_set *, struct timeval *); +#if defined(__NR_pselect) && !_KLIBC_USE_RT_SIG +int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *); +#elif defined(__NR_pselect7) +int pselect7::__pselect7(int, fd_set *, fd_set *, fd_set *, struct timespec *, const sigset_t *, size_t); +#elif defined(__NR_pselect6) +int pselect6::__pselect6(int, fd_set *, fd_set *, fd_set *, struct timespec *, const struct __pselect6 *); +#endif +int poll(struct pollfd *, nfds_t, long); + int ppoll::__ppoll(struct pollfd *, nfds_t, struct timespec *, const sigset_t *, size_t); +int fsync(int); +int fdatasync,fsync::fdatasync(int); +int readv(int, const struct iovec *, int); +int writev(int, const struct iovec *, int); +int ftruncate64,ftruncate::ftruncate(int, off_t); +ssize_t pread64,pread::pread(int, void *, size_t, off_t); +ssize_t pwrite64,pwrite::pwrite(int, void *, size_t, off_t); +int sync_file_range,fdatasync,fsync::sync_file_range(int, off_t, off_t, unsigned int); + int splice(int, off_t *, int, off_t *, size_t, unsigned int); + int tee(int, int, size_t, unsigned int); +ssize_t sendfile64,sendfile::sendfile(int, int, off_t *, size_t, off_t); + +/* + * Signal operations + * + * We really should get rid of the non-rt_* of these, but that takes + * sanitizing for all architectures, sigh. See . + */ +#if _KLIBC_USE_RT_SIG + int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t); + int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, void *, size_t); +int rt_sigsuspend::__rt_sigsuspend(const sigset_t *, size_t); +int rt_sigpending::__rt_sigpending(sigset_t *, size_t); +int rt_sigprocmask::__rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t); + void rt_sigreturn::__sigreturn(); +#else +int sigaction::__sigaction(int, const struct sigaction *, struct sigaction *); +int sigsuspend(const sigset_t *); +int sigpending(sigset_t *); +int sigprocmask(int, const sigset_t *, sigset_t *); +#endif +int kill(pid_t, int); + unsigned int alarm(unsigned int); +int getitimer(int, struct itimerval *); +int setitimer(int, const struct itimerval *, struct itimerval *); + +/* + * Time-related system calls + */ + time_t time(time_t *); +clock_t times(struct tms *); +int gettimeofday(struct timeval *, struct timezone *); +int settimeofday(const struct timeval *, const struct timezone *); +int nanosleep(const struct timespec *, struct timespec *); + int pause(); + +/* + * Memory + */ + void * brk::__brk(void *); +int munmap(void *, size_t); +void * mremap(void *, size_t, size_t, unsigned long); +int msync(const void *, size_t, int); +int mprotect(const void *, size_t, int); +# if _KLIBC_USE_MMAP2 + void * mmap2::__mmap2(void *, size_t, int, int, int, long); +# else + void * mmap(void *, size_t, int, int, int, long); +int mlockall(int); +int munlockall(); +int mlock(const void *, size_t); +int munlock(const void *, size_t); +#endif + +/* + * System stuff + */ +int uname(struct utsname *); +int setdomainname(const char *, size_t); +int sethostname(const char *, size_t); +long init_module(void *, unsigned long, const char *); +long delete_module(const char *, unsigned int); +int reboot::__reboot(int, int, int, void *); +int syslog::klogctl(int, char *, int); +int sysinfo(struct sysinfo *); + +/* + * Low-level I/O (generally architecture-specific); + */ + int iopl(int); + int ioperm(unsigned long, unsigned long, int); + int vm86(struct vm86_struct *); + +/* + * Most architectures have the socket interfaces using regular + * system calls. + */ + long socketcall::__socketcall(int, const unsigned long *); +#include "SOCKETCALLS.def" diff --git a/usr/klibc/__put_env.c b/usr/klibc/__put_env.c new file mode 100644 index 0000000..30d415c --- /dev/null +++ b/usr/klibc/__put_env.c @@ -0,0 +1,74 @@ +/* + * __put_env.c - common code for putenv() and setenv() + */ + +#include +#include +#include +#include +#include "env.h" + +static size_t __environ_size; +static char **__environ_alloc; + +/* str should be a duplicated version of the input string; + len is the length of the key including the = sign */ + +int __put_env(char *str, size_t len, int overwrite) +{ + static char *const null_environ = { NULL }; + char **p, *q; + char **newenv; + size_t n; + + if (!environ) + environ = (char **)null_environ; + + n = 1; /* Include space for final NULL */ + for (p = environ; (q = *p); p++) { + n++; + if (!strncmp(q, str, len)) { + if (!overwrite) + free(str); + else + *p = str; /* Possible memory leak... */ + return 0; + } + } + + if (__environ_alloc && environ != __environ_alloc) { + free(__environ_alloc); + __environ_alloc = NULL; + } + + /* Need to extend the environment */ + if (n < __environ_size) { + p[1] = NULL; + *p = str; + return 0; + } else { + if (__environ_alloc) { + newenv = + realloc(__environ_alloc, + (__environ_size << 1) * sizeof(char *)); + if (!newenv) + return -1; + + __environ_size <<= 1; + } else { + /* Make a reasonable guess how much more space + we need */ + size_t newsize = n + 32; + newenv = malloc(newsize * sizeof(char *)); + if (!newenv) + return -1; + + memcpy(newenv, environ, n * sizeof(char *)); + __environ_size = newsize; + } + newenv[n-1] = str; /* Old NULL position */ + newenv[n] = NULL; + environ = newenv; + } + return 0; +} diff --git a/usr/klibc/__shared_init.c b/usr/klibc/__shared_init.c new file mode 100644 index 0000000..592a3db --- /dev/null +++ b/usr/klibc/__shared_init.c @@ -0,0 +1,2 @@ +#define SHARED 1 +#include "libc_init.c" diff --git a/usr/klibc/__signal.c b/usr/klibc/__signal.c new file mode 100644 index 0000000..d174b8e --- /dev/null +++ b/usr/klibc/__signal.c @@ -0,0 +1,20 @@ +/* + * __signal.c + */ + +#include + +__sighandler_t __signal(int signum, __sighandler_t handler, int flags) +{ + struct sigaction sa; + + sa.sa_handler = handler; + sa.sa_flags = flags; + sigemptyset(&sa.sa_mask); + + if (sigaction(signum, &sa, &sa)) { + return (__sighandler_t) SIG_ERR; + } else { + return (__sighandler_t) sa.sa_handler; + } +} diff --git a/usr/klibc/__static_init.c b/usr/klibc/__static_init.c new file mode 100644 index 0000000..0b59eed --- /dev/null +++ b/usr/klibc/__static_init.c @@ -0,0 +1,2 @@ +#define SHARED 0 +#include "libc_init.c" diff --git a/usr/klibc/abort.c b/usr/klibc/abort.c new file mode 100644 index 0000000..4629a17 --- /dev/null +++ b/usr/klibc/abort.c @@ -0,0 +1,18 @@ +/* + * abort.c + */ + +#include +#include +#include + +void abort(void) +{ + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGABRT); + sigprocmask(SIG_UNBLOCK, &set, NULL); + raise(SIGABRT); + _exit(255); /* raise() should have killed us */ +} diff --git a/usr/klibc/alarm.c b/usr/klibc/alarm.c new file mode 100644 index 0000000..8bd74c5 --- /dev/null +++ b/usr/klibc/alarm.c @@ -0,0 +1,25 @@ +/* + * alarm.c + */ + +#include +#include + +#ifndef __NR_alarm + +/* Emulate alarm() via setitimer() */ + +unsigned int alarm(unsigned int seconds) +{ + struct itimerval iv; + + iv.it_interval.tv_sec = iv.it_interval.tv_usec = 0; + iv.it_value.tv_sec = seconds; + iv.it_value.tv_usec = 0; + + setitimer(ITIMER_REAL, &iv, &iv); + + return iv.it_value.tv_sec + (iv.it_value.tv_usec ? 1 : 0); +} + +#endif diff --git a/usr/klibc/arch/README b/usr/klibc/arch/README new file mode 100644 index 0000000..662b9d3 --- /dev/null +++ b/usr/klibc/arch/README @@ -0,0 +1,81 @@ +To port klibc to a new architecture, you need: + +a) A directory structure + +Each archtecture has a klibc/arch/ directory, which should include an +MCONFIG and a Makefile.inc file, and an include/arch/ directory, which +includes some architecture-specific header files, including +klibc/archconfig.h. + + +b) Architecture-specific configuration + (include/arch/*/klibc/sysconfig.h) + +This file can set configuration variables from +include/klibc/sysconfig.h. + + +c) Startup code + (klibc/arch/*/crt0.S) + +The crt0.S assembly routine typically corresponds to the following +pseudo-C code. In addition, each architecture needs any support +routines that gcc-generated code expects to find in the system library +-- Alpha, for example, needs divide subroutines. + +The "getenvtest" test program is a very good test for proper crt0.S +functionality. + + +extern __noreturn __libc_init(void *, void *); + +__noreturn _start(void) +{ + void *elf_data = get_elf_data_address(); /* Usually the stack address */ + void *atexit_ptr = get_atexit_ptr(); /* Usually in a register */ + + /* Some architectures need this for debugging to work */ + setup_null_stack_frame_if_necessary(); + + __libc_init(elf_data, atexit_ptr); +} + + +d) A setenv implementation + (klibc/arch/*/setjmp.S, include/arch/*klibc/archsetjmp.h) + +On most (but not all!) architectures, this entails creating a setjmp +buffer big enough to hold all callee-saved registers, plus the stack +pointer and the return address. In setjmp.S you have: + +* A "setjmp" function that writes out the callee-saved registers, the + stack pointer and the return address to the buffer pointed to by the + first argument, and then returns zero normally. + + On some architectures you need to take some kind of action to make + sure the contents of the stack is actually manifest in memory and + not cached in the CPU. In some cases (e.g. on SPARC) this will + automatically spill the registers onto the stack; then they don't + need to be spilled into the jmp_buf. + +* A "longjmp" function that read back these same registers from the + jmp_buf pointed to by the first argument, and returns the second + argument *to the address specified in the jmp_buf*. + + On some architectures you need to take some kind of action to flush + any cached stack data or return stack. + + +e) Any support functions needed by gcc, *unless* they are in libgcc + *and* libgcc is usable for klibc on your particular platform. If + libgcc isn't usable for klibc (on MIPS, for example, libgcc is + compiled in a way that is not compatible with klibc) there are + reasonably good clones of most of the libgcc functions in the libgcc + directory. To use them, add them to ARCHOBJS in + klibc/arch/*/Makefile.inc. + + +f) A link location for the shared klibc. This should be specified in + SHAREDFLAGS in klibc/arch/*/MCONFIG. + + This is not applicable to no-MMU architectures. diff --git a/usr/klibc/asprintf.c b/usr/klibc/asprintf.c new file mode 100644 index 0000000..a3f5f00 --- /dev/null +++ b/usr/klibc/asprintf.c @@ -0,0 +1,30 @@ +/* + * asprintf.c + */ + +#include +#include +#include + +int asprintf(char **bufp, const char *format, ...) +{ + va_list ap, ap1; + int rv; + int bytes; + char *p; + + va_start(ap, format); + va_copy(ap1, ap); + + bytes = vsnprintf(NULL, 0, format, ap1) + 1; + va_end(ap1); + + *bufp = p = malloc(bytes); + if (!p) + return -1; + + rv = vsnprintf(p, bytes, format, ap); + va_end(ap); + + return rv; +} diff --git a/usr/klibc/assert.c b/usr/klibc/assert.c new file mode 100644 index 0000000..cca4129 --- /dev/null +++ b/usr/klibc/assert.c @@ -0,0 +1,14 @@ +/* + * assert.c + */ + +#include +#include +#include +#include + +__noreturn __assert_fail(const char *expr, const char *file, unsigned int line) +{ + printf("Assertion %s failed, file %s, line %u\n", expr, file, line); + abort(); +} diff --git a/usr/klibc/atexit.c b/usr/klibc/atexit.c new file mode 100644 index 0000000..af1b461 --- /dev/null +++ b/usr/klibc/atexit.c @@ -0,0 +1,10 @@ +/* + * atexit.c + */ + +#include + +int atexit(void (*fctn) (void)) +{ + return on_exit((void (*)(int, void *))fctn, NULL); +} diff --git a/usr/klibc/atexit.h b/usr/klibc/atexit.h new file mode 100644 index 0000000..5018689 --- /dev/null +++ b/usr/klibc/atexit.h @@ -0,0 +1,18 @@ +/* + * atexit.h + * + * atexit()/on_exit() internal definitions + */ + +#ifndef ATEXIT_H +#define ATEXIT_H + +struct atexit { + void (*fctn) (int, void *); + void *arg; /* on_exit() parameter */ + struct atexit *next; +}; + +extern struct atexit *__atexit_list; + +#endif /* ATEXIT_H */ diff --git a/usr/klibc/atoi.c b/usr/klibc/atoi.c new file mode 100644 index 0000000..a6ec0bf --- /dev/null +++ b/usr/klibc/atoi.c @@ -0,0 +1,3 @@ +#define TYPE int +#define NAME atoi +#include "atox.c" diff --git a/usr/klibc/atol.c b/usr/klibc/atol.c new file mode 100644 index 0000000..e65484e --- /dev/null +++ b/usr/klibc/atol.c @@ -0,0 +1,3 @@ +#define TYPE long +#define NAME atol +#include "atox.c" diff --git a/usr/klibc/atoll.c b/usr/klibc/atoll.c new file mode 100644 index 0000000..25df79e --- /dev/null +++ b/usr/klibc/atoll.c @@ -0,0 +1,3 @@ +#define TYPE long long +#define NAME atoll +#include "atox.c" diff --git a/usr/klibc/atox.c b/usr/klibc/atox.c new file mode 100644 index 0000000..c013bb4 --- /dev/null +++ b/usr/klibc/atox.c @@ -0,0 +1,14 @@ +/* + * atox.c + * + * atoi(), atol(), atoll() + */ + +#include +#include +#include + +TYPE NAME(const char *nptr) +{ + return (TYPE) strntoumax(nptr, (char **)NULL, 10, ~(size_t) 0); +} diff --git a/usr/klibc/brk.c b/usr/klibc/brk.c new file mode 100644 index 0000000..ceb42b0 --- /dev/null +++ b/usr/klibc/brk.c @@ -0,0 +1,24 @@ +/* brk.c - Change data segment size */ + +/* Written 2000 by Werner Almesberger */ + +#include +#include +#include + +char *__current_brk; /* Common with sbrk.c */ + +/* + * The Linux brk() isn't what most people expect, so we call the + * system call __brk() and provide a wrapper. + */ +int brk(void *end_data_segment) +{ + char *new_brk; + + new_brk = __brk(end_data_segment); + if (new_brk != end_data_segment) + return -1; + __current_brk = new_brk; + return 0; +} diff --git a/usr/klibc/bsd_signal.c b/usr/klibc/bsd_signal.c new file mode 100644 index 0000000..4e6238c --- /dev/null +++ b/usr/klibc/bsd_signal.c @@ -0,0 +1,11 @@ +/* + * bsd_signal.c + */ + +#include + +__sighandler_t bsd_signal(int signum, __sighandler_t handler) +{ + /* BSD signal() semantics */ + return __signal(signum, handler, SA_RESTART); +} diff --git a/usr/klibc/bsearch.c b/usr/klibc/bsearch.c new file mode 100644 index 0000000..1c8b07f --- /dev/null +++ b/usr/klibc/bsearch.c @@ -0,0 +1,26 @@ +/* + * bsearch.c + */ + +#include + +void *bsearch(const void *key, const void *base, size_t nmemb, + size_t size, int (*cmp) (const void *, const void *)) +{ + while (nmemb) { + size_t mididx = nmemb / 2; + const void *midobj = base + mididx * size; + int diff = cmp(key, midobj); + + if (diff == 0) + return (void *)midobj; + + if (diff > 0) { + base = midobj + size; + nmemb -= mididx + 1; + } else + nmemb = mididx; + } + + return NULL; +} diff --git a/usr/klibc/calloc.c b/usr/klibc/calloc.c new file mode 100644 index 0000000..3db7664 --- /dev/null +++ b/usr/klibc/calloc.c @@ -0,0 +1,20 @@ +/* + * calloc.c + */ + +#include +#include + +/* FIXME: This should look for multiplication overflow */ + +void *calloc(size_t nmemb, size_t size) +{ + void *ptr; + + size *= nmemb; + ptr = malloc(size); + if (ptr) + memset(ptr, 0, size); + + return ptr; +} diff --git a/usr/klibc/clearenv.c b/usr/klibc/clearenv.c new file mode 100644 index 0000000..7c2435e --- /dev/null +++ b/usr/klibc/clearenv.c @@ -0,0 +1,17 @@ +/* + * clearenv.c + * + * Empty the environment + */ + +#include +#include +#include "env.h" + +/* Note: if environ has been malloc'd, it will be freed on the next + setenv() or putenv() */ +int clearenv(void) +{ + environ = (char **)__null_environ; + return 0; +} diff --git a/usr/klibc/closelog.c b/usr/klibc/closelog.c new file mode 100644 index 0000000..0437710 --- /dev/null +++ b/usr/klibc/closelog.c @@ -0,0 +1,18 @@ +/* + * closelog.c + */ + +#include +#include + +extern int __syslog_fd; + +void closelog(void) +{ + int logfd = __syslog_fd; + + if (logfd != -1) { + close(logfd); + __syslog_fd = -1; + } +} diff --git a/usr/klibc/creat.c b/usr/klibc/creat.c new file mode 100644 index 0000000..b503bca --- /dev/null +++ b/usr/klibc/creat.c @@ -0,0 +1,12 @@ +/* + * creat.c + */ + +#include +#include +#include + +int creat(const char *pathname, mode_t mode) +{ + return open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode); +} diff --git a/usr/klibc/ctype/ctypefunc.h b/usr/klibc/ctype/ctypefunc.h new file mode 100644 index 0000000..f9e247d --- /dev/null +++ b/usr/klibc/ctype/ctypefunc.h @@ -0,0 +1,13 @@ +/* + * ctype/ctype.h + * + * Common header for out-of-line ctype functions + */ + +#define __CTYPE_NO_INLINE +#include + +#define CTYPEFUNC(X) \ + int X(int c) { \ + return __ctype_##X(c); \ + } diff --git a/usr/klibc/ctype/isalnum.c b/usr/klibc/ctype/isalnum.c new file mode 100644 index 0000000..57af18b --- /dev/null +++ b/usr/klibc/ctype/isalnum.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isalnum) diff --git a/usr/klibc/ctype/isalpha.c b/usr/klibc/ctype/isalpha.c new file mode 100644 index 0000000..8f2effe --- /dev/null +++ b/usr/klibc/ctype/isalpha.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isalpha) diff --git a/usr/klibc/ctype/isascii.c b/usr/klibc/ctype/isascii.c new file mode 100644 index 0000000..6a974d5 --- /dev/null +++ b/usr/klibc/ctype/isascii.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isascii) diff --git a/usr/klibc/ctype/isblank.c b/usr/klibc/ctype/isblank.c new file mode 100644 index 0000000..7728550 --- /dev/null +++ b/usr/klibc/ctype/isblank.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isblank) diff --git a/usr/klibc/ctype/iscntrl.c b/usr/klibc/ctype/iscntrl.c new file mode 100644 index 0000000..81db804 --- /dev/null +++ b/usr/klibc/ctype/iscntrl.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(iscntrl) diff --git a/usr/klibc/ctype/isdigit.c b/usr/klibc/ctype/isdigit.c new file mode 100644 index 0000000..41a39d9 --- /dev/null +++ b/usr/klibc/ctype/isdigit.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isdigit) diff --git a/usr/klibc/ctype/isgraph.c b/usr/klibc/ctype/isgraph.c new file mode 100644 index 0000000..e5b83d1 --- /dev/null +++ b/usr/klibc/ctype/isgraph.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isgraph) diff --git a/usr/klibc/ctype/islower.c b/usr/klibc/ctype/islower.c new file mode 100644 index 0000000..9e179ae --- /dev/null +++ b/usr/klibc/ctype/islower.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(islower) diff --git a/usr/klibc/ctype/isprint.c b/usr/klibc/ctype/isprint.c new file mode 100644 index 0000000..9c6a351 --- /dev/null +++ b/usr/klibc/ctype/isprint.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isprint) diff --git a/usr/klibc/ctype/ispunct.c b/usr/klibc/ctype/ispunct.c new file mode 100644 index 0000000..36b5258 --- /dev/null +++ b/usr/klibc/ctype/ispunct.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(ispunct) diff --git a/usr/klibc/ctype/isspace.c b/usr/klibc/ctype/isspace.c new file mode 100644 index 0000000..aed06c8 --- /dev/null +++ b/usr/klibc/ctype/isspace.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isspace) diff --git a/usr/klibc/ctype/isupper.c b/usr/klibc/ctype/isupper.c new file mode 100644 index 0000000..70a139b --- /dev/null +++ b/usr/klibc/ctype/isupper.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isupper) diff --git a/usr/klibc/ctype/isxdigit.c b/usr/klibc/ctype/isxdigit.c new file mode 100644 index 0000000..ab89c1f --- /dev/null +++ b/usr/klibc/ctype/isxdigit.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(isxdigit) diff --git a/usr/klibc/ctype/tolower.c b/usr/klibc/ctype/tolower.c new file mode 100644 index 0000000..24ca72b --- /dev/null +++ b/usr/klibc/ctype/tolower.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(tolower) diff --git a/usr/klibc/ctype/toupper.c b/usr/klibc/ctype/toupper.c new file mode 100644 index 0000000..15763f7 --- /dev/null +++ b/usr/klibc/ctype/toupper.c @@ -0,0 +1,2 @@ +#include "ctypefunc.h" +CTYPEFUNC(toupper) diff --git a/usr/klibc/ctypes.c b/usr/klibc/ctypes.c new file mode 100644 index 0000000..deb566a --- /dev/null +++ b/usr/klibc/ctypes.c @@ -0,0 +1,284 @@ +/* + * ctypes.c + * + * This is the array that defines classes. + * This assumes ISO 8859-1. + */ + +#include + +const unsigned char __ctypes[257] = { + 0, /* EOF */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl | __ctype_space, /* BS */ + __ctype_cntrl | __ctype_space, /* TAB */ + __ctype_cntrl | __ctype_space, /* LF */ + __ctype_cntrl | __ctype_space, /* VT */ + __ctype_cntrl | __ctype_space, /* FF */ + __ctype_cntrl | __ctype_space, /* CR */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_print | __ctype_space, /* space */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_digit | __ctype_xdigit, /* digit */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper | __ctype_xdigit, /* A-F */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_upper, /* G-Z */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower | __ctype_xdigit, /* a-f */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_lower, /* g-z */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + __ctype_cntrl, /* control character */ + + __ctype_print | __ctype_space, /* NBSP */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_punct, /* punctuation */ + + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_upper, /* upper accented */ + __ctype_print | __ctype_lower, /* lower accented */ + + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_punct, /* punctuation */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ + __ctype_print | __ctype_lower, /* lower accented */ +}; diff --git a/usr/klibc/daemon.c b/usr/klibc/daemon.c new file mode 100644 index 0000000..61b88dd --- /dev/null +++ b/usr/klibc/daemon.c @@ -0,0 +1,35 @@ +/* + * daemon.c - "daemonize" a process + */ + +#include +#include +#include + +int daemon(int nochdir, int noclose) +{ + int nullfd; + pid_t f; + + if (!nochdir) { + if (chdir("/")) + return -1; + } + + if (!noclose) { + if ((nullfd = open("/dev/null", O_RDWR)) < 0 || + dup2(nullfd, 0) < 0 || + dup2(nullfd, 1) < 0 || + dup2(nullfd, 2) < 0) + return -1; + close(nullfd); + } + + f = fork(); + if (f < 0) + return -1; + else if (f > 0) + _exit(0); + + return setsid(); +} diff --git a/usr/klibc/env.h b/usr/klibc/env.h new file mode 100644 index 0000000..ae70be8 --- /dev/null +++ b/usr/klibc/env.h @@ -0,0 +1,10 @@ +#ifndef ENV_H +#define ENV_H + +/* str should be a duplicated version of the input string; + len is the length of the key including the = sign */ +int __put_env(char *str, size_t len, int overwrite); + +extern char *const __null_environ[]; + +#endif diff --git a/usr/klibc/exec_l.c b/usr/klibc/exec_l.c new file mode 100644 index 0000000..76b70df --- /dev/null +++ b/usr/klibc/exec_l.c @@ -0,0 +1,59 @@ +/* + * exec_l.c + * + * Common implementation of execl() execle() execlp() + */ + +#include +#include +#include + +int NAME(const char *path, const char *arg0, ...) +{ + va_list ap, cap; + int argc = 1, rv; + const char **argv, **argp; + const char *arg; + char *const *envp; + + va_start(ap, arg0); + va_copy(cap, ap); + + /* Count the number of arguments */ + do { + arg = va_arg(cap, const char *); + argc++; + } while (arg); + + va_end(cap); + + /* Allocate memory for the pointer array */ + argp = argv = alloca(argc * sizeof(const char *)); + if (!argv) { + va_end(ap); + return -1; + } + + /* Copy the list into an array */ + *argp++ = arg0; + do { + *argp++ = arg = va_arg(ap, const char *); + } while (arg); + +#if EXEC_E + /* execle() takes one more argument for the environment pointer */ + envp = va_arg(ap, char *const *); +#else + envp = environ; +#endif + +#if EXEC_P + rv = execvpe(path, (char * const *)argv, envp); +#else + rv = execve(path, (char * const *)argv, envp); +#endif + + va_end(ap); + + return rv; +} diff --git a/usr/klibc/execl.c b/usr/klibc/execl.c new file mode 100644 index 0000000..4581113 --- /dev/null +++ b/usr/klibc/execl.c @@ -0,0 +1,8 @@ +/* + * execl.c + */ + +#define NAME execl +#define EXEC_P 0 +#define EXEC_E 0 +#include "exec_l.c" diff --git a/usr/klibc/execle.c b/usr/klibc/execle.c new file mode 100644 index 0000000..b073988 --- /dev/null +++ b/usr/klibc/execle.c @@ -0,0 +1,8 @@ +/* + * execle.c + */ + +#define NAME execle +#define EXEC_P 0 +#define EXEC_E 1 +#include "exec_l.c" diff --git a/usr/klibc/execlp.c b/usr/klibc/execlp.c new file mode 100644 index 0000000..65c9aa4 --- /dev/null +++ b/usr/klibc/execlp.c @@ -0,0 +1,8 @@ +/* + * execlp.c + */ + +#define NAME execlp +#define EXEC_P 1 +#define EXEC_E 0 +#include "exec_l.c" diff --git a/usr/klibc/execlpe.c b/usr/klibc/execlpe.c new file mode 100644 index 0000000..fef972f --- /dev/null +++ b/usr/klibc/execlpe.c @@ -0,0 +1,8 @@ +/* + * execlpe.c + */ + +#define NAME execlpe +#define EXEC_P 1 +#define EXEC_E 1 +#include "exec_l.c" diff --git a/usr/klibc/execv.c b/usr/klibc/execv.c new file mode 100644 index 0000000..29e5737 --- /dev/null +++ b/usr/klibc/execv.c @@ -0,0 +1,11 @@ +/* + * execv.c + */ + +#include +#include + +int execv(const char *path, char *const *argv) +{ + return execve(path, argv, environ); +} diff --git a/usr/klibc/execvp.c b/usr/klibc/execvp.c new file mode 100644 index 0000000..5a9f31d --- /dev/null +++ b/usr/klibc/execvp.c @@ -0,0 +1,11 @@ +/* + * execvp.c + */ + +#include +#include + +int execvp(const char *path, char *const *argv) +{ + return execvpe(path, argv, environ); +} diff --git a/usr/klibc/execvpe.c b/usr/klibc/execvpe.c new file mode 100644 index 0000000..0b844f2 --- /dev/null +++ b/usr/klibc/execvpe.c @@ -0,0 +1,75 @@ +/* + * execvpe.c + * + * execvpe() function (from which we build execlp, execlpe, execvp). + * + * This version of execvpe() will *not* spawn /bin/sh if the command + * return ENOEXEC. That's what #! is for, folks! + * + * Since execlpe() and execvpe() aren't in POSIX, nor in glibc, + * I have followed QNX precedent in the implementation of the PATH: + * the PATH that is used is the one in the current environment, not + * in the new environment. Otherwise it would be impossible to pass + * a different PATH to the new process than the one one would want to + * use to search. + */ + +#include +#include +#include +#include +#include + +#define DEFAULT_PATH "/bin:/usr/bin:." + +int execvpe(const char *file, char *const *argv, char *const *envp) +{ + char path[PATH_MAX]; + const char *searchpath, *esp; + size_t prefixlen, filelen, totallen; + + if (strchr(file, '/')) /* Specific path */ + return execve(file, argv, envp); + + filelen = strlen(file); + + searchpath = getenv("PATH"); + if (!searchpath) + searchpath = DEFAULT_PATH; + + errno = ENOENT; /* Default errno, if execve() doesn't + change it */ + + do { + esp = strchr(searchpath, ':'); + if (esp) + prefixlen = esp - searchpath; + else + prefixlen = strlen(searchpath); + + if (prefixlen == 0 || searchpath[prefixlen - 1] == '/') { + totallen = prefixlen + filelen; + if (totallen >= PATH_MAX) + continue; + memcpy(path, searchpath, prefixlen); + memcpy(path + prefixlen, file, filelen); + } else { + totallen = prefixlen + filelen + 1; + if (totallen >= PATH_MAX) + continue; + memcpy(path, searchpath, prefixlen); + path[prefixlen] = '/'; + memcpy(path + prefixlen + 1, file, filelen); + } + path[totallen] = '\0'; + + execve(path, argv, envp); + if (errno == E2BIG || errno == ENOEXEC || + errno == ENOMEM || errno == ETXTBSY) + break; /* Report this as an error, no more search */ + + searchpath = esp + 1; + } while (esp); + + return -1; +} diff --git a/usr/klibc/exit.c b/usr/klibc/exit.c new file mode 100644 index 0000000..92f11c5 --- /dev/null +++ b/usr/klibc/exit.c @@ -0,0 +1,30 @@ +/* + * exit.c + * + * exit(), including the handling of the atexit chain. + */ + +#include +#include +#include +#include "atexit.h" + +/* Link chain for atexit/on_exit */ +struct atexit *__atexit_list; + +__noreturn exit(int rv) +{ + struct atexit *ap; + + for (ap = __atexit_list; ap; ap = ap->next) { + /* This assumes extra args are harmless. They should + be in all normal C ABIs, but if an architecture has + some particularly bizarre ABI this might be worth + watching out for. */ + ap->fctn(rv, ap->arg); + } + + /* Handle any library destructors if we ever start using them... */ + + _exit(rv); +} diff --git a/usr/klibc/fgetc.c b/usr/klibc/fgetc.c new file mode 100644 index 0000000..9092eae --- /dev/null +++ b/usr/klibc/fgetc.c @@ -0,0 +1,19 @@ +/* + * fgetc.c + * + * Extremely slow fgetc implementation, using _fread(). If people + * actually need character-oriented input to be fast, we may actually + * have to implement buffering. Sigh. + */ + +#include +#include +#include +#include + +int fgetc(FILE *f) +{ + unsigned char ch; + + return (_fread(&ch, 1, f) == 1) ? (int)ch : EOF; +} diff --git a/usr/klibc/fgets.c b/usr/klibc/fgets.c new file mode 100644 index 0000000..4e9cf68 --- /dev/null +++ b/usr/klibc/fgets.c @@ -0,0 +1,31 @@ +/* + * fgets.c + * + * This will be very slow due to the implementation of getc(), + * but we don't have anywhere to put characters we don't need from + * the input. + */ + +#include + +char *fgets(char *s, int n, FILE *f) +{ + int ch; + char *p = s; + + while (n > 1) { + ch = getc(f); + if (ch == EOF) { + *p = '\0'; + return NULL; + } + *p++ = ch; + n--; + if (ch == '\n') + break; + } + if (n) + *p = '\0'; + + return s; +} diff --git a/usr/klibc/fopen.c b/usr/klibc/fopen.c new file mode 100644 index 0000000..6fa80d7 --- /dev/null +++ b/usr/klibc/fopen.c @@ -0,0 +1,39 @@ +/* + * fopen.c + */ + +#include +#include +#include + +/* This depends on O_RDONLY == 0, O_WRONLY == 1, O_RDWR == 2 */ + +FILE *fopen(const char *file, const char *mode) +{ + int flags = O_RDONLY; + int plus = 0; + + while (*mode) { + switch (*mode++) { + case 'r': + flags = O_RDONLY; + break; + case 'w': + flags = O_WRONLY | O_CREAT | O_TRUNC; + break; + case 'a': + flags = O_WRONLY | O_CREAT | O_APPEND; + break; + case '+': + plus = 1; + break; + } + } + + if (plus) { + flags = (flags & ~(O_RDONLY | O_WRONLY)) | O_RDWR; + } + + /* Note: __create_file(-1) == NULL, so this is safe */ + return __create_file(open(file, flags, 0666)); +} diff --git a/usr/klibc/fork.c b/usr/klibc/fork.c new file mode 100644 index 0000000..b07486e --- /dev/null +++ b/usr/klibc/fork.c @@ -0,0 +1,21 @@ +/* + * fork.c + * + * This is normally just a syscall stub, but at least one system + * doesn't have sys_fork, only sys_clone... + */ + +#include +#include +#include +#include +#include + +#if !_KLIBC_NO_MMU && !defined(__NR_fork) + +pid_t fork(void) +{ + return __clone(SIGCHLD, 0); +} + +#endif /* __NR_fork */ diff --git a/usr/klibc/fprintf.c b/usr/klibc/fprintf.c new file mode 100644 index 0000000..8403923 --- /dev/null +++ b/usr/klibc/fprintf.c @@ -0,0 +1,19 @@ +/* + * fprintf.c + */ + +#include +#include + +#define BUFFER_SIZE 16384 + +int fprintf(FILE * file, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vfprintf(file, format, ap); + va_end(ap); + return rv; +} diff --git a/usr/klibc/fputc.c b/usr/klibc/fputc.c new file mode 100644 index 0000000..386d86c --- /dev/null +++ b/usr/klibc/fputc.c @@ -0,0 +1,14 @@ +/* + * fputc.c + * + * gcc "printf decompilation" expects this to exist... + */ + +#include + +int fputc(int c, FILE *f) +{ + unsigned char ch = c; + + return _fwrite(&ch, 1, f) == 1 ? ch : EOF; +} diff --git a/usr/klibc/fputs.c b/usr/klibc/fputs.c new file mode 100644 index 0000000..fb240d6 --- /dev/null +++ b/usr/klibc/fputs.c @@ -0,0 +1,15 @@ +/* + * fputs.c + * + * This isn't quite fputs() in the stdio sense, since we don't + * have stdio, but it takes a file descriptor argument instead + * of the FILE *. + */ + +#include +#include + +int fputs(const char *s, FILE *file) +{ + return _fwrite(s, strlen(s), file); +} diff --git a/usr/klibc/fread.c b/usr/klibc/fread.c new file mode 100644 index 0000000..b9433aa --- /dev/null +++ b/usr/klibc/fread.c @@ -0,0 +1,33 @@ +/* + * fread.c + */ + +#include +#include +#include + +size_t _fread(void *buf, size_t count, FILE *f) +{ + size_t bytes = 0; + ssize_t rv; + char *p = buf; + + while (count) { + rv = read(fileno(f), p, count); + if (rv == -1) { + if (errno == EINTR) { + errno = 0; + continue; + } else + break; + } else if (rv == 0) { + break; + } + + p += rv; + bytes += rv; + count -= rv; + } + + return bytes; +} diff --git a/usr/klibc/fread2.c b/usr/klibc/fread2.c new file mode 100644 index 0000000..c9c6ed8 --- /dev/null +++ b/usr/klibc/fread2.c @@ -0,0 +1,13 @@ +/* + * fread2.c + * + * The actual fread() function as a non-inline + */ + +#define __NO_FREAD_FWRITE_INLINES +#include + +size_t fread(void *ptr, size_t size, size_t nmemb, FILE * f) +{ + return _fread(ptr, size * nmemb, f) / size; +} diff --git a/usr/klibc/fstatfs.c b/usr/klibc/fstatfs.c new file mode 100644 index 0000000..614f2ec --- /dev/null +++ b/usr/klibc/fstatfs.c @@ -0,0 +1,19 @@ +/* + * fstatfs.c + * + * On architectures which do fstatfs64, wrap the system call + */ + +#include +#include + +#ifdef __NR_fstatfs64 + +extern int __fstatfs64(int, size_t, struct statfs *); + +int fstatfs(int fd, struct statfs *buf) +{ + return __fstatfs64(fd, sizeof *buf, buf); +} + +#endif diff --git a/usr/klibc/fwrite.c b/usr/klibc/fwrite.c new file mode 100644 index 0000000..cba8de8 --- /dev/null +++ b/usr/klibc/fwrite.c @@ -0,0 +1,33 @@ +/* + * fwrite.c + */ + +#include +#include +#include + +size_t _fwrite(const void *buf, size_t count, FILE *f) +{ + size_t bytes = 0; + ssize_t rv; + const char *p = buf; + + while (count) { + rv = write(fileno(f), p, count); + if (rv == -1) { + if (errno == EINTR) { + errno = 0; + continue; + } else + break; + } else if (rv == 0) { + break; + } + + p += rv; + bytes += rv; + count -= rv; + } + + return bytes; +} diff --git a/usr/klibc/fwrite2.c b/usr/klibc/fwrite2.c new file mode 100644 index 0000000..b5ab0a4 --- /dev/null +++ b/usr/klibc/fwrite2.c @@ -0,0 +1,13 @@ +/* + * fwrite2.c + * + * The actual fwrite() function as a non-inline + */ + +#define __NO_FREAD_FWRITE_INLINES +#include + +size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE * f) +{ + return _fwrite(ptr, size * nmemb, f) / size; +} diff --git a/usr/klibc/getcwd.c b/usr/klibc/getcwd.c new file mode 100644 index 0000000..22ec812 --- /dev/null +++ b/usr/klibc/getcwd.c @@ -0,0 +1,15 @@ +/* + * getcwd.c + * + * The system call behaves differently than the library function. + */ + +#include +#include + +extern int __getcwd(char *buf, size_t size); + +char *getcwd(char *buf, size_t size) +{ + return (__getcwd(buf, size) < 0) ? NULL : buf; +} diff --git a/usr/klibc/getdomainname.c b/usr/klibc/getdomainname.c new file mode 100644 index 0000000..61722ca --- /dev/null +++ b/usr/klibc/getdomainname.c @@ -0,0 +1,25 @@ +/* + * getdomainname.c + */ + +#include +#include +#include +#include + +int getdomainname(char *name, size_t len) +{ + struct utsname un; + + if (!uname(&un)) + return -1; + + if (len < strlen(un.domainname) + 1) { + errno = EINVAL; + return -1; + } + + strcpy(name, un.domainname); + + return 0; +} diff --git a/usr/klibc/getenv.c b/usr/klibc/getenv.c new file mode 100644 index 0000000..3a4ae5e --- /dev/null +++ b/usr/klibc/getenv.c @@ -0,0 +1,24 @@ +/* + * getenv.c + */ + +#include +#include +#include + +char *getenv(const char *name) +{ + char **p, *q; + int len = strlen(name); + + if (!environ) + return NULL; + + for (p = environ; (q = *p); p++) { + if (!strncmp(name, q, len) && q[len] == '=') { + return q + (len + 1); + } + } + + return NULL; +} diff --git a/usr/klibc/gethostname.c b/usr/klibc/gethostname.c new file mode 100644 index 0000000..5326b5f --- /dev/null +++ b/usr/klibc/gethostname.c @@ -0,0 +1,25 @@ +/* + * gethostname.c + */ + +#include +#include +#include +#include + +int gethostname(char *name, size_t len) +{ + struct utsname un; + + if (!uname(&un)) + return -1; + + if (len < strlen(un.nodename) + 1) { + errno = EINVAL; + return -1; + } + + strcpy(name, un.nodename); + + return 0; +} diff --git a/usr/klibc/getopt.c b/usr/klibc/getopt.c new file mode 100644 index 0000000..806735d --- /dev/null +++ b/usr/klibc/getopt.c @@ -0,0 +1,97 @@ +/* + * getopt.c + * + * Simple POSIX getopt(), no GNU extensions... + */ + +#include +#include +#include + +char *optarg; +int optind, opterr, optopt; +static struct getopt_private_state { + const char *optptr; + const char *last_optstring; + char *const *last_argv; +} pvt; + +int getopt(int argc, char *const *argv, const char *optstring) +{ + const char *carg; + const char *osptr; + int opt; + + /* getopt() relies on a number of different global state + variables, which can make this really confusing if there is + more than one use of getopt() in the same program. This + attempts to detect that situation by detecting if the + "optstring" or "argv" argument have changed since last time + we were called; if so, reinitialize the query state. */ + + if (optstring != pvt.last_optstring || argv != pvt.last_argv || + optind < 1 || optind > argc) { + /* optind doesn't match the current query */ + pvt.last_optstring = optstring; + pvt.last_argv = argv; + optind = 1; + pvt.optptr = NULL; + } + + carg = argv[optind]; + + /* First, eliminate all non-option cases */ + + if (!carg || carg[0] != '-' || !carg[1]) { + return -1; + } + + if (carg[1] == '-' && !carg[2]) { + optind++; + return -1; + } + + if ((uintptr_t) (pvt.optptr - carg) > (uintptr_t) strlen(carg)) { + /* Someone frobbed optind, change to new opt. */ + pvt.optptr = carg + 1; + } + + opt = *pvt.optptr++; + + if (opt != ':' && (osptr = strchr(optstring, opt))) { + if (osptr[1] == ':') { + if (*pvt.optptr) { + /* Argument-taking option with attached + argument */ + optarg = (char *)pvt.optptr; + optind++; + } else { + /* Argument-taking option with non-attached + argument */ + if (argv[optind + 1]) { + optarg = (char *)argv[optind+1]; + optind += 2; + } else { + /* Missing argument */ + optind++; + return (optstring[0] == ':') + ? ':' : '?'; + } + } + return opt; + } else { + /* Non-argument-taking option */ + /* pvt.optptr will remember the exact position to + resume at */ + if (!*pvt.optptr) + optind++; + return opt; + } + } else { + /* Unknown option */ + optopt = opt; + if (!*pvt.optptr) + optind++; + return '?'; + } +} diff --git a/usr/klibc/getpgrp.c b/usr/klibc/getpgrp.c new file mode 100644 index 0000000..b20b17a --- /dev/null +++ b/usr/klibc/getpgrp.c @@ -0,0 +1,10 @@ +/* + * getpgrp.c + */ + +#include + +pid_t getpgrp(void) +{ + return getpgid(0); +} diff --git a/usr/klibc/getpriority.c b/usr/klibc/getpriority.c new file mode 100644 index 0000000..01d6e06 --- /dev/null +++ b/usr/klibc/getpriority.c @@ -0,0 +1,23 @@ +/* + * getpriority.c + * + * Needs to do some post-syscall mangling to distinguish error returns... + * but only on some platforms. Sigh. + */ + +#include +#include +#include +#include + +#if !defined(__alpha__) && !defined(__ia64__) + +extern int __getpriority(int, int); + +int getpriority(int which, int who) +{ + int rv = __getpriority(which, who); + return (rv < 0) ? rv : 20-rv; +} + +#endif diff --git a/usr/klibc/getpt.c b/usr/klibc/getpt.c new file mode 100644 index 0000000..76ca371 --- /dev/null +++ b/usr/klibc/getpt.c @@ -0,0 +1,17 @@ +/* + * getpt.c + * + * GNU extension to the standard Unix98 pty suite + */ + +#include +#include +#include +#include +#include +#include + +int getpt(void) +{ + return open("/dev/ptmx", O_RDWR | O_NOCTTY); +} diff --git a/usr/klibc/globals.c b/usr/klibc/globals.c new file mode 100644 index 0000000..72ae91f --- /dev/null +++ b/usr/klibc/globals.c @@ -0,0 +1,10 @@ +/* + * globals.c + * + * These have to be defined somewhere... + */ +#include +#include + +int errno; +char **environ; diff --git a/usr/klibc/inet/bindresvport.c b/usr/klibc/inet/bindresvport.c new file mode 100644 index 0000000..e22c1c2 --- /dev/null +++ b/usr/klibc/inet/bindresvport.c @@ -0,0 +1,46 @@ +/* + * inet/bindresvport.c + */ + +#include +#include +#include +#include +#include +#include + +#define START_PORT 768 +#define END_PORT IPPORT_RESERVED +#define NUM_PORTS (END_PORT - START_PORT) + +int bindresvport(int sd, struct sockaddr_in *sin) +{ + struct sockaddr_in me; + static short port; + int ret = 0; + int i; + + if (sin == NULL) { + memset(&me, 0, sizeof(me)); + sin = &me; + sin->sin_family = AF_INET; + } else if (sin->sin_family != AF_INET) { + errno = EPFNOSUPPORT; + return -1; + } + + if (port == 0) + port = START_PORT + (getpid() % NUM_PORTS); + + for (i = 0; i < NUM_PORTS; i++, port++) { + if (port == END_PORT) + port = START_PORT; + sin->sin_port = htons(port); + + ret = bind(sd, (struct sockaddr *)sin, sizeof(*sin)); + if (ret != -1) + break; + } + + return ret; +} diff --git a/usr/klibc/inet/inet_addr.c b/usr/klibc/inet/inet_addr.c new file mode 100644 index 0000000..2ef4535 --- /dev/null +++ b/usr/klibc/inet/inet_addr.c @@ -0,0 +1,14 @@ +/* + * inet/inet_addr.c + */ + +#include +#include + +uint32_t inet_addr(const char *str) +{ + struct in_addr a; + int rv = inet_aton(str, &a); + + return rv ? INADDR_NONE : a.s_addr; +} diff --git a/usr/klibc/inet/inet_aton.c b/usr/klibc/inet/inet_aton.c new file mode 100644 index 0000000..beceeea --- /dev/null +++ b/usr/klibc/inet/inet_aton.c @@ -0,0 +1,22 @@ +/* + * inet/inet_aton.c + */ + +#include +#include + +int inet_aton(const char *str, struct in_addr *addr) +{ + union { + uint8_t b[4]; + uint32_t l; + } a; + + if (sscanf(str, "%hhu.%hhu.%hhu.%hhu", + &a.b[0], &a.b[1], &a.b[2], &a.b[3]) == 4) { + addr->s_addr = a.l; /* Always in network byte order */ + return 1; + } else { + return 0; + } +} diff --git a/usr/klibc/inet/inet_ntoa.c b/usr/klibc/inet/inet_ntoa.c new file mode 100644 index 0000000..6dbf057 --- /dev/null +++ b/usr/klibc/inet/inet_ntoa.c @@ -0,0 +1,16 @@ +/* + * inet/inet_ntoa.c + */ + +#include +#include +#include + +char *inet_ntoa(struct in_addr addr) +{ + static char name[16]; + const uint8_t *cp = (const uint8_t *) &addr.s_addr; + + sprintf(name, "%u.%u.%u.%u", cp[0], cp[1], cp[2], cp[3]); + return name; +} diff --git a/usr/klibc/inet/inet_ntop.c b/usr/klibc/inet/inet_ntop.c new file mode 100644 index 0000000..ef31a18 --- /dev/null +++ b/usr/klibc/inet/inet_ntop.c @@ -0,0 +1,53 @@ +/* + * inet/inet_ntop.c + */ + +#include +#include +#include +#include +#include + +const char *inet_ntop(int af, const void *cp, char *buf, size_t len) +{ + size_t xlen; + + switch (af) { + case AF_INET: + { + const uint8_t *bp = (const uint8_t *) + &((const struct in_addr *)cp)->s_addr; + + xlen = snprintf(buf, len, "%u.%u.%u.%u", + bp[0], bp[1], bp[2], bp[3]); + } + break; + + case AF_INET6: + { + const struct in6_addr *s = (const struct in6_addr *)cp; + + xlen = snprintf(buf, len, "%x:%x:%x:%x:%x:%x:%x:%x", + ntohs(s->s6_addr16[0]), + ntohs(s->s6_addr16[1]), + ntohs(s->s6_addr16[2]), + ntohs(s->s6_addr16[3]), + ntohs(s->s6_addr16[4]), + ntohs(s->s6_addr16[5]), + ntohs(s->s6_addr16[6]), + ntohs(s->s6_addr16[7])); + } + break; + + default: + errno = EAFNOSUPPORT; + return NULL; + } + + if (xlen > len) { + errno = ENOSPC; + return NULL; + } + + return buf; +} diff --git a/usr/klibc/inet/inet_pton.c b/usr/klibc/inet/inet_pton.c new file mode 100644 index 0000000..19fe16e --- /dev/null +++ b/usr/klibc/inet/inet_pton.c @@ -0,0 +1,78 @@ +/* + * inet/inet_pton.c + */ + +#include +#include +#include +#include +#include +#include +#include + +static inline int hexval(int ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'A' && ch <= 'F') { + return ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'f') { + return ch - 'a' + 10; + } else { + return -1; + } +} + +int inet_pton(int af, const char *src, void *dst) +{ + switch (af) { + case AF_INET: + return inet_aton(src, (struct in_addr *)dst); + + case AF_INET6: + { + struct in6_addr *d = (struct in6_addr *)dst; + int colons = 0, dcolons = 0; + int i; + const char *p; + + /* A double colon will increment colons by 2, + dcolons by 1 */ + for (p = dst; *p; p++) { + if (p[0] == ':') { + colons++; + if (p[1] == ':') + dcolons++; + } else if (!isxdigit(*p)) + return 0; /* Invalid address */ + } + + if (colons > 7 || dcolons > 1 + || (!dcolons && colons != 7)) + return 0; /* Invalid address */ + + memset(d, 0, sizeof(struct in6_addr)); + + i = 0; + for (p = dst; *p; p++) { + if (*p == ':') { + if (p[1] == ':') { + i += (8 - colons); + } else { + i++; + } + } else { + d->s6_addr16[i] = + htons((ntohs(d->s6_addr16[i]) << 4) + + hexval(*p)); + } + } + + return 1; + } + + default: + errno = EAFNOSUPPORT; + return -1; + } +} diff --git a/usr/klibc/interp.S b/usr/klibc/interp.S new file mode 100644 index 0000000..4b15cfb --- /dev/null +++ b/usr/klibc/interp.S @@ -0,0 +1,13 @@ +# +# This is a hack to generate the .intrp section, which then +# ld turns into an PT_INTERP header. +# +# NOTE: The .interp section needs to be "a", or it doesnt work... +# + + .section ".interp","a" + .ascii LIBDIR + .ascii "/klibc-" + .ascii SOHASH + .ascii ".so" + .byte 0 diff --git a/usr/klibc/isatty.c b/usr/klibc/isatty.c new file mode 100644 index 0000000..b4a84b7 --- /dev/null +++ b/usr/klibc/isatty.c @@ -0,0 +1,20 @@ +/* + * isatty.c + */ + +#include +#include +#include + +int isatty(int fd) +{ + int old_errno = errno; + int istty; + pid_t dummy; + + /* All ttys support TIOCGPGRP */ + istty = !ioctl(fd, TIOCGPGRP, &dummy); + errno = old_errno; + + return istty; +} diff --git a/usr/klibc/jrand48.c b/usr/klibc/jrand48.c new file mode 100644 index 0000000..8e2b3ac --- /dev/null +++ b/usr/klibc/jrand48.c @@ -0,0 +1,24 @@ +/* + * jrand48.c + */ + +#include +#include + +long jrand48(unsigned short xsubi[3]) +{ + uint64_t x; + + /* The xsubi[] array is littleendian by spec */ + x = (uint64_t) (uint16_t) xsubi[0] + + ((uint64_t) (uint16_t) xsubi[1] << 16) + + ((uint64_t) (uint16_t) xsubi[2] << 32); + + x = (0x5deece66dULL * x) + 0xb; + + xsubi[0] = (unsigned short)(uint16_t) x; + xsubi[1] = (unsigned short)(uint16_t) (x >> 16); + xsubi[2] = (unsigned short)(uint16_t) (x >> 32); + + return (long)(int32_t) (x >> 16); +} diff --git a/usr/klibc/libc_init.c b/usr/klibc/libc_init.c new file mode 100644 index 0000000..55460ce --- /dev/null +++ b/usr/klibc/libc_init.c @@ -0,0 +1,107 @@ +/* + * libc_init.c + * + * This function takes the raw data block set up by the ELF loader + * in the kernel and parses it. It is invoked by crt0.S which makes + * any necessary adjustments and passes calls this function using + * the standard C calling convention. + * + * The arguments are: + * uintptr_t *elfdata -- The ELF loader data block; usually from the stack. + * Basically a pointer to argc. + * void (*onexit)(void) -- Function to install into onexit + */ + +/* + * Several Linux ABIs don't pass the onexit pointer, and the ones that + * do never use it. Therefore, unless USE_ONEXIT is defined, we just + * ignore the onexit pointer. + */ +/* #define USE_ONEXIT */ + +#include +#include +#include +#include +#include +#include "atexit.h" + +/* This file is included from __static_init.c or __shared_init.c */ +#ifndef SHARED +# error "SHARED should be defined to 0 or 1" +#endif + +char **environ; +unsigned int __page_size, __page_shift; + +struct auxentry { + uintptr_t type; + uintptr_t v; +}; + +__noreturn __libc_init(uintptr_t * elfdata, void (*onexit) (void)) +{ + int argc; + char **argv, **envp, **envend; + struct auxentry *auxentry; +#if SHARED + typedef int (*main_t) (int, char **, char **); + main_t MAIN = NULL; +#else + extern int main(int, char **, char **); +#define MAIN main +#endif + unsigned int page_size = 0, page_shift = 0; + +#ifdef USE_ONEXIT + if (onexit) { + static struct atexit at_exit; + + at_exit.fctn = (void (*)(int, void *))onexit; + /* at_exit.next = NULL already */ + __atexit_list = &at_exit; + } +#else + (void)onexit; /* Ignore this... */ +#endif + + argc = (int)*elfdata++; + argv = (char **)elfdata; + envp = argv + (argc + 1); + + /* The auxillary entry vector is after all the environment vars */ + for (envend = envp; *envend; envend++) ; + auxentry = (struct auxentry *)(envend + 1); + + while (auxentry->type) { + switch (auxentry->type) { +#if SHARED + case AT_ENTRY: + MAIN = (main_t) (auxentry->v); + break; +#endif + case AT_PAGESZ: + page_size = (unsigned int)(auxentry->v); + break; + } + auxentry++; + } + + __page_size = page_size; + +#if __GNUC__ >= 4 + /* unsigned int is 32 bits on all our architectures */ + page_shift = __builtin_clz(page_size) ^ 31; +#elif defined(__i386__) || defined(__x86_64__) + asm("bsrl %1,%0": "=r"(page_shift):"r"(page_size)); +#else + while (page_size > 1) { + page_shift++; + page_size >>= 1; + } +#endif + __page_shift = page_shift; + + environ = envp; + exit(MAIN(argc, argv, envp)); +} diff --git a/usr/klibc/libgcc/__ashldi3.c b/usr/klibc/libgcc/__ashldi3.c new file mode 100644 index 0000000..95937f0 --- /dev/null +++ b/usr/klibc/libgcc/__ashldi3.c @@ -0,0 +1,23 @@ +/* + * libgcc/__ashldi3.c + */ + +#include +#include + +uint64_t __ashldi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vh = (vl << c); + vl = 0; + } else { + vh = (vh << c) + (vl >> (32 - c)); + vl = (vl << c); + } + + return ((uint64_t) vh << 32) + vl; +} diff --git a/usr/klibc/libgcc/__ashrdi3.c b/usr/klibc/libgcc/__ashrdi3.c new file mode 100644 index 0000000..14e6d18 --- /dev/null +++ b/usr/klibc/libgcc/__ashrdi3.c @@ -0,0 +1,23 @@ +/* + * libgcc/__ashrdi3.c + */ + +#include +#include + +uint64_t __ashrdi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vl = ((int32_t) vh >> c); + vh = (int32_t) vh >> 31; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = ((int32_t) vh >> c); + } + + return ((uint64_t) vh << 32) + vl; +} diff --git a/usr/klibc/libgcc/__clzsi2.c b/usr/klibc/libgcc/__clzsi2.c new file mode 100644 index 0000000..ebb11f0 --- /dev/null +++ b/usr/klibc/libgcc/__clzsi2.c @@ -0,0 +1,36 @@ +/* + * libgcc/__clzsi2.c + * + * Returns the leading number of 0 bits in the argument + */ + +#include +#include + +uint32_t __clzsi2(uint32_t v) +{ + int p = 31; + + if (v & 0xffff0000) { + p -= 16; + v >>= 16; + } + if (v & 0xff00) { + p -= 8; + v >>= 8; + } + if (v & 0xf0) { + p -= 4; + v >>= 4; + } + if (v & 0xc) { + p -= 2; + v >>= 2; + } + if (v & 0x2) { + p -= 1; + v >>= 1; + } + + return p; +} diff --git a/usr/klibc/libgcc/__divdi3.c b/usr/klibc/libgcc/__divdi3.c new file mode 100644 index 0000000..973fe63 --- /dev/null +++ b/usr/klibc/libgcc/__divdi3.c @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +int64_t __divdi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmoddi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} diff --git a/usr/klibc/libgcc/__divsi3.c b/usr/klibc/libgcc/__divsi3.c new file mode 100644 index 0000000..35420f5 --- /dev/null +++ b/usr/klibc/libgcc/__divsi3.c @@ -0,0 +1,29 @@ +/* + * libgcc/__divsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +int32_t __divsi3(int32_t num, int32_t den) +{ + int minus = 0; + int32_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + v = __udivmodsi4(num, den, NULL); + if (minus) + v = -v; + + return v; +} diff --git a/usr/klibc/libgcc/__lshrdi3.c b/usr/klibc/libgcc/__lshrdi3.c new file mode 100644 index 0000000..765e1f2 --- /dev/null +++ b/usr/klibc/libgcc/__lshrdi3.c @@ -0,0 +1,23 @@ +/* + * libgcc/__lshrdi3.c + */ + +#include +#include + +uint64_t __lshrdi3(uint64_t v, int cnt) +{ + int c = cnt & 31; + uint32_t vl = (uint32_t) v; + uint32_t vh = (uint32_t) (v >> 32); + + if (cnt & 32) { + vl = (vh >> c); + vh = 0; + } else { + vl = (vl >> c) + (vh << (32 - c)); + vh = (vh >> c); + } + + return ((uint64_t) vh << 32) + vl; +} diff --git a/usr/klibc/libgcc/__moddi3.c b/usr/klibc/libgcc/__moddi3.c new file mode 100644 index 0000000..0e7ed98 --- /dev/null +++ b/usr/klibc/libgcc/__moddi3.c @@ -0,0 +1,29 @@ +/* + * arch/i386/libgcc/__moddi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +int64_t __moddi3(int64_t num, int64_t den) +{ + int minus = 0; + int64_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmoddi4(num, den, (uint64_t *) & v); + if (minus) + v = -v; + + return v; +} diff --git a/usr/klibc/libgcc/__modsi3.c b/usr/klibc/libgcc/__modsi3.c new file mode 100644 index 0000000..33a21ba --- /dev/null +++ b/usr/klibc/libgcc/__modsi3.c @@ -0,0 +1,29 @@ +/* + * libgcc/__modsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +int32_t __modsi3(int32_t num, int32_t den) +{ + int minus = 0; + int32_t v; + + if (num < 0) { + num = -num; + minus = 1; + } + if (den < 0) { + den = -den; + minus ^= 1; + } + + (void)__udivmodsi4(num, den, (uint32_t *) & v); + if (minus) + v = -v; + + return v; +} diff --git a/usr/klibc/libgcc/__udivdi3.c b/usr/klibc/libgcc/__udivdi3.c new file mode 100644 index 0000000..5eea461 --- /dev/null +++ b/usr/klibc/libgcc/__udivdi3.c @@ -0,0 +1,13 @@ +/* + * arch/i386/libgcc/__divdi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +uint64_t __udivdi3(uint64_t num, uint64_t den) +{ + return __udivmoddi4(num, den, NULL); +} diff --git a/usr/klibc/libgcc/__udivmoddi4.c b/usr/klibc/libgcc/__udivmoddi4.c new file mode 100644 index 0000000..aa86112 --- /dev/null +++ b/usr/klibc/libgcc/__udivmoddi4.c @@ -0,0 +1,32 @@ +#include +#include + +uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem_p) +{ + uint64_t quot = 0, qbit = 1; + + if (den == 0) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int64_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} diff --git a/usr/klibc/libgcc/__udivmodsi4.c b/usr/klibc/libgcc/__udivmodsi4.c new file mode 100644 index 0000000..54980f0 --- /dev/null +++ b/usr/klibc/libgcc/__udivmodsi4.c @@ -0,0 +1,32 @@ +#include +#include + +uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem_p) +{ + uint32_t quot = 0, qbit = 1; + + if (den == 0) { + __divide_error(); + return 0; /* If trap returns... */ + } + + /* Left-justify denominator and count shift */ + while ((int32_t) den >= 0) { + den <<= 1; + qbit <<= 1; + } + + while (qbit) { + if (den <= num) { + num -= den; + quot += qbit; + } + den >>= 1; + qbit >>= 1; + } + + if (rem_p) + *rem_p = num; + + return quot; +} diff --git a/usr/klibc/libgcc/__udivsi3.c b/usr/klibc/libgcc/__udivsi3.c new file mode 100644 index 0000000..5635f3f --- /dev/null +++ b/usr/klibc/libgcc/__udivsi3.c @@ -0,0 +1,13 @@ +/* + * libgcc/__divsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +uint32_t __udivsi3(uint32_t num, uint32_t den) +{ + return __udivmodsi4(num, den, NULL); +} diff --git a/usr/klibc/libgcc/__umoddi3.c b/usr/klibc/libgcc/__umoddi3.c new file mode 100644 index 0000000..1fc754a --- /dev/null +++ b/usr/klibc/libgcc/__umoddi3.c @@ -0,0 +1,16 @@ +/* + * arch/i386/libgcc/__umoddi3.c + */ + +#include +#include + +extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t * rem); + +uint64_t __umoddi3(uint64_t num, uint64_t den) +{ + uint64_t v; + + (void)__udivmoddi4(num, den, &v); + return v; +} diff --git a/usr/klibc/libgcc/__umodsi3.c b/usr/klibc/libgcc/__umodsi3.c new file mode 100644 index 0000000..85e6e3c --- /dev/null +++ b/usr/klibc/libgcc/__umodsi3.c @@ -0,0 +1,16 @@ +/* + * libgcc/__umodsi3.c + */ + +#include +#include + +extern uint32_t __udivmodsi4(uint32_t num, uint32_t den, uint32_t * rem); + +uint32_t __umodsi3(uint32_t num, uint32_t den) +{ + uint32_t v; + + (void)__udivmodsi4(num, den, &v); + return v; +} diff --git a/usr/klibc/llseek.c b/usr/klibc/llseek.c new file mode 100644 index 0000000..93d813b --- /dev/null +++ b/usr/klibc/llseek.c @@ -0,0 +1,30 @@ +/* + * llseek.c + * + * On 32-bit platforms, we need to use the _llseek() system call + * rather than lseek(), to be able to handle large disks. _llseek() + * isn't just a normal syscall which takes a 64-bit argument; it needs + * to return a 64-bit value and so takes an extra pointer. + */ + +#include +#include +#include + +#if _BITSIZE == 32 + +extern int __llseek(int fd, unsigned long hi, unsigned long lo, off_t * res, + int whence); + +off_t lseek(int fd, off_t offset, int whence) +{ + off_t result; + int rv; + + rv = __llseek(fd, (unsigned long)(offset >> 32), (unsigned long)offset, + &result, whence); + + return rv ? (off_t) - 1 : result; +} + +#endif diff --git a/usr/klibc/lrand48.c b/usr/klibc/lrand48.c new file mode 100644 index 0000000..7dfcf92 --- /dev/null +++ b/usr/klibc/lrand48.c @@ -0,0 +1,13 @@ +/* + * lrand48.c + */ + +#include +#include + +unsigned short __rand48_seed[3]; /* Common with mrand48.c, srand48.c */ + +long lrand48(void) +{ + return (uint32_t) jrand48(__rand48_seed) >> 1; +} diff --git a/usr/klibc/makeerrlist.pl b/usr/klibc/makeerrlist.pl new file mode 100644 index 0000000..43c747c --- /dev/null +++ b/usr/klibc/makeerrlist.pl @@ -0,0 +1,98 @@ +#!/usr/bin/perl +# +# This creates sys_errlist from through somewhat +# heuristic matching. It presumes the relevant entries are of the form +# #define Exxxx /* comment */ +# + +use FileHandle; + +%errors = (); +%errmsg = (); +$maxerr = -1; +@includelist = (); # Include directories + +sub parse_file($) { + my($file) = @_; + my($fh) = new FileHandle; + my($line, $error, $msg); + my($kernelonly) = 0; + my($root); + + print STDERR "opening $file\n" unless ( $quiet ); + + $ok = 0; + foreach $root ( @includelist ) { + if ( $fh->open($root.'//'.$file, '<') ) { + $ok = 1; + last; + } + } + + if ( ! $ok ) { + die "$0: Cannot find file $file\n"; + } + + while ( defined($line = <$fh>) ) { + if ( $kernelonly ) { + if ( $line =~ /^\#\s*endif/ ) { + $kernelonly--; + } elsif ( $line =~ /^\#\sif/ ) { + $kernelonly++; + } + } else { + if ( $line =~ /^\#\s*define\s+([A-Z0-9_]+)\s+([0-9]+)\s*\/\*\s*(.*\S)\s*\*\// ) { + $error = $1; + $errno = $2+0; + $msg = $3; + print STDERR "$error ($errno) => \"$msg\"\n" unless ( $quiet ); + $errors{$errno} = $error; + $errmsg{$errno} = $msg; + $maxerr = $errno if ( $errno > $maxerr ); + } elsif ( $line =~ /^\#\s*include\s+[\<\"](.*)[\>\"]/ ) { + parse_file($1); + } elsif ( $line =~ /^\#\s*ifdef\s+__KERNEL__/ ) { + $kernelonly++; + } + } + } + close($fh); + print STDERR "closing $file\n" unless ( $quiet ); +} + +$v = $ENV{'KBUILD_VERBOSE'}; +$quiet = defined($v) ? !$v : 0; + +foreach $arg ( @ARGV ) { + if ( $arg eq '-q' ) { + $quiet = 1; + } elsif ( $arg =~ /^-(errlist|errnos|maxerr)$/ ) { + $type = $arg; + } elsif ( $arg =~ '^\-I' ) { + push(@includelist, "$'"); + } else { + # Ignore + } +} + +parse_file('linux/errno.h'); + +if ( $type eq '-errlist' ) { + print "#include \n"; + printf "const int sys_nerr = %d;\n", $maxerr+1; + printf "const char * const sys_errlist[%d] = {\n", $maxerr+1; + foreach $e ( sort(keys(%errors)) ) { + printf " [%s] = \"%s\",\n", $errors{$e}, $errmsg{$e}; + } + print "};\n"; +} elsif ( $type eq '-errnos' ) { + print "#include \n"; + printf "const int sys_nerr = %d;\n", $maxerr+1; + printf "const char * const sys_errlist[%d] = {\n", $maxerr+1; + foreach $e ( sort(keys(%errors)) ) { + printf " [%s] = \"%s\",\n", $errors{$e}, $errors{$e}; + } + print "};\n"; +} elsif ( $type eq '-maxerr' ) { + print $maxerr, "\n"; +} diff --git a/usr/klibc/malloc.c b/usr/klibc/malloc.c new file mode 100644 index 0000000..f2da1db --- /dev/null +++ b/usr/klibc/malloc.c @@ -0,0 +1,200 @@ +/* + * malloc.c + * + * Very simple linked-list based malloc()/free(). + */ + +#include +#include +#include +#include "malloc.h" + +/* Both the arena list and the free memory list are double linked + list with head node. This the head node. Note that the arena list + is sorted in order of address. */ +struct free_arena_header __malloc_head = { + { + ARENA_TYPE_HEAD, + 0, + &__malloc_head, + &__malloc_head, + }, + &__malloc_head, + &__malloc_head +}; + +static void *__malloc_from_block(struct free_arena_header *fp, size_t size) +{ + size_t fsize; + struct free_arena_header *nfp, *na; + + fsize = fp->a.size; + + /* We need the 2* to account for the larger requirements of a + free block */ + if (fsize >= size + 2 * sizeof(struct arena_header)) { + /* Bigger block than required -- split block */ + nfp = (struct free_arena_header *)((char *)fp + size); + na = fp->a.next; + + nfp->a.type = ARENA_TYPE_FREE; + nfp->a.size = fsize - size; + fp->a.type = ARENA_TYPE_USED; + fp->a.size = size; + + /* Insert into all-block chain */ + nfp->a.prev = fp; + nfp->a.next = na; + na->a.prev = nfp; + fp->a.next = nfp; + + /* Replace current block on free chain */ + nfp->next_free = fp->next_free; + nfp->prev_free = fp->prev_free; + fp->next_free->prev_free = nfp; + fp->prev_free->next_free = nfp; + } else { + /* Allocate the whole block */ + fp->a.type = ARENA_TYPE_USED; + + /* Remove from free chain */ + fp->next_free->prev_free = fp->prev_free; + fp->prev_free->next_free = fp->next_free; + } + + return (void *)(&fp->a + 1); +} + +static struct free_arena_header *__free_block(struct free_arena_header *ah) +{ + struct free_arena_header *pah, *nah; + + pah = ah->a.prev; + nah = ah->a.next; + if (pah->a.type == ARENA_TYPE_FREE && + (char *)pah + pah->a.size == (char *)ah) { + /* Coalesce into the previous block */ + pah->a.size += ah->a.size; + pah->a.next = nah; + nah->a.prev = pah; + +#ifdef DEBUG_MALLOC + ah->a.type = ARENA_TYPE_DEAD; +#endif + + ah = pah; + pah = ah->a.prev; + } else { + /* Need to add this block to the free chain */ + ah->a.type = ARENA_TYPE_FREE; + + ah->next_free = __malloc_head.next_free; + ah->prev_free = &__malloc_head; + __malloc_head.next_free = ah; + ah->next_free->prev_free = ah; + } + + /* In either of the previous cases, we might be able to merge + with the subsequent block... */ + if (nah->a.type == ARENA_TYPE_FREE && + (char *)ah + ah->a.size == (char *)nah) { + ah->a.size += nah->a.size; + + /* Remove the old block from the chains */ + nah->next_free->prev_free = nah->prev_free; + nah->prev_free->next_free = nah->next_free; + ah->a.next = nah->a.next; + nah->a.next->a.prev = ah; + +#ifdef DEBUG_MALLOC + nah->a.type = ARENA_TYPE_DEAD; +#endif + } + + /* Return the block that contains the called block */ + return ah; +} + +void *malloc(size_t size) +{ + struct free_arena_header *fp; + struct free_arena_header *pah; + size_t fsize; + + if (size == 0) + return NULL; + + /* Add the obligatory arena header, and round up */ + size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; + + for (fp = __malloc_head.next_free; fp->a.type != ARENA_TYPE_HEAD; + fp = fp->next_free) { + if (fp->a.size >= size) { + /* Found fit -- allocate out of this block */ + return __malloc_from_block(fp, size); + } + } + + /* Nothing found... need to request a block from the kernel */ + fsize = (size + MALLOC_CHUNK_MASK) & ~MALLOC_CHUNK_MASK; + +#if _KLIBC_MALLOC_USES_SBRK + fp = (struct free_arena_header *)sbrk(fsize); +#else + fp = (struct free_arena_header *) + mmap(NULL, fsize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +#endif + + if (fp == (struct free_arena_header *)MAP_FAILED) { + return NULL; /* Failed to get a block */ + } + + /* Insert the block into the management chains. We need to set + up the size and the main block list pointer, the rest of + the work is logically identical to free(). */ + fp->a.type = ARENA_TYPE_FREE; + fp->a.size = fsize; + + /* We need to insert this into the main block list in the proper + place -- this list is required to be sorted. Since we most likely + get memory assignments in ascending order, search backwards for + the proper place. */ + for (pah = __malloc_head.a.prev; pah->a.type != ARENA_TYPE_HEAD; + pah = pah->a.prev) { + if (pah < fp) + break; + } + + /* Now pah points to the node that should be the predecessor of + the new node */ + fp->a.next = pah->a.next; + fp->a.prev = pah; + pah->a.next = fp; + fp->a.next->a.prev = fp; + + /* Insert into the free chain and coalesce with adjacent blocks */ + fp = __free_block(fp); + + /* Now we can allocate from this block */ + return __malloc_from_block(fp, size); +} + +void free(void *ptr) +{ + struct free_arena_header *ah; + + if (!ptr) + return; + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + +#ifdef DEBUG_MALLOC + assert(ah->a.type == ARENA_TYPE_USED); +#endif + + __free_block(ah); + + /* Here we could insert code to return memory to the system. */ +} diff --git a/usr/klibc/malloc.h b/usr/klibc/malloc.h new file mode 100644 index 0000000..1108322 --- /dev/null +++ b/usr/klibc/malloc.h @@ -0,0 +1,47 @@ +/* + * malloc.h + * + * Internals for the memory allocator + */ + +#include +#include +#include + +/* + * This structure should be a power of two. This becomes the + * alignment unit. + */ +struct free_arena_header; + +struct arena_header { + size_t type; + size_t size; /* Also gives the location of the next entry */ + struct free_arena_header *next, *prev; +}; + +#ifdef DEBUG_MALLOC +#define ARENA_TYPE_USED 0x64e69c70 +#define ARENA_TYPE_FREE 0x012d610a +#define ARENA_TYPE_HEAD 0x971676b5 +#define ARENA_TYPE_DEAD 0xeeeeeeee +#else +#define ARENA_TYPE_USED 0 +#define ARENA_TYPE_FREE 1 +#define ARENA_TYPE_HEAD 2 +#endif + +#define MALLOC_CHUNK_MASK (_KLIBC_MALLOC_CHUNK_SIZE-1) + +#define ARENA_SIZE_MASK (~(sizeof(struct arena_header)-1)) + +/* + * This structure should be no more than twice the size of the + * previous structure. + */ +struct free_arena_header { + struct arena_header a; + struct free_arena_header *next_free, *prev_free; +}; + +extern struct free_arena_header __malloc_head; diff --git a/usr/klibc/memccpy.c b/usr/klibc/memccpy.c new file mode 100644 index 0000000..83d02c9 --- /dev/null +++ b/usr/klibc/memccpy.c @@ -0,0 +1,23 @@ +/* + * memccpy.c + * + * memccpy() + */ + +#include +#include + +void *memccpy(void *dst, const void *src, int c, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while (n--) { + *q++ = ch = *p++; + if (ch == (char)c) + return q; + } + + return NULL; /* No instance of "c" found */ +} diff --git a/usr/klibc/memchr.c b/usr/klibc/memchr.c new file mode 100644 index 0000000..f1947fb --- /dev/null +++ b/usr/klibc/memchr.c @@ -0,0 +1,19 @@ +/* + * memchr.c + */ + +#include +#include + +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *sp = s; + + while (n--) { + if (*sp == (unsigned char)c) + return (void *)sp; + sp++; + } + + return NULL; +} diff --git a/usr/klibc/memcmp.c b/usr/klibc/memcmp.c new file mode 100644 index 0000000..3ce9941 --- /dev/null +++ b/usr/klibc/memcmp.c @@ -0,0 +1,19 @@ +/* + * memcmp.c + */ + +#include + +int memcmp(const void *s1, const void *s2, size_t n) +{ + const unsigned char *c1 = s1, *c2 = s2; + int d = 0; + + while (n--) { + d = (int)*c1++ - (int)*c2++; + if (d) + break; + } + + return d; +} diff --git a/usr/klibc/memcpy.c b/usr/klibc/memcpy.c new file mode 100644 index 0000000..5ce206d --- /dev/null +++ b/usr/klibc/memcpy.c @@ -0,0 +1,29 @@ +/* + * memcpy.c + */ + +#include +#include + +void *memcpy(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) + size_t nl = n >> 2; + asm volatile ("cld ; rep ; movsl ; movl %3,%0 ; rep ; movsb":"+c" (nl), + "+S"(p), "+D"(q) + :"r"(n & 3)); +#elif defined(__x86_64__) + size_t nq = n >> 3; + asm volatile ("cld ; rep ; movsq ; movl %3,%%ecx ; rep ; movsb":"+c" + (nq), "+S"(p), "+D"(q) + :"r"((uint32_t) (n & 7))); +#else + while (n--) { + *q++ = *p++; + } +#endif + + return dst; +} diff --git a/usr/klibc/memmem.c b/usr/klibc/memmem.c new file mode 100644 index 0000000..8b5faa0 --- /dev/null +++ b/usr/klibc/memmem.c @@ -0,0 +1,52 @@ +/* + * memmem.c + * + * Find a byte string inside a longer byte string + * + * This uses the "Not So Naive" algorithm, a very simple but + * usually effective algorithm, see: + * + * http://www-igm.univ-mlv.fr/~lecroq/string/ + */ + +#include + +void *memmem(const void *haystack, size_t n, const void *needle, size_t m) +{ + const unsigned char *y = (const unsigned char *)haystack; + const unsigned char *x = (const unsigned char *)needle; + + size_t j, k, l; + + if (m > n || !m || !n) + return NULL; + + if (1 != m) { + if (x[0] == x[1]) { + k = 2; + l = 1; + } else { + k = 1; + l = 2; + } + + j = 0; + while (j <= n - m) { + if (x[1] != y[j + 1]) { + j += k; + } else { + if (!memcmp(x + 2, y + j + 2, m - 2) + && x[0] == y[j]) + return (void *)&y[j]; + j += l; + } + } + } else + do { + if (*y == *x) + return (void *)y; + y++; + } while (--n); + + return NULL; +} diff --git a/usr/klibc/memmove.c b/usr/klibc/memmove.c new file mode 100644 index 0000000..659c778 --- /dev/null +++ b/usr/klibc/memmove.c @@ -0,0 +1,36 @@ +/* + * memmove.c + */ + +#include + +void *memmove(void *dst, const void *src, size_t n) +{ + const char *p = src; + char *q = dst; +#if defined(__i386__) || defined(__x86_64__) + if (q < p) { + asm volatile("cld ; rep ; movsb" + : "+c" (n), "+S"(p), "+D"(q)); + } else { + p += (n - 1); + q += (n - 1); + asm volatile("std ; rep ; movsb" + : "+c" (n), "+S"(p), "+D"(q)); + } +#else + if (q < p) { + while (n--) { + *q++ = *p++; + } + } else { + p += n; + q += n; + while (n--) { + *--q = *--p; + } + } +#endif + + return dst; +} diff --git a/usr/klibc/memrchr.c b/usr/klibc/memrchr.c new file mode 100644 index 0000000..ff6d711 --- /dev/null +++ b/usr/klibc/memrchr.c @@ -0,0 +1,19 @@ +/* + * memrchr.c + */ + +#include +#include + +void *memrchr(const void *s, int c, size_t n) +{ + const unsigned char *sp = (const unsigned char *)s + n - 1; + + while (n--) { + if (*sp == (unsigned char)c) + return (void *)sp; + sp--; + } + + return NULL; +} diff --git a/usr/klibc/memset.c b/usr/klibc/memset.c new file mode 100644 index 0000000..aa00b5b --- /dev/null +++ b/usr/klibc/memset.c @@ -0,0 +1,30 @@ +/* + * memset.c + */ + +#include +#include + +void *memset(void *dst, int c, size_t n) +{ + char *q = dst; + +#if defined(__i386__) + size_t nl = n >> 2; + asm volatile ("cld ; rep ; stosl ; movl %3,%0 ; rep ; stosb" + : "+c" (nl), "+D" (q) + : "a" ((unsigned char)c * 0x01010101U), "r" (n & 3)); +#elif defined(__x86_64__) + size_t nq = n >> 3; + asm volatile ("cld ; rep ; stosq ; movl %3,%%ecx ; rep ; stosb" + :"+c" (nq), "+D" (q) + : "a" ((unsigned char)c * 0x0101010101010101U), + "r" ((uint32_t) n & 7)); +#else + while (n--) { + *q++ = c; + } +#endif + + return dst; +} diff --git a/usr/klibc/memswap.c b/usr/klibc/memswap.c new file mode 100644 index 0000000..b32315c --- /dev/null +++ b/usr/klibc/memswap.c @@ -0,0 +1,24 @@ +/* + * memswap() + * + * Swaps the contents of two nonoverlapping memory areas. + * This really could be done faster... + */ + +#include + +void memswap(void *m1, void *m2, size_t n) +{ + char *p = m1; + char *q = m2; + char tmp; + + while (n--) { + tmp = *p; + *p = *q; + *q = tmp; + + p++; + q++; + } +} diff --git a/usr/klibc/mmap.c b/usr/klibc/mmap.c new file mode 100644 index 0000000..9b1dcd9 --- /dev/null +++ b/usr/klibc/mmap.c @@ -0,0 +1,40 @@ +/* + * mmap.c + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Set in SYSCALLS whether or not we should use an unadorned mmap() system + * call (typical on 64-bit architectures). + */ +#if !_KLIBC_NO_MMU && _KLIBC_USE_MMAP2 + +/* This architecture uses mmap2(). The Linux mmap2() system call takes + a page offset as the offset argument. We need to make sure we have + the proper conversion in place. */ + +extern void *__mmap2(void *, size_t, int, int, int, size_t); + +void *mmap(void *start, size_t length, int prot, int flags, int fd, + off_t offset) +{ + const int mmap2_shift = _KLIBC_MMAP2_SHIFT; + const off_t mmap2_mask = ((off_t) 1 << mmap2_shift) - 1; + + if (offset & mmap2_mask) { + errno = EINVAL; + return MAP_FAILED; + } + + return __mmap2(start, length, prot, flags, fd, + (size_t) offset >> mmap2_shift); +} + +#endif diff --git a/usr/klibc/mrand48.c b/usr/klibc/mrand48.c new file mode 100644 index 0000000..e3b73cc --- /dev/null +++ b/usr/klibc/mrand48.c @@ -0,0 +1,13 @@ +/* + * mrand48.c + */ + +#include +#include + +unsigned short __rand48_seed[3]; /* Common with lrand48.c, srand48.c */ + +long mrand48(void) +{ + return jrand48(__rand48_seed); +} diff --git a/usr/klibc/nice.c b/usr/klibc/nice.c new file mode 100644 index 0000000..e6e99ac --- /dev/null +++ b/usr/klibc/nice.c @@ -0,0 +1,19 @@ +/* + * nice.c + */ + +#include +#include +#include +#include + +#ifndef __NR_nice + +int nice(int inc) +{ + pid_t me = getpid(); + return setpriority(me, PRIO_PROCESS, + getpriority(me, PRIO_PROCESS) + inc); +} + +#endif diff --git a/usr/klibc/nrand48.c b/usr/klibc/nrand48.c new file mode 100644 index 0000000..cb3532b --- /dev/null +++ b/usr/klibc/nrand48.c @@ -0,0 +1,11 @@ +/* + * nrand48.c + */ + +#include +#include + +long nrand48(unsigned short xsubi[3]) +{ + return (long)((uint32_t) jrand48(xsubi) >> 1); +} diff --git a/usr/klibc/nullenv.c b/usr/klibc/nullenv.c new file mode 100644 index 0000000..ba7e71c --- /dev/null +++ b/usr/klibc/nullenv.c @@ -0,0 +1,8 @@ +/* + * nullenv.c + */ + +#include +#include "env.h" + +char * const __null_environ[] = { NULL }; diff --git a/usr/klibc/onexit.c b/usr/klibc/onexit.c new file mode 100644 index 0000000..15a96b5 --- /dev/null +++ b/usr/klibc/onexit.c @@ -0,0 +1,23 @@ +/* + * onexit.c + */ + +#include +#include +#include "atexit.h" + +int on_exit(void (*fctn) (int, void *), void *arg) +{ + struct atexit *as = malloc(sizeof(struct atexit)); + + if (!as) + return -1; + + as->fctn = fctn; + as->arg = arg; + + as->next = __atexit_list; + __atexit_list = as; + + return 0; +} diff --git a/usr/klibc/open.c b/usr/klibc/open.c new file mode 100644 index 0000000..9b0897a --- /dev/null +++ b/usr/klibc/open.c @@ -0,0 +1,22 @@ +/* + * open.c + * + * On 32-bit platforms we need to pass O_LARGEFILE to the open() + * system call, to indicate that we're 64-bit safe. + */ + +#define _KLIBC_IN_OPEN_C +#include +#include +#include + +#if _BITSIZE == 32 && !defined(__i386__) + +extern int __open(const char *, int, mode_t); + +int open(const char *pathname, int flags, mode_t mode) +{ + return __open(pathname, flags | O_LARGEFILE, mode); +} + +#endif diff --git a/usr/klibc/openat.c b/usr/klibc/openat.c new file mode 100644 index 0000000..83c87cd --- /dev/null +++ b/usr/klibc/openat.c @@ -0,0 +1,22 @@ +/* + * openat.c + * + * On 32-bit platforms we need to pass O_LARGEFILE to the openat() + * system call, to indicate that we're 64-bit safe. + */ + +#define _KLIBC_IN_OPEN_C +#include +#include +#include + +#if _BITSIZE == 32 && !defined(__i386__) && defined(__NR_openat) + +extern int __openat(int, const char *, int, mode_t); + +int openat(int dirfd, const char *pathname, int flags, mode_t mode) +{ + return __openat(dirfd, pathname, flags | O_LARGEFILE, mode); +} + +#endif diff --git a/usr/klibc/pause.c b/usr/klibc/pause.c new file mode 100644 index 0000000..cec97a8 --- /dev/null +++ b/usr/klibc/pause.c @@ -0,0 +1,17 @@ +/* + * pause.c + */ + +#include +#include +#include +#include + +#ifndef __NR_pause + +int pause(void) +{ + return select(0, NULL, NULL, NULL, NULL); +} + +#endif diff --git a/usr/klibc/perror.c b/usr/klibc/perror.c new file mode 100644 index 0000000..3177057 --- /dev/null +++ b/usr/klibc/perror.c @@ -0,0 +1,13 @@ +/* + * perror.c + */ + +#include +#include +#include + +void perror(const char *s) +{ + int e = errno; + fprintf(stderr, "%s: %s\n", s, strerror(e)); +} diff --git a/usr/klibc/ppoll.c b/usr/klibc/ppoll.c new file mode 100644 index 0000000..5e20a89 --- /dev/null +++ b/usr/klibc/ppoll.c @@ -0,0 +1,19 @@ +/* + * ppoll.c + */ + +#include +#include + +#ifdef __NR_ppoll + +__extern int __ppoll(struct pollfd *, nfds_t, struct timespec *, + const sigset_t *, size_t); + +int ppoll(struct pollfd *ufds, nfds_t nfds, struct timespec *timeout, + const sigset_t * sigmask) +{ + return __ppoll(ufds, nfds, timeout, sigmask, sizeof *sigmask); +} + +#endif diff --git a/usr/klibc/printf.c b/usr/klibc/printf.c new file mode 100644 index 0000000..02bdba0 --- /dev/null +++ b/usr/klibc/printf.c @@ -0,0 +1,19 @@ +/* + * printf.c + */ + +#include +#include + +#define BUFFER_SIZE 16384 + +int printf(const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vfprintf(stdout, format, ap); + va_end(ap); + return rv; +} diff --git a/usr/klibc/pselect.c b/usr/klibc/pselect.c new file mode 100644 index 0000000..1bb6852 --- /dev/null +++ b/usr/klibc/pselect.c @@ -0,0 +1,42 @@ +/* + * pselect.c + */ + +#include +#include + +#if defined(__NR_pselect) && !_KLIBC_USE_RT_SIG + +/* Don't need to do anything here; use syscall stub directly */ + +#elif defined(__NR_pselect7) + +__extern int __pselect7(int, fd_set *, fd_set *, fd_set *, + const struct timespec *, const sigset_t *, size_t); + +int pselect(int n, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, + const struct timespec *timeout, const sigset_t * sigmask) +{ + return __pselect7(n, readfds, writefds, exceptfds, + timeout, sigmask, sizeof *sigmask); +} + +#elif defined(__NR_pselect6) + +struct __pselect6 { + const sigset_t *sigmask; + size_t sigsize; +}; + +__extern int __pselect6(int, fd_set *, fd_set *, fd_set *, + const struct timespec *, const struct __pselect6 *); + +int pselect(int n, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, + const struct timespec *timeout, const sigset_t * sigmask) +{ + struct __pselect6 extended_sigmask = { sigmask, sizeof *sigmask }; + return __pselect6(n, readfds, writefds, exceptfds, + timeout, &extended_sigmask); +} + +#endif diff --git a/usr/klibc/pty.c b/usr/klibc/pty.c new file mode 100644 index 0000000..7fcb2ba --- /dev/null +++ b/usr/klibc/pty.c @@ -0,0 +1,31 @@ +/* + * pty.c + * + * Basic Unix98 PTY functionality; assumes devpts mounted on /dev/pts + */ + +#include +#include +#include +#include +#include + +char *ptsname(int fd) +{ + static char buffer[32]; /* Big enough to hold even a 64-bit pts no */ + unsigned int ptyno; + + if (ioctl(fd, TIOCGPTN, &ptyno)) + return NULL; + + snprintf(buffer, sizeof buffer, "/dev/pts/%u", ptyno); + + return buffer; +} + +int unlockpt(int fd) +{ + int unlock = 0; + + return ioctl(fd, TIOCSPTLCK, &unlock); +} diff --git a/usr/klibc/putchar.c b/usr/klibc/putchar.c new file mode 100644 index 0000000..e2224ca --- /dev/null +++ b/usr/klibc/putchar.c @@ -0,0 +1,15 @@ +/* + * putchar.c + * + * - gcc wants this + */ + +#include + +#undef putchar /* Defined as a macro */ +int putchar(int); + +int putchar(int c) +{ + return fputc(c, stdout); +} diff --git a/usr/klibc/putenv.c b/usr/klibc/putenv.c new file mode 100644 index 0000000..5059ecb --- /dev/null +++ b/usr/klibc/putenv.c @@ -0,0 +1,37 @@ +/* + * putenv.c + */ + +#include +#include +#include +#include +#include "env.h" + +int putenv(const char *str) +{ + char *s; + const char *e, *z; + + if (!str) { + errno = EINVAL; + return -1; + } + + e = NULL; + for (z = str; *z; z++) { + if (*z == '=') + e = z; + } + + if (!e) { + errno = EINVAL; + return -1; + } + + s = strdup(str); + if (!s) + return -1; + + return __put_env(s, e - str, 1); +} diff --git a/usr/klibc/puts.c b/usr/klibc/puts.c new file mode 100644 index 0000000..27e16e2 --- /dev/null +++ b/usr/klibc/puts.c @@ -0,0 +1,13 @@ +/* + * puts.c + */ + +#include + +int puts(const char *s) +{ + if (fputs(s, stdout) < 0) + return -1; + + return _fwrite("\n", 1, stdout); +} diff --git a/usr/klibc/qsort.c b/usr/klibc/qsort.c new file mode 100644 index 0000000..e6e8395 --- /dev/null +++ b/usr/klibc/qsort.c @@ -0,0 +1,42 @@ +/* + * qsort.c + * + * This is actually combsort. It's an O(n log n) algorithm with + * simplicity/small code size being its main virtue. + */ + +#include +#include + +static inline size_t newgap(size_t gap) +{ + gap = (gap * 10) / 13; + if (gap == 9 || gap == 10) + gap = 11; + + if (gap < 1) + gap = 1; + return gap; +} + +void qsort(void *base, size_t nmemb, size_t size, + int (*compar) (const void *, const void *)) +{ + size_t gap = nmemb; + size_t i, j; + char *p1, *p2; + int swapped; + + do { + gap = newgap(gap); + swapped = 0; + + for (i = 0, p1 = base; i < nmemb - gap; i++, p1 += size) { + j = i + gap; + if (compar(p1, p2 = (char *)base + j * size) > 0) { + memswap(p1, p2, size); + swapped = 1; + } + } + } while (gap > 1 || swapped); +} diff --git a/usr/klibc/raise.c b/usr/klibc/raise.c new file mode 100644 index 0000000..3b9d23d --- /dev/null +++ b/usr/klibc/raise.c @@ -0,0 +1,11 @@ +/* + * raise.c + */ + +#include +#include + +int raise(int signal) +{ + return kill(getpid(), signal); +} diff --git a/usr/klibc/readdir.c b/usr/klibc/readdir.c new file mode 100644 index 0000000..453fc08 --- /dev/null +++ b/usr/klibc/readdir.c @@ -0,0 +1,57 @@ +/* + * readdir.c: opendir/readdir/closedir + */ + +#include +#include +#include + +#define __KLIBC_DIRENT_INTERNALS +#include + +DIR *opendir(const char *name) +{ + DIR *dp = malloc(sizeof(DIR)); + + if (!dp) + return NULL; + + dp->__fd = open(name, O_DIRECTORY | O_RDONLY); + + if (dp->__fd < 0) { + free(dp); + return NULL; + } + + dp->bytes_left = 0; + + return dp; +} + +struct dirent *readdir(DIR *dir) +{ + struct dirent *dent; + int rv; + + if (!dir->bytes_left) { + rv = getdents(dir->__fd, dir->buffer, sizeof(dir->buffer)); + if (rv <= 0) + return NULL; + dir->bytes_left = rv; + dir->next = dir->buffer; + } + + dent = dir->next; + dir->next = (struct dirent *)((char *)dir->next + dent->d_reclen); + dir->bytes_left -= dent->d_reclen; + + return dent; +} + +int closedir(DIR *dir) +{ + int rv; + rv = close(dir->__fd); + free(dir); + return rv; +} diff --git a/usr/klibc/realloc.c b/usr/klibc/realloc.c new file mode 100644 index 0000000..3b41ccf --- /dev/null +++ b/usr/klibc/realloc.c @@ -0,0 +1,48 @@ +/* + * realloc.c + */ + +#include +#include + +#include "malloc.h" + +/* FIXME: This is cheesy, it should be fixed later */ + +void *realloc(void *ptr, size_t size) +{ + struct free_arena_header *ah; + void *newptr; + size_t oldsize; + + if (!ptr) + return malloc(size); + + if (size == 0) { + free(ptr); + return NULL; + } + + /* Add the obligatory arena header, and round up */ + size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK; + + ah = (struct free_arena_header *) + ((struct arena_header *)ptr - 1); + + if (ah->a.size >= size && size >= (ah->a.size >> 2)) { + /* This field is a good size already. */ + return ptr; + } else { + /* Make me a new block. This is kind of bogus; we should + be checking the adjacent blocks to see if we can do an + in-place adjustment... fix that later. */ + + oldsize = ah->a.size - sizeof(struct arena_header); + + newptr = malloc(size); + memcpy(newptr, ptr, (size < oldsize) ? size : oldsize); + free(ptr); + + return newptr; + } +} diff --git a/usr/klibc/reboot.c b/usr/klibc/reboot.c new file mode 100644 index 0000000..5795dc3 --- /dev/null +++ b/usr/klibc/reboot.c @@ -0,0 +1,15 @@ +/* + * reboot.c + */ + +#include +#include +#include + +/* This provides the one-argument glibc-ish version of reboot. + The full four-argument system call is available as __reboot(). */ + +int reboot(int flag) +{ + return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, flag, NULL); +} diff --git a/usr/klibc/recv.c b/usr/klibc/recv.c new file mode 100644 index 0000000..0baa00a --- /dev/null +++ b/usr/klibc/recv.c @@ -0,0 +1,11 @@ +/* + * recv.c + */ + +#include +#include + +int recv(int s, void *buf, size_t len, unsigned int flags) +{ + return recvfrom(s, buf, len, flags, NULL, 0); +} diff --git a/usr/klibc/remove.c b/usr/klibc/remove.c new file mode 100644 index 0000000..9088204 --- /dev/null +++ b/usr/klibc/remove.c @@ -0,0 +1,18 @@ +/* + * remove.c + */ + +#include +#include +#include + +int remove(const char *pathname) +{ + int rv; + + rv = unlink(pathname); + if (rv == -1 && errno == EISDIR) + return rmdir(pathname); + + return rv; +} diff --git a/usr/klibc/sbrk.c b/usr/klibc/sbrk.c new file mode 100644 index 0000000..4896ce0 --- /dev/null +++ b/usr/klibc/sbrk.c @@ -0,0 +1,45 @@ +/* sbrk.c - Change data segment size */ + +/* Written 2000 by Werner Almesberger */ +/* Modified 2003-2004 for klibc by H. Peter Anvin */ + +#include +#include +#include +#include +#include "malloc.h" + +#if !_KLIBC_NO_MMU /* uClinux doesn't have brk() */ + +char *__current_brk; /* Common with brk.c */ + +/* p is an address, a is alignment; must be a power of 2 */ +static inline void *align_up(void *p, uintptr_t a) +{ + return (void *)(((uintptr_t) p + a - 1) & ~(a - 1)); +} + +void *sbrk(ptrdiff_t increment) +{ + char *start, *end, *new_brk; + + if (!__current_brk) + __current_brk = __brk(NULL); + + start = align_up(__current_brk, _KLIBC_SBRK_ALIGNMENT); + end = start + increment; + + new_brk = __brk(end); + + if (new_brk == (void *)-1) + return (void *)-1; + else if (new_brk < end) { + errno = ENOMEM; + return (void *)-1; + } + + __current_brk = new_brk; + return start; +} + +#endif /* !_KLIBC_NO_MMU */ diff --git a/usr/klibc/seed48.c b/usr/klibc/seed48.c new file mode 100644 index 0000000..ccdf183 --- /dev/null +++ b/usr/klibc/seed48.c @@ -0,0 +1,18 @@ +/* + * seed48.c + */ + +#include +#include +#include + +unsigned short __rand48_seed[3]; + +unsigned short *seed48(const unsigned short xsubi[3]) +{ + static unsigned short oldseed[3]; + memcpy(oldseed, __rand48_seed, sizeof __rand48_seed); + memcpy(__rand48_seed, xsubi, sizeof __rand48_seed); + + return oldseed; +} diff --git a/usr/klibc/send.c b/usr/klibc/send.c new file mode 100644 index 0000000..a867dd1 --- /dev/null +++ b/usr/klibc/send.c @@ -0,0 +1,11 @@ +/* + * send.c + */ + +#include +#include + +int send(int s, const void *buf, size_t len, unsigned int flags) +{ + return sendto(s, buf, len, flags, NULL, 0); +} diff --git a/usr/klibc/setegid.c b/usr/klibc/setegid.c new file mode 100644 index 0000000..6af966f --- /dev/null +++ b/usr/klibc/setegid.c @@ -0,0 +1,10 @@ +/* + * setegid.c + */ + +#include + +int setegid(gid_t egid) +{ + return setregid(-1, egid); +} diff --git a/usr/klibc/setenv.c b/usr/klibc/setenv.c new file mode 100644 index 0000000..45a7aad --- /dev/null +++ b/usr/klibc/setenv.c @@ -0,0 +1,42 @@ +/* + * setenv.c + */ + +#include +#include +#include +#include +#include "env.h" + +int setenv(const char *name, const char *val, int overwrite) +{ + const char *z; + char *s; + size_t l1, l2; + + if (!name || !name[0]) { + errno = EINVAL; + return -1; + } + + l1 = 0; + for (z = name; *z; z++) { + l1++; + if (*z == '=') { + errno = EINVAL; + return -1; + } + } + + l2 = strlen(val); + + s = malloc(l1 + l2 + 2); + if (!s) + return -1; + + memcpy(s, name, l1); + s[l1] = '='; + memcpy(s + l1 + 1, val, l2 + 1); + + return __put_env(s, l1 + 1, overwrite); +} diff --git a/usr/klibc/seteuid.c b/usr/klibc/seteuid.c new file mode 100644 index 0000000..18dddb1 --- /dev/null +++ b/usr/klibc/seteuid.c @@ -0,0 +1,10 @@ +/* + * seteuid.c + */ + +#include + +int seteuid(uid_t euid) +{ + return setreuid(-1, euid); +} diff --git a/usr/klibc/setpgrp.c b/usr/klibc/setpgrp.c new file mode 100644 index 0000000..75bbcc7 --- /dev/null +++ b/usr/klibc/setpgrp.c @@ -0,0 +1,10 @@ +/* + * setpgrp.c + */ + +#include + +int setpgrp(void) +{ + return setpgid(0, 0); +} diff --git a/usr/klibc/sha1hash.c b/usr/klibc/sha1hash.c new file mode 100644 index 0000000..c29eebf --- /dev/null +++ b/usr/klibc/sha1hash.c @@ -0,0 +1,317 @@ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +----------------- +Modified 7/98 +By James H. Brown +Still 100% Public Domain + +Corrected a problem which generated improper hash values on 16 bit machines +Routine SHA1Update changed from + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int +len) +to + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned +long len) + +The 'len' parameter was declared an int which works fine on 32 bit machines. +However, on 16 bit machines an int is too small for the shifts being done +against +it. This caused the hash function to generate incorrect values if len was +greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). + +Since the file IO in main() reads 16K at a time, any file 8K or larger would +be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million +"a"s). + +I also changed the declaration of variables i & j in SHA1Update to +unsigned long from unsigned int for the same reason. + +These changes should make no difference to any 32 bit implementations since +an +int and a long are the same size in those environments. + +-- +I also corrected a few compiler warnings generated by Borland C. +1. Added #include for exit() prototype +2. Removed unused variable 'j' in SHA1Final +3. Changed exit(0) to return(0) at end of main. + +ALL changes I made can be located by searching for comments containing 'JHB' +----------------- +Modified 8/98 +By Steve Reid +Still 100% public domain + +1- Removed #include and used return() instead of exit() +2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) +3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net + +----------------- +Modified 4/01 +By Saul Kravitz +Still 100% PD +Modified to run on Compaq Alpha hardware. + +----------------- +Modified 2/03 +By H. Peter Anvin +Still 100% PD +Modified to run on any hardware with and +Changed the driver program + +*/ + +/* +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define SHA1HANDSOFF */ + +#include +#include +#include +#include /* For htonl/ntohl/htons/ntohs */ + +/* #include */ /* prototype for exit() - JHB */ +/* Using return() instead of exit() - SWR */ + +typedef struct { + uint32_t state[5]; + uint32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(uint32_t state[5], unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len); /* +JHB */ +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#define blk0(i) (block->l[i] = ntohl(block->l[i])) +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +#ifdef VERBOSE /* SAK */ +void SHAPrintContext(SHA1_CTX *context, char *msg){ + printf("%s (%d,%d) %x %x %x %x %x\n", + msg, + context->count[0], context->count[1], + context->state[0], + context->state[1], + context->state[2], + context->state[3], + context->state[4]); +} +#endif + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(uint32_t state[5], unsigned char buffer[64]) +{ +uint32_t a, b, c, d, e; +typedef union { + unsigned char c[64]; + uint32_t l[16]; +} CHAR64LONG16; +CHAR64LONG16* block; +#ifdef SHA1HANDSOFF +static unsigned char workspace[64]; + block = (CHAR64LONG16*)workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len) /* +JHB */ +{ +uint32_t i, j; /* JHB */ + +#ifdef VERBOSE + SHAPrintContext(context, "before"); +#endif + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +#ifdef VERBOSE + SHAPrintContext(context, "after "); +#endif +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +uint32_t i; /* JHB */ +unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() +*/ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = 0; /* JHB */ + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(finalcount, 0, 8); /* SWR */ +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + +/*************************************************************/ + +/* This is not quite the MIME base64 algorithm: it uses _ instead of /, + and instead of padding the output with = characters we just make the + output shorter. */ +char *mybase64(uint8_t digest[20]) +{ + static const char charz[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + uint8_t input[21]; + static char output[28]; + int i, j; + uint8_t *p; + char *q; + uint32_t bv; + + memcpy(input, digest, 20); + input[20] = 0; /* Pad to multiple of 3 bytes */ + + p = input; q = output; + for ( i = 0 ; i < 7 ; i++ ) { + bv = (p[0] << 16) | (p[1] << 8) | p[2]; + p += 3; + for ( j = 0 ; j < 4 ; j++ ) { + *q++ = charz[(bv >> 18) & 0x3f]; + bv <<= 6; + } + } + *--q = '\0'; /* The last character is not significant */ + return output; +} + +int main(int argc, char** argv) +{ + int i; + SHA1_CTX context; + uint8_t digest[20], buffer[16384]; + FILE* file; + + if (argc < 2) { + file = stdin; + } + else { + if (!(file = fopen(argv[1], "rb"))) { + fputs("Unable to open file.", stderr); + return(-1); + } + } + SHA1Init(&context); + while (!feof(file)) { /* note: what if ferror(file) */ + i = fread(buffer, 1, 16384, file); + SHA1Update(&context, buffer, i); + } + SHA1Final(digest, &context); + fclose(file); + + puts(mybase64(digest)); + + return 0; +} diff --git a/usr/klibc/sigabbrev.c b/usr/klibc/sigabbrev.c new file mode 100644 index 0000000..21a799c --- /dev/null +++ b/usr/klibc/sigabbrev.c @@ -0,0 +1,121 @@ +/* + * sigabbrev.h + * + * Construct the abbreviated signal list + */ + +#include +#include + +const char *const sys_sigabbrev[NSIG] = { +#ifdef SIGABRT + [SIGABRT] = "ABRT", +#endif +#ifdef SIGALRM + [SIGALRM] = "ALRM", +#endif +#ifdef SIGBUS + [SIGBUS] = "BUS", +#endif +#ifdef SIGCHLD + [SIGCHLD] = "CHLD", +#endif +#if defined(SIGCLD) && (SIGCHLD != SIGCLD) + [SIGCLD] = "CLD", +#endif +#ifdef SIGEMT + [SIGEMT] = "EMT", +#endif +#ifdef SIGFPE + [SIGFPE] = "FPE", +#endif +#ifdef SIGHUP + [SIGHUP] = "HUP", +#endif +#ifdef SIGILL + [SIGILL] = "ILL", +#endif + /* SIGINFO == SIGPWR */ +#ifdef SIGINT + [SIGINT] = "INT", +#endif +#ifdef SIGIO + [SIGIO] = "IO", +#endif +#if defined(SIGIOT) && (SIGIOT != SIGABRT) + [SIGIOT] = "IOT", +#endif +#ifdef SIGKILL + [SIGKILL] = "KILL", +#endif +#if defined(SIGLOST) && (SIGLOST != SIGIO) && (SIGLOST != SIGPWR) + [SIGLOST] = "LOST", +#endif +#ifdef SIGPIPE + [SIGPIPE] = "PIPE", +#endif +#if defined(SIGPOLL) && (SIGPOLL != SIGIO) + [SIGPOLL] = "POLL", +#endif +#ifdef SIGPROF + [SIGPROF] = "PROF", +#endif +#ifdef SIGPWR + [SIGPWR] = "PWR", +#endif +#ifdef SIGQUIT + [SIGQUIT] = "QUIT", +#endif + /* SIGRESERVE == SIGUNUSED */ +#ifdef SIGSEGV + [SIGSEGV] = "SEGV", +#endif +#ifdef SIGSTKFLT + [SIGSTKFLT] = "STKFLT", +#endif +#ifdef SIGSTOP + [SIGSTOP] = "STOP", +#endif +#ifdef SIGSYS + [SIGSYS] = "SYS", +#endif +#ifdef SIGTERM + [SIGTERM] = "TERM", +#endif +#ifdef SIGTSTP + [SIGTSTP] = "TSTP", +#endif +#ifdef SIGTTIN + [SIGTTIN] = "TTIN", +#endif +#ifdef SIGTTOU + [SIGTTOU] = "TTOU", +#endif +#ifdef SIGURG + [SIGURG] = "URG", +#endif +#ifdef SIGUSR1 + [SIGUSR1] = "USR1", +#endif +#ifdef SIGUSR2 + [SIGUSR2] = "USR2", +#endif +#ifdef SIGVTALRM + [SIGVTALRM] = "VTALRM", +#endif +#ifdef SIGWINCH + [SIGWINCH] = "WINCH", +#endif +#ifdef SIGXCPU + [SIGXCPU] = "XCPU", +#endif +#ifdef SIGXFSZ + [SIGXFSZ] = "XFSZ", +#endif +#ifdef SIGTRAP + [SIGTRAP] = "TRAP", +#endif +#ifdef SIGCONT + [SIGCONT] = "CONT", +#endif +}; diff --git a/usr/klibc/sigaction.c b/usr/klibc/sigaction.c new file mode 100644 index 0000000..658c3ad --- /dev/null +++ b/usr/klibc/sigaction.c @@ -0,0 +1,60 @@ +/* + * sigaction.c + */ + +#include +#include +#include + +__extern void __sigreturn(void); +__extern int __sigaction(int, const struct sigaction *, struct sigaction *); +#ifdef __sparc__ +__extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *, + void (*)(void), size_t); +#else +__extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *, + size_t); +#endif + +int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + int rv; + +#if _KLIBC_NEEDS_SA_RESTORER + struct sigaction sa; + + if (act && !(act->sa_flags & SA_RESTORER)) { + sa = *act; + act = &sa; + + /* The kernel can't be trusted to have a valid default + restorer */ + sa.sa_flags |= SA_RESTORER; + sa.sa_restorer = &__sigreturn; + } +#endif + +#if _KLIBC_USE_RT_SIG +# ifdef __sparc__ + { + void (*restorer)(void); + restorer = (act && act->sa_flags & SA_RESTORER) + ? (void (*)(void))((uintptr_t)act->sa_restorer - 8) + : NULL; + rv = __rt_sigaction(sig, act, oact, restorer, sizeof(sigset_t)); + } +# else + rv = __rt_sigaction(sig, act, oact, sizeof(sigset_t)); +# endif +#else + rv = __sigaction(sig, act, oact); +#endif + +#if _KLIBC_NEEDS_SA_RESTORER + if (oact && (oact->sa_restorer == &__sigreturn)) { + oact->sa_flags &= ~SA_RESTORER; + } +#endif + + return rv; +} diff --git a/usr/klibc/siglist.c b/usr/klibc/siglist.c new file mode 100644 index 0000000..d690049 --- /dev/null +++ b/usr/klibc/siglist.c @@ -0,0 +1,121 @@ +/* + * siglist.h + * + * Construct the signal list + */ + +#include +#include + +const char *const sys_siglist[NSIG] = { +#ifdef SIGABRT + [SIGABRT] = "Aborted", +#endif +#ifdef SIGALRM + [SIGALRM] = "Alarm clock", +#endif +#ifdef SIGBUS + [SIGBUS] = "Bus error", +#endif +#ifdef SIGCHLD + [SIGCHLD] = "Child exited", +#endif +#if defined(SIGCLD) && (SIGCHLD != SIGCLD) + [SIGCLD] = "Child exited", +#endif +#ifdef SIGEMT + [SIGEMT] = "Emulation trap", +#endif +#ifdef SIGFPE + [SIGFPE] = "Floating point exception", +#endif +#ifdef SIGHUP + [SIGHUP] = "Hangup", +#endif +#ifdef SIGILL + [SIGILL] = "Illegal instruction", +#endif + /* SIGINFO == SIGPWR */ +#ifdef SIGINT + [SIGINT] = "Interrupt", +#endif +#ifdef SIGIO + [SIGIO] = "I/O possible", +#endif +#if defined(SIGIOT) && (SIGIOT != SIGABRT) + [SIGIOT] = "I/O trap", +#endif +#ifdef SIGKILL + [SIGKILL] = "Killed", +#endif +#if defined(SIGLOST) && (SIGLOST != SIGIO) && (SIGLOST != SIGPWR) + [SIGLOST] = "Lock lost", +#endif +#ifdef SIGPIPE + [SIGPIPE] = "Broken pipe", +#endif +#if defined(SIGPOLL) && (SIGPOLL != SIGIO) + [SIGPOLL] = "Pollable event", +#endif +#ifdef SIGPROF + [SIGPROF] = "Profiling timer expired", +#endif +#ifdef SIGPWR + [SIGPWR] = "Power failure", +#endif +#ifdef SIGQUIT + [SIGQUIT] = "Quit", +#endif + /* SIGRESERVE == SIGUNUSED */ +#ifdef SIGSEGV + [SIGSEGV] = "Segment violation", +#endif +#ifdef SIGSTKFLT + [SIGSTKFLT] = "Stack fault", +#endif +#ifdef SIGSTOP + [SIGSTOP] = "Stopped (signal)", +#endif +#ifdef SIGSYS + [SIGSYS] = "Bad system call", +#endif +#ifdef SIGTERM + [SIGTERM] = "Terminated", +#endif +#ifdef SIGTSTP + [SIGTSTP] = "Stopped", +#endif +#ifdef SIGTTIN + [SIGTTIN] = "Stopped (tty input)", +#endif +#ifdef SIGTTOU + [SIGTTOU] = "Stopped (tty output)", +#endif +#ifdef SIGURG + [SIGURG] = "Urgent I/O condition", +#endif +#ifdef SIGUSR1 + [SIGUSR1] = "User signal 1", +#endif +#ifdef SIGUSR2 + [SIGUSR2] = "User signal 2", +#endif +#ifdef SIGVTALRM + [SIGVTALRM] = "Virtual timer expired", +#endif +#ifdef SIGWINCH + [SIGWINCH] = "Window size changed", +#endif +#ifdef SIGXCPU + [SIGXCPU] = "CPU time limit exceeded", +#endif +#ifdef SIGXFSZ + [SIGXFSZ] = "File size limit exceeded", +#endif +#ifdef SIGTRAP + [SIGTRAP] = "Trace/breakpoint trap", +#endif +#ifdef SIGCONT + [SIGCONT] = "Continue", +#endif +}; diff --git a/usr/klibc/siglongjmp.c b/usr/klibc/siglongjmp.c new file mode 100644 index 0000000..31042cb --- /dev/null +++ b/usr/klibc/siglongjmp.c @@ -0,0 +1,15 @@ +/* + * siglongjmp.c + * + * sigsetjmp() is a macro, by necessity (it's either that or write + * it in assembly), but siglongjmp() is a normal function. + */ + +#include +#include + +__noreturn siglongjmp(sigjmp_buf buf, int retval) +{ + sigprocmask(SIG_SETMASK, &buf->__sigs, NULL); + longjmp(buf->__jmpbuf, retval); +} diff --git a/usr/klibc/sigpending.c b/usr/klibc/sigpending.c new file mode 100644 index 0000000..26fd3e9 --- /dev/null +++ b/usr/klibc/sigpending.c @@ -0,0 +1,18 @@ +/* + * sigpending.c + */ + +#include +#include +#include + +#if _KLIBC_USE_RT_SIG + +__extern int __rt_sigpending(sigset_t *, size_t); + +int sigpending(sigset_t * set) +{ + return __rt_sigpending(set, sizeof(sigset_t)); +} + +#endif diff --git a/usr/klibc/sigprocmask.c b/usr/klibc/sigprocmask.c new file mode 100644 index 0000000..ea12c13 --- /dev/null +++ b/usr/klibc/sigprocmask.c @@ -0,0 +1,18 @@ +/* + * sigprocmask.c + */ + +#include +#include +#include + +#if _KLIBC_USE_RT_SIG + +__extern int __rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t); + +int sigprocmask(int how, const sigset_t * set, sigset_t * oset) +{ + return __rt_sigprocmask(how, set, oset, sizeof(sigset_t)); +} + +#endif diff --git a/usr/klibc/sigsuspend.c b/usr/klibc/sigsuspend.c new file mode 100644 index 0000000..4d910d5 --- /dev/null +++ b/usr/klibc/sigsuspend.c @@ -0,0 +1,18 @@ +/* + * sigsuspend.c + */ + +#include +#include +#include + +#if _KLIBC_USE_RT_SIG + +__extern int __rt_sigsuspend(const sigset_t *, size_t); + +int sigsuspend(const sigset_t * mask) +{ + return __rt_sigsuspend(mask, sizeof *mask); +} + +#endif diff --git a/usr/klibc/sleep.c b/usr/klibc/sleep.c new file mode 100644 index 0000000..750c51d --- /dev/null +++ b/usr/klibc/sleep.c @@ -0,0 +1,20 @@ +/* + * sleep.c + */ + +#include +#include + +unsigned int sleep(unsigned int seconds) +{ + struct timespec ts; + + ts.tv_sec = seconds; + ts.tv_nsec = 0; + if (!nanosleep(&ts, &ts)) + return 0; + else if (errno == EINTR) + return ts.tv_sec; + else + return -1; +} diff --git a/usr/klibc/snprintf.c b/usr/klibc/snprintf.c new file mode 100644 index 0000000..713b3cd --- /dev/null +++ b/usr/klibc/snprintf.c @@ -0,0 +1,16 @@ +/* + * snprintf.c + */ + +#include + +int snprintf(char *buffer, size_t n, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, n, format, ap); + va_end(ap); + return rv; +} diff --git a/usr/klibc/socketcalls.pl b/usr/klibc/socketcalls.pl new file mode 100644 index 0000000..e6f75ab --- /dev/null +++ b/usr/klibc/socketcalls.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl + +$v = $ENV{'KBUILD_VERBOSE'}; +$quiet = defined($v) ? !$v : 0; + +@args = (); +for $arg ( @ARGV ) { + if ( $arg =~ /^-/ ) { + if ( $arg eq '-q' ) { + $quiet = 1; + } else { + die "$0: Unknown option: $arg\n"; + } + } else { + push(@args, $arg); + } +} +($file, $arch, $outputdir) = @args; + +if (!open(FILE, "< $file")) { + die "$file: $!\n"; +} + +print "socketcall-objs := "; +while ( defined($line = ) ) { + chomp $line; + $line =~ s/\s*(|\#.*|\/\/.*)$//; # Strip comments and trailing blanks + next unless $line; + + if ( $line =~ /^\s*\<\?\>\s*(.*)\s+([_a-zA-Z][_a-zA-Z0-9]+)\s*\((.*)\)\s*\;$/ ) { + $type = $1; + $name = $2; + $argv = $3; + + @args = split(/\s*\,\s*/, $argv); + @cargs = (); + + $i = 0; + for $arg ( @args ) { + push(@cargs, "$arg a".$i++); + } + $nargs = $i; + print " \\\n\t${name}.o"; + + if ( $arch eq 'i386' ) { + open(OUT, "> ${outputdir}/${name}.S") + or die "$0: Cannot open ${outputdir}/${name}.S\n"; + + print OUT "#include \n"; + print OUT "\n"; + print OUT "\t.text\n"; + print OUT "\t.align 4\n"; + print OUT "\t.globl ${name}\n"; + print OUT "\t.type ${name},\@function\n"; + print OUT "${name}:\n"; + print OUT "\tpushl \$SYS_\U${name}\n"; + print OUT "\tjmp __socketcall_common\n"; + print OUT "\t.size ${name},.-${name}\n"; + close(OUT); + } else { + open(OUT, "> ${outputdir}/${name}.c") + or die "$0: Cannot open ${outputdir}/${name}.c\n"; + + print OUT "#include \"socketcommon.h\"\n"; + print OUT "\n"; + print OUT "#ifndef __NR_${name}\n\n"; + + print OUT "extern long __socketcall(int, const unsigned long *);\n\n"; + + print OUT "$type $name (", join(', ', @cargs), ")\n"; + print OUT "{\n"; + print OUT " unsigned long args[$nargs];\n"; + for ( $i = 0 ; $i < $nargs ; $i++ ) { + print OUT " args[$i] = (unsigned long)a$i;\n"; + } + print OUT " return ($type) __socketcall(SYS_\U${name}\E, args);\n"; + print OUT "}\n\n"; + + print OUT "#endif\n"; + + close(OUT); + } + } else { + die "$file:$.: Could not parse input\n"; + } +} + +print "\n"; diff --git a/usr/klibc/socketcalls/Kbuild b/usr/klibc/socketcalls/Kbuild new file mode 100644 index 0000000..c106182 --- /dev/null +++ b/usr/klibc/socketcalls/Kbuild @@ -0,0 +1,50 @@ +# +# Generate socket calls based on SOCKETCALLS.def +# + +# Include automatically generated Makefile fragment. +# It contains definition of socketcall-objs specifying name of all .o files +ifeq ($(clean),) +-include $(obj)/socketcalls.mk +endif + +# Listing of all .o files +always := socketcalls.list + +##### +# Generate socket calls stubs +# Based on input from SOCKETCALLS.def generate socket call stubs +targets := socketcalls.list +targets += socketcalls.mk +targets += SOCKETCALLS.i +targets += $(socketcall-objs) +clean-files += *.S *.c *.o *.list + +EXTRA_KLIBCCFLAGS := -I$(srctree)/$(src) + +quiet_cmd_makelist = LIST $@ + cmd_makelist = echo '$(filter-out FORCE,$^)' > $@ + +# Create list of all files +$(obj)/socketcalls.list: $(call objectify,$(socketcall-objs)) FORCE + $(call if_changed,makelist) + +# Generate assembler file (.i) +# We pass -ansi to keep cpp from define e.g. "i386" as well as "__i386__" +quiet_cmd_socketcall.i = GEN $@ + cmd_socketcall.i = $(KLIBCCC) $(klibccflags) -D__ASSEMBLY__ \ + -ansi -x c -E -o $@ $< +$(obj)/SOCKETCALLS.i: $(KLIBCSRC)/SOCKETCALLS.def FORCE + $(call if_changed_dep,socketcall.i) + +# Generate socketcall stubs +quiet_cmd_socketcalls = GEN $@ + cmd_socketcalls = $(PERL) $(KLIBCSRC)/socketcalls.pl \ + $(obj)/SOCKETCALLS.i \ + $(KLIBCARCH) $(obj) > $@ \ + || ( rm -f $@ ; exit 1 ) + +$(obj)/socketcalls.mk: $(KLIBCSRC)/socketcalls.pl \ + $(obj)/SOCKETCALLS.i \ + $(src)/socketcommon.h + $(call cmd,socketcalls) diff --git a/usr/klibc/socketcalls/socketcommon.h b/usr/klibc/socketcalls/socketcommon.h new file mode 100644 index 0000000..9c4b11f --- /dev/null +++ b/usr/klibc/socketcalls/socketcommon.h @@ -0,0 +1,16 @@ +/* + * socketcommon.h + * + * Common header file for socketcall stubs + */ + +#define __IN_SYS_COMMON +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/usr/klibc/sprintf.c b/usr/klibc/sprintf.c new file mode 100644 index 0000000..c6d8758 --- /dev/null +++ b/usr/klibc/sprintf.c @@ -0,0 +1,18 @@ +/* + * sprintf.c + */ + +#include +#include + +int sprintf(char *buffer, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsnprintf(buffer, ~(size_t) 0, format, ap); + va_end(ap); + + return rv; +} diff --git a/usr/klibc/srand48.c b/usr/klibc/srand48.c new file mode 100644 index 0000000..e1c9567 --- /dev/null +++ b/usr/klibc/srand48.c @@ -0,0 +1,15 @@ +/* + * srand48.c + */ + +#include +#include + +unsigned short __rand48_seed[3]; /* Common with mrand48.c, lrand48.c */ + +void srand48(long seedval) +{ + __rand48_seed[0] = 0x330e; + __rand48_seed[1] = (unsigned short)seedval; + __rand48_seed[2] = (unsigned short)((uint32_t) seedval >> 16); +} diff --git a/usr/klibc/sscanf.c b/usr/klibc/sscanf.c new file mode 100644 index 0000000..f53b276 --- /dev/null +++ b/usr/klibc/sscanf.c @@ -0,0 +1,17 @@ +/* + * sscanf() + */ + +#include + +int sscanf(const char *str, const char *format, ...) +{ + va_list ap; + int rv; + + va_start(ap, format); + rv = vsscanf(str, format, ap); + va_end(ap); + + return rv; +} diff --git a/usr/klibc/statfs.c b/usr/klibc/statfs.c new file mode 100644 index 0000000..b8b8700 --- /dev/null +++ b/usr/klibc/statfs.c @@ -0,0 +1,19 @@ +/* + * statfs.c + * + * On architectures which do statfs64, wrap the system call + */ + +#include +#include + +#ifdef __NR_statfs64 + +extern int __statfs64(const char *, size_t, struct statfs *); + +int statfs(const char *path, struct statfs *buf) +{ + return __statfs64(path, sizeof *buf, buf); +} + +#endif diff --git a/usr/klibc/strcasecmp.c b/usr/klibc/strcasecmp.c new file mode 100644 index 0000000..ee1f28b --- /dev/null +++ b/usr/klibc/strcasecmp.c @@ -0,0 +1,24 @@ +/* + * strcasecmp.c + */ + +#include +#include + +int strcasecmp(const char *s1, const char *s2) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (1) { + /* toupper() expects an unsigned char (implicitly cast to int) + as input, and returns an int, which is exactly what we want. */ + d = toupper(ch = *c1++) - toupper(*c2++); + if (d || !ch) + break; + } + + return d; +} diff --git a/usr/klibc/strcat.c b/usr/klibc/strcat.c new file mode 100644 index 0000000..6c5b673 --- /dev/null +++ b/usr/klibc/strcat.c @@ -0,0 +1,11 @@ +/* + * strcat.c + */ + +#include + +char *strcat(char *dst, const char *src) +{ + strcpy(strchr(dst, '\0'), src); + return dst; +} diff --git a/usr/klibc/strchr.c b/usr/klibc/strchr.c new file mode 100644 index 0000000..6040cc4 --- /dev/null +++ b/usr/klibc/strchr.c @@ -0,0 +1,19 @@ +/* + * strchr.c + */ + +#include +#include + +char *strchr(const char *s, int c) +{ + while (*s != (char)c) { + if (!*s) + return NULL; + s++; + } + + return (char *)s; +} + +__ALIAS(char *, index, (const char *, int), strchr) diff --git a/usr/klibc/strcmp.c b/usr/klibc/strcmp.c new file mode 100644 index 0000000..3ab9f5a --- /dev/null +++ b/usr/klibc/strcmp.c @@ -0,0 +1,21 @@ +/* + * strcmp.c + */ + +#include + +int strcmp(const char *s1, const char *s2) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (1) { + d = (int)(ch = *c1++) - (int)*c2++; + if (d || !ch) + break; + } + + return d; +} diff --git a/usr/klibc/strcpy.c b/usr/klibc/strcpy.c new file mode 100644 index 0000000..aa656cf --- /dev/null +++ b/usr/klibc/strcpy.c @@ -0,0 +1,20 @@ +/* + * strcpy.c + * + * strcpy() + */ + +#include + +char *strcpy(char *dst, const char *src) +{ + char *q = dst; + const char *p = src; + char ch; + + do { + *q++ = ch = *p++; + } while (ch); + + return dst; +} diff --git a/usr/klibc/strcspn.c b/usr/klibc/strcspn.c new file mode 100644 index 0000000..bb3ac72 --- /dev/null +++ b/usr/klibc/strcspn.c @@ -0,0 +1,10 @@ +/* + * strcspn + */ + +#include "strxspn.h" + +size_t strcspn(const char *s, const char *reject) +{ + return __strxspn(s, reject, 1); +} diff --git a/usr/klibc/strdup.c b/usr/klibc/strdup.c new file mode 100644 index 0000000..905b51d --- /dev/null +++ b/usr/klibc/strdup.c @@ -0,0 +1,17 @@ +/* + * strdup.c + */ + +#include +#include + +char *strdup(const char *s) +{ + int l = strlen(s) + 1; + char *d = malloc(l); + + if (d) + memcpy(d, s, l); + + return d; +} diff --git a/usr/klibc/strerror.c b/usr/klibc/strerror.c new file mode 100644 index 0000000..fed0e49 --- /dev/null +++ b/usr/klibc/strerror.c @@ -0,0 +1,33 @@ +/* + * strerror.c + */ + +#include + +char *strerror(int errnum) +{ + static char message[32] = "error "; /* enough for error 2^63-1 */ + char numbuf[32]; + char *p; + unsigned int e = (unsigned int)errnum; + +#ifdef WITH_ERRLIST + extern const int sys_nerr; + extern const char *const sys_errlist[]; + + if (e < (unsigned int)sys_nerr && sys_errlist[e]) + return (char *)sys_errlist[e]; +#endif + + p = numbuf + sizeof numbuf; + *--p = '\0'; + + do { + *--p = (e % 10) + '0'; + e /= 10; + } while (e); + + memcpy(message + 6, p, (numbuf + sizeof numbuf) - p); + + return message; +} diff --git a/usr/klibc/strlcat.c b/usr/klibc/strlcat.c new file mode 100644 index 0000000..80c3375 --- /dev/null +++ b/usr/klibc/strlcat.c @@ -0,0 +1,31 @@ +/* + * strlcat.c + */ + +#include +#include + +size_t strlcat(char *dst, const char *src, size_t size) +{ + size_t bytes = 0; + char *q = dst; + const char *p = src; + char ch; + + while (bytes < size && *q) { + q++; + bytes++; + } + if (bytes == size) + return (bytes + strlen(src)); + + while ((ch = *p++)) { + if (bytes + 1 < size) + *q++ = ch; + + bytes++; + } + + *q = '\0'; + return bytes; +} diff --git a/usr/klibc/strlcpy.c b/usr/klibc/strlcpy.c new file mode 100644 index 0000000..51c72d8 --- /dev/null +++ b/usr/klibc/strlcpy.c @@ -0,0 +1,27 @@ +/* + * strlcpy.c + */ + +#include +#include + +size_t strlcpy(char *dst, const char *src, size_t size) +{ + size_t bytes = 0; + char *q = dst; + const char *p = src; + char ch; + + while ((ch = *p++)) { + if (bytes + 1 < size) + *q++ = ch; + + bytes++; + } + + /* If size == 0 there is no space for a final null... */ + if (size) + *q = '\0'; + + return bytes; +} diff --git a/usr/klibc/strlen.c b/usr/klibc/strlen.c new file mode 100644 index 0000000..86526a5 --- /dev/null +++ b/usr/klibc/strlen.c @@ -0,0 +1,13 @@ +/* + * strlen() + */ + +#include + +size_t strlen(const char *s) +{ + const char *ss = s; + while (*ss) + ss++; + return ss - s; +} diff --git a/usr/klibc/strncasecmp.c b/usr/klibc/strncasecmp.c new file mode 100644 index 0000000..0551935 --- /dev/null +++ b/usr/klibc/strncasecmp.c @@ -0,0 +1,24 @@ +/* + * strncasecmp.c + */ + +#include +#include + +int strncasecmp(const char *s1, const char *s2, size_t n) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (n--) { + /* toupper() expects an unsigned char (implicitly cast to int) + as input, and returns an int, which is exactly what we want. */ + d = toupper(ch = *c1++) - toupper(*c2++); + if (d || !ch) + break; + } + + return d; +} diff --git a/usr/klibc/strncat.c b/usr/klibc/strncat.c new file mode 100644 index 0000000..beb026c --- /dev/null +++ b/usr/klibc/strncat.c @@ -0,0 +1,22 @@ +/* + * strncat.c + */ + +#include +#include + +char *strncat(char *dst, const char *src, size_t n) +{ + char *q = strchr(dst, '\0'); + const char *p = src; + char ch; + + while (n--) { + *q++ = ch = *p++; + if (!ch) + return dst; + } + *q = '\0'; + + return dst; +} diff --git a/usr/klibc/strncmp.c b/usr/klibc/strncmp.c new file mode 100644 index 0000000..5235545 --- /dev/null +++ b/usr/klibc/strncmp.c @@ -0,0 +1,21 @@ +/* + * strncmp.c + */ + +#include + +int strncmp(const char *s1, const char *s2, size_t n) +{ + const unsigned char *c1 = (const unsigned char *)s1; + const unsigned char *c2 = (const unsigned char *)s2; + unsigned char ch; + int d = 0; + + while (n--) { + d = (int)(ch = *c1++) - (int)*c2++; + if (d || !ch) + break; + } + + return d; +} diff --git a/usr/klibc/strncpy.c b/usr/klibc/strncpy.c new file mode 100644 index 0000000..fffc118 --- /dev/null +++ b/usr/klibc/strncpy.c @@ -0,0 +1,24 @@ +/* + * strncpy.c + */ + +#include + +char *strncpy(char *dst, const char *src, size_t n) +{ + char *q = dst; + const char *p = src; + char ch; + + while (n) { + n--; + *q++ = ch = *p++; + if (!ch) + break; + } + + /* The specs say strncpy() fills the entire buffer with NUL. Sigh. */ + memset(q, 0, n); + + return dst; +} diff --git a/usr/klibc/strndup.c b/usr/klibc/strndup.c new file mode 100644 index 0000000..8b5974a --- /dev/null +++ b/usr/klibc/strndup.c @@ -0,0 +1,17 @@ +/* + * strndup.c + */ + +#include +#include + +char *strndup(const char *s, size_t n) +{ + int l = n > strlen(s) ? strlen(s) + 1 : n + 1; + char *d = malloc(l); + + if (d) + memcpy(d, s, l); + d[n] = '\0'; + return d; +} diff --git a/usr/klibc/strnlen.c b/usr/klibc/strnlen.c new file mode 100644 index 0000000..1678f4b --- /dev/null +++ b/usr/klibc/strnlen.c @@ -0,0 +1,18 @@ +/* + * strnlen() + */ + +#include + +size_t strnlen(const char *s, size_t maxlen) +{ + const char *ss = s; + + /* Important: the maxlen test must precede the reference through ss; + since the byte beyond the maximum may segfault */ + while ((maxlen > 0) && *ss) { + ss++; + maxlen--; + } + return ss - s; +} diff --git a/usr/klibc/strntoimax.c b/usr/klibc/strntoimax.c new file mode 100644 index 0000000..179d9e5 --- /dev/null +++ b/usr/klibc/strntoimax.c @@ -0,0 +1,13 @@ +/* + * strntoimax.c + * + * strntoimax() + */ + +#include +#include + +intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n) +{ + return (intmax_t) strntoumax(nptr, endptr, base, n); +} diff --git a/usr/klibc/strntoumax.c b/usr/klibc/strntoumax.c new file mode 100644 index 0000000..3440967 --- /dev/null +++ b/usr/klibc/strntoumax.c @@ -0,0 +1,76 @@ +/* + * strntoumax.c + * + * The strntoumax() function and associated + */ + +#include +#include +#include + +static inline int digitval(int ch) +{ + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } else if (ch >= 'A' && ch <= 'Z') { + return ch - 'A' + 10; + } else if (ch >= 'a' && ch <= 'z') { + return ch - 'a' + 10; + } else { + return -1; + } +} + +uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) +{ + int minus = 0; + uintmax_t v = 0; + int d; + + while (n && isspace((unsigned char)*nptr)) { + nptr++; + n--; + } + + /* Single optional + or - */ + if (n) { + char c = *nptr; + if (c == '-' || c == '+') { + minus = (c == '-'); + nptr++; + n--; + } + } + + if (base == 0) { + if (n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + base = 16; + } else if (n >= 1 && nptr[0] == '0') { + n--; + nptr++; + base = 8; + } else { + base = 10; + } + } else if (base == 16) { + if (n >= 2 && nptr[0] == '0' && + (nptr[1] == 'x' || nptr[1] == 'X')) { + n -= 2; + nptr += 2; + } + } + + while (n && (d = digitval(*nptr)) >= 0 && d < base) { + v = v * base + d; + n--; + nptr++; + } + + if (endptr) + *endptr = (char *)nptr; + + return minus ? -v : v; +} diff --git a/usr/klibc/strpbrk.c b/usr/klibc/strpbrk.c new file mode 100644 index 0000000..ba53d02 --- /dev/null +++ b/usr/klibc/strpbrk.c @@ -0,0 +1,12 @@ +/* + * strpbrk + */ + +#include "strxspn.h" + +char *strpbrk(const char *s, const char *accept) +{ + const char *ss = s + __strxspn(s, accept, 1); + + return *ss ? (char *)ss : NULL; +} diff --git a/usr/klibc/strrchr.c b/usr/klibc/strrchr.c new file mode 100644 index 0000000..e36d37e --- /dev/null +++ b/usr/klibc/strrchr.c @@ -0,0 +1,21 @@ +/* + * strrchr.c + */ + +#include +#include + +char *strrchr(const char *s, int c) +{ + const char *found = NULL; + + while (*s) { + if (*s == (char)c) + found = s; + s++; + } + + return (char *)found; +} + +__ALIAS(char *, rindex, (const char *, int), strrchr) diff --git a/usr/klibc/strsep.c b/usr/klibc/strsep.c new file mode 100644 index 0000000..44e76bd --- /dev/null +++ b/usr/klibc/strsep.c @@ -0,0 +1,21 @@ +/* + * strsep.c + */ + +#include + +char *strsep(char **stringp, const char *delim) +{ + char *s = *stringp; + char *e; + + if (!s) + return NULL; + + e = strpbrk(s, delim); + if (e) + *e++ = '\0'; + + *stringp = e; + return s; +} diff --git a/usr/klibc/strsignal.c b/usr/klibc/strsignal.c new file mode 100644 index 0000000..e345e9c --- /dev/null +++ b/usr/klibc/strsignal.c @@ -0,0 +1,26 @@ +/* + * strsignal.c + */ + +#include +#include +#include + +char *strsignal(int sig) +{ + static char buf[64]; + + if ((unsigned)sig < _NSIG && sys_siglist[sig]) + return (char *)sys_siglist[sig]; + +#ifdef SIGRTMIN + if (sig >= SIGRTMIN && sig <= SIGRTMAX) { + snprintf(buf, sizeof buf, "Real-time signal %d", + sig - SIGRTMIN); + return buf; + } +#endif + + snprintf(buf, sizeof buf, "Signal %d", sig); + return buf; +} diff --git a/usr/klibc/strspn.c b/usr/klibc/strspn.c new file mode 100644 index 0000000..1222ce4 --- /dev/null +++ b/usr/klibc/strspn.c @@ -0,0 +1,10 @@ +/* + * strspn + */ + +#include "strxspn.h" + +size_t strspn(const char *s, const char *accept) +{ + return __strxspn(s, accept, 0); +} diff --git a/usr/klibc/strstr.c b/usr/klibc/strstr.c new file mode 100644 index 0000000..8850858 --- /dev/null +++ b/usr/klibc/strstr.c @@ -0,0 +1,11 @@ +/* + * strstr.c + */ + +#include + +char *strstr(const char *haystack, const char *needle) +{ + return (char *)memmem(haystack, strlen(haystack), needle, + strlen(needle)); +} diff --git a/usr/klibc/strtoimax.c b/usr/klibc/strtoimax.c new file mode 100644 index 0000000..0cdd088 --- /dev/null +++ b/usr/klibc/strtoimax.c @@ -0,0 +1,3 @@ +#define TYPE intmax_t +#define NAME strtoimax +#include "strtox.c" diff --git a/usr/klibc/strtok.c b/usr/klibc/strtok.c new file mode 100644 index 0000000..24aaad0 --- /dev/null +++ b/usr/klibc/strtok.c @@ -0,0 +1,15 @@ +/* + * strtok.c + */ + +#include + +char *strtok(char *s, const char *delim) +{ + static char *holder; + + if (s) + holder = s; + + return strsep(&holder, delim); +} diff --git a/usr/klibc/strtol.c b/usr/klibc/strtol.c new file mode 100644 index 0000000..9efc8b9 --- /dev/null +++ b/usr/klibc/strtol.c @@ -0,0 +1,3 @@ +#define TYPE signed long +#define NAME strtol +#include "strtox.c" diff --git a/usr/klibc/strtoll.c b/usr/klibc/strtoll.c new file mode 100644 index 0000000..a9428c7 --- /dev/null +++ b/usr/klibc/strtoll.c @@ -0,0 +1,3 @@ +#define TYPE signed long long +#define NAME strtoll +#include "strtox.c" diff --git a/usr/klibc/strtotimespec.c b/usr/klibc/strtotimespec.c new file mode 100644 index 0000000..b426bf8 --- /dev/null +++ b/usr/klibc/strtotimespec.c @@ -0,0 +1,5 @@ +#define NAME strtotimespec +#define TIMEX struct timespec +#define FSEC tv_nsec +#define DECIMALS 9 +#include "strtotimex.c" diff --git a/usr/klibc/strtotimeval.c b/usr/klibc/strtotimeval.c new file mode 100644 index 0000000..280d4bc --- /dev/null +++ b/usr/klibc/strtotimeval.c @@ -0,0 +1,5 @@ +#define NAME strtotimeval +#define TIMEX struct timeval +#define FSEC tv_usec +#define DECIMALS 6 +#include "strtotimex.c" diff --git a/usr/klibc/strtotimex.c b/usr/klibc/strtotimex.c new file mode 100644 index 0000000..7f59a4f --- /dev/null +++ b/usr/klibc/strtotimex.c @@ -0,0 +1,39 @@ +/* + * strtotimex.c + * + * Nonstandard function which takes a string and converts it to a + * struct timespec/timeval. Returns a pointer to the first non-numeric + * character in the string. + * + */ + +#include +#include +#include +#include + +char *NAME(const char *str, TIMEX * ts) +{ + int n; + char *s, *s0; + __typeof__(ts->FSEC) fs; /* Fractional seconds */ + + ts->tv_sec = strntoumax(str, &s, 10, ~(size_t) 0); + fs = 0; + + if (*s == '.') { + s0 = s + 1; + + fs = strntoumax(s0, &s, 10, DECIMALS); + n = s - s0; + + while (isdigit(*s)) + s++; + + for (; n < DECIMALS; n++) + fs *= 10; + } + + ts->FSEC = fs; + return s; +} diff --git a/usr/klibc/strtoul.c b/usr/klibc/strtoul.c new file mode 100644 index 0000000..3189aaa --- /dev/null +++ b/usr/klibc/strtoul.c @@ -0,0 +1,3 @@ +#define TYPE unsigned long +#define NAME strtoul +#include "strtox.c" diff --git a/usr/klibc/strtoull.c b/usr/klibc/strtoull.c new file mode 100644 index 0000000..83c14e9 --- /dev/null +++ b/usr/klibc/strtoull.c @@ -0,0 +1,3 @@ +#define TYPE unsigned long long +#define NAME strtoull +#include "strtox.c" diff --git a/usr/klibc/strtoumax.c b/usr/klibc/strtoumax.c new file mode 100644 index 0000000..a379710 --- /dev/null +++ b/usr/klibc/strtoumax.c @@ -0,0 +1,3 @@ +#define TYPE uintmax_t +#define NAME strtoumax +#include "strtox.c" diff --git a/usr/klibc/strtox.c b/usr/klibc/strtox.c new file mode 100644 index 0000000..54bdefc --- /dev/null +++ b/usr/klibc/strtox.c @@ -0,0 +1,13 @@ +/* + * strtox.c + * + * strto...() functions, by macro definition + */ + +#include +#include + +TYPE NAME(const char *nptr, char **endptr, int base) +{ + return (TYPE) strntoumax(nptr, endptr, base, ~(size_t) 0); +} diff --git a/usr/klibc/strxspn.c b/usr/klibc/strxspn.c new file mode 100644 index 0000000..99bdbff --- /dev/null +++ b/usr/klibc/strxspn.c @@ -0,0 +1,29 @@ +/* + * strpbrk + */ + +#include +#include +#include +#include +#include "strxspn.h" + +size_t __strxspn(const char *s, const char *map, int parity) +{ + char matchmap[UCHAR_MAX + 1]; + size_t n = 0; + + /* Create bitmap */ + memset(matchmap, 0, sizeof matchmap); + while (*map) + matchmap[(unsigned char)*map++] = 1; + + /* Make sure the null character never matches */ + matchmap[0] = parity; + + /* Calculate span length */ + while (matchmap[(unsigned char)*s++] ^ parity) + n++; + + return n; +} diff --git a/usr/klibc/strxspn.h b/usr/klibc/strxspn.h new file mode 100644 index 0000000..ce56ff2 --- /dev/null +++ b/usr/klibc/strxspn.h @@ -0,0 +1,12 @@ +/* + * strxspn.h + */ + +#ifndef STRXSPN_H +#define STRXSPN_H + +#include + +extern size_t __strxspn(const char *s, const char *map, int parity); + +#endif diff --git a/usr/klibc/syscalls.pl b/usr/klibc/syscalls.pl new file mode 100644 index 0000000..3ff0222 --- /dev/null +++ b/usr/klibc/syscalls.pl @@ -0,0 +1,286 @@ +#!/usr/bin/perl +# +# Script to parse the SYSCALLS file and generate appropriate +# stubs. +# +# Pass 1: generate the C array of sizes +# Pass 2: generate the syscall stubs and other output +# + +# +# Convert a string to a C array of characters, +# e.g. foo -> 'f','o','o','\0', +# +sub chararray($) { + use bytes; + + my($s) = @_; + my($i, $c); + my($a) = ''; + + for ($i = 0; $i < length($s); $i++) { + $c = substr($s, $i, 1); + if (ord($c) < 32 || ord($c) > 126) { + $a .= sprintf("0x%02x,", ord($c)); + } elsif ($c eq "\\" || $c eq "\'") { + $a .= "\'\\$c\',"; + } else { + $a .= "\'$c\',"; + } + } + + return $a; +} + +# +# This extracts an ASCIIZ string for the type and the additional +# information. This is open-coded, because unpack("Z*") apparently +# is broken in Perl 5.6.1. +# +sub get_one_type($) { + use bytes; + + my($typestr) = @_; + my $i, $c; + my $l = length($typestr); + + for ($i = 0; $i < $l-3; $i++) { + $c = substr($typestr, $i, 1); + if ($c eq "\0") { + return (substr($typestr, 0, $i), + unpack("CC", substr($typestr, $i+1, 2)), + substr($typestr, $i+3)); + } + } + + return (undef, undef, undef, undef); +} + +$v = $ENV{'KBUILD_VERBOSE'}; +$quiet = defined($v) && ($v == 0) ? 1 : undef; + +@args = (); +undef $pass; +for $arg ( @ARGV ) { + if ( $arg =~ /^-/ ) { + if ( $arg eq '-q' ) { + $quiet = 1; + } elsif ( $arg eq '-v' ) { + $quiet = 0; + } elsif ( $arg =~ /\-([0-9]+)$/ ) { + $pass = $1+0; + } else { + die "$0: Unknown option: $arg\n"; + } + } else { + push(@args, $arg); + } +} +($file, $sysstub, $arch, $bits, $unistd, $outputdir, + $havesyscall, $typesize) = @args; + +if (!$pass) { + die "$0: Need to specify pass\n"; +} + +$quiet = ($pass != 2) unless defined($quiet); + +require "$sysstub"; + +if (!open(UNISTD, "< $unistd\0")) { + die "$0: $unistd: $!\n"; +} + +while ( defined($line = ) ) { + chomp $line; + + if ( $line =~ /^\#\s*define\s+__NR_([A-Za-z0-9_]+)\s+(.*\S)\s*$/ ) { + $syscalls{$1} = $2; + print STDERR "SYSCALL FOUND: $1\n" unless ( $quiet ); + } +} +close(UNISTD); + +if ($pass == 2) { + use bytes; + + if (!open(TYPESIZE, "< $typesize\0")) { + die "$0: $typesize: $!\n"; + } + + binmode TYPESIZE; + + $len = -s TYPESIZE; + if (read(TYPESIZE, $typebin, $len) != $len) { + die "$0: $typesize: short read: $!\n"; + } + close(TYPESIZE); + + $ix = index($typebin, "\x7a\xc8\xdb\x4e\x97\xb4\x9c\x19"); + if ($ix < 0) { + die "$0: $typesize: magic number not found\n"; + } + + # Remove magic number and bytes before it + $typebin = substr($typebin, $ix+8); + + # Expand the types until a terminating null + %typesize = (); + while (1) { + my $n, $sz, $si; + ($n, $sz, $si, $typebin) = get_one_type($typebin); + last if (length($n) == 0); + $typesize{$n} = $sz; + $typesign{$n} = $si; + print STDERR "TYPE $n: size $sz, sign $si\n" unless ($quiet); + } +} else { + # List here any types which should be sized even if they never occur + # in any system calls at all. + %type_list = ('int' => 1, 'long' => 1, 'long long' => 1, + 'void *' => 1, + 'intptr_t' => 1, 'uintptr_t' => 1, + 'intmax_t' => 1, 'uintmax_t' => 1); +} + +if ($pass == 2) { + if (!open(HAVESYS, "> $havesyscall\0")) { + die "$0: $havesyscall: $!\n"; + } + + print HAVESYS "#ifndef _KLIBC_HAVESYSCALL_H\n"; + print HAVESYS "#define _KLIBC_HAVESYSCALL_H 1\n\n"; +} + +if (!open(FILE, "< $file\0")) { + die "$0: $file: $!\n"; +} + + +if ($pass == 2) { + print "syscall-objs := "; +} + + +while ( defined($line = ) ) { + chomp $line; + $line =~ s/\s*(|\#.*|\/\/.*)$//; # Strip comments and trailing blanks + next unless $line; + + if ( $line =~ /^\s*(\<[^\>]+\>\s+|)([A-Za-z0-9_\*\s]+)\s+([A-Za-z0-9_,]+)(|\@[A-Za-z0-9_]+)(|\:\:[A-Za-z0-9_]+)\s*\(([^\:\)]*)\)\s*\;$/ ) { + $archs = $1; + $type = $2; + $snames = $3; + $stype = $4; + $fname = $5; + $argv = $6; + + $doit = 1; + $maybe = 0; + if ( $archs ne '' ) { + die "$file:$.: Invalid architecture spec: <$archs>\n" + unless ( $archs =~ /^\<(|\?)(|\!)([^\>\!\?]*)\>/ ); + $maybe = $1 ne ''; + $not = $2 ne ''; + $list = $3; + + $doit = $not || ($list eq ''); + + @list = split(/,/, $list); + foreach $a ( @list ) { + if ( $a eq $arch || $a eq $bits ) { + $doit = !$not; + last; + } + } + } + next if ( ! $doit ); + + undef $sname; + foreach $sn ( split(/,/, $snames) ) { + if ( defined $syscalls{$sn} ) { + $sname = $sn; + last; + } + } + if ( !defined($sname) ) { + next if ( $maybe ); + die "$file:$.: Undefined system call: $snames\n"; + } + + $type =~ s/\s*$//; + $stype =~ s/^\@//; + + if ( $fname eq '' ) { + $fname = $sname; + } else { + $fname =~ s/^\:\://; + } + + $argv =~ s/^\s+//; + $argv =~ s/\s+$//; + + if ($argv eq 'void') { + @args = (); + } else { + @args = split(/\s*\,\s*/, $argv); + } + + if ($pass == 1) { + # Pass 1: Add the types to the type list + foreach $a (@args) { + $type_list{$a}++; + } + } else { + # Pass 2: make sure all types defined, and actually generate stubs + + foreach $a (@args) { + if (!defined($typesize{$a})) { + die "$0: $typesize: type name missing: $a\n"; + } + } + + print HAVESYS "#define _KLIBC_HAVE_SYSCALL_${fname} ${sname}\n"; + print " \\\n\t${fname}.o"; + make_sysstub($outputdir, $fname, $type, $sname, $stype, @args); + } + } else { + die "$file:$.: Could not parse input: \"$line\"\n"; + } +} + +if ($pass == 1) { + # Pass 1: generate typesize.c + if (!open(TYPESIZE, "> $typesize")) { + die "$0: cannot create file: $typesize: $!\n"; + } + + print TYPESIZE "#include \"syscommon.h\"\n"; + + # This compares -2 < 1 in the appropriate type, which is true for + # signed types and false for unsigned types. We use -2 and 1 since + # gcc complains about comparing unsigned types with zero, and might + # complain equally about -1 in the future. + # + # This test is valid (as in, doesn't cause the compiler to barf) + # for pointers as well as for integral types; if we ever add system + # calls which take any other kinds of types than that then this needs + # to be smarter. + print TYPESIZE "#define SIGNED(X) ((X)-2 < (X)1)\n"; + + print TYPESIZE "\n"; + print TYPESIZE "const unsigned char type_sizes[] = {\n"; + print TYPESIZE "\t0x7a,0xc8,0xdb,0x4e,0x97,0xb4,0x9c,0x19, /* magic */\n"; + foreach $t (sort(keys(%type_list))) { + print TYPESIZE "\t", chararray($t), "0, sizeof($t), SIGNED($t),\n"; + } + print TYPESIZE "\t0, 0,\n"; # End sentinel + print TYPESIZE "};\n"; + close(TYPESIZE); +} else { + # Pass 2: finalize output files + print "\n"; + + print HAVESYS "\n#endif\n"; + close(HAVESYS); +} diff --git a/usr/klibc/syscalls/Kbuild b/usr/klibc/syscalls/Kbuild new file mode 100644 index 0000000..a1d408d --- /dev/null +++ b/usr/klibc/syscalls/Kbuild @@ -0,0 +1,94 @@ +# +# kbuild file for generating syscall stubs +# + +# Include automatically generated Makefile fragment. +# It contains definition of syscall-objs specifying name of all .o files +ifeq ($(clean),) +-include $(obj)/syscalls.mk +endif + +# Listing of all .o files +always := syscalls.list + + +##### +# Generate syscalls stubs +# Based on list in SYSCALLS.def generate stubs for sys calls. Actual arch code +# is defined in an arch specific perl file +targets += syscalls.mk +targets += syscalls.list +targets += SYSCALLS.i syscalls.nrs +targets += typesize.c typesize.o typesize.bin +targets += $(syscall-objs) + +# Side effect of running syscalls.pl +clean-files += $(objtree)/$(KLIBCINC)/klibc/havesyscall.h +clean-files += $(KLIBCINC)/klibc/havesyscall.h +# All the syscall stubs +clean-files += *.o *.S *.c *.list *.bin + +EXTRA_KLIBCCFLAGS := -I$(srctree)/$(src) + +quiet_cmd_makelist = LIST $@ + cmd_makelist = echo '$(filter-out FORCE,$^)' > $@ + +# Create list of all files +$(obj)/syscalls.list: $(call objectify,$(syscall-objs)) FORCE + $(call if_changed,makelist) + +# Generate assembler file (.i) +# We pass -ansi to keep cpp from define e.g. "i386" as well as "__i386__" +quiet_cmd_syscall.i = GEN $@ + cmd_syscall.i = $(KLIBCCC) $(klibccflags) -D__ASSEMBLY__ \ + -ansi -x c -E -o $@ $< +$(obj)/SYSCALLS.i: $(KLIBCSRC)/SYSCALLS.def FORCE + $(call if_changed_dep,syscall.i) + +# Get syscalls numbers +quiet_cmd_syscall.nrs = GEN $@ + cmd_syscall.nrs = $(KLIBCCC) $(klibccflags) -Wp,-dM -x c -E -o $@ $< +$(obj)/syscalls.nrs: $(KLIBCINC)/sys/syscall.h FORCE + $(call if_changed_dep,syscall.nrs) + +# Generate typesize.c +quiet_cmd_syscalsz = GEN $@ + cmd_syscalsz = mkdir -p $(KLIBCINC)/klibc/; \ + $(PERL) $(KLIBCSRC)/syscalls.pl -1 $(obj)/SYSCALLS.i \ + $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \ + $(KLIBCARCH) $(KLIBCBITSIZE) $(obj)/syscalls.nrs \ + $(obj) \ + $(KLIBCINC)/klibc/havesyscall.h \ + $(obj)/typesize.c > $@ \ + || ( rm -f $@ ; exit 1 ) + +$(obj)/typesize.c: $(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i \ + $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \ + $(src)/syscommon.h $(obj)/syscalls.nrs FORCE + $(call if_changed,syscalsz) + +# Convert typesize.o to typesize.bin +quiet_cmd_mkbin = OBJCOPY $@ + cmd_mkbin = $(KLIBCOBJCOPY) -O binary $< $@ + +$(obj)/typesize.bin: $(obj)/typesize.o FORCE + $(call if_changed,mkbin) + +# Generate $(KLIBINC)/klibc/havesyscall.h + makefile fragment +# Using sysstub.pl in arch dir generate all .S files +quiet_cmd_syscalls = GEN $@ + cmd_syscalls = mkdir -p $(KLIBCINC)/klibc/; \ + $(PERL) $(KLIBCSRC)/syscalls.pl -2 $(obj)/SYSCALLS.i \ + $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \ + $(KLIBCARCH) $(KLIBCBITSIZE) $(obj)/syscalls.nrs \ + $(obj) \ + $(KLIBCINC)/klibc/havesyscall.h \ + $(obj)/typesize.bin > $@ \ + || ( rm -f $@ ; exit 1 ) + +$(obj)/syscalls.mk: $(KLIBCSRC)/syscalls.pl $(obj)/SYSCALLS.i \ + $(KLIBCSRC)/arch/$(KLIBCARCHDIR)/sysstub.ph \ + $(call objectify, $(syscall-objs:.o=.S)) \ + $(src)/syscommon.h $(obj)/syscalls.nrs \ + $(obj)/typesize.bin FORCE + $(call if_changed,syscalls) diff --git a/usr/klibc/syscalls/syscommon.h b/usr/klibc/syscalls/syscommon.h new file mode 100644 index 0000000..0acae12 --- /dev/null +++ b/usr/klibc/syscalls/syscommon.h @@ -0,0 +1,33 @@ +/* + * syscommon.h + * + * Common header file for system call stubs + */ + +#define __IN_SYS_COMMON +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __i386__ +# include +#endif diff --git a/usr/klibc/syslog.c b/usr/klibc/syslog.c new file mode 100644 index 0000000..4052eaa --- /dev/null +++ b/usr/klibc/syslog.c @@ -0,0 +1,89 @@ +/* + * syslog.c + * + * Issue syslog messages via the kernel printk queue. + */ + +#include +#include +#include +#include +#include +#include + +/* Maximum size for a kernel message */ +#define BUFLEN 1024 + +/* Logging node */ +#define LOGDEV "/dev/kmsg" + +/* Max length of ID string */ +#define MAXID 31 /* MAXID+5 must be < BUFLEN */ + +int __syslog_fd = -1; +static char id[MAXID + 1]; +static int syslog_flags = 0; + +void openlog(const char *ident, int option, int facility) +{ + int fd; + + (void)option; + (void)facility; /* Unused */ + + if (__syslog_fd == -1) { + __syslog_fd = fd = open(LOGDEV, O_WRONLY); + if (fd == -1) + return; + fcntl(fd, F_SETFD, (long)FD_CLOEXEC); + } + + syslog_flags = option; + + strncpy(id, ident ? ident : "", MAXID); +} + +void vsyslog(int prio, const char *format, va_list ap) +{ + char buf[BUFLEN]; + int len; + int fd; + + if (__syslog_fd == -1) + openlog(NULL, 0, 0); + + buf[0] = '<'; + buf[1] = LOG_PRI(prio) + '0'; + buf[2] = '>'; + len = 3; + + if (syslog_flags & LOG_PID) + len += sprintf(buf + 3, "%s[%u]: ", id, getpid()); + else if (*id) + len += sprintf(buf + 3, "%s: ", id); + + len += vsnprintf(buf + len, BUFLEN - len, format, ap); + + if (len > BUFLEN - 1) + len = BUFLEN - 1; + if (buf[len - 1] != '\n') + buf[len++] = '\n'; + + fd = __syslog_fd; + if (fd == -1) + fd = 2; /* Failed to open log, write to stderr */ + + write(fd, buf, len); + + if (syslog_flags & LOG_PERROR) + _fwrite(buf + 3, len - 3, stderr); +} + +void syslog(int prio, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vsyslog(prio, format, ap); + va_end(ap); +} diff --git a/usr/klibc/system.c b/usr/klibc/system.c new file mode 100644 index 0000000..4478b21 --- /dev/null +++ b/usr/klibc/system.c @@ -0,0 +1,61 @@ +/* + * system.c + * + * The system() function. If this turns out to actually be *used*, + * we may want to try to detect the very simple cases (no shell magic) + * and handle them internally, instead of requiring that /bin/sh be + * present. + */ + +#include +#include +#include +#include +#include + +int system(const char *string) +{ + pid_t pid; + struct sigaction ignore, old_int, old_quit; + sigset_t masked, oldmask; + static const char *argv[] = { "/bin/sh", "-c", NULL, NULL }; + int status; + + /* Block SIGCHLD and ignore SIGINT and SIGQUIT */ + /* Do this before the fork() to avoid races */ + + ignore.sa_handler = SIG_IGN; + sigemptyset(&ignore.sa_mask); + ignore.sa_flags = 0; + sigaction(SIGINT, &ignore, &old_int); + sigaction(SIGQUIT, &ignore, &old_quit); + + sigemptyset(&masked); + sigaddset(&masked, SIGCHLD); + sigprocmask(SIG_BLOCK, &masked, &oldmask); + + pid = fork(); + + if (pid < 0) + return -1; + else if (pid == 0) { + sigaction(SIGINT, &old_int, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + argv[2] = string; + + execve(argv[0], (char *const *)argv, (char *const *)environ); + _exit(127); + } + + /* else... */ + + waitpid(pid, &status, 0); + + sigaction(SIGINT, &old_int, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + return status; +} diff --git a/usr/klibc/sysv_signal.c b/usr/klibc/sysv_signal.c new file mode 100644 index 0000000..beee7d7 --- /dev/null +++ b/usr/klibc/sysv_signal.c @@ -0,0 +1,11 @@ +/* + * sysv_signal.c + */ + +#include + +__sighandler_t sysv_signal(int signum, __sighandler_t handler) +{ + /* Linux/SysV signal() semantics */ + return __signal(signum, handler, SA_RESETHAND); +} diff --git a/usr/klibc/time.c b/usr/klibc/time.c new file mode 100644 index 0000000..a0c366b --- /dev/null +++ b/usr/klibc/time.c @@ -0,0 +1,23 @@ +/* + * time.c + */ + +#include +#include +#include + +#ifndef __NR_time + +time_t time(time_t * t) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + if (t) + *t = (time_t) tv.tv_sec; + + return (time_t) tv.tv_sec; +} + +#endif diff --git a/usr/klibc/umount.c b/usr/klibc/umount.c new file mode 100644 index 0000000..d31a300 --- /dev/null +++ b/usr/klibc/umount.c @@ -0,0 +1,12 @@ +/* + * umount.c + * + * Single-argument form of umount + */ + +#include + +int umount(const char *dir) +{ + return umount2(dir, 0); +} diff --git a/usr/klibc/unsetenv.c b/usr/klibc/unsetenv.c new file mode 100644 index 0000000..c5cc95a --- /dev/null +++ b/usr/klibc/unsetenv.c @@ -0,0 +1,44 @@ +/* + * unsetenv.c + */ + +#include +#include +#include +#include +#include "env.h" + +int unsetenv(const char *name) +{ + size_t len; + char **p, *q; + const char *z; + + if (!name || !name[0]) { + errno = EINVAL; + return -1; + } + + len = 0; + for (z = name; *z; z++) { + len++; + if (*z == '=') { + errno = EINVAL; + return -1; + } + } + + if (!environ) + return 0; + + for (p = environ; (q = *p); p++) { + if (!strncmp(name, q, len) && q[len] == '=') + break; + } + + for (; (q = *p); p++) { + p[0] = p[1]; + } + + return 0; +} diff --git a/usr/klibc/usleep.c b/usr/klibc/usleep.c new file mode 100644 index 0000000..93bfabe --- /dev/null +++ b/usr/klibc/usleep.c @@ -0,0 +1,15 @@ +/* + * usleep.c + */ + +#include +#include + +void usleep(unsigned long usec) +{ + struct timespec ts; + + ts.tv_sec = usec / 1000000UL; + ts.tv_nsec = (usec % 1000000UL) * 1000; + while (nanosleep(&ts, &ts) == -1 && errno == EINTR) ; +} diff --git a/usr/klibc/utime.c b/usr/klibc/utime.c new file mode 100644 index 0000000..cb8f50a --- /dev/null +++ b/usr/klibc/utime.c @@ -0,0 +1,24 @@ +/* + * utime.c + */ + +#include +#include +#include +#include + +#ifndef __NR_utime + +int utime(const char *filename, const struct utimbuf *buf) +{ + struct timeval tvp[2]; + + tvp[0].tv_sec = buf->actime; + tvp[0].tv_usec = 0; + tvp[1].tv_sec = buf->modtime; + tvp[1].tv_usec = 0; + + return utimes(filename, tvp); +} + +#endif diff --git a/usr/klibc/vasprintf.c b/usr/klibc/vasprintf.c new file mode 100644 index 0000000..cdc302f --- /dev/null +++ b/usr/klibc/vasprintf.c @@ -0,0 +1,25 @@ +/* + * vasprintf.c + */ + +#include +#include +#include + +int vasprintf(char **bufp, const char *format, va_list ap) +{ + va_list ap1; + int bytes; + char *p; + + va_copy(ap1, ap); + + bytes = vsnprintf(NULL, 0, format, ap1) + 1; + va_end(ap1); + + *bufp = p = malloc(bytes); + if (!p) + return -1; + + return vsnprintf(p, bytes, format, ap); +} diff --git a/usr/klibc/version b/usr/klibc/version new file mode 100644 index 0000000..b2e46d1 --- /dev/null +++ b/usr/klibc/version @@ -0,0 +1 @@ +1.4.8 diff --git a/usr/klibc/vfork.c b/usr/klibc/vfork.c new file mode 100644 index 0000000..df33756 --- /dev/null +++ b/usr/klibc/vfork.c @@ -0,0 +1,13 @@ +/* + * vfork.c + * + * Emulate vfork() with fork() if necessary + */ + +#include +#include +#include + +#if !_KLIBC_NO_MMU && !_KLIBC_REAL_VFORK +__ALIAS(int, vfork, (void), fork) +#endif diff --git a/usr/klibc/vfprintf.c b/usr/klibc/vfprintf.c new file mode 100644 index 0000000..6f5663b --- /dev/null +++ b/usr/klibc/vfprintf.c @@ -0,0 +1,26 @@ +/* + * vfprintf.c + */ + +#include +#include +#include +#include + +#define BUFFER_SIZE 32768 + +int vfprintf(FILE * file, const char *format, va_list ap) +{ + int rv; + char buffer[BUFFER_SIZE]; + + rv = vsnprintf(buffer, BUFFER_SIZE, format, ap); + + if (rv < 0) + return rv; + + if (rv > BUFFER_SIZE - 1) + rv = BUFFER_SIZE - 1; + + return _fwrite(buffer, rv, file); +} diff --git a/usr/klibc/vprintf.c b/usr/klibc/vprintf.c new file mode 100644 index 0000000..d6bfeaf --- /dev/null +++ b/usr/klibc/vprintf.c @@ -0,0 +1,11 @@ +/* + * vprintf.c + */ + +#include +#include + +int vprintf(const char *format, va_list ap) +{ + return vfprintf(stdout, format, ap); +} diff --git a/usr/klibc/vsnprintf.c b/usr/klibc/vsnprintf.c new file mode 100644 index 0000000..26be710 --- /dev/null +++ b/usr/klibc/vsnprintf.c @@ -0,0 +1,488 @@ +/* + * vsnprintf.c + * + * vsnprintf(), from which the rest of the printf() + * family is built + */ + +#include +#include +#include +#include +#include +#include + +enum flags { + FL_ZERO = 0x01, /* Zero modifier */ + FL_MINUS = 0x02, /* Minus modifier */ + FL_PLUS = 0x04, /* Plus modifier */ + FL_TICK = 0x08, /* ' modifier */ + FL_SPACE = 0x10, /* Space modifier */ + FL_HASH = 0x20, /* # modifier */ + FL_SIGNED = 0x40, /* Number is signed */ + FL_UPPER = 0x80 /* Upper case digits */ +}; + +/* These may have to be adjusted on certain implementations */ +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2 +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +#define EMIT(x) ({ if (o nchars) { + while (width > nchars) { + EMIT(' '); + width--; + } + } + + /* Emit nondigits */ + if (minus) + EMIT('-'); + else if (flags & FL_PLUS) + EMIT('+'); + else if (flags & FL_SPACE) + EMIT(' '); + + if ((flags & FL_HASH) && base == 16) { + EMIT('0'); + EMIT((flags & FL_UPPER) ? 'X' : 'x'); + } + + /* Emit zero padding */ + if ((flags & (FL_MINUS | FL_ZERO)) == FL_ZERO && width > ndigits) { + while (width > nchars) { + EMIT('0'); + width--; + } + } + + /* Generate the number. This is done from right to left. */ + q += ndigits; /* Advance the pointer to end of number */ + o += ndigits; + qq = q; + oo = o; /* Temporary values */ + + b4tick = tickskip; + while (ndigits > 0) { + if (!b4tick--) { + qq--; + oo--; + ndigits--; + if (oo < n) + *qq = '_'; + b4tick = tickskip - 1; + } + qq--; + oo--; + ndigits--; + if (oo < n) + *qq = digits[val % base]; + val /= base; + } + + /* Emit late space padding */ + while ((flags & FL_MINUS) && width > nchars) { + EMIT(' '); + width--; + } + + return o; +} + +int vsnprintf(char *buffer, size_t n, const char *format, va_list ap) +{ + const char *p = format; + char ch; + char *q = buffer; + size_t o = 0; /* Number of characters output */ + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + int width = 0; + int prec = -1; + int base; + size_t sz; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_prec, /* Field precision */ + st_modifiers /* Length or conversion modifiers */ + } state = st_normal; + const char *sarg; /* %s string argument */ + char carg; /* %c char argument */ + int slen; /* String length */ + + while ((ch = *p++)) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = 0; + prec = -1; + } else { + EMIT(ch); + } + break; + + case st_flags: + switch (ch) { + case '-': + flags |= FL_MINUS; + break; + case '+': + flags |= FL_PLUS; + break; + case '\'': + flags |= FL_TICK; + break; + case ' ': + flags |= FL_SPACE; + break; + case '#': + flags |= FL_HASH; + break; + case '0': + flags |= FL_ZERO; + break; + default: + state = st_width; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else if (ch == '*') { + width = va_arg(ap, int); + if (width < 0) { + width = -width; + flags |= FL_MINUS; + } + } else if (ch == '.') { + prec = 0; /* Precision given */ + state = st_prec; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_prec: + if (ch >= '0' && ch <= '9') { + prec = prec * 10 + (ch - '0'); + } else if (ch == '*') { + prec = va_arg(ap, int); + if (prec < 0) + prec = -1; + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank += 2; + break; + default: + /* Output modifiers - terminal sequences */ + + /* Next state will be normal */ + state = st_normal; + + /* Canonicalize rank */ + if (rank < MIN_RANK) + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + flags |= FL_UPPER; + /* fall through */ + case 'p': /* Pointer */ + base = 16; + prec = (CHAR_BIT*sizeof(void *)+3)/4; + flags |= FL_HASH; + val = (uintmax_t)(uintptr_t) + va_arg(ap, void *); + goto is_integer; + + case 'd': /* Signed decimal output */ + case 'i': + base = 10; + flags |= FL_SIGNED; + switch (rank) { + case rank_char: + /* Yes, all these casts are + needed... */ + val = (uintmax_t)(intmax_t) + (signed char) + va_arg(ap, signed int); + break; + case rank_short: + val = (uintmax_t)(intmax_t) + (signed short) + va_arg(ap, signed int); + break; + case rank_int: + val = (uintmax_t)(intmax_t) + va_arg(ap, signed int); + break; + case rank_long: + val = (uintmax_t)(intmax_t) + va_arg(ap, signed long); + break; + case rank_longlong: + val = (uintmax_t)(intmax_t) + va_arg(ap, + signed long long); + break; + } + goto is_integer; + case 'o': /* Octal */ + base = 8; + goto is_unsigned; + case 'u': /* Unsigned decimal */ + base = 10; + goto is_unsigned; + case 'X': /* Upper case hexadecimal */ + flags |= FL_UPPER; + /* fall through */ + case 'x': /* Hexadecimal */ + base = 16; + goto is_unsigned; + + is_unsigned: + switch (rank) { + case rank_char: + val = (uintmax_t) + (unsigned char) + va_arg(ap, unsigned + int); + break; + case rank_short: + val = (uintmax_t) + (unsigned short) + va_arg(ap, unsigned + int); + break; + case rank_int: + val = (uintmax_t) + va_arg(ap, unsigned + int); + break; + case rank_long: + val = (uintmax_t) + va_arg(ap, unsigned + long); + break; + case rank_longlong: + val = (uintmax_t) + va_arg(ap, unsigned + long long); + break; + } + /* fall through */ + + is_integer: + sz = format_int(q, (o < n) ? n - o : 0, + val, flags, base, + width, prec); + q += sz; + o += sz; + break; + + case 'c': /* Character */ + carg = (char)va_arg(ap, int); + sarg = &carg; + slen = 1; + goto is_string; + case 's': /* String */ + sarg = va_arg(ap, const char *); + sarg = sarg ? sarg : "(null)"; + slen = strlen(sarg); + goto is_string; + + is_string: + { + char sch; + int i; + + if (prec != -1 && slen > prec) + slen = prec; + + if (width > slen + && !(flags & FL_MINUS)) { + char pad = + (flags & FL_ZERO) ? + '0' : ' '; + while (width > slen) { + EMIT(pad); + width--; + } + } + for (i = slen; i; i--) { + sch = *sarg++; + EMIT(sch); + } + if (width > slen + && (flags & FL_MINUS)) { + while (width > slen) { + EMIT(' '); + width--; + } + } + } + break; + + case 'n': + { + /* Output the number of + characters written */ + + switch (rank) { + case rank_char: + *va_arg(ap, + signed char *) + = o; + break; + case rank_short: + *va_arg(ap, + signed short *) + = o; + break; + case rank_int: + *va_arg(ap, + signed int *) + = o; + break; + case rank_long: + *va_arg(ap, + signed long *) + = o; + break; + case rank_longlong: + *va_arg(ap, + signed long long *) + = o; + break; + } + } + break; + + default: /* Anything else, including % */ + EMIT(ch); + break; + } + } + } + } + + /* Null-terminate the string */ + if (o < n) + *q = '\0'; /* No overflow */ + else if (n > 0) + buffer[n - 1] = '\0'; /* Overflow - terminate at end of buffer */ + + return o; +} diff --git a/usr/klibc/vsprintf.c b/usr/klibc/vsprintf.c new file mode 100644 index 0000000..51f5d87 --- /dev/null +++ b/usr/klibc/vsprintf.c @@ -0,0 +1,11 @@ +/* + * vsprintf.c + */ + +#include +#include + +int vsprintf(char *buffer, const char *format, va_list ap) +{ + return vsnprintf(buffer, ~(size_t) 0, format, ap); +} diff --git a/usr/klibc/vsscanf.c b/usr/klibc/vsscanf.c new file mode 100644 index 0000000..56aa22b --- /dev/null +++ b/usr/klibc/vsscanf.c @@ -0,0 +1,378 @@ +/* + * vsscanf.c + * + * vsscanf(), from which the rest of the scanf() + * family is built + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef LONG_BIT +#define LONG_BIT (CHAR_BIT*sizeof(long)) +#endif + +enum flags { + FL_SPLAT = 0x01, /* Drop the value, do not assign */ + FL_INV = 0x02, /* Character-set with inverse */ + FL_WIDTH = 0x04, /* Field width specified */ + FL_MINUS = 0x08, /* Negative number */ +}; + +enum ranks { + rank_char = -2, + rank_short = -1, + rank_int = 0, + rank_long = 1, + rank_longlong = 2, + rank_ptr = INT_MAX /* Special value used for pointers */ +}; + +#define MIN_RANK rank_char +#define MAX_RANK rank_longlong + +#define INTMAX_RANK rank_longlong +#define SIZE_T_RANK rank_long +#define PTRDIFF_T_RANK rank_long + +enum bail { + bail_none = 0, /* No error condition */ + bail_eof, /* Hit EOF */ + bail_err /* Conversion mismatch */ +}; + +static inline const char *skipspace(const char *p) +{ + while (isspace((unsigned char)*p)) + p++; + return p; +} + +#undef set_bit +static inline void set_bit(unsigned long *bitmap, unsigned int bit) +{ + bitmap[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT); +} + +#undef test_bit +static inline int test_bit(unsigned long *bitmap, unsigned int bit) +{ + return (int)(bitmap[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1; +} + +int vsscanf(const char *buffer, const char *format, va_list ap) +{ + const char *p = format; + char ch; + const char *q = buffer; + const char *qq; + uintmax_t val = 0; + int rank = rank_int; /* Default rank */ + unsigned int width = UINT_MAX; + int base; + enum flags flags = 0; + enum { + st_normal, /* Ground state */ + st_flags, /* Special flags */ + st_width, /* Field width */ + st_modifiers, /* Length or conversion modifiers */ + st_match_init, /* Initial state of %[ sequence */ + st_match, /* Main state of %[ sequence */ + st_match_range, /* After - in a %[ sequence */ + } state = st_normal; + char *sarg = NULL; /* %s %c or %[ string argument */ + enum bail bail = bail_none; + int sign; + int converted = 0; /* Successful conversions */ + unsigned long matchmap[((1 << CHAR_BIT) + (LONG_BIT - 1)) / LONG_BIT]; + int matchinv = 0; /* Is match map inverted? */ + unsigned char range_start = 0; + + while ((ch = *p++) && !bail) { + switch (state) { + case st_normal: + if (ch == '%') { + state = st_flags; + flags = 0; + rank = rank_int; + width = UINT_MAX; + } else if (isspace((unsigned char)ch)) { + q = skipspace(q); + } else { + if (*q == ch) + q++; + else + bail = bail_err; /* Match failure */ + } + break; + + case st_flags: + switch (ch) { + case '*': + flags |= FL_SPLAT; + break; + case '0'...'9': + width = (ch - '0'); + state = st_width; + flags |= FL_WIDTH; + break; + default: + state = st_modifiers; + p--; /* Process this character again */ + break; + } + break; + + case st_width: + if (ch >= '0' && ch <= '9') { + width = width * 10 + (ch - '0'); + } else { + state = st_modifiers; + p--; /* Process this character again */ + } + break; + + case st_modifiers: + switch (ch) { + /* Length modifiers - nonterminal sequences */ + case 'h': + rank--; /* Shorter rank */ + break; + case 'l': + rank++; /* Longer rank */ + break; + case 'j': + rank = INTMAX_RANK; + break; + case 'z': + rank = SIZE_T_RANK; + break; + case 't': + rank = PTRDIFF_T_RANK; + break; + case 'L': + case 'q': + rank = rank_longlong; /* long double/long long */ + break; + + default: + /* Output modifiers - terminal sequences */ + /* Next state will be normal */ + state = st_normal; + + /* Canonicalize rank */ + if (rank < MIN_RANK) + rank = MIN_RANK; + else if (rank > MAX_RANK) + rank = MAX_RANK; + + switch (ch) { + case 'P': /* Upper case pointer */ + case 'p': /* Pointer */ + rank = rank_ptr; + base = 0; + sign = 0; + goto scan_int; + + case 'i': /* Base-independent integer */ + base = 0; + sign = 1; + goto scan_int; + + case 'd': /* Decimal integer */ + base = 10; + sign = 1; + goto scan_int; + + case 'o': /* Octal integer */ + base = 8; + sign = 0; + goto scan_int; + + case 'u': /* Unsigned decimal integer */ + base = 10; + sign = 0; + goto scan_int; + + case 'x': /* Hexadecimal integer */ + case 'X': + base = 16; + sign = 0; + goto scan_int; + + case 'n': /* # of characters consumed */ + val = (q - buffer); + goto set_integer; + + scan_int: + q = skipspace(q); + if (!*q) { + bail = bail_eof; + break; + } + val = + strntoumax(q, (char **)&qq, base, + width); + if (qq == q) { + bail = bail_err; + break; + } + q = qq; + converted++; + /* fall through */ + + set_integer: + if (!(flags & FL_SPLAT)) { + switch (rank) { + case rank_char: + *va_arg(ap, + unsigned char *) + = val; + break; + case rank_short: + *va_arg(ap, + unsigned short + *) = val; + break; + case rank_int: + *va_arg(ap, + unsigned int *) + = val; + break; + case rank_long: + *va_arg(ap, + unsigned long *) + = val; + break; + case rank_longlong: + *va_arg(ap, + unsigned long + long *) = val; + break; + case rank_ptr: + *va_arg(ap, void **) = + (void *) + (uintptr_t)val; + break; + } + } + break; + + case 'c': /* Character */ + /* Default width == 1 */ + width = (flags & FL_WIDTH) ? width : 1; + sarg = va_arg(ap, char *); + while (width--) { + if (!*q) { + bail = bail_eof; + break; + } + *sarg++ = *q++; + } + if (!bail) + converted++; + break; + + case 's': /* String */ + { + char *sp; + sp = sarg = va_arg(ap, char *); + while (width-- && *q + && + !isspace((unsigned char) + *q)) { + *sp++ = *q++; + } + if (sarg != sp) { + /* Terminate output */ + *sp = '\0'; + converted++; + } else { + bail = bail_eof; + } + } + break; + + case '[': /* Character range */ + sarg = va_arg(ap, char *); + state = st_match_init; + matchinv = 0; + memset(matchmap, 0, sizeof matchmap); + break; + + case '%': /* %% sequence */ + if (*q == '%') + q++; + else + bail = bail_err; + break; + + default: /* Anything else */ + /* Unknown sequence */ + bail = bail_err; + break; + } + } + break; + + case st_match_init: /* Initial state for %[ match */ + if (ch == '^' && !(flags & FL_INV)) { + matchinv = 1; + } else { + set_bit(matchmap, (unsigned char)ch); + state = st_match; + } + break; + + case st_match: /* Main state for %[ match */ + if (ch == ']') { + goto match_run; + } else if (ch == '-') { + range_start = (unsigned char)ch; + state = st_match_range; + } else { + set_bit(matchmap, (unsigned char)ch); + } + break; + + case st_match_range: /* %[ match after - */ + if (ch == ']') { + /* - was last character */ + set_bit(matchmap, (unsigned char)'-'); + goto match_run; + } else { + int i; + for (i = range_start; i < (unsigned char)ch; + i++) + set_bit(matchmap, i); + state = st_match; + } + break; + + match_run: /* Match expression finished */ + qq = q; + while (width && *q + && test_bit(matchmap, + (unsigned char)*q) ^ matchinv) { + *sarg++ = *q++; + } + if (q != qq) { + *sarg = '\0'; + converted++; + } else { + bail = *q ? bail_err : bail_eof; + } + break; + } + } + + if (bail == bail_eof && !converted) + converted = -1; /* Return EOF (-1) */ + + return converted; +} diff --git a/usr/klibc/wait.c b/usr/klibc/wait.c new file mode 100644 index 0000000..73bb1a2 --- /dev/null +++ b/usr/klibc/wait.c @@ -0,0 +1,12 @@ +/* + * wait.c + */ + +#include +#include +#include + +pid_t wait(int *status) +{ + return wait4((pid_t) - 1, status, 0, NULL); +} diff --git a/usr/klibc/wait3.c b/usr/klibc/wait3.c new file mode 100644 index 0000000..1f35414 --- /dev/null +++ b/usr/klibc/wait3.c @@ -0,0 +1,12 @@ +/* + * wait3.c + */ + +#include +#include +#include + +pid_t wait3(int *status, int options, struct rusage * rusage) +{ + return wait4((pid_t) - 1, status, options, rusage); +} diff --git a/usr/klibc/waitpid.c b/usr/klibc/waitpid.c new file mode 100644 index 0000000..a157122 --- /dev/null +++ b/usr/klibc/waitpid.c @@ -0,0 +1,12 @@ +/* + * waitpid.c + */ + +#include +#include +#include + +pid_t waitpid(pid_t pid, int *status, int options) +{ + return wait4(pid, status, options, NULL); +}