PageRenderTime 114ms CodeModel.GetById 23ms app.highlight 51ms RepoModel.GetById 19ms app.codeStats 0ms

/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/*
 26 * History:
 27 * ================================================================
 28 * 2010-08-29 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include <pthread.h>
 33#include "ftk_app_shell.h"
 34#include "ftk_source_shell.h"
 35
 36typedef struct _PrivInfo
 37{
 38	FtkBitmap* icon;
 39	FtkWidget* input_entry;
 40	FtkWidget* output_text_view;
 41
 42	int read_fd;
 43	int write_fd;
 44
 45	FtkSource* shell_source;
 46}PrivInfo;
 47
 48static FtkBitmap* ftk_app_shell_get_icon(FtkApp* thiz)
 49{
 50	DECL_PRIV(thiz, priv);
 51	const char* name="shell.png";
 52	char file_name[FTK_MAX_PATH + 1] = {0};
 53	return_val_if_fail(priv != NULL, NULL);
 54	
 55	if(priv->icon != NULL) return priv->icon;
 56	
 57	snprintf(file_name, FTK_MAX_PATH, "%s/icons/%s", APP_DATA_DIR, name);
 58	priv->icon = ftk_bitmap_factory_load(ftk_default_bitmap_factory(), file_name);
 59	if(priv->icon != NULL) return priv->icon;
 60
 61	snprintf(file_name, FTK_MAX_PATH, "%s/icons/%s", APP_LOCAL_DATA_DIR, name);
 62	priv->icon = ftk_bitmap_factory_load(ftk_default_bitmap_factory(), file_name);
 63
 64	return priv->icon;
 65}
 66
 67static const char* ftk_app_shell_get_name(FtkApp* thiz)
 68{
 69	return _("Shell");
 70}
 71
 72static Ret ftk_app_shell_exec(FtkApp* thiz, FtkEvent* event)
 73{
 74	DECL_PRIV(thiz, priv);
 75	const char* cmd = NULL;
 76	char buffer[1024] = {0};
 77	ssize_t write_ret = 0;
 78	return_val_if_fail(thiz != NULL && event != NULL, RET_FAIL);
 79
 80	if(event->type != FTK_EVT_KEY_UP || event->u.key.code != FTK_KEY_ENTER)
 81	{
 82		return RET_OK;
 83	}
 84
 85	cmd = ftk_entry_get_text(priv->input_entry);
 86
 87	if(strncmp(cmd, "exit", 4) == 0 || strncmp(cmd, "quit", 4) == 0)
 88	{
 89		ftk_widget_unref(ftk_widget_toplevel(priv->input_entry));
 90	}
 91	else
 92	{
 93		ftk_snprintf(buffer, sizeof(buffer), "%s\n", cmd);
 94		write_ret = write(priv->write_fd, buffer, strlen(buffer));
 95
 96		ftk_entry_set_text(priv->input_entry, "");
 97		ftk_text_view_set_text(priv->output_text_view, buffer, -1);
 98	}
 99
100	return RET_REMOVE;
101}
102
103static void ftk_app_shell_reset(FtkApp* thiz)
104{
105	DECL_PRIV(thiz, priv);
106	priv->input_entry = NULL;
107	priv->output_text_view = NULL;
108	
109	close(priv->write_fd);
110	priv->read_fd = 0;
111	priv->write_fd = 0;
112
113	ftk_source_disable(priv->shell_source);
114	ftk_main_loop_remove_source(ftk_default_main_loop(), priv->shell_source);
115	priv->shell_source = NULL;
116
117	return;
118}
119
120#define SHELL_CMD1 "/bin/bash"
121#define SHELL_CMD2 "/bin/sh"
122
123static const char* ftk_app_shell_get_shell(FtkApp* thiz)
124{
125	if(access(SHELL_CMD1, 0) == 0)
126	{
127		return SHELL_CMD1;
128	}
129
130	if(access(SHELL_CMD2, 0) == 0)
131	{
132		return SHELL_CMD2;
133	}
134
135	return NULL;
136}
137
138static Ret ftk_app_shell_create_shell_process(FtkApp* thiz)
139{
140	int ret = 0;
141	DECL_PRIV(thiz, priv);
142	int parent_to_child[2] = {0};
143	int child_to_parent[2] = {0};
144	const char* shell = ftk_app_shell_get_shell(thiz);
145
146	return_val_if_fail(shell != NULL, RET_FAIL);
147
148	if(pipe(parent_to_child) < 0) goto failed;
149	if(pipe(child_to_parent) < 0) goto failed;
150	if((ret = fork()) < 0) goto failed;
151	
152	if(ret == 0)
153	{
154		close(parent_to_child[1]);
155		close(child_to_parent[0]);
156
157		dup2(parent_to_child[0], STDIN_FILENO);
158		dup2(child_to_parent[1], STDOUT_FILENO);
159		dup2(child_to_parent[1], STDERR_FILENO);
160
161		execl(shell, shell, NULL);
162		_exit(0);
163	}
164	else
165	{
166		close(parent_to_child[0]);
167		close(child_to_parent[1]);
168
169		priv->read_fd = child_to_parent[0];
170		priv->write_fd = parent_to_child[1];
171
172	}
173
174	return RET_OK;
175
176failed:
177	if(parent_to_child[0] > 0) close(parent_to_child[0]);
178	if(parent_to_child[1] > 0) close(parent_to_child[1]);
179	if(child_to_parent[0] > 0) close(child_to_parent[0]);
180	if(child_to_parent[1] > 0) close(child_to_parent[1]);
181	
182	return 0;
183}
184	
185static Ret ftk_app_shell_run(FtkApp* thiz, int argc, char* argv[])
186{
187	DECL_PRIV(thiz, priv);
188	FtkWidget* entry = NULL;
189	FtkWidget* text_view = NULL;
190	FtkWidget* win = ftk_app_window_create();
191	int width = ftk_widget_width(win);
192	int height = ftk_widget_height(win);
193
194	ftk_window_set_animation_hint(win, "app_main_window");
195	ftk_widget_set_text(win, _("Shell"));
196	text_view = ftk_text_view_create(win, 0, 0, width, height - 30);
197	ftk_text_view_set_readonly(text_view, 1);
198	entry = ftk_entry_create(win, 0, height - 30, width, 30);
199	ftk_entry_set_tips(entry, _("Input command at here."));
200	ftk_widget_set_event_listener(entry, (FtkListener)ftk_app_shell_exec, thiz);
201	ftk_window_set_focus(win, entry);
202
203	priv->input_entry = entry;
204	priv->output_text_view = text_view;
205
206	ftk_widget_set_user_data(win, (FtkDestroy)ftk_app_shell_reset, thiz);
207
208#ifdef HAS_MAIN
209	FTK_QUIT_WHEN_WIDGET_CLOSE(win);
210#endif
211	
212	if(ftk_app_shell_create_shell_process(thiz) == RET_OK)
213	{
214		priv->shell_source = ftk_source_shell_create(priv->read_fd, priv->output_text_view);
215		ftk_main_loop_add_source(ftk_default_main_loop(), priv->shell_source);
216	}
217
218	ftk_widget_show_all(win, 1);
219
220	return RET_OK;
221}
222
223static void ftk_app_shell_destroy(FtkApp* thiz)
224{
225	FTK_FREE(thiz);
226
227	return;
228}
229
230FtkApp* ftk_app_shell_create(void)
231{
232	FtkApp* thiz = FTK_ZALLOC(sizeof(FtkApp) + sizeof(PrivInfo));
233
234	if(thiz != NULL)
235	{
236		thiz->run = ftk_app_shell_run;
237		thiz->get_icon = ftk_app_shell_get_icon;
238		thiz->get_name = ftk_app_shell_get_name;
239		thiz->destroy = ftk_app_shell_destroy;
240	}
241
242	return thiz;
243}