stdlib.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. #include <stdlib.h>
  2. #include <sys/mman.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <string.h>
  6. #include <alloca.h>
  7. #include <assert.h>
  8. #include <errno.h>
  9. #include <ctype.h>
  10. #include <AK/Assertions.h>
  11. #include <AK/Types.h>
  12. #include <Kernel/Syscall.h>
  13. #include <AK/StdLibExtras.h>
  14. #include <AK/HashMap.h>
  15. #include <AK/AKString.h>
  16. extern "C" {
  17. typedef void(*__atexit_handler)();
  18. static int __atexit_handler_count = 0;
  19. static __atexit_handler __atexit_handlers[32];
  20. void exit(int status)
  21. {
  22. for (int i = 0; i < __atexit_handler_count; ++i)
  23. __atexit_handlers[i]();
  24. extern void _fini();
  25. _fini();
  26. _exit(status);
  27. ASSERT_NOT_REACHED();
  28. }
  29. int atexit(void (*handler)())
  30. {
  31. ASSERT(__atexit_handler_count < 32);
  32. __atexit_handlers[__atexit_handler_count++] = handler;
  33. return 0;
  34. }
  35. void abort()
  36. {
  37. // FIXME: Implement proper abort().
  38. exit(253);
  39. }
  40. char* getenv(const char* name)
  41. {
  42. size_t vl = strlen(name);
  43. for (size_t i = 0; environ[i]; ++i) {
  44. const char* decl = environ[i];
  45. char* eq = strchr(decl, '=');
  46. if (!eq)
  47. continue;
  48. size_t varLength = eq - decl;
  49. if (vl != varLength)
  50. continue;
  51. if (strncmp(decl, name, varLength) == 0) {
  52. return eq + 1;
  53. }
  54. }
  55. return nullptr;
  56. }
  57. int putenv(char* new_var)
  58. {
  59. char* new_eq = strchr(new_var, '=');
  60. // FIXME: should remove the var from the environment.
  61. if (!new_eq)
  62. return 0;
  63. auto new_var_len = new_eq - new_var;
  64. size_t environ_size = 0;
  65. for (; environ[environ_size]; ++environ_size) {
  66. char* old_var = environ[environ_size];
  67. char* old_eq = strchr(old_var, '=');
  68. ASSERT(old_eq);
  69. auto old_var_len = old_eq - old_var;
  70. if (new_var_len != old_var_len)
  71. continue; // can't match
  72. if (strncmp(new_var, old_var, new_var_len) == 0) {
  73. environ[environ_size] = new_var;
  74. return 0;
  75. }
  76. }
  77. // At this point, we need to append the new var.
  78. // 2 here: one for the new var, one for the sentinel value.
  79. char **new_environ = (char**)malloc((environ_size + 2) * sizeof(char*));
  80. if (new_environ == nullptr) {
  81. errno = ENOMEM;
  82. return -1;
  83. }
  84. for (size_t i = 0; environ[i]; ++i) {
  85. new_environ[i] = environ[i];
  86. }
  87. new_environ[environ_size] = new_var;
  88. new_environ[environ_size + 1] = nullptr;
  89. // swap new and old
  90. // note that the initial environ is not heap allocated!
  91. extern bool __environ_is_malloced;
  92. if (__environ_is_malloced)
  93. free(environ);
  94. __environ_is_malloced = true;
  95. environ = new_environ;
  96. return 0;
  97. }
  98. double strtod(const char* str, char** endptr)
  99. {
  100. (void)str;
  101. (void)endptr;
  102. dbgprintf("LibC: strtod: '%s'\n", str);
  103. ASSERT_NOT_REACHED();
  104. }
  105. float strtof(const char* str, char** endptr)
  106. {
  107. (void)str;
  108. (void)endptr;
  109. dbgprintf("LibC: strtof: '%s'\n", str);
  110. ASSERT_NOT_REACHED();
  111. }
  112. double atof(const char* str)
  113. {
  114. dbgprintf("LibC: atof: '%s'\n", str);
  115. ASSERT_NOT_REACHED();
  116. }
  117. int atoi(const char* str)
  118. {
  119. size_t len = strlen(str);
  120. int value = 0;
  121. bool isNegative = false;
  122. for (size_t i = 0; i < len; ++i) {
  123. if (i == 0 && str[0] == '-') {
  124. isNegative = true;
  125. continue;
  126. }
  127. if (str[i] < '0' || str[i] > '9')
  128. return value;
  129. value = value * 10;
  130. value += str[i] - '0';
  131. }
  132. return isNegative ? -value : value;
  133. }
  134. long atol(const char* str)
  135. {
  136. static_assert(sizeof(int) == sizeof(long));
  137. return atoi(str);
  138. }
  139. long long atoll(const char* str)
  140. {
  141. dbgprintf("FIXME(Libc): atoll('%s') passing through to atol()\n", str);
  142. return atol(str);
  143. }
  144. static char ptsname_buf[32];
  145. char* ptsname(int fd)
  146. {
  147. if (ptsname_r(fd, ptsname_buf, sizeof(ptsname_buf)) < 0)
  148. return nullptr;
  149. return ptsname_buf;
  150. }
  151. int ptsname_r(int fd, char* buffer, size_t size)
  152. {
  153. int rc = syscall(SC_ptsname_r, fd, buffer, size);
  154. __RETURN_WITH_ERRNO(rc, rc, -1);
  155. }
  156. static unsigned long s_next_rand = 1;
  157. int rand()
  158. {
  159. s_next_rand = s_next_rand * 1103515245 + 12345;
  160. return((unsigned)(s_next_rand/((RAND_MAX + 1) * 2)) % (RAND_MAX + 1));
  161. }
  162. void srand(unsigned seed)
  163. {
  164. s_next_rand = seed;
  165. }
  166. int abs(int i)
  167. {
  168. return i < 0 ? -i : i;
  169. }
  170. long int random()
  171. {
  172. return rand();
  173. }
  174. void srandom(unsigned seed)
  175. {
  176. srand(seed);
  177. }
  178. int system(const char* command)
  179. {
  180. auto child = fork();
  181. if (!child) {
  182. int rc = execl("/bin/sh", "sh", "-c", command, nullptr);
  183. if (rc < 0)
  184. perror("execl");
  185. exit(0);
  186. }
  187. int wstatus;
  188. waitpid(child, &wstatus, 0);
  189. return WEXITSTATUS(wstatus);
  190. }
  191. char* mktemp(char* pattern)
  192. {
  193. int length = strlen(pattern);
  194. // FIXME: Check for an invalid template pattern and return EINVAL.
  195. if (length < 6) {
  196. pattern[0] = '\0';
  197. errno = EINVAL;
  198. return pattern;
  199. }
  200. int start = length - 6;
  201. static constexpr char random_characters[] = "abcdefghijklmnopqrstuvwxyz0123456789";
  202. for (int attempt = 0; attempt < 100; ++attempt) {
  203. for (int i = 0; i < 6; ++i)
  204. pattern[start + i] = random_characters[(rand() % sizeof(random_characters))];
  205. struct stat st;
  206. int rc = lstat(pattern, &st);
  207. if (rc < 0 && errno == ENOENT)
  208. return pattern;
  209. }
  210. pattern[0] = '\0';
  211. errno = EEXIST;
  212. return pattern;
  213. }
  214. void* bsearch(const void* key, const void* base, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
  215. {
  216. dbgprintf("FIXME(LibC): bsearch(%p, %p, %u, %u, %p)\n", key, base, nmemb, size, compar);
  217. ASSERT_NOT_REACHED();
  218. }
  219. div_t div(int numerator, int denominator)
  220. {
  221. div_t result;
  222. result.quot = numerator / denominator;
  223. result.rem = numerator % denominator;
  224. return result;
  225. }
  226. ldiv_t ldiv(long numerator, long denominator)
  227. {
  228. ldiv_t result;
  229. result.quot = numerator / denominator;
  230. result.rem = numerator % denominator;
  231. return result;
  232. }
  233. size_t mbstowcs(wchar_t*, const char*, size_t)
  234. {
  235. ASSERT_NOT_REACHED();
  236. }
  237. long strtol(const char* str, char** endptr, int base)
  238. {
  239. const char* s = str;
  240. unsigned long acc;
  241. int c;
  242. unsigned long cutoff;
  243. int neg = 0;
  244. int any;
  245. int cutlim;
  246. do {
  247. c = *s++;
  248. } while (isspace(c));
  249. if (c == '-') {
  250. neg = 1;
  251. c = *s++;
  252. } else if (c == '+')
  253. c = *s++;
  254. if ((base == 0 || base == 16) &&
  255. c == '0' && (*s == 'x' || *s == 'X')) {
  256. c = s[1];
  257. s += 2;
  258. base = 16;
  259. }
  260. if (base == 0)
  261. base = c == '0' ? 8 : 10;
  262. cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
  263. cutlim = cutoff % (unsigned long)base;
  264. cutoff /= (unsigned long)base;
  265. for (acc = 0, any = 0;; c = *s++) {
  266. if (isdigit(c))
  267. c -= '0';
  268. else if (isalpha(c))
  269. c -= isupper(c) ? 'A' - 10 : 'a' - 10;
  270. else
  271. break;
  272. if (c >= base)
  273. break;
  274. if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
  275. any = -1;
  276. else {
  277. any = 1;
  278. acc *= base;
  279. acc += c;
  280. }
  281. }
  282. if (any < 0) {
  283. acc = neg ? LONG_MIN : LONG_MAX;
  284. errno = ERANGE;
  285. } else if (neg)
  286. acc = -acc;
  287. if (endptr)
  288. *endptr = const_cast<char*>((any ? s - 1 : str));
  289. return acc;
  290. }
  291. unsigned long strtoul(const char* str, char** endptr, int base)
  292. {
  293. auto value = strtol(str, endptr, base);
  294. ASSERT(value >= 0);
  295. return value;
  296. }
  297. }