PageRenderTime 128ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/apimod/lib.c

http://illusion.googlecode.com/
C | 792 lines | 671 code | 83 blank | 38 comment | 112 complexity | 14d8d4cc3da021968ad8f29867ad2e0e MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /*
  2. Copyright (C) 2011 Salil Bhagurkar
  3. This file is part of illusion
  4. illusion is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. illusion is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with illusion. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /*
  16. * These headers are only used for the macros/constants defined. No functions
  17. * from the kernel can be called from here, as we will be in user mode.
  18. */
  19. #include <klib/lib.h>
  20. #include <apimod/apimod.h>
  21. #include <kernel/errors.h>
  22. #include <kernel/page.h>
  23. #include <kernel/input.h>
  24. #include <kernel/vfs.h>
  25. /*
  26. * The user mode library provided by APIMOD to any application
  27. */
  28. static int dummy()
  29. {
  30. return ENOSUP;
  31. }
  32. uint_t string_length(const char *c)
  33. {
  34. uint_t len = 0;
  35. while((*c) != '\0') {
  36. len++;
  37. c++;
  38. }
  39. return len;
  40. }
  41. bool string_equals(const char *s1, const char *s2)
  42. {
  43. while(1) {
  44. if((*s1) != (*s2))
  45. return false;
  46. if((*s1) == '\0' && (*s2) == '\0')
  47. return true;
  48. else if((*s1) == '\0' || (*s2) == '\0')
  49. return false;
  50. s1++;
  51. s2++;
  52. }
  53. }
  54. char *string_copy(char *dest, const char *src, uint_t max_len)
  55. {
  56. char *dest_orig = dest;
  57. uint_t i = 0;
  58. while(i < (max_len - 1) && (*src) != '\0') {
  59. *dest = *src;
  60. dest++;
  61. src++;
  62. }
  63. if(i == (max_len - 1) || (*src) == '\0')
  64. *dest = '\0';
  65. return dest_orig;
  66. }
  67. void *memory_set(void *start, u8 value, uint_t count)
  68. {
  69. u32 value_l = value | (value << 8) | (value << 16) | (value << 24);
  70. u32 *start_l = (u32 *)start;
  71. uint_t count_l = count / sizeof(u32);
  72. uint_t final = count - count_l * sizeof(u32);
  73. uint_t i;
  74. for(i = 0; i < count_l; i++) {
  75. *start_l++ = value_l;
  76. }
  77. char *start_c = (char *)start_l;
  78. for(i = 0; i < final; i++) {
  79. *start_c++ = value;
  80. }
  81. return start;
  82. }
  83. void *memory_copy(void *dst, void *src, uint_t count)
  84. {
  85. u32 *dst_l = (u32 *)dst;
  86. u32 *src_l = (u32 *)src;
  87. uint_t count_l = count / sizeof(u32);
  88. uint_t final = count - count_l * sizeof(u32);
  89. uint_t i;
  90. for(i = 0; i < count_l; i++) {
  91. *dst_l++ = *src_l++;
  92. }
  93. char *dst_c = (char *)dst_l;
  94. char *src_c = (char *)src_l;
  95. for(i = 0; i < final; i++) {
  96. *dst_c++ = *src_c++;
  97. }
  98. return dst;
  99. }
  100. bool memory_equals(void *m1, void *m2, uint_t count)
  101. {
  102. u8 *m1_c = (u8 *)m1;
  103. u8 *m2_c = (u8 *)m2;
  104. for(uint_t i = 0; i < count; i++) {
  105. if(m1_c[i] != m2_c[i])
  106. return false;
  107. }
  108. return true;
  109. }
  110. int get_version(uint_t *build_number,
  111. uint_t *build_date)
  112. {
  113. return _syscall(SYS_VERSION, (u32)build_number,
  114. (u32)build_date, 0, 0, 0);
  115. }
  116. int release(uint_t reason)
  117. {
  118. return _syscall(SYS_RELEASE, reason, 0, 0, 0, 0);
  119. }
  120. int print(char *stream, uint_t length)
  121. {
  122. return _syscall(SYS_PRINT, (u32)stream, length, 0, 0, 0);
  123. }
  124. int read_input(uint_t *key, uint_t *state)
  125. {
  126. return _syscall(SYS_READINPUT, (u32)key,
  127. (u32)state, 0, 0, 0);
  128. }
  129. int open(char *path, uint_t state, uint_t *fd)
  130. {
  131. return _syscall(SYS_OPEN, (u32)path, state,
  132. (u32)fd, 0, 0);
  133. }
  134. int change_state(uint_t fid, uint_t new_state)
  135. {
  136. return _syscall(SYS_CHANGESTATE, fid, new_state, 0, 0, 0);
  137. }
  138. int get_child(uint_t fid, uint_t *child_fid)
  139. {
  140. return _syscall(SYS_GETCHILD, fid, (u32)child_fid,
  141. 0, 0, 0);
  142. }
  143. int next_child(uint_t fid)
  144. {
  145. return _syscall(SYS_NEXTCHILD, fid, 0, 0, 0, 0);
  146. }
  147. /*
  148. * This requires syscall_try to be set, or this will fail, if the child
  149. * was not found.
  150. */
  151. int find_child(uint_t fid, uint_t *child_fid, char *name)
  152. {
  153. uint_t child;
  154. int err = get_child(fid, &child);
  155. while(!err) {
  156. struct sys_info info;
  157. get_info(child, &info);
  158. if(string_equals(info.name, name)) {
  159. *child_fid = child;
  160. return 0;
  161. }
  162. err = next_child(child);
  163. }
  164. return ENOENT;
  165. }
  166. int get_parent(uint_t fid, uint_t *parent_fid)
  167. {
  168. return _syscall(SYS_GETPARENT, fid, (u32)parent_fid,
  169. 0, 0, 0);
  170. }
  171. int close(uint_t fid)
  172. {
  173. return _syscall(SYS_CLOSE, fid, 0, 0, 0, 0);
  174. }
  175. int read(uint_t fid, void *buf, uint_t offset,
  176. uint_t count)
  177. {
  178. return _syscall(SYS_READ, fid, (u32)buf, offset, count, 0);
  179. }
  180. int write(uint_t fid, void *buf, uint_t offset,
  181. uint_t count)
  182. {
  183. return _syscall(SYS_WRITE, fid, (u32)buf, offset, count, 0);
  184. }
  185. int create(uint_t fid, char *name)
  186. {
  187. return _syscall(SYS_CREATE, fid, (u32)name, 0, 0, 0);
  188. }
  189. int get_info(uint_t fid, struct sys_info *info)
  190. {
  191. return _syscall(SYS_GETINFO, fid, (u32)info, 0, 0, 0);
  192. }
  193. int create_process(uint_t *pid, char *path, char *arguments)
  194. {
  195. return _syscall(SYS_CREATEPROCESS, (u32)pid, (u32)path, (u32)arguments,
  196. 0, 0);
  197. }
  198. int pause_process(uint_t pid)
  199. {
  200. return _syscall(SYS_PAUSEPROCESS, pid, 0, 0, 0, 0);
  201. }
  202. int resume_process(uint_t pid)
  203. {
  204. return _syscall(SYS_RESUMEPROCESS, pid, 0, 0, 0, 0);
  205. }
  206. int printf(const char *fmt, ...)
  207. {
  208. char buf[512];
  209. uint_t sz = 512;
  210. va_list args;
  211. uint_t ret_val;
  212. va_start(args, fmt);
  213. ret_val = vsnprintf(buf,sz,fmt,args);
  214. print(buf, ret_val);
  215. va_end(args);
  216. return ret_val;
  217. }
  218. int insane(int code, const char *fmt, ...)
  219. {
  220. char buf[512];
  221. uint_t sz = 512;
  222. va_list args;
  223. uint_t ret_val;
  224. va_start(args, fmt);
  225. printf("[%d][APIMOD insanity]: ", code);
  226. ret_val = vsnprintf(buf,sz,fmt,args);
  227. print(buf, ret_val);
  228. va_end(args);
  229. exit_process();
  230. return 0;
  231. }
  232. void read_line(char *buf, uint_t buf_len)
  233. {
  234. uint_t i = 0, key;
  235. uint_t state;
  236. while(1) {
  237. read_input(&key, &state);
  238. if(state == KEYSTATE_DOWN) {
  239. char c;
  240. if(key < KEY_NONASCII) {
  241. c = key;
  242. } else {
  243. if(key == KEY_SPACE)
  244. c = ' ';
  245. else if(key == KEY_ENTER) {
  246. buf[i] = '\0';
  247. printf("\n");
  248. break;
  249. } else if(key == KEY_TAB)
  250. c = '\t';
  251. else if(key == KEY_BACKSPACE) {
  252. //Clear one character
  253. if(i > 0) {
  254. i--;
  255. buf[i] = '\0';
  256. printf("\n%s", buf);
  257. }
  258. continue;
  259. } else
  260. continue;
  261. }
  262. if(i < (buf_len - 1)) {
  263. printf("%c", c);
  264. buf[i] = c;
  265. i++;
  266. }
  267. }
  268. }
  269. }
  270. static char *skip_initial(char *str, char delimiter)
  271. {
  272. while((*str) != '\0') {
  273. if((*str) == delimiter)
  274. str++;
  275. else
  276. break;
  277. }
  278. return str;
  279. }
  280. char *separate(char *out, char *_str, char delimiter)
  281. {
  282. char *str = skip_initial(_str, delimiter);
  283. while((*str) != '\0') {
  284. if((*str) == delimiter) {
  285. break;
  286. } else {
  287. *out++ = *str;
  288. }
  289. str++;
  290. }
  291. *out = '\0';
  292. return str;
  293. }
  294. char **get_children(char *path, uint_t *nr_children)
  295. {
  296. uint_t fd, child_fd;
  297. int err = open(path, STATE_READ, &fd);
  298. if(err)
  299. return null;
  300. struct sys_info info;
  301. get_info(fd, &info);
  302. char **arr = (char **)malloc(info.child_count * sizeof(char *));
  303. uint_t i = 0;
  304. err = get_child(fd, &child_fd);
  305. while(err != 0) {
  306. arr[i] = (char *)malloc(VFS_NAME_LEN);
  307. get_info(child_fd, &info);
  308. string_copy(arr[i], info.name, VFS_NAME_LEN);
  309. i++;
  310. err = next_child(child_fd);
  311. }
  312. close(fd);
  313. *nr_children = info.child_count;
  314. return arr;
  315. }
  316. void free_children(char **arr, uint_t nr_children)
  317. {
  318. uint_t i;
  319. for(i = 0; i < nr_children; i++)
  320. free(arr[i], VFS_NAME_LEN);
  321. free(arr, sizeof(char *));
  322. }
  323. int delete_file(char *path)
  324. {
  325. uint_t fd_child, fd_parent;
  326. int err = open(path, STATE_WRITE, &fd_child);
  327. if(err)
  328. return err;
  329. err = get_parent(fd_child, &fd_parent);
  330. if(err) {
  331. close(fd_child);
  332. return err;
  333. }
  334. err = change_state(fd_parent, STATE_WRITE);
  335. if(err) {
  336. close(fd_child);
  337. close(fd_parent);
  338. return err;
  339. }
  340. err = delete(fd_child, fd_parent);
  341. close(fd_parent);
  342. if(err) {
  343. close(fd_child);
  344. return err;
  345. }
  346. return 0;
  347. }
  348. char *read_all_file(uint_t *length, char *path)
  349. {
  350. uint_t fd;
  351. int err = open(path, STATE_READ, &fd);
  352. if(err)
  353. return null;
  354. struct sys_info info;
  355. get_info(fd, &info);
  356. char *data = (char *)malloc(info.length);
  357. err = read(fd, data, 0, info.length);
  358. close(fd);
  359. if(err) {
  360. free(data, info.length);
  361. return null;
  362. }
  363. *length = info.length;
  364. return data;
  365. }
  366. int write_all_file(char *path, char *data, uint_t length)
  367. {
  368. uint_t fd;
  369. int err = open(path, STATE_WRITE, &fd);
  370. if(err)
  371. return err;
  372. err = write(fd, data, 0, length);
  373. if(err) {
  374. close(fd);
  375. return err;
  376. }
  377. err = close(fd);
  378. return err;
  379. }
  380. int create_file(char *path, char *name)
  381. {
  382. uint_t fd;
  383. int err = open(path, STATE_WRITE, &fd);
  384. if(err)
  385. return err;
  386. err = create(fd, name);
  387. close(fd);
  388. return err;
  389. }
  390. int get_info1(uint_t fid, struct sys_info1 *info)
  391. {
  392. return _syscall(SYS_GETINFO1, fid, (u32)info, 0, 0, 0);
  393. }
  394. int delete(uint_t fid, uint_t parent_fid)
  395. {
  396. return _syscall(SYS_DELETE, fid, parent_fid, 0, 0, 0);
  397. }
  398. int get_current(uint_t *fid)
  399. {
  400. return _syscall(SYS_GETCURRENT, (u32)fid, 0, 0, 0, 0);
  401. }
  402. int set_current(uint_t fid)
  403. {
  404. return _syscall(SYS_SETCURRENT, fid, 0, 0, 0, 0);
  405. }
  406. int exit_process()
  407. {
  408. return _syscall(SYS_EXITPROCESS, 0, 0, 0, 0, 0);
  409. }
  410. int string_starts_with(char *str, char *with)
  411. {
  412. while((*with) != '\0') {
  413. if((*str) != (*with))
  414. return 0;
  415. str++;
  416. with++;
  417. }
  418. return 1;
  419. }
  420. void string_to_lower(char *src)
  421. {
  422. while((*src) != '\0') {
  423. char c = *src;
  424. if(c >= 'A' && c <= 'Z')
  425. *src = c - 'A' + 'a';
  426. src++;
  427. }
  428. }
  429. void string_to_higher(char *src)
  430. {
  431. while((*src) != '\0') {
  432. char c = *src;
  433. if(c >= 'a' && c <= 'a')
  434. *src = c - 'a' + 'A';
  435. src++;
  436. }
  437. }
  438. int string_ends_with(char *str, char *with)
  439. {
  440. str += string_length(str) - 1;
  441. uint_t len = string_length(with) - 1;
  442. with += len;
  443. while(len--) {
  444. if((*str) != (*with))
  445. return 0;
  446. str--;
  447. with--;
  448. }
  449. return 1;
  450. }
  451. char *string_cat(char *dst, uint_t dst_buf_len, char *src)
  452. {
  453. char *dst_max = dst + dst_buf_len;
  454. dst += string_length(dst);
  455. while((*src) != '\0' && dst < (dst_max - 1)) {
  456. *dst++ = *src++;
  457. }
  458. *dst = '\0';
  459. return dst;
  460. }
  461. char *string_replace(char *out, size_t out_len, char *str, char *what, char *with)
  462. {
  463. size_t with_len = string_length(with);
  464. size_t what_len = string_length(what);
  465. while((*str) != '\0' && out_len > 1) {
  466. if(string_equals(str, what)) {
  467. if(out_len > with_len) {
  468. string_copy(out, with, out_len);
  469. out_len -= with_len;
  470. out += with_len;
  471. str += what_len;
  472. continue;
  473. }
  474. }
  475. *out = *str;
  476. out_len--;
  477. out++;
  478. str++;
  479. }
  480. *out = '\0';
  481. return out;
  482. }
  483. char *get_arguments(uint_t *len)
  484. {
  485. int err = _syscall(SYS_ARGS, 0, (u32)len, 0, 0, 0);
  486. if(err || (*len) == 0)
  487. return null;
  488. char *args = (char *)malloc(*len);
  489. err = _syscall(SYS_ARGS, (u32)args, (u32)len, 0, 0, 0);
  490. if(err) {
  491. free(args, *len);
  492. return null;
  493. }
  494. return args;
  495. }
  496. int get_device(uint_t *fid)
  497. {
  498. return _syscall(SYS_GETDEV, (u32)fid, 0, 0, 0, 0);
  499. }
  500. int next_device(uint_t fid)
  501. {
  502. return _syscall(SYS_NEXTDEV, fid, 0, 0, 0, 0);
  503. }
  504. void *get_pages(uint_t count)
  505. {
  506. void *pages;
  507. int err = _syscall(SYS_GETPAGES, (u32)(&pages), count, 0, 0, 0);
  508. if(!err)
  509. return pages;
  510. return null;
  511. }
  512. int free_pages(void *pages, uint_t count)
  513. {
  514. return _syscall(SYS_FREEPAGES, (u32)pages, count, 0, 0, 0);
  515. }
  516. #define MAX_MULTIPLIER 1000000000
  517. #define MAX_HEX_MULTIPLIER 0x10000000
  518. uint_t dec_string(char *_str)
  519. {
  520. uint_t len = string_length(_str);
  521. char *str = _str + len - 1;
  522. uint_t number = 0, multiplier = 1;
  523. while(str >= _str && multiplier < MAX_MULTIPLIER) {
  524. if((*str) >= '0' && (*str) <= '9') {
  525. number += ((*str) - '0') * multiplier;
  526. multiplier *= 10;
  527. }
  528. str--;
  529. }
  530. return number;
  531. }
  532. /*
  533. * Note that the string will include a '0' and 'x' at the beginning
  534. */
  535. uint_t hex_string(char *_str)
  536. {
  537. //Move past the '0x'
  538. _str += 2;
  539. uint_t len = string_length(_str);
  540. char *str = _str + len - 1;
  541. uint_t number = 0, multiplier = 1;
  542. while(str >= _str && multiplier <= MAX_HEX_MULTIPLIER) {
  543. if((*str) >= '0' && (*str) <= '9') {
  544. number += ((*str) - '0') * multiplier;
  545. multiplier *= 16;
  546. } else if((*str) >= 'a' && (*str) <= 'f') {
  547. number += ((*str) - 'a' + 10) * multiplier;
  548. multiplier *= 16;
  549. } else if((*str) >= 'A' && (*str) <= 'F') {
  550. number += ((*str) - 'A' + 10) * multiplier;
  551. multiplier *= 16;
  552. }
  553. str--;
  554. }
  555. return number;
  556. }
  557. int wait_for_process(uint_t pid)
  558. {
  559. return _syscall(SYS_WAITFORPROCESS, pid, 0, 0, 0, 0);
  560. }
  561. int kill_process(uint_t pid)
  562. {
  563. return _syscall(SYS_KILLPROCESS, pid, 0, 0, 0, 0);
  564. }
  565. int redirect_out(uint_t pid, uint_t fid)
  566. {
  567. return _syscall(SYS_REDIRECTOUT, pid, fid, 0, 0, 0);
  568. }
  569. int foo()
  570. {
  571. return _syscall(SYS_FOO, 0, 0, 0, 0, 0);
  572. }
  573. int foo_enter()
  574. {
  575. return _syscall(SYS_FOO_ENTER, 0, 0, 0, 0, 0);
  576. }
  577. int foo_leave()
  578. {
  579. return _syscall(SYS_FOO_LEAVE, 0, 0, 0, 0, 0);
  580. }
  581. int try()
  582. {
  583. return _syscall(SYS_TRY, 0, 0, 0, 0, 0);
  584. }
  585. int exit_try()
  586. {
  587. return _syscall(SYS_EXITTRY, 0, 0, 0, 0, 0);
  588. }
  589. static struct apimod_base apimod_base = {
  590. .try = try,
  591. .exit_try = exit_try,
  592. .foo = foo,
  593. .foo_enter = foo_enter,
  594. .foo_leave = foo_leave,
  595. .get_version = get_version,
  596. .exit_process = exit_process,
  597. .release = release,
  598. .create_process = create_process,
  599. .get_current = get_current,
  600. .set_current = set_current,
  601. .get_arguments = get_arguments,
  602. .pause_process = pause_process,
  603. .resume_process = resume_process,
  604. .get_pages = get_pages,
  605. .free_pages = free_pages,
  606. .wait_for_process = wait_for_process,
  607. .kill_process = kill_process,
  608. .redirect_out = redirect_out,
  609. };
  610. static struct apimod_console apimod_console = {
  611. .printf = printf,
  612. .print = print,
  613. .read_input = read_input,
  614. .read_line = read_line,
  615. };
  616. static struct apimod_lib_string apimod_lib_string = {
  617. .length = string_length,
  618. .equals = string_equals,
  619. .copy = string_copy,
  620. .cat = string_cat,
  621. .separate = separate,
  622. .starts_with = string_starts_with,
  623. .ends_with = string_ends_with,
  624. .replace = string_replace,
  625. .vsnprintf = vsnprintf,
  626. .snprintf = snprintf,
  627. .to_lower = string_to_lower,
  628. .to_higher = string_to_higher,
  629. .dec_string = dec_string,
  630. .hex_string = hex_string,
  631. };
  632. static struct apimod_lib_memory apimod_memory = {
  633. .copy = memory_copy,
  634. .set = memory_set,
  635. .malloc = malloc,
  636. .free = free,
  637. .equals = memory_equals,
  638. };
  639. static struct apimod_fs apimod_fs = {
  640. .open = open,
  641. .close = close,
  642. .read = read,
  643. .write = write,
  644. .get_info = get_info,
  645. .change_state = change_state,
  646. .get_child = get_child,
  647. .next_child = next_child,
  648. .find_child = find_child,
  649. .get_parent = get_parent,
  650. .get_info1 = get_info1,
  651. .create = create,
  652. .delete = delete,
  653. .get_device = get_device,
  654. .next_device = next_device,
  655. };
  656. static struct apimod_fs1 apimod_fs1 = {
  657. .get_children = get_children,
  658. .free_children = free_children,
  659. .read_all_file = read_all_file,
  660. .write_all_file = write_all_file,
  661. .create_file = create_file,
  662. .delete_file = delete_file,
  663. };
  664. static struct apimod_ini apimod_ini = {
  665. .read = ini_read,
  666. .dispose = ini_dispose,
  667. .get_value = ini_get_value,
  668. .get_class = ini_get_class,
  669. };
  670. static struct apimod_string apimod_string = {
  671. .init = string_init,
  672. .append_char = string_append_char,
  673. .append = string_append,
  674. .init_from = string_init_from,
  675. .new = string_new,
  676. .deinit = string_deinit,
  677. .delete = string_delete,
  678. };
  679. /*
  680. * This is called by a user mode application to get any of the interfaces
  681. * defined above
  682. */
  683. int apimod_get_interface(char *name, void **interface)
  684. {
  685. if(string_equals(name, "console")) {
  686. *interface = &apimod_console;
  687. } else if(string_equals(name, "base")) {
  688. *interface = &apimod_base;
  689. } else if(string_equals(name, "lib_string")) {
  690. *interface = &apimod_lib_string;
  691. } else if(string_equals(name, "fs")) {
  692. *interface = &apimod_fs;
  693. } else if(string_equals(name, "memory")) {
  694. *interface = &apimod_memory;
  695. } else if(string_equals(name, "ini")) {
  696. *interface = &apimod_ini;
  697. } else if(string_equals(name, "fs1")) {
  698. *interface = &apimod_fs1;
  699. } else if(string_equals(name, "string")) {
  700. *interface = &apimod_string;
  701. } else {
  702. insane(EPARAM, "apimod_get_interface: Invalid interface requested: %s\n", name);
  703. }
  704. return 0;
  705. }