diff --git a/LibC/Makefile b/LibC/Makefile index ba3a69695b..471e70c205 100644 --- a/LibC/Makefile +++ b/LibC/Makefile @@ -40,6 +40,7 @@ LIBC_OBJS = \ poll.o \ locale.o \ arpa/inet.o \ + netdb.o \ crt0.o ASM_OBJS = setjmp.no diff --git a/LibC/arpa/inet.cpp b/LibC/arpa/inet.cpp index a85ee697a7..790b9eb715 100644 --- a/LibC/arpa/inet.cpp +++ b/LibC/arpa/inet.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -47,5 +48,14 @@ int inet_pton(int af, const char* src, void* dst) return 0; } +in_addr_t inet_addr(const char* str) +{ + in_addr_t tmp; + int rc = inet_pton(AF_INET, str, &tmp); + if (rc < 0) + return INADDR_NONE; + return tmp; +} + } diff --git a/LibC/netdb.cpp b/LibC/netdb.cpp new file mode 100644 index 0000000000..3be3bc868e --- /dev/null +++ b/LibC/netdb.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +extern "C" { + +static hostent __gethostbyname_buffer; +static in_addr_t __gethostbyname_address; +static in_addr_t* __gethostbyname_address_list_buffer[2]; + +hostent* gethostbyname(const char* name) +{ + if (!strcmp(name, "boards.4channel.org")) { + __gethostbyname_buffer.h_name = "boards.4channel.org"; + __gethostbyname_buffer.h_aliases = nullptr; + __gethostbyname_buffer.h_addrtype = AF_INET; + __gethostbyname_address = 0x4b4f1168; + __gethostbyname_address_list_buffer[0] = &__gethostbyname_address; + __gethostbyname_address_list_buffer[1] = nullptr; + __gethostbyname_buffer.h_addr_list = (char**)__gethostbyname_address_list_buffer; + __gethostbyname_buffer.h_length = 4; + return &__gethostbyname_buffer; + } + dbgprintf("FIXME(LibC): gethostbyname(%s)\n", name); + return nullptr; +} + +} + diff --git a/LibC/netdb.h b/LibC/netdb.h new file mode 100644 index 0000000000..727c212e9a --- /dev/null +++ b/LibC/netdb.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +__BEGIN_DECLS + +struct hostent { + char* h_name; + char** h_aliases; + int h_addrtype; + int h_length; + char** h_addr_list; +}; + +struct hostent *gethostbyname(const char*); + +__END_DECLS diff --git a/LibC/netinet/in.h b/LibC/netinet/in.h index 2eef065265..f0a59de8be 100644 --- a/LibC/netinet/in.h +++ b/LibC/netinet/in.h @@ -6,7 +6,9 @@ __BEGIN_DECLS typedef uint32_t in_addr_t; +in_addr_t inet_addr(const char*); #define INADDR_ANY ((in_addr_t)0) +#define INADDR_NONE ((in_addr_t)-1) __END_DECLS diff --git a/LibC/stdio.cpp b/LibC/stdio.cpp index 33eaff3123..2b8e9186bf 100644 --- a/LibC/stdio.cpp +++ b/LibC/stdio.cpp @@ -351,8 +351,20 @@ void perror(const char* s) FILE* fopen(const char* pathname, const char* mode) { - assert(!strcmp(mode, "r") || !strcmp(mode, "rb")); - int fd = open(pathname, O_RDONLY); + int flags = 0; + if (!strcmp(mode, "r") || !strcmp(mode, "rb")) + flags = O_RDONLY; + else if (!strcmp(mode, "r+") || !strcmp(mode, "rb+")) + flags = O_RDWR; + else if (!strcmp(mode, "w") || !strcmp(mode, "wb")) + flags = O_WRONLY | O_CREAT | O_TRUNC; + else if (!strcmp(mode, "w+") || !strcmp(mode, "wb+")) + flags = O_RDWR | O_CREAT | O_TRUNC; + else { + fprintf(stderr, "FIXME(LibC): fopen('%s', '%s')\n", pathname, mode); + ASSERT_NOT_REACHED(); + } + int fd = open(pathname, flags, 0666); if (fd < 0) return nullptr; return make_FILE(fd); @@ -368,7 +380,7 @@ FILE* freopen(const char* pathname, const char* mode, FILE* stream) FILE* fdopen(int fd, const char* mode) { - assert(!strcmp(mode, "r") || !strcmp(mode, "rb")); + // FIXME: Verify that the mode matches how fd is already open. if (fd < 0) return nullptr; return make_FILE(fd); @@ -404,5 +416,13 @@ int pclose(FILE*) assert(false); } +int remove(const char* pathname) +{ + int rc = unlink(pathname); + if (rc < 0 && errno != EISDIR) + return -1; + return rmdir(pathname); +} + } diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp index 8d0b9aa153..68281627cc 100644 --- a/LibC/stdlib.cpp +++ b/LibC/stdlib.cpp @@ -161,6 +161,8 @@ void* calloc(size_t count, size_t size) void* realloc(void *ptr, size_t size) { + if (!ptr) + return malloc(size); validate_mallocation(ptr, "realloc()"); auto* header = (MallocHeader*)((((byte*)ptr) - sizeof(MallocHeader))); size_t old_size = header->size; @@ -288,6 +290,12 @@ long atol(const char* str) return atoi(str); } +long long atoll(const char* str) +{ + dbgprintf("FIXME(Libc): atoll('%s') passing through to atol()\n", str); + return atol(str); +} + static char ptsname_buf[32]; char* ptsname(int fd) { @@ -335,9 +343,32 @@ int system(const char* command) return execl("/bin/sh", "sh", "-c", command, nullptr); } -char* mktemp(char*) +char* mktemp(char* pattern) { - ASSERT_NOT_REACHED(); + int length = strlen(pattern); + + // FIXME: Check for an invalid template pattern and return EINVAL. + if (length < 6) { + pattern[0] = '\0'; + errno = EINVAL; + return pattern; + } + + int start = length - 6; + + static constexpr char random_characters[] = "abcdefghijklmnopqrstuvwxyz0123456789"; + + for (int attempt = 0; attempt < 100; ++attempt) { + for (int i = 0; i < 6; ++i) + pattern[start + i] = random_characters[(rand() % sizeof(random_characters))]; + struct stat st; + int rc = lstat(pattern, &st); + if (rc < 0 && errno == ENOENT) + return pattern; + } + pattern[0] = '\0'; + errno = EEXIST; + return pattern; } void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) diff --git a/LibC/stdlib.h b/LibC/stdlib.h index a5d2069ba1..cd5ff2c297 100644 --- a/LibC/stdlib.h +++ b/LibC/stdlib.h @@ -18,6 +18,7 @@ char* getenv(const char* name); int putenv(char*); int atoi(const char*); long atol(const char*); +long long atoll(const char*); double strtod(const char*, char** endptr); long strtol(const char*, char** endptr, int base); unsigned long strtoul(const char*, char** endptr, int base); diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index fe9ade86b8..de24904dd0 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -26,6 +26,11 @@ pid_t fork() __RETURN_WITH_ERRNO(rc, rc, -1); } +int execv(const char* path, char* const argv[]) +{ + return execve(path, argv, nullptr); +} + int execve(const char* filename, char* const argv[], char* const envp[]) { int rc = syscall(SC_execve, filename, argv, envp); diff --git a/LibC/unistd.h b/LibC/unistd.h index a5ce7936fe..7d33acd22a 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -22,6 +22,7 @@ int get_shared_buffer_size(int shared_buffer_id); int read_tsc(unsigned* lsw, unsigned* msw); inline int getpagesize() { return 4096; } pid_t fork(); +int execv(const char* path, char* const argv[]); int execve(const char* filename, char* const argv[], char* const envp[]); int execvp(const char* filename, char* const argv[]); int execl(const char* filename, const char* arg, ...);