From aaf7355c5ededfcdc877c7f2989fb1ba02dfb848 Mon Sep 17 00:00:00 2001 From: Danny Holman Date: Mon, 27 May 2024 13:53:52 -0500 Subject: libk: create a subset libc for kernel use Create a subset of the C library for use inside the kernel. Signed-off-by: Danny Holman --- Makefile | 17 ++++-- include/kernel/container_of.h | 10 ---- include/kernel/data/list.h | 32 ---------- include/kernel/data/ringbuf.h | 50 ---------------- include/kernel/io.h | 9 --- include/kernel/kmalloc.h | 18 ------ include/kernel/string.h | 18 ------ include/libk/container_of.h | 10 ++++ include/libk/data/list.h | 32 ++++++++++ include/libk/data/ringbuf.h | 50 ++++++++++++++++ include/libk/io.h | 10 ++++ include/libk/kmalloc.h | 19 ++++++ include/libk/string.h | 19 ++++++ kernel/init.c | 30 +++++----- kernel/io.c | 84 -------------------------- kernel/string.c | 130 ----------------------------------------- libk/io.c | 78 +++++++++++++++++++++++++ libk/stack_protector.c | 11 ++++ libk/string.c | 133 ++++++++++++++++++++++++++++++++++++++++++ 19 files changed, 391 insertions(+), 369 deletions(-) delete mode 100644 include/kernel/container_of.h delete mode 100644 include/kernel/data/list.h delete mode 100644 include/kernel/data/ringbuf.h delete mode 100644 include/kernel/io.h delete mode 100644 include/kernel/kmalloc.h delete mode 100644 include/kernel/string.h create mode 100644 include/libk/container_of.h create mode 100644 include/libk/data/list.h create mode 100644 include/libk/data/ringbuf.h create mode 100644 include/libk/io.h create mode 100644 include/libk/kmalloc.h create mode 100644 include/libk/string.h delete mode 100644 kernel/io.c delete mode 100644 kernel/string.c create mode 100644 libk/io.c create mode 100644 libk/stack_protector.c create mode 100644 libk/string.c diff --git a/Makefile b/Makefile index 043e883..9a50fb6 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ ARCH?=i386 CC:=i686-elf-gcc VERSION:="$(shell git describe --abbrev=4 --dirty --always --tags)" INCLUDE:=$(INCLUDE) -CFLAGS:=$(CFLAGS) -Wall -Wextra -DVERSION=\"$(VERSION)\" -ggdb +CFLAGS:=$(CFLAGS) -Wall -Wextra -DVERSION=\"$(VERSION)\" -ggdb -fstack-protector-all -O0 LDFLAGS:=$(LDFLAGS) LIBS:=$(LIBS) ARCH:=$(ARCH) @@ -24,21 +24,28 @@ LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS) KERNEL=vmbox +LIBK_OBJS=libk/string.o \ + libk/io.o \ + libk/stack_protector.o \ + libk/ubsan.o \ + KERNEL_OBJS=$(KERNEL_ARCH_OBJS) \ kernel/init.o \ - kernel/string.o \ - kernel/io.o \ kernel/panic.o \ + kernel/vfs.o \ kernel/sched.o \ + kernel/kthread.o \ OBJS=$(ARCHDIR)/boot/crti.o \ $(ARCHDIR)/crtbegin.o \ $(KERNEL_OBJS) \ + $(LIBK_OBJS) \ $(ARCHDIR)/crtend.o \ $(ARCHDIR)/boot/crtn.o \ LINK_LIST=$(LDFLAGS) \ $(KERNEL_OBJS) \ + $(LIBK_OBJS) \ $(LIBS) \ .PHONY: all clean install install-headers install-kernel @@ -87,9 +94,9 @@ install-disk: $(KERNEL) mcopy -i a.img vmbox ::vmbox run: $(KERNEL) - qemu-system-i386 -kernel $(KERNEL) -serial stdio + qemu-system-i386 -kernel $(KERNEL) -serial stdio -m 3G -drive file=a.img,format=raw -append "root=/dev/sda init=/bin/sh" debug: $(KERNEL) - qemu-system-i386 -kernel $(KERNEL) -s -S + qemu-system-i386 -kernel $(KERNEL) -s -S -m 3G -drive file=a.img,format=raw -append "root=/dev/sda init=/bin/sh" & -include $(OBJS:.o=.d) diff --git a/include/kernel/container_of.h b/include/kernel/container_of.h deleted file mode 100644 index 1b5b444..0000000 --- a/include/kernel/container_of.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef KERNEL_CONTAINER_OF_H -#define KERNEL_CONTAINER_OF_H - -#ifndef container_of -#define container_of(ptr, type, member) ({ \ - const typeof(((type*)0)->member)*__mptr = (ptr); \ - (type*)((char*)__mptr - offsetof(type, member)); }) -#endif - -#endif diff --git a/include/kernel/data/list.h b/include/kernel/data/list.h deleted file mode 100644 index b61cfaa..0000000 --- a/include/kernel/data/list.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef KERNEL_LIST_H -#define KERNEL_LIST_H - -#include - -struct list_head { - struct list_head *next; - struct list_head *prev; -}; - -static inline void list_add(struct list_head *new, struct list_head *head) { - struct list_head *temp = head; - while (temp->next != NULL) - temp = temp->next; - - temp->next = new; - new->prev = temp; - new->next = NULL; -} - -static inline void list_del(struct list_head *item) { - struct list_head *next = item->next; - struct list_head *prev = item->prev; - if (next != NULL) - next->prev = prev; - if (prev != NULL) - prev->next = next; - item->next = NULL; - item->prev = NULL; -} - -#endif diff --git a/include/kernel/data/ringbuf.h b/include/kernel/data/ringbuf.h deleted file mode 100644 index 25a7125..0000000 --- a/include/kernel/data/ringbuf.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef KERNEL_RINGBUF_H -#define KERNEL_RINGBUF_H - -#include -#include -#include - -struct ringbuf { - void *buffer; - void *buf_end; - uint32_t capacity; - uint32_t count; - uint32_t size; - void *head; - void *tail; -}; - -static inline void rb_init(struct ringbuf *rb, uint32_t capacity, uint32_t size) { - rb->buffer = kmalloc(capacity * size); - rb->buf_end = (char*)rb->buffer + (capacity * size); - rb->capacity = capacity; - rb->size = size; - rb->head = rb->buffer; - rb->tail = rb->buffer; -} - -static inline int rb_push_back(struct ringbuf *rb, const void *item, size_t size) { - if (rb->count == rb->capacity) - return -1; - if (size > rb->size) - return -1; - - void *tmp = rb->tail + rb->size; - if (tmp > rb->head + rb->capacity * rb->size) - rb->tail = rb->head; - memcpy(rb->tail, item, size); - rb->tail += rb->size; - rb->count++; - return 0; -} - -static inline void rb_pop_front(struct ringbuf *rb, void *item) { - memcpy(item, rb->tail, rb->size); - rb->tail = (char*)rb->tail + rb->size; - if (rb->tail == rb->buf_end) - rb->tail = rb->buffer; - rb->count--; -} - -#endif diff --git a/include/kernel/io.h b/include/kernel/io.h deleted file mode 100644 index cf8404a..0000000 --- a/include/kernel/io.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef KERNEL_IO_H -#define KERNEL_IO_H - -#include - -int vkprintf(const char *fmt, va_list args); -int kprintf(const char *fmt, ...); - -#endif diff --git a/include/kernel/kmalloc.h b/include/kernel/kmalloc.h deleted file mode 100644 index d8debd1..0000000 --- a/include/kernel/kmalloc.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef KERNEL_KMALLOC_H -#define KERNEL_KMALLOC_H - -#include -#include - -struct mem_block { - uintptr_t start; - size_t size; - int alloc; - struct mem_block *next; -}; - -void kmalloc_init(void); -void* kmalloc(size_t sz); -void kfree(void *ptr); - -#endif diff --git a/include/kernel/string.h b/include/kernel/string.h deleted file mode 100644 index 76bf610..0000000 --- a/include/kernel/string.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef STRING_H -#define STRING_H - -#include - -int memcmp(const void *str1, const void *str2, size_t n); -void* memcpy(void* __restrict dest, const void* __restrict src, size_t n); -void* memmove(void* __restrict dest, const void* __restrict src, size_t n); -void* memset(void *str, int c, size_t n); -int strncmp(const char *str1, const char *str2, size_t n); -int strcmp(const char *str1, const char *str2); -size_t strlen(const char *str); -char* strncpy(char* __restrict dest, const char* __restrict src, size_t n); -char* strcpy(char* __restrict dest, const char* __restrict src); -char* strcat(char* __restrict dest, const char* __restrict src); -char* strtok(char* __restrict str, const char* __restrict delim); - -#endif diff --git a/include/libk/container_of.h b/include/libk/container_of.h new file mode 100644 index 0000000..fdc400c --- /dev/null +++ b/include/libk/container_of.h @@ -0,0 +1,10 @@ +#ifndef LIBK_CONTAINER_OF_H +#define LIBK_CONTAINER_OF_H + +#ifndef container_of +#define container_of(ptr, type, member) ({ \ + const typeof(((type*)0)->member)*__mptr = (ptr); \ + (type*)((char*)__mptr - offsetof(type, member)); }) +#endif + +#endif diff --git a/include/libk/data/list.h b/include/libk/data/list.h new file mode 100644 index 0000000..69eee3a --- /dev/null +++ b/include/libk/data/list.h @@ -0,0 +1,32 @@ +#ifndef LIBK_LIST_H +#define LIBK_LIST_H + +#include + +struct list_head { + struct list_head *next; + struct list_head *prev; +}; + +static inline void list_add(struct list_head *new, struct list_head *head) { + struct list_head *temp = head; + while (temp->next != NULL) + temp = temp->next; + + temp->next = new; + new->prev = temp; + new->next = NULL; +} + +static inline void list_del(struct list_head *item) { + struct list_head *next = item->next; + struct list_head *prev = item->prev; + if (next != NULL) + next->prev = prev; + if (prev != NULL) + prev->next = next; + item->next = NULL; + item->prev = NULL; +} + +#endif diff --git a/include/libk/data/ringbuf.h b/include/libk/data/ringbuf.h new file mode 100644 index 0000000..cc6d77b --- /dev/null +++ b/include/libk/data/ringbuf.h @@ -0,0 +1,50 @@ +#ifndef LIBK_RINGBUF_H +#define LIBK_RINGBUF_H + +#include +#include +#include + +struct ringbuf { + void *buffer; + void *buf_end; + uint32_t capacity; + uint32_t count; + uint32_t size; + void *head; + void *tail; +}; + +static inline void rb_init(struct ringbuf *rb, uint32_t capacity, uint32_t size) { + rb->buffer = kmalloc(capacity * size); + rb->buf_end = (char*)rb->buffer + (capacity * size); + rb->capacity = capacity; + rb->size = size; + rb->head = rb->buffer; + rb->tail = rb->buffer; +} + +static inline int rb_push_back(struct ringbuf *rb, const void *item, size_t size) { + if (rb->count == rb->capacity) + return -1; + if (size > rb->size) + return -1; + + void *tmp = rb->tail + rb->size; + if (tmp > rb->head + rb->capacity * rb->size) + rb->tail = rb->head; + memcpy(rb->tail, item, size); + rb->tail += rb->size; + rb->count++; + return 0; +} + +static inline void rb_pop_front(struct ringbuf *rb, void *item) { + memcpy(item, rb->tail, rb->size); + rb->tail = (char*)rb->tail + rb->size; + if (rb->tail == rb->buf_end) + rb->tail = rb->buffer; + rb->count--; +} + +#endif diff --git a/include/libk/io.h b/include/libk/io.h new file mode 100644 index 0000000..72dc5d7 --- /dev/null +++ b/include/libk/io.h @@ -0,0 +1,10 @@ +#ifndef LIBK_IO_H +#define LIBK_IO_H + +#include + +char* convert(unsigned int num, int base); +int vkprintf(const char *fmt, va_list args); +int kprintf(const char *fmt, ...); + +#endif diff --git a/include/libk/kmalloc.h b/include/libk/kmalloc.h new file mode 100644 index 0000000..6573d28 --- /dev/null +++ b/include/libk/kmalloc.h @@ -0,0 +1,19 @@ +#ifndef LIBK_KMALLOC_H +#define LIBK_KMALLOC_H + +#include +#include + +struct mem_block { + void *start; + size_t size; + int alloc; + struct mem_block *next; + struct mem_block *prev; +}; + +void kmalloc_init(void); +void* kmalloc(size_t sz); +void kfree(void *ptr); + +#endif diff --git a/include/libk/string.h b/include/libk/string.h new file mode 100644 index 0000000..1fb4af1 --- /dev/null +++ b/include/libk/string.h @@ -0,0 +1,19 @@ +#ifndef LIBK_STRING_H +#define LIBK_STRING_H + +#include + +int memcmp(const void *str1, const void *str2, size_t n); +void* memcpy(void* __restrict dest, const void* __restrict src, size_t n); +void* memmove(void* __restrict dest, const void* __restrict src, size_t n); +void* memset(void *str, int c, size_t n); +int strncmp(const char *str1, const char *str2, size_t n); +int strcmp(const char *str1, const char *str2); +size_t strlen(const char *str); +char* strncpy(char* __restrict dest, const char* __restrict src, size_t n); +char* strcpy(char* __restrict dest, const char* __restrict src); +char* strncat(char* __restrict dest, const char* __restrict src, size_t n); +char* strcat(char* __restrict dest, const char* __restrict src); +char* strtok(char* __restrict str, const char* __restrict delim); + +#endif diff --git a/kernel/init.c b/kernel/init.c index 98ac05c..d4a3638 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -1,31 +1,35 @@ -#include +#include +#include +#include #include -#include -#include +#include +#include #include void jump_userspace(void); char rootfs[1024]; - -int start_init(int argc, char* argv[]) { - while (1); - return 0; -} +char init_bin[1024]; +int gdbstub = 0; void process_cmd(char *cmdline) { char *token = strtok(cmdline, " "); while (token != NULL) { if (strncmp(token, "root=", 5) == 0) - strcpy(rootfs, &token[6]); + strcpy(rootfs, &token[5]); + if (strncmp(token, "init=", 5) == 0) + strcpy(init_bin, &token[5]); + if (strncmp(token, "gdb", 3) == 0) + gdbstub = 1; + token = strtok(NULL, " "); } } void kernel_main(char *cmdline) { - kmalloc_init(); - kprintf("Box Kernel version %s\n", VERSION); + kprintf("Box kernel version %s\n", VERSION); + process_cmd(cmdline); + serial_init(); sched_init(); - - //jump_userspace(); + //pci_check_buses(); } diff --git a/kernel/io.c b/kernel/io.c deleted file mode 100644 index 0a4ba6d..0000000 --- a/kernel/io.c +++ /dev/null @@ -1,84 +0,0 @@ -#include -#include -#include -#include - -static int ringbuf_init = 0; -static struct ringbuf rb; - -char* convert(unsigned int num, int base) { - static char rep[] = "0123456789ABCDEF"; - static char buffer[50]; - char *ptr; - - ptr = &buffer[49]; - *ptr = '\0'; - - do { - *--ptr = rep[num%base]; - num /= base; - } while (num != 0); - - return ptr; -} - -int vkprintf(const char *fmt, va_list args) { - if (ringbuf_init == 0) { - rb_init(&rb, 1024, 4096); - ringbuf_init = 1; - } - - char *s; - int i; - - char buffer[4096]; - for (size_t n = 0; n < strlen(fmt); n++) { - if (fmt[n] != '%') { - buffer[strlen(buffer)] = fmt[n]; - continue; - } else { - n++; - } - - switch (fmt[n]) { - case 'c': - i = va_arg(args, int); - buffer[strlen(buffer)] = i; - break; - case 's': - s = va_arg(args, char*); - strcat(buffer, s); - break; - case 'd': - i = va_arg(args, int); - if (i < 0) { - i = -i; - strcat(buffer, "-"); - } - strcat(buffer, convert(i, 10)); - break; - case 'o': - i = va_arg(args, unsigned int); - strcat(buffer, convert(i, 10)); - break; - case 'x': - i = va_arg(args, unsigned int); - strcat(buffer, convert(i, 16)); - break; - } - } - rb_push_back(&rb, buffer, strlen(buffer)); - memset(buffer, 0, 4096); - return 0; -} - -int kprintf(const char *fmt, ...) { - va_list args; - int done; - - va_start(args, fmt); - done = vkprintf(fmt, args); - va_end(args); - - return done; -} diff --git a/kernel/string.c b/kernel/string.c deleted file mode 100644 index fa0fd3f..0000000 --- a/kernel/string.c +++ /dev/null @@ -1,130 +0,0 @@ -#include - -int memcmp(const void *str1, const void *str2, size_t n) { - unsigned char const *p1 = str1; - unsigned char const *p2 = str2; - int ret = 0; - - if (str1 == str2) - return 0; - - while (n > 0) { - if (*p1 != *p2) { - ret = (*p1 > *p2)?1:-1; - break; - } - n--; - p1++; - p2++; - } - return ret; -} - -void* memcpy(void* __restrict dest, const void* __restrict src, size_t n) { - if (dest == src) - return dest; - - unsigned char *pdest = dest; - unsigned char const *psrc = src; - for (size_t i = 0; i < n; i++) - pdest[i] = psrc[i]; - return dest; -} - -char* strncpy(char* __restrict dest, const char* __restrict src, size_t n) { - for (int i = 0; i < n; i++) { - if (src[i] == '\0') - break; - dest[i] = src[i]; - } -} - -char* strcpy(char* __restrict dest, const char* __restrict src) { - if (strlen(src) > strlen(dest)) - return NULL; - return (char*)memcpy(dest, src, strlen(src)); -} - -char* strcat(char* __restrict dest, const char* __restrict src) { - return (char*)memcpy(&dest[strlen(dest)], src, strlen(src)); -} - -void* memmove(void* __restrict dest, const void* __restrict src, size_t n) { - if (dest == src) - return dest; - - unsigned char const *psrc = src; - unsigned char buffer[n]; - - for (size_t i = 0; i < n; i++) - buffer[i] = psrc[i]; - return memcpy(dest, (void*)buffer, n); -} - -void* memset(void *str, int c, size_t n) { - unsigned char *p = str; - for (size_t i = 0; i < n; i++) - p[i] = (unsigned char)c; - return str; -} - -int strncmp(const char *str1, const char *str2, size_t n) { - return memcmp(str1, str2, n); -} - -int strcmp(const char *str1, const char *str2) { - size_t str1_sz = strlen(str1); - size_t str2_sz = strlen(str2); - if (str1_sz > str2_sz) - return memcmp(str1, str2, str2_sz); - return memcmp(str1, str2, str1_sz); -} - -size_t strlen(const char *str) { - size_t i = 0; - while (str[i] != '\0') - i++; - return i; -} - -int _is_delim(char c, const char *delim) { - while (*delim != '\0') { - if (c == *delim) - return 1; - delim++; - } - return 0; -} - -char* strtok(char* __restrict str, const char* __restrict delim) { - static char *old_str; - - if (str == NULL) - str = old_str; - - while (1) { - if (_is_delim(*str, delim)) { - str++; - continue; - } - - if (*str == '\0') - return NULL; - break; - } - - char *ret = str; - while (1) { - if (*str == '\0') { - old_str = str; - return ret; - } - - if (_is_delim(*str, delim)) { - *str = '\0'; - old_str = str + 1; - return ret; - } - str++; - } -} diff --git a/libk/io.c b/libk/io.c new file mode 100644 index 0000000..eedc171 --- /dev/null +++ b/libk/io.c @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +char* convert(unsigned int num, int base) { + static char rep[] = "0123456789ABCDEF"; + static char buffer[50]; + char *ptr; + + ptr = &buffer[49]; + *ptr = '\0'; + + do { + *--ptr = rep[num%base]; + num /= base; + } while (num != 0); + + return ptr; +} + +int vkprintf(const char *fmt, va_list args) { + char *s; + int i; + + char buffer[4096]; + memset(buffer, 0, 4096); + for (size_t n = 0; n < strlen(fmt); n++) { + if (fmt[n] != '%') { + buffer[strlen(buffer)] = fmt[n]; + continue; + } else { + n++; + } + + switch (fmt[n]) { + case 'c': + i = va_arg(args, int); + buffer[strlen(buffer)] = i; + break; + case 's': + s = va_arg(args, char*); + strcat(buffer, s); + break; + case 'd': + i = va_arg(args, int); + if (i < 0) { + i = -i; + strcat(buffer, "-"); + } + strcat(buffer, convert(i, 10)); + break; + case 'o': + i = va_arg(args, unsigned int); + strcat(buffer, convert(i, 10)); + break; + case 'x': + i = va_arg(args, unsigned int); + strcat(buffer, convert(i, 16)); + break; + } + } + //tty_write(buffer, strlen(buffer)); + fb_write(buffer, strlen(buffer)); + memset(buffer, 0, 4096); + return 0; +} + +int kprintf(const char *fmt, ...) { + va_list args; + int done; + + va_start(args, fmt); + done = vkprintf(fmt, args); + va_end(args); + + return done; +} diff --git a/libk/stack_protector.c b/libk/stack_protector.c new file mode 100644 index 0000000..78d0302 --- /dev/null +++ b/libk/stack_protector.c @@ -0,0 +1,11 @@ +#include +#include +#include + +#define STACK_CHK_GUARD 0x32E3429E + +uintptr_t __stack_chk_guard = STACK_CHK_GUARD; + +__attribute__((noreturn)) void __stack_chk_fail(void) { + panic("STACK SMASHING IN KERNEL ADDRESS SPACE"); +} diff --git a/libk/string.c b/libk/string.c new file mode 100644 index 0000000..be59397 --- /dev/null +++ b/libk/string.c @@ -0,0 +1,133 @@ +#include + +int memcmp(const void *str1, const void *str2, size_t n) { + unsigned char const *p1 = str1; + unsigned char const *p2 = str2; + int ret = 0; + + if (str1 == str2) + return 0; + + while (n > 0) { + if (*p1 != *p2) { + ret = (*p1 > *p2)?1:-1; + break; + } + n--; + p1++; + p2++; + } + return ret; +} + +void* memcpy(void* __restrict dest, const void* __restrict src, size_t n) { + if (dest == src) + return dest; + + unsigned char *pdest = dest; + unsigned char const *psrc = src; + for (size_t i = 0; i < n; i++) + pdest[i] = psrc[i]; + return dest; +} + +char* strncpy(char* __restrict dest, const char* __restrict src, size_t n) { + for (size_t i = 0; i < n; i++) { + if (src[i] == '\0') + break; + dest[i] = src[i]; + } + return dest; +} + +char* strcpy(char* __restrict dest, const char* __restrict src) { + return (char*)memcpy(dest, src, strlen(src)); +} + +char* strcat(char* __restrict dest, const char* __restrict src) { + return (char*)memcpy(&dest[strlen(dest)], src, strlen(src)); +} + +char* strncat(char* __restrict dest, const char* __restrict src, size_t n) { + return (char*)memcpy(&dest[strlen(dest)], src, n); +} + +void* memmove(void* __restrict dest, const void* __restrict src, size_t n) { + if (dest == src) + return dest; + + unsigned char const *psrc = src; + unsigned char buffer[n]; + + for (size_t i = 0; i < n; i++) + buffer[i] = psrc[i]; + return memcpy(dest, (void*)buffer, n); +} + +void* memset(void *str, int c, size_t n) { + unsigned char *p = str; + for (size_t i = 0; i < n; i++) + p[i] = (unsigned char)c; + return str; +} + +int strncmp(const char *str1, const char *str2, size_t n) { + return memcmp(str1, str2, n); +} + +int strcmp(const char *str1, const char *str2) { + size_t str1_sz = strlen(str1); + size_t str2_sz = strlen(str2); + if (str1_sz > str2_sz) + return memcmp(str1, str2, str2_sz); + return memcmp(str1, str2, str1_sz); +} + +size_t strlen(const char *str) { + size_t i = 0; + while (str[i] != '\0') + i++; + return i; +} + +int _is_delim(char c, const char *delim) { + while (*delim != '\0') { + if (c == *delim) + return 1; + delim++; + } + return 0; +} + +char* strtok(char* __restrict str, const char* __restrict delim) { + static char *old_str; + + if (str == NULL) + str = old_str; + + while (1) { + if (_is_delim(*str, delim)) { + str++; + continue; + } + + if (*str == '\0') + return NULL; + break; + } + + char *ret = str; + while (1) { + if (*str == '\0') { + old_str = str; + return ret; + } + + if (_is_delim(*str, delim)) { + *str = '\0'; + old_str = str + 1; + return ret; + } + str++; + } +} -- cgit v1.2.3