stdlib.cpp 15 KB

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