lwp_args.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2024-01-12 Shell separate argv, envp, aux processing to lwp_args.c
  9. * Bugs fix for script arguments processing.
  10. * support args larger than 4k
  11. */
  12. #include "lwp_args.h"
  13. #include "lwp_internal.h"
  14. #include "mm_page.h"
  15. static void _strvec_init(struct lwp_string_vector *sv)
  16. {
  17. #define DEFAUTL_ARGV_BUFLEN 4
  18. sv->strvec = rt_malloc(DEFAUTL_ARGV_BUFLEN * sizeof(char *));
  19. sv->strvec_buflen = DEFAUTL_ARGV_BUFLEN;
  20. sv->string_count = 0;
  21. }
  22. static void _strvec_detach(struct lwp_string_vector *sv)
  23. {
  24. if (sv->strvec)
  25. {
  26. rt_free(sv->strvec);
  27. }
  28. }
  29. static rt_err_t _strvec_append(struct lwp_string_vector *sv, const char *string)
  30. {
  31. if (sv->string_count == sv->strvec_buflen)
  32. {
  33. void *newptr;
  34. newptr = rt_realloc(sv->strvec, sv->strvec_buflen * 2 * sizeof(char *));
  35. if (!newptr)
  36. return -RT_ENOMEM;
  37. sv->strvec = newptr;
  38. sv->strvec_buflen *= 2;
  39. }
  40. sv->strvec[sv->string_count++] = string;
  41. return RT_EOK;
  42. }
  43. static rt_err_t args_append(struct lwp_args_info *ai, const char *str_addr,
  44. size_t str_len, enum lwp_args_type atype)
  45. {
  46. rt_err_t error;
  47. char *str_bufaddr;
  48. if (ai->strings_length + str_len + 1 > ai->str_buf_size)
  49. {
  50. /* reallocate buffer for this */
  51. void *newptr;
  52. newptr = rt_realloc(ai->str_buf, ai->str_buf_size * 2);
  53. if (!newptr)
  54. return -RT_ENOMEM;
  55. ai->str_buf = newptr;
  56. ai->str_buf_size *= 2;
  57. }
  58. /* append new string to string buffer and update strings_length */
  59. str_bufaddr = &ai->str_buf[ai->strings_length];
  60. if (atype == LWP_ARGS_TYPE_KARG || atype == LWP_ARGS_TYPE_KENVP)
  61. {
  62. strcpy(str_bufaddr, str_addr);
  63. ai->strings_length += str_len + 1;
  64. }
  65. else
  66. {
  67. lwp_get_from_user(str_bufaddr, (void *)str_addr, str_len);
  68. ai->strings_length += str_len;
  69. ai->str_buf[ai->strings_length++] = '\0';
  70. }
  71. /* append new argument or environment */
  72. switch (atype)
  73. {
  74. case LWP_ARGS_TYPE_ARG:
  75. case LWP_ARGS_TYPE_KARG:
  76. error = _strvec_append(&ai->argv, str_bufaddr);
  77. if (!error && ai->argv.string_count == 1)
  78. {
  79. ai->argv0_strlen = str_len;
  80. }
  81. break;
  82. case LWP_ARGS_TYPE_ENVP:
  83. case LWP_ARGS_TYPE_KENVP:
  84. error = _strvec_append(&ai->envp, str_bufaddr);
  85. break;
  86. default:
  87. break;
  88. }
  89. return error;
  90. }
  91. /**
  92. * @brief Override arguments 0 for script interpreter.
  93. *
  94. * Manual: interpreter will be invoked with the following arguments:
  95. * {interpreter [optional-arg] pathname arg...}
  96. * where pathname is the pathname of the file specified as the first
  97. * argument of execve(), and arg... is the series of words pointed
  98. * to by the argv argument of execve(), starting at argv[1]. Note
  99. * that there is no way to get the argv[0] that was passed to the
  100. * execve() call.
  101. */
  102. static rt_err_t _args_override_argv0(struct lwp_args_info *ai, struct lwp_args_info *ow_ai)
  103. {
  104. rt_err_t error = 0;
  105. int i, new_argc, new_strbuf_size, ai_bytes_tobe_copied;
  106. char **new_argv, *new_strbuf, *base;
  107. rt_base_t off;
  108. if (ow_ai == 0 || ow_ai->argv.string_count == 0)
  109. {
  110. return -RT_EINVAL;
  111. }
  112. /* for new argument vector */
  113. new_argc = ai->argv.string_count - 1 + ow_ai->argv.string_count;
  114. new_argv = rt_malloc(new_argc * sizeof(char *));
  115. if (!new_argv)
  116. {
  117. return -RT_ENOMEM;
  118. }
  119. /* for new string buffer */
  120. ai_bytes_tobe_copied = ai->strings_length - (ai->argv0_strlen + 1);
  121. new_strbuf_size = ai_bytes_tobe_copied + ow_ai->strings_length;
  122. new_strbuf = rt_malloc(new_strbuf_size);
  123. if (!new_argv)
  124. {
  125. rt_free(new_argv);
  126. return -RT_ENOMEM;
  127. }
  128. base = new_strbuf;
  129. off = base - ow_ai->str_buf;
  130. /* copy overriding argument strings and argv */
  131. memcpy(base, ow_ai->str_buf, ow_ai->strings_length);
  132. for (i = 0; i < ow_ai->argv.string_count; i++)
  133. {
  134. /* base + ow_ai->argv.strvec[i] - ow_ai->str_buf */
  135. new_argv[i] = (char *)ow_ai->argv.strvec[i] + off;
  136. }
  137. base += ow_ai->strings_length;
  138. off = base - (ai->str_buf + ai->argv0_strlen + 1);
  139. /* copy old argument strings starting from argv[1] and setup new_argv */
  140. memcpy(base, ai->str_buf + ai->argv0_strlen + 1, ai_bytes_tobe_copied);
  141. for (size_t j = 1; j < ai->argv.string_count; i++, j++)
  142. {
  143. /* base + ai->argv->strvec[j] - ai->str_buf */
  144. new_argv[i] = (char *)ai->argv.strvec[j] + off;
  145. }
  146. /* setup envp for ai */
  147. for (i = 0; i < ai->envp.string_count; i++)
  148. {
  149. /* base + ai->envp->strvec[i] - ai->str_buf */
  150. ai->envp.strvec[i] += off;
  151. }
  152. /* replace strings buffer and argv buffer */
  153. ai->str_buf = new_strbuf;
  154. ai->strings_length = new_strbuf_size;
  155. ai->str_buf_size = new_strbuf_size;
  156. ai->argv.string_count = new_argc;
  157. ai->argv.strvec = (void *)new_argv;
  158. ai->argv.strvec_buflen = new_argc;
  159. ai->argv0_strlen = ow_ai->argv0_strlen;
  160. return error;
  161. }
  162. const char *lwp_args_get_argv_0(struct lwp_args_info *ai)
  163. {
  164. return ai->str_buf;
  165. }
  166. static rt_err_t args_init(struct lwp_args_info *ai, size_t str_buf_size)
  167. {
  168. void *str_buf;
  169. str_buf = rt_malloc(str_buf_size);
  170. if (!str_buf)
  171. return -RT_ENOMEM;
  172. memset(ai, 0, sizeof(*ai));
  173. _strvec_init(&ai->argv);
  174. if (!ai->argv.strvec)
  175. {
  176. rt_free(str_buf);
  177. return -RT_ENOMEM;
  178. }
  179. _strvec_init(&ai->envp);
  180. if (!ai->envp.strvec)
  181. {
  182. rt_free(str_buf);
  183. _strvec_detach(&ai->argv);
  184. return -RT_ENOMEM;
  185. }
  186. ai->str_buf_size = str_buf_size;
  187. ai->str_buf = str_buf;
  188. return RT_EOK;
  189. }
  190. #define STR_BUF_DEFAULT_SIZE 2048
  191. rt_err_t lwp_args_init(struct lwp_args_info *ai)
  192. {
  193. return args_init(ai, STR_BUF_DEFAULT_SIZE);
  194. }
  195. void lwp_args_detach(struct lwp_args_info *ai)
  196. {
  197. _strvec_detach(&ai->argv);
  198. _strvec_detach(&ai->envp);
  199. rt_free(ai->str_buf);
  200. }
  201. #ifdef ARCH_MM_MMU
  202. struct process_aux *lwp_argscopy(struct rt_lwp *lwp, struct lwp_args_info *ai)
  203. {
  204. int size = sizeof(rt_base_t) * 4; /* store argc, argv_NULL, envp_NULL, aux_NULL */
  205. char *str_ua;
  206. const char **args_ua;
  207. const char **iter;
  208. rt_base_t off;
  209. struct process_aux_item pa_item;
  210. struct process_aux *aux_ua;
  211. size_t prot = PROT_READ | PROT_WRITE;
  212. size_t flags = MAP_FIXED | MAP_PRIVATE;
  213. rt_base_t argc = ai->argv.string_count;
  214. rt_base_t envc = ai->envp.string_count;
  215. /**
  216. * counts the bytes to storage the args
  217. */
  218. size += argc * sizeof(char *) + envc * sizeof(char *)
  219. + ai->strings_length + sizeof(struct process_aux);
  220. args_ua = lwp_mmap2(lwp, (void *)(USER_STACK_VEND), size, prot, flags, -1, 0);
  221. if (args_ua == RT_NULL)
  222. {
  223. return RT_NULL;
  224. }
  225. /**
  226. * @brief Put data from args info to user space
  227. * argc, argv[], NULL, envp[], NULL, aux[], NULL, strings
  228. */
  229. iter = args_ua;
  230. /* argc */
  231. lwp_data_put(lwp, iter++, &argc, sizeof(char *));
  232. /* strings */
  233. str_ua = (char *)((rt_ubase_t)args_ua +
  234. (1 + argc + 1 + envc + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(rt_base_t));
  235. lwp_data_put(lwp, str_ua, ai->str_buf, ai->strings_length);
  236. /* argv */
  237. off = str_ua - ai->str_buf;
  238. for (size_t i = 0; i < argc; i++)
  239. {
  240. /* str_ua + ai->argv.strvec[i] - ai->str_buf */
  241. ai->argv.strvec[i] += off;
  242. }
  243. lwp_data_put(lwp, iter, ai->argv.strvec, sizeof(char *) * ai->argv.string_count);
  244. iter += ai->argv.string_count;
  245. /* NULL */
  246. lwp_data_set(lwp, iter++, 0, sizeof(char *));
  247. /* envp */
  248. for (size_t i = 0; i < envc; i++)
  249. {
  250. /* str_ua + ai->envp.strvec[i] - ai->str_buf */
  251. ai->envp.strvec[i] += off;
  252. }
  253. lwp_data_put(lwp, iter, ai->envp.strvec, sizeof(char *) * ai->envp.string_count);
  254. iter += ai->envp.string_count;
  255. /* NULL */
  256. lwp_data_set(lwp, iter++, 0, sizeof(char *));
  257. /* aux */
  258. aux_ua = (struct process_aux *)iter;
  259. pa_item.key = AT_EXECFN;
  260. pa_item.value = (size_t)str_ua;
  261. lwp_data_put(lwp, iter, &pa_item, sizeof(pa_item));
  262. iter += AUX_ARRAY_ITEMS_NR * 2;
  263. /* NULL */
  264. lwp_data_set(lwp, iter++, 0, sizeof(char *));
  265. lwp->args = args_ua;
  266. return aux_ua;
  267. }
  268. #else
  269. static struct process_aux *lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv, char **envp)
  270. {
  271. #ifdef ARCH_MM_MMU
  272. int size = sizeof(int) * 5; /* store argc, argv, envp, aux, NULL */
  273. struct process_aux *aux;
  274. #else
  275. int size = sizeof(int) * 4; /* store argc, argv, envp, NULL */
  276. #endif /* ARCH_MM_MMU */
  277. int *args;
  278. char *str;
  279. char **new_argve;
  280. int i;
  281. int len;
  282. for (i = 0; i < argc; i++)
  283. {
  284. size += (rt_strlen(argv[i]) + 1);
  285. }
  286. size += (sizeof(int) * argc);
  287. i = 0;
  288. if (envp)
  289. {
  290. while (envp[i] != 0)
  291. {
  292. size += (rt_strlen(envp[i]) + 1);
  293. size += sizeof(int);
  294. i++;
  295. }
  296. }
  297. #ifdef ARCH_MM_MMU
  298. /* for aux */
  299. size += sizeof(struct process_aux);
  300. args = (int *)rt_malloc(size);
  301. if (args == RT_NULL)
  302. {
  303. return RT_NULL;
  304. }
  305. /* argc, argv[], 0, envp[], 0 */
  306. str = (char *)((size_t)args + (argc + 2 + i + 1 + AUX_ARRAY_ITEMS_NR * 2 + 1) * sizeof(int));
  307. #else
  308. args = (int *)rt_malloc(size);
  309. if (args == RT_NULL)
  310. {
  311. return RT_NULL;
  312. }
  313. str = (char*)((int)args + (argc + 2 + i + 1) * sizeof(int));
  314. #endif /* ARCH_MM_MMU */
  315. new_argve = (char **)&args[1];
  316. args[0] = argc;
  317. for (i = 0; i < argc; i++)
  318. {
  319. len = rt_strlen(argv[i]) + 1;
  320. new_argve[i] = str;
  321. lwp_memcpy(str, argv[i], len);
  322. str += len;
  323. }
  324. new_argve[i] = 0;
  325. i++;
  326. new_argve[i] = 0;
  327. if (envp)
  328. {
  329. int j;
  330. for (j = 0; envp[j] != 0; j++)
  331. {
  332. len = rt_strlen(envp[j]) + 1;
  333. new_argve[i] = str;
  334. lwp_memcpy(str, envp[j], len);
  335. str += len;
  336. i++;
  337. }
  338. new_argve[i] = 0;
  339. }
  340. #ifdef ARCH_MM_MMU
  341. /* aux */
  342. aux = (struct process_aux *)(new_argve + i);
  343. aux->item[0].key = AT_EXECFN;
  344. aux->item[0].value = (uint32_t)(size_t)new_argve[0];
  345. i += AUX_ARRAY_ITEMS_NR * 2;
  346. new_argve[i] = 0;
  347. lwp->args = args;
  348. return aux;
  349. #else
  350. lwp->args = args;
  351. lwp->args_length = size;
  352. return (struct process_aux *)(new_argve + i);
  353. #endif /* ARCH_MM_MMU */
  354. }
  355. #endif
  356. rt_err_t lwp_args_put(struct lwp_args_info *args, const char **strv_addr, enum lwp_args_type atype)
  357. {
  358. rt_err_t error;
  359. int iter = 0;
  360. int len;
  361. const char *arg_ptr;
  362. while (1)
  363. {
  364. if (atype == LWP_ARGS_TYPE_ARG || atype == LWP_ARGS_TYPE_ENVP)
  365. {
  366. len = lwp_get_from_user(&arg_ptr, strv_addr + iter++, sizeof(char *));
  367. if (len != sizeof(char *))
  368. {
  369. return -EFAULT;
  370. }
  371. if (arg_ptr == NULL)
  372. {
  373. break;
  374. }
  375. len = lwp_user_strlen(arg_ptr);
  376. if (len < 0)
  377. {
  378. return -EFAULT;
  379. }
  380. }
  381. else
  382. {
  383. arg_ptr = strv_addr[iter++];
  384. if (arg_ptr == NULL)
  385. {
  386. break;
  387. }
  388. len = strlen(arg_ptr);
  389. }
  390. error = args_append(args, arg_ptr, len, atype);
  391. if (error)
  392. {
  393. return error;
  394. }
  395. }
  396. return 0;
  397. }
  398. /**
  399. * @brief Put argument vector to args object
  400. */
  401. rt_err_t lwp_args_put_argv(struct lwp_args_info *args, const char **argv_uaddr)
  402. {
  403. return lwp_args_put(args, argv_uaddr, LWP_ARGS_TYPE_ARG);
  404. }
  405. /**
  406. * @brief Put argument vector to args object
  407. */
  408. rt_err_t lwp_args_put_envp(struct lwp_args_info *args, const char **envp_uaddr)
  409. {
  410. return lwp_args_put(args, envp_uaddr, LWP_ARGS_TYPE_ENVP);
  411. }
  412. /**
  413. * read words until reach nextline or EOF.
  414. * words copied into buffer is never truncated.
  415. */
  416. #define READFILE_STAT_EOF_REACHED 0
  417. #define READFILE_STAT_NEXTLINE_REACHED 0
  418. #define READFILE_STAT_TRUNCATED 1
  419. #define READFILE_STAT_CAN_READMORE(stat) (stat)
  420. static int _readfile(int fd, size_t maxbytes, char *buffer, int *p_readlen)
  421. {
  422. int readlen;
  423. int stat;
  424. char *nlp;
  425. readlen = read(fd, buffer, maxbytes - 1);
  426. if (readlen <= 0)
  427. {
  428. /* eof, failed */
  429. stat = READFILE_STAT_EOF_REACHED;
  430. buffer[0] = '\0';
  431. }
  432. else
  433. {
  434. if ((nlp = strchr(buffer, '\n')) == NULL)
  435. {
  436. if (readlen == maxbytes - 1)
  437. {
  438. int tailing_wordlen = 0;
  439. char *cp = buffer + readlen - 1;
  440. for (; *cp && *cp != ' ' && *cp != '\t'; cp--, tailing_wordlen++)
  441. ;
  442. if (tailing_wordlen)
  443. {
  444. lseek(fd, -tailing_wordlen, SEEK_CUR);
  445. readlen -= tailing_wordlen;
  446. stat = READFILE_STAT_TRUNCATED;
  447. }
  448. else
  449. {
  450. stat = READFILE_STAT_EOF_REACHED;
  451. }
  452. }
  453. else
  454. {
  455. stat = READFILE_STAT_EOF_REACHED;
  456. }
  457. }
  458. else
  459. {
  460. stat = READFILE_STAT_NEXTLINE_REACHED;
  461. readlen = nlp - buffer;
  462. }
  463. buffer[readlen] = '\0';
  464. }
  465. if (p_readlen)
  466. *p_readlen = readlen;
  467. return stat;
  468. }
  469. static char *_find_word(char *cp)
  470. {
  471. for (; (*cp == ' ') || (*cp == '\t'); cp++)
  472. ;
  473. return cp;
  474. }
  475. static char *_seperate_and_get_nextword(char *cp)
  476. {
  477. /* find next whitespace */
  478. for (; *cp && (*cp != ' ') && (*cp != '\t'); cp++)
  479. ;
  480. /* seperate words */
  481. while ((*cp == ' ') || (*cp == '\t'))
  482. {
  483. *cp++ = '\0';
  484. }
  485. return cp;
  486. }
  487. #define INTERP_BUF_SIZE 128
  488. rt_err_t lwp_args_load_script(struct lwp_args_info *ai, const char *filename)
  489. {
  490. rt_err_t error = -1;
  491. int fd = -RT_ERROR;
  492. int len;
  493. int rf_stat;
  494. char interp[INTERP_BUF_SIZE];
  495. char *cp, *nextword;
  496. char script_magic[2];
  497. struct lwp_args_info ow_ai = {0};
  498. fd = open(filename, O_BINARY | O_RDONLY, 0);
  499. if (fd < 0)
  500. {
  501. goto quit;
  502. }
  503. /**
  504. * verify an interpreter script by matching script file magic
  505. * eg: #!/bin/sh
  506. */
  507. len = read(fd, script_magic, sizeof(script_magic));
  508. if (len != 2 || memcmp(script_magic, "#!", sizeof(script_magic)))
  509. {
  510. goto quit;
  511. }
  512. /* setup a new args struct to save script arguments */
  513. if (args_init(&ow_ai, INTERP_BUF_SIZE))
  514. {
  515. goto quit;
  516. }
  517. while (1)
  518. {
  519. /* read file to buffer (avoid any truncated words in buffer) */
  520. rf_stat = _readfile(fd, INTERP_BUF_SIZE, interp, &len);
  521. if (len <= 0)
  522. {
  523. goto quit;
  524. }
  525. /* find first word until reaching nil */
  526. cp = _find_word(interp);
  527. if (*cp == '\0')
  528. {
  529. if (READFILE_STAT_CAN_READMORE(rf_stat))
  530. continue;
  531. else
  532. break;
  533. }
  534. do
  535. {
  536. nextword = _seperate_and_get_nextword(cp);
  537. args_append(&ow_ai, cp, strlen(cp), LWP_ARGS_TYPE_KARG);
  538. cp = nextword;
  539. }
  540. while (*cp);
  541. if (READFILE_STAT_CAN_READMORE(rf_stat))
  542. continue;
  543. else
  544. break;
  545. }
  546. if (ow_ai.argv.string_count == 0)
  547. {
  548. goto quit; /* No interpreter name found */
  549. }
  550. args_append(&ow_ai, filename, strlen(filename), LWP_ARGS_TYPE_KARG);
  551. error = _args_override_argv0(ai, &ow_ai);
  552. if (error)
  553. {
  554. goto quit;
  555. }
  556. quit:
  557. lwp_args_detach(&ow_ai);
  558. if (fd >= 0)
  559. {
  560. close(fd);
  561. }
  562. return error;
  563. }
  564. char **lwp_get_command_line_args(struct rt_lwp *lwp)
  565. {
  566. size_t argc = 0;
  567. char **argv = NULL;
  568. int ret;
  569. size_t i;
  570. size_t len;
  571. if (lwp)
  572. {
  573. ret = lwp_data_get(lwp, &argc, lwp->args, sizeof(argc));
  574. if (ret == 0)
  575. {
  576. return RT_NULL;
  577. }
  578. argv = (char**)rt_calloc((argc + 1), sizeof(char*));
  579. if (argv)
  580. {
  581. for (i = 0; i < argc; i++)
  582. {
  583. char *argvp = NULL;
  584. ret = lwp_data_get(lwp, &argvp, &((char **)lwp->args)[1 + i], sizeof(argvp));
  585. if (ret == 0)
  586. {
  587. goto error_exit;
  588. }
  589. len = lwp_user_strlen_ext(lwp, argvp);
  590. if (len >= 0)
  591. {
  592. argv[i] = (char*)rt_malloc(len + 1);
  593. ret = lwp_data_get(lwp, argv[i], argvp, len);
  594. if (ret != len)
  595. {
  596. goto error_exit;
  597. }
  598. argv[i][len] = '\0';
  599. }
  600. else
  601. {
  602. goto error_exit;
  603. }
  604. }
  605. argv[argc] = NULL;
  606. }
  607. }
  608. return argv;
  609. error_exit:
  610. lwp_free_command_line_args(argv);
  611. return RT_NULL;
  612. }
  613. void lwp_print_envp(struct rt_lwp *lwp)
  614. {
  615. rt_size_t envp_counts;
  616. char **kenvp_array = lwp_get_envp(lwp, &envp_counts);
  617. if (kenvp_array)
  618. {
  619. rt_kprintf("envp_counts: %d\n", envp_counts);
  620. for (size_t i = 0; i < envp_counts; i++)
  621. {
  622. rt_kprintf("envp[%d]: %s\n", i, kenvp_array[i]);
  623. }
  624. }
  625. lwp_free_command_line_args(kenvp_array);
  626. return ;
  627. }
  628. char** lwp_get_envp(struct rt_lwp *lwp, rt_size_t *penvp_counts)
  629. {
  630. int ret, len;
  631. rt_base_t argc;
  632. char **p_kenvp = RT_NULL;
  633. char *envp, **p_envp;
  634. size_t envp_counts = 0;
  635. if (lwp)
  636. {
  637. ret = lwp_data_get(lwp, &argc, lwp->args, sizeof(argc));
  638. if (ret == 0)
  639. {
  640. return RT_NULL;
  641. }
  642. p_envp = (char **)lwp->args + 1 + argc + 1;
  643. /* counts envp */
  644. while (lwp_data_get(lwp, &envp, p_envp, sizeof(void *)) == sizeof(void *)
  645. && envp != NULL)
  646. {
  647. p_envp++;
  648. envp_counts++;
  649. }
  650. p_kenvp = (char **)rt_malloc((envp_counts + 1) * sizeof(char *));
  651. if (p_kenvp)
  652. {
  653. /* copy env from envp array */
  654. p_envp = (char **)lwp->args + 1 + argc + 1;
  655. for (size_t i = 0; i < envp_counts; i++)
  656. {
  657. ret = lwp_data_get(lwp, &envp, &p_envp[i], sizeof(char *));
  658. if (ret != sizeof(char **))
  659. {
  660. lwp_free_command_line_args(p_kenvp);
  661. return RT_NULL;
  662. }
  663. len = lwp_user_strlen_ext(lwp, envp);
  664. if (len > 0)
  665. {
  666. p_kenvp[i] = (char*)rt_malloc(len + 1);
  667. ret = lwp_data_get(lwp, p_kenvp[i], envp, len + 1);
  668. if (ret != len + 1)
  669. {
  670. lwp_free_command_line_args(p_kenvp);
  671. return RT_NULL;
  672. }
  673. }
  674. else
  675. {
  676. p_kenvp[i] = NULL;
  677. }
  678. }
  679. if (penvp_counts)
  680. *penvp_counts = envp_counts;
  681. p_kenvp[envp_counts] = NULL;
  682. }
  683. }
  684. return p_kenvp;
  685. }
  686. void lwp_free_command_line_args(char** argv)
  687. {
  688. size_t i;
  689. if (argv)
  690. {
  691. for (i = 0; argv[i]; i++)
  692. {
  693. rt_free(argv[i]);
  694. }
  695. rt_free(argv);
  696. }
  697. }