/apps/shell/ftk_app_shell.c

http://ftk.googlecode.com/ · C · 243 lines · 165 code · 49 blank · 29 comment · 34 complexity · 87794f517c9349c59f28d7f7a2743f19 MD5 · raw file

  1. /*
  2. * File: ftk_all_shell.h
  3. * Author: Li XianJing <xianjimli@hotmail.com>
  4. * Brief: shell
  5. *
  6. * Copyright (c) 2009 - 2010 Li XianJing <xianjimli@hotmail.com>
  7. *
  8. * Licensed under the Academic Free License version 2.1
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. /*
  25. * History:
  26. * ================================================================
  27. * 2010-08-29 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include <pthread.h>
  31. #include "ftk_app_shell.h"
  32. #include "ftk_source_shell.h"
  33. typedef struct _PrivInfo
  34. {
  35. FtkBitmap* icon;
  36. FtkWidget* input_entry;
  37. FtkWidget* output_text_view;
  38. int read_fd;
  39. int write_fd;
  40. FtkSource* shell_source;
  41. }PrivInfo;
  42. static FtkBitmap* ftk_app_shell_get_icon(FtkApp* thiz)
  43. {
  44. DECL_PRIV(thiz, priv);
  45. const char* name="shell.png";
  46. char file_name[FTK_MAX_PATH + 1] = {0};
  47. return_val_if_fail(priv != NULL, NULL);
  48. if(priv->icon != NULL) return priv->icon;
  49. snprintf(file_name, FTK_MAX_PATH, "%s/icons/%s", APP_DATA_DIR, name);
  50. priv->icon = ftk_bitmap_factory_load(ftk_default_bitmap_factory(), file_name);
  51. if(priv->icon != NULL) return priv->icon;
  52. snprintf(file_name, FTK_MAX_PATH, "%s/icons/%s", APP_LOCAL_DATA_DIR, name);
  53. priv->icon = ftk_bitmap_factory_load(ftk_default_bitmap_factory(), file_name);
  54. return priv->icon;
  55. }
  56. static const char* ftk_app_shell_get_name(FtkApp* thiz)
  57. {
  58. return _("Shell");
  59. }
  60. static Ret ftk_app_shell_exec(FtkApp* thiz, FtkEvent* event)
  61. {
  62. DECL_PRIV(thiz, priv);
  63. const char* cmd = NULL;
  64. char buffer[1024] = {0};
  65. ssize_t write_ret = 0;
  66. return_val_if_fail(thiz != NULL && event != NULL, RET_FAIL);
  67. if(event->type != FTK_EVT_KEY_UP || event->u.key.code != FTK_KEY_ENTER)
  68. {
  69. return RET_OK;
  70. }
  71. cmd = ftk_entry_get_text(priv->input_entry);
  72. if(strncmp(cmd, "exit", 4) == 0 || strncmp(cmd, "quit", 4) == 0)
  73. {
  74. ftk_widget_unref(ftk_widget_toplevel(priv->input_entry));
  75. }
  76. else
  77. {
  78. ftk_snprintf(buffer, sizeof(buffer), "%s\n", cmd);
  79. write_ret = write(priv->write_fd, buffer, strlen(buffer));
  80. ftk_entry_set_text(priv->input_entry, "");
  81. ftk_text_view_set_text(priv->output_text_view, buffer, -1);
  82. }
  83. return RET_REMOVE;
  84. }
  85. static void ftk_app_shell_reset(FtkApp* thiz)
  86. {
  87. DECL_PRIV(thiz, priv);
  88. priv->input_entry = NULL;
  89. priv->output_text_view = NULL;
  90. close(priv->write_fd);
  91. priv->read_fd = 0;
  92. priv->write_fd = 0;
  93. ftk_source_disable(priv->shell_source);
  94. ftk_main_loop_remove_source(ftk_default_main_loop(), priv->shell_source);
  95. priv->shell_source = NULL;
  96. return;
  97. }
  98. #define SHELL_CMD1 "/bin/bash"
  99. #define SHELL_CMD2 "/bin/sh"
  100. static const char* ftk_app_shell_get_shell(FtkApp* thiz)
  101. {
  102. if(access(SHELL_CMD1, 0) == 0)
  103. {
  104. return SHELL_CMD1;
  105. }
  106. if(access(SHELL_CMD2, 0) == 0)
  107. {
  108. return SHELL_CMD2;
  109. }
  110. return NULL;
  111. }
  112. static Ret ftk_app_shell_create_shell_process(FtkApp* thiz)
  113. {
  114. int ret = 0;
  115. DECL_PRIV(thiz, priv);
  116. int parent_to_child[2] = {0};
  117. int child_to_parent[2] = {0};
  118. const char* shell = ftk_app_shell_get_shell(thiz);
  119. return_val_if_fail(shell != NULL, RET_FAIL);
  120. if(pipe(parent_to_child) < 0) goto failed;
  121. if(pipe(child_to_parent) < 0) goto failed;
  122. if((ret = fork()) < 0) goto failed;
  123. if(ret == 0)
  124. {
  125. close(parent_to_child[1]);
  126. close(child_to_parent[0]);
  127. dup2(parent_to_child[0], STDIN_FILENO);
  128. dup2(child_to_parent[1], STDOUT_FILENO);
  129. dup2(child_to_parent[1], STDERR_FILENO);
  130. execl(shell, shell, NULL);
  131. _exit(0);
  132. }
  133. else
  134. {
  135. close(parent_to_child[0]);
  136. close(child_to_parent[1]);
  137. priv->read_fd = child_to_parent[0];
  138. priv->write_fd = parent_to_child[1];
  139. }
  140. return RET_OK;
  141. failed:
  142. if(parent_to_child[0] > 0) close(parent_to_child[0]);
  143. if(parent_to_child[1] > 0) close(parent_to_child[1]);
  144. if(child_to_parent[0] > 0) close(child_to_parent[0]);
  145. if(child_to_parent[1] > 0) close(child_to_parent[1]);
  146. return 0;
  147. }
  148. static Ret ftk_app_shell_run(FtkApp* thiz, int argc, char* argv[])
  149. {
  150. DECL_PRIV(thiz, priv);
  151. FtkWidget* entry = NULL;
  152. FtkWidget* text_view = NULL;
  153. FtkWidget* win = ftk_app_window_create();
  154. int width = ftk_widget_width(win);
  155. int height = ftk_widget_height(win);
  156. ftk_window_set_animation_hint(win, "app_main_window");
  157. ftk_widget_set_text(win, _("Shell"));
  158. text_view = ftk_text_view_create(win, 0, 0, width, height - 30);
  159. ftk_text_view_set_readonly(text_view, 1);
  160. entry = ftk_entry_create(win, 0, height - 30, width, 30);
  161. ftk_entry_set_tips(entry, _("Input command at here."));
  162. ftk_widget_set_event_listener(entry, (FtkListener)ftk_app_shell_exec, thiz);
  163. ftk_window_set_focus(win, entry);
  164. priv->input_entry = entry;
  165. priv->output_text_view = text_view;
  166. ftk_widget_set_user_data(win, (FtkDestroy)ftk_app_shell_reset, thiz);
  167. #ifdef HAS_MAIN
  168. FTK_QUIT_WHEN_WIDGET_CLOSE(win);
  169. #endif
  170. if(ftk_app_shell_create_shell_process(thiz) == RET_OK)
  171. {
  172. priv->shell_source = ftk_source_shell_create(priv->read_fd, priv->output_text_view);
  173. ftk_main_loop_add_source(ftk_default_main_loop(), priv->shell_source);
  174. }
  175. ftk_widget_show_all(win, 1);
  176. return RET_OK;
  177. }
  178. static void ftk_app_shell_destroy(FtkApp* thiz)
  179. {
  180. FTK_FREE(thiz);
  181. return;
  182. }
  183. FtkApp* ftk_app_shell_create(void)
  184. {
  185. FtkApp* thiz = FTK_ZALLOC(sizeof(FtkApp) + sizeof(PrivInfo));
  186. if(thiz != NULL)
  187. {
  188. thiz->run = ftk_app_shell_run;
  189. thiz->get_icon = ftk_app_shell_get_icon;
  190. thiz->get_name = ftk_app_shell_get_name;
  191. thiz->destroy = ftk_app_shell_destroy;
  192. }
  193. return thiz;
  194. }