Serenity Operating System
1/*
2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Assertions.h>
8#include <AK/CharacterTypes.h>
9#include <AK/FloatingPointStringConversions.h>
10#include <AK/HashMap.h>
11#include <AK/Noncopyable.h>
12#include <AK/Random.h>
13#include <AK/StdLibExtras.h>
14#include <AK/Types.h>
15#include <AK/Utf8View.h>
16#include <alloca.h>
17#include <assert.h>
18#include <bits/pthread_cancel.h>
19#include <ctype.h>
20#include <errno.h>
21#include <fcntl.h>
22#include <pthread.h>
23#include <signal.h>
24#include <spawn.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <sys/auxv.h>
29#include <sys/internals.h>
30#include <sys/ioctl.h>
31#include <sys/mman.h>
32#include <sys/stat.h>
33#include <sys/sysmacros.h>
34#include <sys/wait.h>
35#include <syscall.h>
36#include <unistd.h>
37#include <wchar.h>
38
39static void strtons(char const* str, char** endptr)
40{
41 assert(endptr);
42 char* ptr = const_cast<char*>(str);
43 while (isspace(*ptr)) {
44 ptr += 1;
45 }
46 *endptr = ptr;
47}
48
49enum Sign {
50 Negative,
51 Positive,
52};
53
54static Sign strtosign(char const* str, char** endptr)
55{
56 assert(endptr);
57 if (*str == '+') {
58 *endptr = const_cast<char*>(str + 1);
59 return Sign::Positive;
60 } else if (*str == '-') {
61 *endptr = const_cast<char*>(str + 1);
62 return Sign::Negative;
63 } else {
64 *endptr = const_cast<char*>(str);
65 return Sign::Positive;
66 }
67}
68
69enum DigitConsumeDecision {
70 Consumed,
71 PosOverflow,
72 NegOverflow,
73 Invalid,
74};
75
76template<typename T, T min_value, T max_value>
77class NumParser {
78 AK_MAKE_NONMOVABLE(NumParser);
79
80public:
81 NumParser(Sign sign, int base)
82 : m_base(base)
83 , m_num(0)
84 , m_sign(sign)
85 {
86 m_cutoff = positive() ? (max_value / base) : (min_value / base);
87 m_max_digit_after_cutoff = positive() ? (max_value % base) : (min_value % base);
88 }
89
90 int parse_digit(char ch)
91 {
92 int digit;
93 if (isdigit(ch))
94 digit = ch - '0';
95 else if (islower(ch))
96 digit = ch - ('a' - 10);
97 else if (isupper(ch))
98 digit = ch - ('A' - 10);
99 else
100 return -1;
101
102 if (static_cast<T>(digit) >= m_base)
103 return -1;
104
105 return digit;
106 }
107
108 DigitConsumeDecision consume(char ch)
109 {
110 int digit = parse_digit(ch);
111 if (digit == -1)
112 return DigitConsumeDecision::Invalid;
113
114 if (!can_append_digit(digit)) {
115 if (m_sign != Sign::Negative) {
116 return DigitConsumeDecision::PosOverflow;
117 } else {
118 return DigitConsumeDecision::NegOverflow;
119 }
120 }
121
122 m_num *= m_base;
123 m_num += positive() ? digit : -digit;
124
125 return DigitConsumeDecision::Consumed;
126 }
127
128 T number() const { return m_num; };
129
130private:
131 bool can_append_digit(int digit)
132 {
133 bool const is_below_cutoff = positive() ? (m_num < m_cutoff) : (m_num > m_cutoff);
134
135 if (is_below_cutoff) {
136 return true;
137 } else {
138 return m_num == m_cutoff && digit <= m_max_digit_after_cutoff;
139 }
140 }
141
142 bool positive() const
143 {
144 return m_sign != Sign::Negative;
145 }
146
147 const T m_base;
148 T m_num;
149 T m_cutoff;
150 int m_max_digit_after_cutoff;
151 Sign m_sign;
152};
153
154typedef NumParser<int, INT_MIN, INT_MAX> IntParser;
155typedef NumParser<long long, LONG_LONG_MIN, LONG_LONG_MAX> LongLongParser;
156typedef NumParser<unsigned long long, 0ULL, ULONG_LONG_MAX> ULongLongParser;
157
158static bool is_either(char* str, int offset, char lower, char upper)
159{
160 char ch = *(str + offset);
161 return ch == lower || ch == upper;
162}
163
164template<typename Callback>
165inline int generate_unique_filename(char* pattern, size_t suffix_length, Callback callback)
166{
167 size_t length = strlen(pattern);
168
169 if (length < 6 + suffix_length || memcmp(pattern + length - 6 - suffix_length, "XXXXXX", 6))
170 return EINVAL;
171
172 size_t start = length - 6 - suffix_length;
173
174 constexpr char random_characters[] = "abcdefghijklmnopqrstuvwxyz0123456789";
175
176 for (int attempt = 0; attempt < 100; ++attempt) {
177 for (int i = 0; i < 6; ++i)
178 pattern[start + i] = random_characters[(arc4random() % (sizeof(random_characters) - 1))];
179 if (callback() == IterationDecision::Break)
180 return 0;
181 }
182
183 return EEXIST;
184}
185
186static bool is_infinity_string(char* parse_ptr, char** endptr)
187{
188 if (is_either(parse_ptr, 0, 'i', 'I')) {
189 if (is_either(parse_ptr, 1, 'n', 'N')) {
190 if (is_either(parse_ptr, 2, 'f', 'F')) {
191 parse_ptr += 3;
192 if (is_either(parse_ptr, 0, 'i', 'I')) {
193 if (is_either(parse_ptr, 1, 'n', 'N')) {
194 if (is_either(parse_ptr, 2, 'i', 'I')) {
195 if (is_either(parse_ptr, 3, 't', 'T')) {
196 if (is_either(parse_ptr, 4, 'y', 'Y')) {
197 parse_ptr += 5;
198 }
199 }
200 }
201 }
202 }
203 if (endptr)
204 *endptr = parse_ptr;
205
206 return true;
207 }
208 }
209 }
210
211 return false;
212}
213
214static bool is_nan_string(char* parse_ptr, char** endptr)
215{
216 // FIXME: Actually parse (or at least skip) the (n-char-sequenceopt) part
217 if (is_either(parse_ptr, 0, 'n', 'N')) {
218 if (is_either(parse_ptr, 1, 'a', 'A')) {
219 if (is_either(parse_ptr, 2, 'n', 'N')) {
220 if (endptr)
221 *endptr = parse_ptr + 3;
222 return true;
223 }
224 }
225 }
226
227 return false;
228}
229
230template<FloatingPoint T>
231static T c_str_to_floating_point(char const* str, char** endptr)
232{
233 // First, they decompose the input string into three parts:
234 char* parse_ptr = const_cast<char*>(str);
235
236 // An initial, possibly empty, sequence of white-space characters (as specified by isspace())
237 strtons(parse_ptr, &parse_ptr);
238
239 // A subject sequence interpreted as a floating-point constant or representing infinity or NaN
240
241 if (*parse_ptr == '\0') {
242 if (endptr)
243 *endptr = const_cast<char*>(str);
244 return 0.;
245 }
246
247 bool is_hex = [&] {
248 // A hexfloat must start with either 0x, 0X, -0x or -0X and have something after it
249 char const* parse_head = parse_ptr;
250 if (*parse_head == '-')
251 ++parse_head;
252
253 if (*parse_head != '0')
254 return false;
255
256 ++parse_head;
257
258 if (*parse_head != 'x')
259 return false;
260
261 ++parse_head;
262
263 // We must have at least one digit but it can come after the "decimal" point.
264
265 if (is_ascii_hex_digit(*parse_head))
266 return true;
267
268 if (*parse_head != '.')
269 return false;
270
271 ++parse_head;
272
273 return is_ascii_hex_digit(*parse_head);
274 }();
275
276 AK::FloatingPointParseResults<T> double_parse_result;
277 if (is_hex) {
278 // A 0x or 0X, then a non-empty sequence of hexadecimal digits optionally containing a radix character;
279 // then an optional binary exponent part consisting of the character 'p' or the character 'P',
280 // optionally followed by a '+' or '-' character, and then followed by one or more decimal digits
281
282 double_parse_result = AK::parse_first_hexfloat_until_zero_character<T>(parse_ptr);
283 } else {
284 // A non-empty sequence of decimal digits optionally containing a radix character;
285 // then an optional exponent part consisting of the character 'e' or the character 'E',
286 // optionally followed by a '+' or '-' character, and then followed by one or more decimal digits
287 double_parse_result = AK::parse_first_floating_point_until_zero_character<T>(parse_ptr);
288 }
289
290 if (double_parse_result.error == AK::FloatingPointError::None) {
291 // The only way to get NaN (which we shouldn't) or infinities is rounding up to them so we
292 // have to set ERANGE in that case.
293 if (!__builtin_isfinite(double_parse_result.value))
294 errno = ERANGE;
295
296 if (endptr)
297 *endptr = const_cast<char*>(double_parse_result.end_ptr);
298 return double_parse_result.value;
299 }
300
301 if (double_parse_result.error == AK::FloatingPointError::RoundedDownToZero || double_parse_result.error == AK::FloatingPointError::OutOfRange) {
302 // This is a special case for strtod, where we have a double so close to zero we had to round
303 // it to zero, in which case we have to set ERANGE
304 errno = ERANGE;
305
306 if (endptr)
307 *endptr = const_cast<char*>(double_parse_result.end_ptr);
308 return double_parse_result.value;
309 }
310
311 // The only way we are here is if the input was not valid for parse_first_floating_point or not a valid hex float
312 // So the only cases left are:
313 // - One of INF or INFINITY, ignoring case
314 // - One of NAN or NAN(n-char-sequenceopt), ignoring case in the NAN part
315
316 const Sign sign = strtosign(parse_ptr, &parse_ptr);
317
318 if (is_infinity_string(parse_ptr, endptr)) {
319 // Don't set errno to ERANGE here:
320 // The caller may want to distinguish between "input is
321 // literal infinity" and "input is not literal infinity
322 // but did not fit into double".
323 if (sign != Sign::Negative)
324 return static_cast<T>(__builtin_huge_val());
325 else
326 return static_cast<T>(-__builtin_huge_val());
327 }
328
329 if (is_nan_string(parse_ptr, endptr)) {
330 errno = ERANGE;
331 // FIXME: Do we actually want to return "different" NaN bit values?
332 if (sign != Sign::Negative)
333 return static_cast<T>(__builtin_nan(""));
334 else
335 return static_cast<T>(-__builtin_nan(""));
336 }
337
338 // If no conversion could be performed, 0 shall be returned, and errno may be set to [EINVAL].
339 // FIXME: This is in the posix standard linked from strtod but not in implementations of strtod
340 // and not in the man pages for linux strtod.
341 if (endptr)
342 *endptr = const_cast<char*>(str);
343 return 0;
344}
345
346extern "C" {
347
348void exit(int status)
349{
350 __cxa_finalize(nullptr);
351
352 if (secure_getenv("LIBC_DUMP_MALLOC_STATS"))
353 serenity_dump_malloc_stats();
354
355 extern void _fini();
356 _fini();
357 fflush(nullptr);
358
359#ifndef _DYNAMIC_LOADER
360 __pthread_key_destroy_for_current_thread();
361#endif
362
363 _exit(status);
364}
365
366static void __atexit_to_cxa_atexit(void* handler)
367{
368 reinterpret_cast<void (*)()>(handler)();
369}
370
371int atexit(void (*handler)())
372{
373 return __cxa_atexit(__atexit_to_cxa_atexit, (void*)handler, nullptr);
374}
375
376void _abort()
377{
378 // According to the GCC manual __builtin_trap() can call abort() so using it here might not seem safe at first. However,
379 // on all the platforms we support GCC emits an undefined instruction instead of a call.
380 __builtin_trap();
381}
382
383void abort()
384{
385 // For starters, send ourselves a SIGABRT.
386 raise(SIGABRT);
387 // If that didn't kill us, try harder.
388 sigset_t set;
389 sigemptyset(&set);
390 sigaddset(&set, SIGABRT);
391 sigprocmask(SIG_UNBLOCK, &set, nullptr);
392 raise(SIGABRT);
393 _abort();
394}
395
396static HashTable<FlatPtr> s_malloced_environment_variables;
397
398static void free_environment_variable_if_needed(char const* var)
399{
400 if (!s_malloced_environment_variables.contains((FlatPtr)var))
401 return;
402 free(const_cast<char*>(var));
403 s_malloced_environment_variables.remove((FlatPtr)var);
404}
405
406char* getenv(char const* name)
407{
408 size_t vl = strlen(name);
409 for (size_t i = 0; environ[i]; ++i) {
410 char const* decl = environ[i];
411 char* eq = strchr(decl, '=');
412 if (!eq)
413 continue;
414 size_t varLength = eq - decl;
415 if (vl != varLength)
416 continue;
417 if (strncmp(decl, name, varLength) == 0) {
418 return eq + 1;
419 }
420 }
421 return nullptr;
422}
423
424char* secure_getenv(char const* name)
425{
426 if (getauxval(AT_SECURE))
427 return nullptr;
428 return getenv(name);
429}
430
431// https://pubs.opengroup.org/onlinepubs/9699919799/functions/unsetenv.html
432int unsetenv(char const* name)
433{
434 auto new_var_len = strlen(name);
435 size_t environ_size = 0;
436 int skip = -1;
437
438 for (; environ[environ_size]; ++environ_size) {
439 char* old_var = environ[environ_size];
440 char* old_eq = strchr(old_var, '=');
441 VERIFY(old_eq);
442 size_t old_var_len = old_eq - old_var;
443
444 if (new_var_len != old_var_len)
445 continue; // can't match
446
447 if (strncmp(name, old_var, new_var_len) == 0)
448 skip = environ_size;
449 }
450
451 if (skip == -1)
452 return 0; // not found: no failure.
453
454 // Shuffle the existing array down by one.
455 memmove(&environ[skip], &environ[skip + 1], ((environ_size - 1) - skip) * sizeof(environ[0]));
456 environ[environ_size - 1] = nullptr;
457
458 free_environment_variable_if_needed(name);
459 return 0;
460}
461
462int clearenv()
463{
464 size_t environ_size = 0;
465 for (; environ[environ_size]; ++environ_size) {
466 environ[environ_size] = NULL;
467 }
468 *environ = NULL;
469 return 0;
470}
471
472// https://pubs.opengroup.org/onlinepubs/9699919799/functions/setenv.html
473int setenv(char const* name, char const* value, int overwrite)
474{
475 if (!overwrite && getenv(name))
476 return 0;
477 auto const total_length = strlen(name) + strlen(value) + 2;
478 auto* var = (char*)malloc(total_length);
479 snprintf(var, total_length, "%s=%s", name, value);
480 s_malloced_environment_variables.set((FlatPtr)var);
481 return putenv(var);
482}
483
484// A non-evil version of putenv that will strdup the env (and free it later)
485int serenity_putenv(char const* new_var, size_t length)
486{
487 auto* var = strndup(new_var, length);
488 s_malloced_environment_variables.set((FlatPtr)var);
489 return putenv(var);
490}
491
492// https://pubs.opengroup.org/onlinepubs/9699919799/functions/putenv.html
493int putenv(char* new_var)
494{
495 char* new_eq = strchr(new_var, '=');
496
497 if (!new_eq)
498 return unsetenv(new_var);
499
500 auto new_var_len = new_eq - new_var;
501 int environ_size = 0;
502 for (; environ[environ_size]; ++environ_size) {
503 char* old_var = environ[environ_size];
504 char* old_eq = strchr(old_var, '=');
505 VERIFY(old_eq);
506 auto old_var_len = old_eq - old_var;
507
508 if (new_var_len != old_var_len)
509 continue; // can't match
510
511 if (strncmp(new_var, old_var, new_var_len) == 0) {
512 free_environment_variable_if_needed(old_var);
513 environ[environ_size] = new_var;
514 return 0;
515 }
516 }
517
518 // At this point, we need to append the new var.
519 // 2 here: one for the new var, one for the sentinel value.
520 auto** new_environ = static_cast<char**>(kmalloc_array(environ_size + 2, sizeof(char*)));
521 if (new_environ == nullptr) {
522 errno = ENOMEM;
523 return -1;
524 }
525
526 for (int i = 0; environ[i]; ++i) {
527 new_environ[i] = environ[i];
528 }
529
530 new_environ[environ_size] = new_var;
531 new_environ[environ_size + 1] = nullptr;
532
533 // swap new and old
534 // note that the initial environ is not heap allocated!
535 extern bool __environ_is_malloced;
536 if (__environ_is_malloced)
537 free(environ);
538 __environ_is_malloced = true;
539 environ = new_environ;
540 return 0;
541}
542
543static char const* __progname = NULL;
544
545char const* getprogname()
546{
547 return __progname;
548}
549
550void setprogname(char const* progname)
551{
552 for (int i = strlen(progname) - 1; i >= 0; i--) {
553 if (progname[i] == '/') {
554 __progname = progname + i + 1;
555 return;
556 }
557 }
558
559 __progname = progname;
560}
561
562// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtod.html
563double strtod(char const* str, char** endptr)
564{
565 return c_str_to_floating_point<double>(str, endptr);
566}
567
568// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtold.html
569long double strtold(char const* str, char** endptr)
570{
571 assert(sizeof(double) == sizeof(long double));
572 return strtod(str, endptr);
573}
574
575// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtof.html
576float strtof(char const* str, char** endptr)
577{
578 return c_str_to_floating_point<float>(str, endptr);
579}
580
581// https://pubs.opengroup.org/onlinepubs/9699919799/functions/atof.html
582double atof(char const* str)
583{
584 return strtod(str, nullptr);
585}
586
587// https://pubs.opengroup.org/onlinepubs/9699919799/functions/atoi.html
588int atoi(char const* str)
589{
590 long value = strtol(str, nullptr, 10);
591 if (value > INT_MAX) {
592 return INT_MAX;
593 }
594 return value;
595}
596
597// https://pubs.opengroup.org/onlinepubs/9699919799/functions/atol.html
598long atol(char const* str)
599{
600 return strtol(str, nullptr, 10);
601}
602
603// https://pubs.opengroup.org/onlinepubs/9699919799/functions/atoll.html
604long long atoll(char const* str)
605{
606 return strtoll(str, nullptr, 10);
607}
608
609static char ptsname_buf[32];
610// https://pubs.opengroup.org/onlinepubs/9699919799/functions/ptsname.html
611char* ptsname(int fd)
612{
613 if (ptsname_r(fd, ptsname_buf, sizeof(ptsname_buf)) < 0)
614 return nullptr;
615 return ptsname_buf;
616}
617
618int ptsname_r(int fd, char* buffer, size_t size)
619{
620 struct stat stat;
621 if (fstat(fd, &stat) < 0)
622 return -1;
623
624 StringBuilder devpts_path_builder;
625 devpts_path_builder.append("/dev/pts/"sv);
626
627 int master_pty_index = 0;
628 // Note: When the user opens a PTY from /dev/ptmx with posix_openpt(), the open file descriptor
629 // points to /dev/ptmx, (major number is 5 and minor number is 2), but internally
630 // in the kernel, it points to a new MasterPTY device. When we do ioctl with TIOCGPTN option
631 // on the open file descriptor, it actually asks the MasterPTY what is the assigned index
632 // of it when the PTYMultiplexer created it.
633 if (ioctl(fd, TIOCGPTN, &master_pty_index) < 0)
634 return -1;
635
636 if (master_pty_index < 0) {
637 errno = EINVAL;
638 return -1;
639 }
640
641 devpts_path_builder.appendff("{:d}", master_pty_index);
642 if (devpts_path_builder.length() > size) {
643 errno = ERANGE;
644 return -1;
645 }
646 memset(buffer, 0, devpts_path_builder.length() + 1);
647 auto full_devpts_path_string = devpts_path_builder.to_deprecated_string();
648 if (!full_devpts_path_string.copy_characters_to_buffer(buffer, size)) {
649 errno = ERANGE;
650 return -1;
651 }
652 return 0;
653}
654
655static unsigned long s_next_rand = 1;
656
657// https://pubs.opengroup.org/onlinepubs/9699919799/functions/rand.html
658int rand()
659{
660 s_next_rand = s_next_rand * 1103515245 + 12345;
661 return ((unsigned)(s_next_rand / ((RAND_MAX + 1) * 2)) % (RAND_MAX + 1));
662}
663
664// https://pubs.opengroup.org/onlinepubs/9699919799/functions/srand.html
665void srand(unsigned seed)
666{
667 s_next_rand = seed;
668}
669
670// https://pubs.opengroup.org/onlinepubs/9699919799/functions/abs.html
671int abs(int i)
672{
673 return i < 0 ? -i : i;
674}
675
676// https://pubs.opengroup.org/onlinepubs/9699919799/functions/labs.html
677long int labs(long int i)
678{
679 return i < 0 ? -i : i;
680}
681
682// https://pubs.opengroup.org/onlinepubs/9699919799/functions/llabs.html
683long long int llabs(long long int i)
684{
685 return i < 0 ? -i : i;
686}
687
688// https://pubs.opengroup.org/onlinepubs/9699919799/functions/random.html
689long int random()
690{
691 return rand();
692}
693
694// https://pubs.opengroup.org/onlinepubs/9699919799/functions/srandom.html
695void srandom(unsigned seed)
696{
697 srand(seed);
698}
699
700// https://pubs.opengroup.org/onlinepubs/9699919799/functions/system.html
701int system(char const* command)
702{
703 __pthread_maybe_cancel();
704
705 if (!command)
706 return 1;
707
708 pid_t child;
709 char const* argv[] = { "sh", "-c", command, nullptr };
710 if ((errno = posix_spawn(&child, "/bin/sh", nullptr, nullptr, const_cast<char**>(argv), environ)))
711 return -1;
712 int wstatus;
713 waitpid(child, &wstatus, 0);
714 return WEXITSTATUS(wstatus);
715}
716
717// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mktemp.html
718char* mktemp(char* pattern)
719{
720 auto error = generate_unique_filename(pattern, 0, [&] {
721 struct stat st;
722 int rc = lstat(pattern, &st);
723 if (rc < 0 && errno == ENOENT)
724 return IterationDecision::Break;
725 return IterationDecision::Continue;
726 });
727 if (error) {
728 pattern[0] = '\0';
729 errno = error;
730 }
731 return pattern;
732}
733
734// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkstemp.html
735int mkstemp(char* pattern)
736{
737 return mkstemps(pattern, 0);
738}
739
740// https://man7.org/linux/man-pages/man3/mkstemps.3.html
741int mkstemps(char* pattern, int suffix_length)
742{
743 VERIFY(suffix_length >= 0);
744 int fd = -1;
745 auto error = generate_unique_filename(pattern, static_cast<size_t>(suffix_length), [&] {
746 fd = open(pattern, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); // I'm using the flags I saw glibc using.
747 if (fd >= 0)
748 return IterationDecision::Break;
749 return IterationDecision::Continue;
750 });
751 if (error) {
752 errno = error;
753 return -1;
754 }
755 return fd;
756}
757
758// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mkdtemp.html
759char* mkdtemp(char* pattern)
760{
761 auto error = generate_unique_filename(pattern, 0, [&] {
762 if (mkdir(pattern, 0700) == 0)
763 return IterationDecision::Break;
764 return IterationDecision::Continue;
765 });
766 if (error) {
767 errno = error;
768 return nullptr;
769 }
770 return pattern;
771}
772
773// https://pubs.opengroup.org/onlinepubs/9699919799/functions/bsearch.html
774void* bsearch(void const* key, void const* base, size_t nmemb, size_t size, int (*compar)(void const*, void const*))
775{
776 char* start = static_cast<char*>(const_cast<void*>(base));
777 while (nmemb > 0) {
778 char* middle_memb = start + (nmemb / 2) * size;
779 int comparison = compar(key, middle_memb);
780 if (comparison == 0)
781 return middle_memb;
782 else if (comparison > 0) {
783 start = middle_memb + size;
784 --nmemb;
785 }
786 nmemb /= 2;
787 }
788
789 return nullptr;
790}
791
792// https://pubs.opengroup.org/onlinepubs/9699919799/functions/div.html
793div_t div(int numerator, int denominator)
794{
795 div_t result;
796 result.quot = numerator / denominator;
797 result.rem = numerator % denominator;
798
799 if (numerator >= 0 && result.rem < 0) {
800 result.quot++;
801 result.rem -= denominator;
802 }
803 return result;
804}
805
806// https://pubs.opengroup.org/onlinepubs/9699919799/functions/ldiv.html
807ldiv_t ldiv(long numerator, long denominator)
808{
809 ldiv_t result;
810 result.quot = numerator / denominator;
811 result.rem = numerator % denominator;
812
813 if (numerator >= 0 && result.rem < 0) {
814 result.quot++;
815 result.rem -= denominator;
816 }
817 return result;
818}
819
820// https://pubs.opengroup.org/onlinepubs/9699919799/functions/lldiv.html
821lldiv_t lldiv(long long numerator, long long denominator)
822{
823 lldiv_t result;
824 result.quot = numerator / denominator;
825 result.rem = numerator % denominator;
826
827 if (numerator >= 0 && result.rem < 0) {
828 result.quot++;
829 result.rem -= denominator;
830 }
831 return result;
832}
833
834// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mblen.html
835int mblen(char const* s, size_t n)
836{
837 // POSIX: Equivalent to mbtowc(NULL, s, n), but we mustn't change the state of mbtowc.
838 static mbstate_t internal_state = {};
839
840 // Reset the internal state and ask whether we have shift states.
841 if (s == nullptr) {
842 internal_state = {};
843 return 0;
844 }
845
846 size_t ret = mbrtowc(nullptr, s, n, &internal_state);
847
848 // Incomplete characters get returned as illegal sequence.
849 if (ret == -2ul) {
850 errno = EILSEQ;
851 return -1;
852 }
853
854 return ret;
855}
856
857// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mbstowcs.html
858size_t mbstowcs(wchar_t* pwcs, char const* s, size_t n)
859{
860 static mbstate_t state = {};
861 return mbsrtowcs(pwcs, &s, n, &state);
862}
863
864// https://pubs.opengroup.org/onlinepubs/9699919799/functions/mbtowc.html
865int mbtowc(wchar_t* pwc, char const* s, size_t n)
866{
867 static mbstate_t internal_state = {};
868
869 // Reset the internal state and ask whether we have shift states.
870 if (s == nullptr) {
871 internal_state = {};
872 return 0;
873 }
874
875 size_t ret = mbrtowc(pwc, s, n, &internal_state);
876
877 // Incomplete characters get returned as illegal sequence.
878 // Internal state is undefined, so don't bother with resetting.
879 if (ret == -2ul) {
880 errno = EILSEQ;
881 return -1;
882 }
883
884 return ret;
885}
886
887// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wctomb.html
888int wctomb(char* s, wchar_t wc)
889{
890 static mbstate_t _internal_state = {};
891
892 // nullptr asks whether we have state-dependent encodings, but we don't have any.
893 if (s == nullptr)
894 return 0;
895
896 return static_cast<int>(wcrtomb(s, wc, &_internal_state));
897}
898
899// https://pubs.opengroup.org/onlinepubs/9699919799/functions/wcstombs.html
900size_t wcstombs(char* dest, wchar_t const* src, size_t max)
901{
902 char* original_dest = dest;
903 while ((size_t)(dest - original_dest) < max) {
904 StringView v { (char const*)src, sizeof(wchar_t) };
905
906 // FIXME: dependent on locale, for now utf-8 is supported.
907 Utf8View utf8 { v };
908 if (*utf8.begin() == '\0') {
909 *dest = '\0';
910 return (size_t)(dest - original_dest); // Exclude null character in returned size
911 }
912
913 for (auto byte : utf8) {
914 if (byte != '\0')
915 *dest++ = byte;
916 }
917 ++src;
918 }
919 return max;
920}
921
922// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html
923long strtol(char const* str, char** endptr, int base)
924{
925 long long value = strtoll(str, endptr, base);
926 if (value < LONG_MIN) {
927 errno = ERANGE;
928 return LONG_MIN;
929 } else if (value > LONG_MAX) {
930 errno = ERANGE;
931 return LONG_MAX;
932 }
933 return value;
934}
935
936// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoul.html
937unsigned long strtoul(char const* str, char** endptr, int base)
938{
939 unsigned long long value = strtoull(str, endptr, base);
940 if (value > ULONG_MAX) {
941 errno = ERANGE;
942 return ULONG_MAX;
943 }
944 return value;
945}
946
947// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoll.html
948long long strtoll(char const* str, char** endptr, int base)
949{
950 // Parse spaces and sign
951 char* parse_ptr = const_cast<char*>(str);
952 strtons(parse_ptr, &parse_ptr);
953 const Sign sign = strtosign(parse_ptr, &parse_ptr);
954
955 // Parse base
956 if (base == 0) {
957 if (*parse_ptr == '0') {
958 if (tolower(*(parse_ptr + 1)) == 'x') {
959 base = 16;
960 parse_ptr += 2;
961 } else {
962 base = 8;
963 }
964 } else {
965 base = 10;
966 }
967 }
968
969 // Parse actual digits.
970 LongLongParser digits { sign, base };
971 bool digits_usable = false;
972 bool should_continue = true;
973 bool overflow = false;
974 do {
975 bool is_a_digit;
976 if (overflow) {
977 is_a_digit = digits.parse_digit(*parse_ptr) >= 0;
978 } else {
979 DigitConsumeDecision decision = digits.consume(*parse_ptr);
980 switch (decision) {
981 case DigitConsumeDecision::Consumed:
982 is_a_digit = true;
983 // The very first actual digit must pass here:
984 digits_usable = true;
985 break;
986 case DigitConsumeDecision::PosOverflow:
987 case DigitConsumeDecision::NegOverflow:
988 is_a_digit = true;
989 overflow = true;
990 break;
991 case DigitConsumeDecision::Invalid:
992 is_a_digit = false;
993 break;
994 default:
995 VERIFY_NOT_REACHED();
996 }
997 }
998
999 should_continue = is_a_digit;
1000 parse_ptr += should_continue;
1001 } while (should_continue);
1002
1003 if (!digits_usable) {
1004 // No actual number value available.
1005 if (endptr)
1006 *endptr = const_cast<char*>(str);
1007 return 0;
1008 }
1009
1010 if (endptr)
1011 *endptr = parse_ptr;
1012
1013 if (overflow) {
1014 errno = ERANGE;
1015 if (sign != Sign::Negative) {
1016 return LONG_LONG_MAX;
1017 } else {
1018 return LONG_LONG_MIN;
1019 }
1020 }
1021
1022 return digits.number();
1023}
1024
1025// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoull.html
1026unsigned long long strtoull(char const* str, char** endptr, int base)
1027{
1028 // Parse spaces and sign
1029 char* parse_ptr = const_cast<char*>(str);
1030 strtons(parse_ptr, &parse_ptr);
1031
1032 if (base == 16) {
1033 // Dr. POSIX: "If the value of base is 16, the characters 0x or 0X may optionally precede
1034 // the sequence of letters and digits, following the sign if present."
1035 if (*parse_ptr == '0') {
1036 if (tolower(*(parse_ptr + 1)) == 'x')
1037 parse_ptr += 2;
1038 }
1039 }
1040 // Parse base
1041 if (base == 0) {
1042 if (*parse_ptr == '0') {
1043 if (tolower(*(parse_ptr + 1)) == 'x') {
1044 base = 16;
1045 parse_ptr += 2;
1046 } else {
1047 base = 8;
1048 }
1049 } else {
1050 base = 10;
1051 }
1052 }
1053
1054 // Parse actual digits.
1055 ULongLongParser digits { Sign::Positive, base };
1056 bool digits_usable = false;
1057 bool should_continue = true;
1058 bool overflow = false;
1059 do {
1060 bool is_a_digit;
1061 if (overflow) {
1062 is_a_digit = digits.parse_digit(*parse_ptr) >= 0;
1063 } else {
1064 DigitConsumeDecision decision = digits.consume(*parse_ptr);
1065 switch (decision) {
1066 case DigitConsumeDecision::Consumed:
1067 is_a_digit = true;
1068 // The very first actual digit must pass here:
1069 digits_usable = true;
1070 break;
1071 case DigitConsumeDecision::PosOverflow:
1072 case DigitConsumeDecision::NegOverflow:
1073 is_a_digit = true;
1074 overflow = true;
1075 break;
1076 case DigitConsumeDecision::Invalid:
1077 is_a_digit = false;
1078 break;
1079 default:
1080 VERIFY_NOT_REACHED();
1081 }
1082 }
1083
1084 should_continue = is_a_digit;
1085 parse_ptr += should_continue;
1086 } while (should_continue);
1087
1088 if (!digits_usable) {
1089 // No actual number value available.
1090 if (endptr)
1091 *endptr = const_cast<char*>(str);
1092 return 0;
1093 }
1094
1095 if (endptr)
1096 *endptr = parse_ptr;
1097
1098 if (overflow) {
1099 errno = ERANGE;
1100 return LONG_LONG_MAX;
1101 }
1102
1103 return digits.number();
1104}
1105
1106uint32_t arc4random(void)
1107{
1108 uint32_t buf;
1109 arc4random_buf(&buf, sizeof(buf));
1110 return buf;
1111}
1112
1113static pthread_mutex_t s_randomness_mutex = PTHREAD_MUTEX_INITIALIZER;
1114static u8* s_randomness_buffer;
1115static size_t s_randomness_index;
1116
1117void arc4random_buf(void* buffer, size_t buffer_size)
1118{
1119 pthread_mutex_lock(&s_randomness_mutex);
1120
1121 size_t bytes_needed = buffer_size;
1122 auto* ptr = static_cast<u8*>(buffer);
1123
1124 while (bytes_needed > 0) {
1125 if (!s_randomness_buffer || s_randomness_index >= PAGE_SIZE) {
1126 if (!s_randomness_buffer) {
1127 s_randomness_buffer = static_cast<u8*>(mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_RANDOMIZED, 0, 0));
1128 VERIFY(s_randomness_buffer != MAP_FAILED);
1129 __pthread_fork_atfork_register_child(
1130 [] {
1131 munmap(s_randomness_buffer, PAGE_SIZE);
1132 s_randomness_buffer = nullptr;
1133 s_randomness_index = 0;
1134 });
1135 }
1136 syscall(SC_getrandom, s_randomness_buffer, PAGE_SIZE);
1137 s_randomness_index = 0;
1138 }
1139
1140 size_t available_bytes = PAGE_SIZE - s_randomness_index;
1141 size_t bytes_to_copy = min(bytes_needed, available_bytes);
1142
1143 memcpy(ptr, s_randomness_buffer + s_randomness_index, bytes_to_copy);
1144
1145 s_randomness_index += bytes_to_copy;
1146 bytes_needed -= bytes_to_copy;
1147 ptr += bytes_to_copy;
1148 }
1149
1150 pthread_mutex_unlock(&s_randomness_mutex);
1151}
1152
1153uint32_t arc4random_uniform(uint32_t max_bounds)
1154{
1155 return AK::get_random_uniform(max_bounds);
1156}
1157
1158// https://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html
1159char* realpath(char const* pathname, char* buffer)
1160{
1161 if (!pathname) {
1162 errno = EFAULT;
1163 return nullptr;
1164 }
1165 size_t size = PATH_MAX;
1166 bool self_allocated = false;
1167 if (buffer == nullptr) {
1168 // Since we self-allocate, try to sneakily use a smaller buffer instead, in an attempt to use less memory.
1169 size = 64;
1170 buffer = (char*)malloc(size);
1171 self_allocated = true;
1172 }
1173 Syscall::SC_realpath_params params { { pathname, strlen(pathname) }, { buffer, size } };
1174 int rc = syscall(SC_realpath, ¶ms);
1175 if (rc < 0) {
1176 if (self_allocated)
1177 free(buffer);
1178 errno = -rc;
1179 return nullptr;
1180 }
1181 if (self_allocated && static_cast<size_t>(rc) > size) {
1182 // There was silent truncation, *and* we can simply retry without the caller noticing.
1183 free(buffer);
1184 size = static_cast<size_t>(rc);
1185 buffer = (char*)malloc(size);
1186 params.buffer = { buffer, size };
1187 rc = syscall(SC_realpath, ¶ms);
1188 if (rc < 0) {
1189 // Can only happen if we lose a race. Let's pretend we lost the race in the first place.
1190 free(buffer);
1191 errno = -rc;
1192 return nullptr;
1193 }
1194 size_t new_size = static_cast<size_t>(rc);
1195 if (new_size < size) {
1196 // If we're here, the symlink has become longer while we were looking at it.
1197 // There's not much we can do, unless we want to loop endlessly
1198 // in this case. Let's leave it up to the caller whether to loop.
1199 free(buffer);
1200 errno = EAGAIN;
1201 return nullptr;
1202 }
1203 }
1204 errno = 0;
1205 return buffer;
1206}
1207
1208// https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html
1209int posix_openpt(int flags)
1210{
1211 if (flags & ~(O_RDWR | O_NOCTTY | O_CLOEXEC)) {
1212 errno = EINVAL;
1213 return -1;
1214 }
1215
1216 return open("/dev/ptmx", flags);
1217}
1218
1219// https://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html
1220int grantpt([[maybe_unused]] int fd)
1221{
1222 return 0;
1223}
1224
1225// https://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html
1226int unlockpt([[maybe_unused]] int fd)
1227{
1228 return 0;
1229}
1230}
1231
1232// https://pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html
1233void _Exit(int status)
1234{
1235 _exit(status);
1236}