stdlib.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. #include <AK/Assertions.h>
  2. #include <AK/HashMap.h>
  3. #include <AK/StdLibExtras.h>
  4. #include <AK/String.h>
  5. #include <AK/Types.h>
  6. #include <AK/Utf8View.h>
  7. #include <Kernel/Syscall.h>
  8. #include <alloca.h>
  9. #include <assert.h>
  10. #include <ctype.h>
  11. #include <errno.h>
  12. #include <signal.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <sys/mman.h>
  17. #include <sys/stat.h>
  18. #include <sys/wait.h>
  19. #include <unistd.h>
  20. extern "C" {
  21. typedef void (*__atexit_handler)();
  22. static int __atexit_handler_count = 0;
  23. static __atexit_handler __atexit_handlers[32];
  24. void exit(int status)
  25. {
  26. for (int i = 0; i < __atexit_handler_count; ++i)
  27. __atexit_handlers[i]();
  28. extern void _fini();
  29. _fini();
  30. fflush(stdout);
  31. fflush(stderr);
  32. _exit(status);
  33. ASSERT_NOT_REACHED();
  34. }
  35. int atexit(void (*handler)())
  36. {
  37. ASSERT(__atexit_handler_count < 32);
  38. __atexit_handlers[__atexit_handler_count++] = handler;
  39. return 0;
  40. }
  41. void abort()
  42. {
  43. raise(SIGABRT);
  44. ASSERT_NOT_REACHED();
  45. }
  46. static HashTable<const char*> s_malloced_environment_variables;
  47. static void free_environment_variable_if_needed(const char* var)
  48. {
  49. if (!s_malloced_environment_variables.contains(var))
  50. return;
  51. free(const_cast<char*>(var));
  52. s_malloced_environment_variables.remove(var);
  53. }
  54. char* getenv(const char* name)
  55. {
  56. size_t vl = strlen(name);
  57. for (size_t i = 0; environ[i]; ++i) {
  58. const char* decl = environ[i];
  59. char* eq = strchr(decl, '=');
  60. if (!eq)
  61. continue;
  62. size_t varLength = eq - decl;
  63. if (vl != varLength)
  64. continue;
  65. if (strncmp(decl, name, varLength) == 0) {
  66. return eq + 1;
  67. }
  68. }
  69. return nullptr;
  70. }
  71. int unsetenv(const char* name)
  72. {
  73. auto new_var_len = strlen(name);
  74. size_t environ_size = 0;
  75. int skip = -1;
  76. for (; environ[environ_size]; ++environ_size) {
  77. char* old_var = environ[environ_size];
  78. char* old_eq = strchr(old_var, '=');
  79. ASSERT(old_eq);
  80. size_t old_var_len = old_eq - old_var;
  81. if (new_var_len != old_var_len)
  82. continue; // can't match
  83. if (strncmp(name, old_var, new_var_len) == 0)
  84. skip = environ_size;
  85. }
  86. if (skip == -1)
  87. return 0; // not found: no failure.
  88. // Shuffle the existing array down by one.
  89. memmove(&environ[skip], &environ[skip + 1], ((environ_size - 1) - skip) * sizeof(environ[0]));
  90. environ[environ_size - 1] = nullptr;
  91. free_environment_variable_if_needed(name);
  92. return 0;
  93. }
  94. int setenv(const char* name, const char* value, int overwrite)
  95. {
  96. if (!overwrite && !getenv(name))
  97. return 0;
  98. auto length = strlen(name) + strlen(value) + 2;
  99. auto* var = (char*)malloc(length);
  100. snprintf(var, length, "%s=%s", name, value);
  101. s_malloced_environment_variables.set(var);
  102. return putenv(var);
  103. }
  104. int putenv(char* new_var)
  105. {
  106. char* new_eq = strchr(new_var, '=');
  107. if (!new_eq)
  108. return unsetenv(new_var);
  109. auto new_var_len = new_eq - new_var;
  110. int environ_size = 0;
  111. for (; environ[environ_size]; ++environ_size) {
  112. char* old_var = environ[environ_size];
  113. char* old_eq = strchr(old_var, '=');
  114. ASSERT(old_eq);
  115. auto old_var_len = old_eq - old_var;
  116. if (new_var_len != old_var_len)
  117. continue; // can't match
  118. if (strncmp(new_var, old_var, new_var_len) == 0) {
  119. free_environment_variable_if_needed(old_var);
  120. environ[environ_size] = new_var;
  121. return 0;
  122. }
  123. }
  124. // At this point, we need to append the new var.
  125. // 2 here: one for the new var, one for the sentinel value.
  126. char** new_environ = (char**)malloc((environ_size + 2) * sizeof(char*));
  127. if (new_environ == nullptr) {
  128. errno = ENOMEM;
  129. return -1;
  130. }
  131. for (int i = 0; environ[i]; ++i) {
  132. new_environ[i] = environ[i];
  133. }
  134. new_environ[environ_size] = new_var;
  135. new_environ[environ_size + 1] = nullptr;
  136. // swap new and old
  137. // note that the initial environ is not heap allocated!
  138. extern bool __environ_is_malloced;
  139. if (__environ_is_malloced)
  140. free(environ);
  141. __environ_is_malloced = true;
  142. environ = new_environ;
  143. return 0;
  144. }
  145. }
  146. double strtod(const char* str, char** endptr)
  147. {
  148. (void)str;
  149. (void)endptr;
  150. dbgprintf("LibC: strtod: '%s'\n", str);
  151. ASSERT_NOT_REACHED();
  152. }
  153. long double strtold(const char* str, char** endptr)
  154. {
  155. (void)str;
  156. (void)endptr;
  157. dbgprintf("LibC: strtold: '%s'\n", str);
  158. ASSERT_NOT_REACHED();
  159. }
  160. float strtof(const char* str, char** endptr)
  161. {
  162. (void)str;
  163. (void)endptr;
  164. dbgprintf("LibC: strtof: '%s'\n", str);
  165. ASSERT_NOT_REACHED();
  166. }
  167. double atof(const char* str)
  168. {
  169. size_t len = strlen(str);
  170. size_t weight = 1;
  171. int exp_val = 0;
  172. double value = 0.0f;
  173. double fraction = 0.0f;
  174. bool has_sign = false;
  175. bool is_negative = false;
  176. bool is_fractional = false;
  177. bool is_scientific = false;
  178. if (str[0] == '-') {
  179. is_negative = true;
  180. has_sign = true;
  181. }
  182. if (str[0] == '+') {
  183. has_sign = true;
  184. }
  185. for (size_t i = has_sign; i < len; i++) {
  186. // Looks like we're about to start working on the fractional part
  187. if (str[i] == '.') {
  188. is_fractional = true;
  189. continue;
  190. }
  191. if (str[i] == 'e' || str[i] == 'E') {
  192. if (str[i + 1] == '-' || str[i + 1] == '+')
  193. exp_val = atoi(str + i + 2);
  194. else
  195. exp_val = atoi(str + i + 1);
  196. is_scientific = true;
  197. continue;
  198. }
  199. if (str[i] < '0' || str[i] > '9' || exp_val != 0)
  200. continue;
  201. if (is_fractional) {
  202. fraction *= 10;
  203. fraction += str[i] - '0';
  204. weight *= 10;
  205. } else {
  206. value = value * 10;
  207. value += str[i] - '0';
  208. }
  209. }
  210. fraction /= weight;
  211. value += fraction;
  212. if (is_scientific) {
  213. bool divide = exp_val < 0;
  214. if (divide)
  215. exp_val *= -1;
  216. for (int i = 0; i < exp_val; i++) {
  217. if (divide)
  218. value /= 10;
  219. else
  220. value *= 10;
  221. }
  222. }
  223. return is_negative ? -value : value;
  224. }
  225. int atoi(const char* str)
  226. {
  227. size_t len = strlen(str);
  228. int value = 0;
  229. bool isNegative = false;
  230. for (size_t i = 0; i < len; ++i) {
  231. if (i == 0 && str[0] == '-') {
  232. isNegative = true;
  233. continue;
  234. }
  235. if (str[i] < '0' || str[i] > '9')
  236. return value;
  237. value = value * 10;
  238. value += str[i] - '0';
  239. }
  240. return isNegative ? -value : value;
  241. }
  242. long atol(const char* str)
  243. {
  244. static_assert(sizeof(int) == sizeof(long));
  245. return atoi(str);
  246. }
  247. long long atoll(const char* str)
  248. {
  249. dbgprintf("FIXME(Libc): atoll('%s') passing through to atol()\n", str);
  250. return atol(str);
  251. }
  252. static char ptsname_buf[32];
  253. char* ptsname(int fd)
  254. {
  255. if (ptsname_r(fd, ptsname_buf, sizeof(ptsname_buf)) < 0)
  256. return nullptr;
  257. return ptsname_buf;
  258. }
  259. int ptsname_r(int fd, char* buffer, size_t size)
  260. {
  261. int rc = syscall(SC_ptsname_r, fd, buffer, size);
  262. __RETURN_WITH_ERRNO(rc, rc, -1);
  263. }
  264. static unsigned long s_next_rand = 1;
  265. int rand()
  266. {
  267. s_next_rand = s_next_rand * 1103515245 + 12345;
  268. return ((unsigned)(s_next_rand / ((RAND_MAX + 1) * 2)) % (RAND_MAX + 1));
  269. }
  270. void srand(unsigned seed)
  271. {
  272. s_next_rand = seed;
  273. }
  274. int abs(int i)
  275. {
  276. return i < 0 ? -i : i;
  277. }
  278. long int random()
  279. {
  280. return rand();
  281. }
  282. void srandom(unsigned seed)
  283. {
  284. srand(seed);
  285. }
  286. int system(const char* command)
  287. {
  288. if (!command)
  289. return 1;
  290. auto child = fork();
  291. if (child < 0)
  292. return -1;
  293. if (!child) {
  294. int rc = execl("/bin/sh", "sh", "-c", command, nullptr);
  295. ASSERT(rc < 0);
  296. perror("execl");
  297. exit(127);
  298. }
  299. int wstatus;
  300. waitpid(child, &wstatus, 0);
  301. return WEXITSTATUS(wstatus);
  302. }
  303. char* mktemp(char* pattern)
  304. {
  305. int length = strlen(pattern);
  306. if (length < 6 || !String(pattern).ends_with("XXXXXX")) {
  307. pattern[0] = '\0';
  308. errno = EINVAL;
  309. return pattern;
  310. }
  311. int start = length - 6;
  312. static constexpr char random_characters[] = "abcdefghijklmnopqrstuvwxyz0123456789";
  313. for (int attempt = 0; attempt < 100; ++attempt) {
  314. for (int i = 0; i < 6; ++i)
  315. pattern[start + i] = random_characters[(rand() % sizeof(random_characters))];
  316. struct stat st;
  317. int rc = lstat(pattern, &st);
  318. if (rc < 0 && errno == ENOENT)
  319. return pattern;
  320. }
  321. pattern[0] = '\0';
  322. errno = EEXIST;
  323. return pattern;
  324. }
  325. int mkstemp(char* pattern)
  326. {
  327. char* path = mktemp(pattern);
  328. int fd = open(path, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); // I'm using the flags I saw glibc using.
  329. if (fd >= 0)
  330. return fd;
  331. return -1;
  332. }
  333. char* mkdtemp(char* pattern)
  334. {
  335. int length = strlen(pattern);
  336. if (length < 6 || !String(pattern).ends_with("XXXXXX")) {
  337. errno = EINVAL;
  338. return nullptr;
  339. }
  340. int start = length - 6;
  341. static constexpr char random_characters[] = "abcdefghijklmnopqrstuvwxyz0123456789";
  342. for (int attempt = 0; attempt < 100; ++attempt) {
  343. for (int i = 0; i < 6; ++i)
  344. pattern[start + i] = random_characters[(rand() % sizeof(random_characters))];
  345. struct stat st;
  346. int rc = lstat(pattern, &st);
  347. if (rc < 0 && errno == ENOENT) {
  348. if (mkdir(pattern, 0700) < 0)
  349. return nullptr;
  350. return pattern;
  351. }
  352. }
  353. errno = EEXIST;
  354. return nullptr;
  355. }
  356. void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void*, const void*))
  357. {
  358. dbgprintf("FIXME(LibC): bsearch(%p, %p, %u, %u, %p)\n", key, base, nmemb, size, compar);
  359. ASSERT_NOT_REACHED();
  360. }
  361. div_t div(int numerator, int denominator)
  362. {
  363. div_t result;
  364. result.quot = numerator / denominator;
  365. result.rem = numerator % denominator;
  366. if (numerator >= 0 && result.rem < 0) {
  367. result.quot++;
  368. result.rem -= denominator;
  369. }
  370. return result;
  371. }
  372. ldiv_t ldiv(long numerator, long denominator)
  373. {
  374. ldiv_t result;
  375. result.quot = numerator / denominator;
  376. result.rem = numerator % denominator;
  377. if (numerator >= 0 && result.rem < 0) {
  378. result.quot++;
  379. result.rem -= denominator;
  380. }
  381. return result;
  382. }
  383. size_t mbstowcs(wchar_t*, const char*, size_t)
  384. {
  385. ASSERT_NOT_REACHED();
  386. }
  387. size_t mbtowc(wchar_t* wch, const char* data, size_t data_size)
  388. {
  389. // FIXME: This needs a real implementation.
  390. UNUSED_PARAM(data_size);
  391. if (wch && data) {
  392. *wch = *data;
  393. return 1;
  394. }
  395. if (!wch && data) {
  396. return 1;
  397. }
  398. return 0;
  399. }
  400. int wctomb(char*, wchar_t)
  401. {
  402. ASSERT_NOT_REACHED();
  403. }
  404. size_t wcstombs(char* dest, const wchar_t* src, size_t max)
  405. {
  406. char* originalDest = dest;
  407. while ((size_t)(dest - originalDest) < max) {
  408. StringView v { (const char*)src, sizeof(wchar_t) };
  409. // FIXME: dependent on locale, for now utf-8 is supported.
  410. Utf8View utf8 { v };
  411. if (*utf8.begin() == '\0') {
  412. *dest = '\0';
  413. return (size_t)(dest - originalDest); // Exclude null character in returned size
  414. }
  415. for (auto byte : utf8) {
  416. if (byte != '\0')
  417. *dest++ = byte;
  418. }
  419. ++src;
  420. }
  421. return max;
  422. }
  423. template<typename T, T min_value, T max_value>
  424. static T strtol_impl(const char* nptr, char** endptr, int base)
  425. {
  426. errno = 0;
  427. if (base < 0 || base == 1 || base > 36) {
  428. errno = EINVAL;
  429. if (endptr)
  430. *endptr = const_cast<char*>(nptr);
  431. return 0;
  432. }
  433. const char* p = nptr;
  434. while (isspace(*p))
  435. ++p;
  436. bool is_negative = false;
  437. if (*p == '-') {
  438. is_negative = true;
  439. ++p;
  440. } else {
  441. if (*p == '+')
  442. ++p;
  443. }
  444. if (base == 0 || base == 16) {
  445. if (base == 0)
  446. base = 10;
  447. if (*p == '0') {
  448. if (*(p + 1) == 'X' || *(p + 1) == 'x') {
  449. p += 2;
  450. base = 16;
  451. } else if (base != 16) {
  452. base = 8;
  453. }
  454. }
  455. }
  456. long cutoff_point = is_negative ? (min_value / base) : (max_value / base);
  457. int max_valid_digit_at_cutoff_point = is_negative ? (min_value % base) : (max_value % base);
  458. long num = 0;
  459. bool has_overflowed = false;
  460. unsigned digits_consumed = 0;
  461. for (;;) {
  462. char ch = *(p++);
  463. int digit;
  464. if (isdigit(ch))
  465. digit = ch - '0';
  466. else if (islower(ch))
  467. digit = ch - ('a' - 10);
  468. else if (isupper(ch))
  469. digit = ch - ('A' - 10);
  470. else
  471. break;
  472. if (digit >= base)
  473. break;
  474. if (has_overflowed)
  475. continue;
  476. bool is_past_cutoff = is_negative ? num < cutoff_point : num > cutoff_point;
  477. if (is_past_cutoff || (num == cutoff_point && digit > max_valid_digit_at_cutoff_point)) {
  478. has_overflowed = true;
  479. num = is_negative ? min_value : max_value;
  480. errno = ERANGE;
  481. } else {
  482. num *= base;
  483. num += is_negative ? -digit : digit;
  484. ++digits_consumed;
  485. }
  486. }
  487. if (endptr) {
  488. if (has_overflowed || digits_consumed > 0)
  489. *endptr = const_cast<char*>(p - 1);
  490. else
  491. *endptr = const_cast<char*>(nptr);
  492. }
  493. return num;
  494. }
  495. long strtol(const char* str, char** endptr, int base)
  496. {
  497. return strtol_impl<long, LONG_MIN, LONG_MAX>(str, endptr, base);
  498. }
  499. unsigned long strtoul(const char* str, char** endptr, int base)
  500. {
  501. auto value = strtol(str, endptr, base);
  502. ASSERT(value >= 0);
  503. return value;
  504. }
  505. long long strtoll(const char* str, char** endptr, int base)
  506. {
  507. return strtol_impl<long long, LONG_LONG_MIN, LONG_LONG_MAX>(str, endptr, base);
  508. }
  509. unsigned long long strtoull(const char* str, char** endptr, int base)
  510. {
  511. auto value = strtoll(str, endptr, base);
  512. ASSERT(value >= 0);
  513. return value;
  514. }
  515. // Serenity's PRNG is not cryptographically secure. Do not rely on this for
  516. // any real crypto! These functions (for now) are for compatibility.
  517. // TODO: In the future, rand can be made determinstic and this not.
  518. uint32_t arc4random(void)
  519. {
  520. char buf[4];
  521. syscall(SC_getrandom, buf, 4, 0);
  522. return *(uint32_t*)buf;
  523. }
  524. void arc4random_buf(void* buffer, size_t buffer_size)
  525. {
  526. // arc4random_buf should never fail, but user supplied buffers could fail.
  527. // However, if the user passes a garbage buffer, that's on them.
  528. syscall(SC_getrandom, buffer, buffer_size, 0);
  529. }
  530. uint32_t arc4random_uniform(uint32_t max_bounds)
  531. {
  532. // XXX: Should actually apply special rules for uniformity; avoid what is
  533. // called "modulo bias".
  534. return arc4random() % max_bounds;
  535. }