123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- #include <AK/AKString.h>
- #include <AK/Assertions.h>
- #include <AK/HashMap.h>
- #include <AK/StdLibExtras.h>
- #include <AK/Types.h>
- #include <Kernel/Syscall.h>
- #include <alloca.h>
- #include <assert.h>
- #include <ctype.h>
- #include <errno.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/wait.h>
- #include <unistd.h>
- extern "C" {
- typedef void(*__atexit_handler)();
- static int __atexit_handler_count = 0;
- static __atexit_handler __atexit_handlers[32];
- void exit(int status)
- {
- for (int i = 0; i < __atexit_handler_count; ++i)
- __atexit_handlers[i]();
- extern void _fini();
- _fini();
- fflush(stdout);
- fflush(stderr);
- _exit(status);
- ASSERT_NOT_REACHED();
- }
- int atexit(void (*handler)())
- {
- ASSERT(__atexit_handler_count < 32);
- __atexit_handlers[__atexit_handler_count++] = handler;
- return 0;
- }
- void abort()
- {
- raise(SIGABRT);
- }
- static HashTable<char*> s_malloced_environment_variables;
- static void free_environment_variable_if_needed(const char* var)
- {
- if (!s_malloced_environment_variables.contains((char*)var))
- return;
- free((void*)var);
- s_malloced_environment_variables.remove((char*)var);
- }
- char* getenv(const char* name)
- {
- size_t vl = strlen(name);
- for (size_t i = 0; environ[i]; ++i) {
- const char* decl = environ[i];
- char* eq = strchr(decl, '=');
- if (!eq)
- continue;
- size_t varLength = eq - decl;
- if (vl != varLength)
- continue;
- if (strncmp(decl, name, varLength) == 0) {
- return eq + 1;
- }
- }
- return nullptr;
- }
- int unsetenv(const char* name)
- {
- auto new_var_len = strlen(name);
- size_t environ_size = 0;
- size_t skip = -1;
- for (; environ[environ_size]; ++environ_size) {
- char* old_var = environ[environ_size];
- char* old_eq = strchr(old_var, '=');
- ASSERT(old_eq);
- auto old_var_len = old_eq - old_var;
- if (new_var_len != old_var_len)
- continue; // can't match
- if (strncmp(name, old_var, new_var_len) == 0)
- skip = environ_size;
- }
- if (skip == -1)
- return 0; // not found: no failure.
- // Shuffle the existing array down by one.
- memmove(&environ[skip], &environ[skip+1], ((environ_size-1)-skip) * sizeof(environ[0]));
- environ[environ_size-1] = nullptr;
- free_environment_variable_if_needed(name);
- return 0;
- }
- int setenv(const char* name, const char* value, int overwrite)
- {
- if (!overwrite && !getenv(name))
- return 0;
- auto length = strlen(name) + strlen(value) + 2;
- auto* var = (char*)malloc(length);
- snprintf(var, length, "%s=%s", name, value);
- s_malloced_environment_variables.set(var);
- return putenv(var);
- }
- int putenv(char* new_var)
- {
- char* new_eq = strchr(new_var, '=');
- if (!new_eq)
- return unsetenv(new_var);
- auto new_var_len = new_eq - new_var;
- size_t environ_size = 0;
- for (; environ[environ_size]; ++environ_size) {
- char* old_var = environ[environ_size];
- char* old_eq = strchr(old_var, '=');
- ASSERT(old_eq);
- auto old_var_len = old_eq - old_var;
- if (new_var_len != old_var_len)
- continue; // can't match
- if (strncmp(new_var, old_var, new_var_len) == 0) {
- free_environment_variable_if_needed(old_var);
- environ[environ_size] = new_var;
- return 0;
- }
- }
- // At this point, we need to append the new var.
- // 2 here: one for the new var, one for the sentinel value.
- char **new_environ = (char**)malloc((environ_size + 2) * sizeof(char*));
- if (new_environ == nullptr) {
- errno = ENOMEM;
- return -1;
- }
- for (size_t i = 0; environ[i]; ++i) {
- new_environ[i] = environ[i];
- }
- new_environ[environ_size] = new_var;
- new_environ[environ_size + 1] = nullptr;
- // swap new and old
- // note that the initial environ is not heap allocated!
- extern bool __environ_is_malloced;
- if (__environ_is_malloced)
- free(environ);
- __environ_is_malloced = true;
- environ = new_environ;
- return 0;
- }
- double strtod(const char* str, char** endptr)
- {
- (void)str;
- (void)endptr;
- dbgprintf("LibC: strtod: '%s'\n", str);
- ASSERT_NOT_REACHED();
- }
- float strtof(const char* str, char** endptr)
- {
- (void)str;
- (void)endptr;
- dbgprintf("LibC: strtof: '%s'\n", str);
- ASSERT_NOT_REACHED();
- }
- double atof(const char* str)
- {
- dbgprintf("LibC: atof: '%s'\n", str);
- ASSERT_NOT_REACHED();
- }
- int atoi(const char* str)
- {
- size_t len = strlen(str);
- int value = 0;
- bool isNegative = false;
- for (size_t i = 0; i < len; ++i) {
- if (i == 0 && str[0] == '-') {
- isNegative = true;
- continue;
- }
- if (str[i] < '0' || str[i] > '9')
- return value;
- value = value * 10;
- value += str[i] - '0';
- }
- return isNegative ? -value : value;
- }
- long atol(const char* str)
- {
- static_assert(sizeof(int) == sizeof(long));
- 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)
- {
- if (ptsname_r(fd, ptsname_buf, sizeof(ptsname_buf)) < 0)
- return nullptr;
- return ptsname_buf;
- }
- int ptsname_r(int fd, char* buffer, size_t size)
- {
- int rc = syscall(SC_ptsname_r, fd, buffer, size);
- __RETURN_WITH_ERRNO(rc, rc, -1);
- }
- static unsigned long s_next_rand = 1;
- int rand()
- {
- s_next_rand = s_next_rand * 1103515245 + 12345;
- return((unsigned)(s_next_rand/((RAND_MAX + 1) * 2)) % (RAND_MAX + 1));
- }
- void srand(unsigned seed)
- {
- s_next_rand = seed;
- }
- int abs(int i)
- {
- return i < 0 ? -i : i;
- }
- long int random()
- {
- return rand();
- }
- void srandom(unsigned seed)
- {
- srand(seed);
- }
- int system(const char* command)
- {
- auto child = fork();
- if (!child) {
- int rc = execl("/bin/sh", "sh", "-c", command, nullptr);
- if (rc < 0)
- perror("execl");
- exit(0);
- }
- int wstatus;
- waitpid(child, &wstatus, 0);
- return WEXITSTATUS(wstatus);
- }
- char* mktemp(char* pattern)
- {
- 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 *))
- {
- dbgprintf("FIXME(LibC): bsearch(%p, %p, %u, %u, %p)\n", key, base, nmemb, size, compar);
- ASSERT_NOT_REACHED();
- }
- div_t div(int numerator, int denominator)
- {
- div_t result;
- result.quot = numerator / denominator;
- result.rem = numerator % denominator;
- return result;
- }
- ldiv_t ldiv(long numerator, long denominator)
- {
- ldiv_t result;
- result.quot = numerator / denominator;
- result.rem = numerator % denominator;
- return result;
- }
- size_t mbstowcs(wchar_t*, const char*, size_t)
- {
- ASSERT_NOT_REACHED();
- }
- long strtol(const char* str, char** endptr, int base)
- {
- const char* s = str;
- unsigned long acc;
- int c;
- unsigned long cutoff;
- int neg = 0;
- int any;
- int cutlim;
- do {
- c = *s++;
- } while (isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else if (c == '+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
- cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
- cutlim = cutoff % (unsigned long)base;
- cutoff /= (unsigned long)base;
- for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = neg ? LONG_MIN : LONG_MAX;
- errno = ERANGE;
- } else if (neg)
- acc = -acc;
- if (endptr)
- *endptr = const_cast<char*>((any ? s - 1 : str));
- return acc;
- }
- unsigned long strtoul(const char* str, char** endptr, int base)
- {
- auto value = strtol(str, endptr, base);
- ASSERT(value >= 0);
- return value;
- }
- }
|