Index: EcnlProtoTool/trunk/ntshell/src/main.c
===================================================================
--- EcnlProtoTool/trunk/ntshell/src/main.c	(revision 434)
+++ EcnlProtoTool/trunk/ntshell/src/main.c	(revision 441)
@@ -48,7 +48,9 @@
 #include "syssvc/serial.h"
 #include "syssvc/syslog.h"
+#include "target_syssvc.h"
 #include "kernel_cfg.h"
 #include "main.h"
-#include "rza1.h"
+#include "fdtable.h"
+#ifndef NTSHELL_NO_SOCKET
 #include <tinet_config.h>
 #include <netinet/in.h>
@@ -70,27 +72,14 @@
 #include "usrcmd.h"
 #include "util/ntopt.h"
-#include "fdtable.h"
-#include "target_syssvc.h"
+#include "netapp/dhcp4_cli.h"
+#include "ntp_cli.h"
+#include "netcmd.h"
+#endif
 
 ID ws_api_mailboxid = MAIN_DATAQUEUE;
 ID ws_mempoolid = MPF_NET_BUF_256;
+extern ntstdio_t *ntstdio;
 
 char command[NTOPT_TEXT_MAXLEN];
-ntstdio_t ntstdio;
-
-unsigned char ntstdio_xi(struct ntstdio_t *handle)
-{
-	char buf[1];
-	if(serial_rea_dat(SIO_PORTID, buf, 1) != 1)
-		return -EIO;
-	return buf[0];
-}
-
-void ntstdio_xo(struct ntstdio_t *handle, unsigned char c)
-{
-	char buf[1];
-	buf[0] = c;
-	serial_wri_dat(SIO_PORTID, buf, 1);
-}
 
 const uint8_t mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC};
@@ -101,5 +90,5 @@
 	"3.5.0",
 	TARGET_NAME,
-    "toppers.jp"
+	"toppers.jp"
 };
 
@@ -113,25 +102,50 @@
 	main_state_start,
 	main_state_idle,
+#ifndef NTSHELL_NO_SOCKET
+	main_state_start_dhcp,
+#endif
+	main_state_servey_cmd,
 };
 
 struct main_obj_t {
 	ntshell_t ntshell;
-	TMO timer;
+	int timer;
 	enum main_state_t state;
 	SYSTIM prev, now;
-	WS_FBS_ID rcvmsg;
-	T_WS_FBS_QUEUE wbs_queue;
-	WS_FBS_ID sndmsg;
+	task_base_t **tasks;
+	int task_count;
+#ifndef NTSHELL_NO_SOCKET
+	uint8_t link;
+	uint8_t link_up;
+	uint8_t up;
+	uint8_t dhcp;
+	uint8_t ntp;
+	ntp_cli_state_t ntp_state;
+#endif
+	bool_t exec;
+	int event_req, event_res;
 };
 struct main_obj_t main_obj;
 
-static void main_change_netif_link(T_IFNET *ether);
+#ifndef NTSHELL_NO_SOCKET
+static void netif_link_callback(T_IFNET *ether);
+static void main_change_netif_link(uint8_t link_up, uint8_t up);
+#endif
 static void main_initialize(struct main_obj_t *obj);
-static TMO main_get_timer(struct main_obj_t *obj);
-static void main_progress(struct main_obj_t *obj, TMO elapse);
-static void main_timeout(struct main_obj_t *obj);
-extern int execute_command(int wait);
+static void main_finalize(struct main_obj_t *obj);
+static int main_get_timer(struct main_obj_t *obj);
+static void main_progress(struct main_obj_t *obj, int elapse);
+static void main_timeout(struct main_obj_t *obj, bool_t wakeup);
+static int execute_command(struct main_obj_t *obj, int wait);
 static int usrcmd_ntopt_callback(long *args, void *extobj);
-
+#ifndef NTSHELL_NO_SOCKET
+static void ntp_cli_state_changed(ntp_cli_state_t state);
+#endif
+
+void stdio_open(ID portid);
+void stdio_input(unsigned char c);
+
+bool_t dhcp_enable;
+int ntshell_exit;
 int shellcmd_exit_code;
 volatile int shellcmd_state;
@@ -139,7 +153,61 @@
 jmp_buf shellcmd_exit;
 
+void main_task_init(task_base_t **tasks, int task_count)
+{
+	main_obj.tasks = tasks;
+	main_obj.task_count = task_count;
+}
+
 int uart_read(char *buf, int cnt, void *extobj)
 {
-	return serial_rea_dat(SIO_PORTID, (char *)buf, cnt);
+	struct main_obj_t *obj = (struct main_obj_t *)extobj;
+	int result;
+	ER ret;
+	int timer;
+	bool_t wakeup = false;
+
+	obj->prev = obj->now;
+
+	if (obj->event_req != obj->event_res) {
+		obj->event_res = obj->event_req;
+		wakeup = true;
+#ifndef NTSHELL_NO_SOCKET
+		if (obj->dhcp) {
+			obj->dhcp = 0;
+			obj->state = main_state_start_dhcp;
+		}
+#endif
+		obj->timer = 0;
+	}
+
+	/* タイマー取得 */
+	timer = main_get_timer(obj);
+
+	/* 待ち */
+	ret = serial_trea_dat(SIO_PORTID, buf, cnt, timer);
+	if ((ret < 0) && (ret != E_OK) && (ret != E_TMOUT) && (ret != E_RLWAI)) {
+		syslog(LOG_NOTICE, "tslp_tsk ret: %s %d", itron_strerror(ret), timer);
+		ntshell_exit = 1;
+		return -1;
+	}
+	if (ret != E_TMOUT)
+		wakeup = true;
+	result = (int)ret;
+
+	ret = get_tim(&obj->now);
+	if (ret != E_OK) {
+		syslog(LOG_NOTICE, "get_tim ret: %s", itron_strerror(ret));
+		ntshell_exit = 1;
+		return -1;
+	}
+
+	/* 時間経過 */
+	int elapse = obj->now - obj->prev;
+	main_progress(obj, elapse);
+
+	/* タイムアウト処理 */
+	main_timeout(obj, wakeup);
+
+	return result;
 }
 
@@ -162,13 +230,37 @@
 	}
 
-	return execute_command(tskid == MAIN_TASK);
-}
+	return execute_command(&main_obj, tskid == MAIN_TASK);
+}
+
+gpio_t led_blue, led_green, led_red, sw;
 
 /*
- * メインタスク
+ *  メインタスク
  */
 void main_task(intptr_t exinf)
 {
 	struct main_obj_t *obj = (struct main_obj_t *)&main_obj;
+
+	gpio_init_out(&led_blue, LED_BLUE);
+	gpio_init_out(&led_green, LED_GREEN);
+	gpio_init_out(&led_red, LED_RED);
+	gpio_init_in(&sw, USER_BUTTON0);
+
+	obj->exec = gpio_read(&sw) == 1;
+
+	gpio_write(&led_blue, 1);
+	gpio_write(&led_green, obj->exec ? 1 : 0);
+	gpio_write(&led_red, 0);
+
+	ether_set_link_callback(main_change_netif_link);
+
+	/* 初期化 */
+	ffarch_init();
+
+	stdio_open(SIO_PORTID);
+
+#ifndef NTSHELL_NO_SOCKET
+	ntp_cli_set_state_changed_cb(ntp_cli_state_changed);
+#endif
 
 	main_initialize(obj);
@@ -177,4 +269,6 @@
 	ntshell_set_prompt(&obj->ntshell, "NTShell>");
 	ntshell_execute(&obj->ntshell);
+
+	main_finalize(obj);
 }
 
@@ -184,54 +278,26 @@
 static void main_initialize(struct main_obj_t *obj)
 {
-	FILINFO fno;
-#if FF_USE_LFN
-	char lfn[FF_MAX_LFN + 1];
-	fno.lfname = lfn;
-	fno.lfsize = FF_MAX_LFN + 1;
-#endif
 	ER ret;
-
-	ntstdio_init(&ntstdio, NTSTDIO_OPTION_LINE_ECHO | NTSTDIO_OPTION_CANON | NTSTDIO_OPTION_LF_CRLF | NTSTDIO_OPTION_LF_CR, ntstdio_xi, ntstdio_xo);
-
-	obj->timer = TMO_FEVR;
+	ID tskid = 0;
+
+	ret = get_tid(&tskid);
+	if (ret != E_OK) {
+		syslog(LOG_ERROR, "get_tid %d", ret);
+		return;
+	}
+
+	obj->timer = 100000;
 	obj->state = main_state_start;
 
-	gpio_t led_blue, led_green, led_red, sw;
-	gpio_init_out(&led_blue, LED_BLUE);
-	gpio_init_out(&led_green, LED_GREEN);
-	gpio_init_out(&led_red, LED_RED);
-	gpio_init_in(&sw, USER_BUTTON0);
-
-	bool_t exec = gpio_read(&sw) == 1;
-
-	gpio_write(&led_blue, 1);
-	gpio_write(&led_green, exec ? 1 : 0);
-	gpio_write(&led_red, 0);
-
-	ether_set_link_callback(main_change_netif_link);
-
-	/* 初期化 */
-	if (mruby_arduino_init() == 0) {
-		gpio_write(&led_blue, 0);
-	}
-	else {
-		gpio_write(&led_blue, 0);
-		gpio_write(&led_red, 1);
-	}
-
+	for (int i = 0; i < obj->task_count; i++) {
+		task_base_t *task = obj->tasks[i];
+		task->on_start(task, tskid);
+	}
+
+	gpio_write(&led_blue, 0);
 	gpio_write(&led_green, 0);
 
 	act_tsk(HTTPD1_TASK);
 	act_tsk(HTTPD2_TASK);
-
-	if (f_stat("1:/upload/main.mrb", &fno) != FR_OK) {
-		exec = false;
-	}
-
-	if (exec) {
-		ntlibc_strlcpy(command, "mruby -b 1:/upload/main.mrb", sizeof(command));
-
-		execute_command(1);
-	}
 
 	ret = get_tim(&obj->now);
@@ -243,10 +309,25 @@
 }
 
+static void main_finalize(struct main_obj_t *obj)
+{
+	for (int i = 0; i < obj->task_count; i++) {
+		task_base_t *task = obj->tasks[i];
+		task->on_end(task);
+	}
+}
+
 /*
  * タイマー取得
  */
-static TMO main_get_timer(struct main_obj_t *obj)
-{
-	TMO timer = obj->timer;
+static int main_get_timer(struct main_obj_t *obj)
+{
+	int timer = obj->timer;
+
+	for (int i = 0; i < obj->task_count; i++) {
+		task_base_t *task = obj->tasks[i];
+		int timer2 = task->get_timer(task);
+		if ((timer == -1) || ((timer2 != -1) && (timer > timer2)))
+			timer = timer2;
+	}
 
 	return timer;
@@ -256,5 +337,5 @@
  * 時間経過
  */
-static void main_progress(struct main_obj_t *obj, TMO elapse)
+static void main_progress(struct main_obj_t *obj, int elapse)
 {
 	if (obj->timer != TMO_FEVR) {
@@ -264,4 +345,9 @@
 		}
 	}
+
+	for (int i = 0; i < obj->task_count; i++) {
+		task_base_t *task = obj->tasks[i];
+		task->progress(task, elapse);
+	}
 }
 
@@ -269,10 +355,82 @@
  * タイムアウト処理
  */
-static void main_timeout(struct main_obj_t *obj)
-{
-	//if (obj->timer == 0) {
-	//}
-}
-
+static void main_timeout(struct main_obj_t *obj, bool_t wakeup)
+{
+	ER ret;
+	uint32_t event = wakeup ? MAIN_EVENT_WAKEUP : 0;
+
+	if (!wakeup && (obj->timer != 0))
+		return;
+
+	switch (obj->state) {
+	case main_state_start:
+#ifndef NTSHELL_NO_SOCKET
+		ether_set_link_callback(netif_link_callback);
+#endif
+		{
+			FILINFO fno;
+#if FF_USE_LFN
+			char lfn[FF_MAX_LFN + 1];
+			fno.lfname = lfn;
+			fno.lfsize = FF_MAX_LFN + 1;
+#endif
+			if (f_stat("1:/upload/main.mrb", &fno) != FR_OK) {
+				obj->exec = false;
+			}
+
+			if (obj->exec) {
+				cmd_execute("mruby -b 1:/upload/main.mrb", obj);
+			}
+		}
+		obj->state = main_state_idle;
+		obj->timer = TMO_FEVR;
+		break;
+#ifndef NTSHELL_NO_SOCKET
+	case main_state_start_dhcp:
+		ret = dhcp4c_renew_info();
+		if (ret == E_OK) {
+			obj->state = main_state_idle;
+			obj->timer = TMO_FEVR;
+		}
+		else {
+			obj->state = main_state_start_dhcp;
+			obj->timer = 1000000;
+		}
+		break;
+#endif
+	default:
+		obj->state = main_state_idle;
+		obj->timer = TMO_FEVR;
+		break;
+	}
+#ifndef NTSHELL_NO_SOCKET
+	if (obj->link) {
+		obj->link = 0;
+		event |= MAIN_EVENT_NETIF_CHANGED;
+		if (obj->link_up)
+			event |= MAIN_EVENT_LINK_UP;
+		if (obj->up)
+			event |= MAIN_EVENT_UP;
+
+		if (obj->link_up && obj->up)
+			ntp_cli_execute();
+
+		main_change_netif_link(obj->link_up, obj->up);
+	}
+	if (obj->ntp) {
+		obj->ntp = 0;
+		if (obj->ntp_state != NTP_CLI_STATE_SYNC)
+			event |= MAIN_EVENT_NTP_ASYNC;
+		else
+			event |= MAIN_EVENT_NTP_SYNC;
+	}
+#endif
+	for (int i = 0; i < obj->task_count; i++) {
+		task_base_t *task = obj->tasks[i];
+		task->process(task, event);
+	}
+}
+
+#ifndef NTSHELL_NO_SOCKET
 /* MACアドレスの設定時に呼ばれる */
 void mbed_mac_address(char *mac)
@@ -281,5 +439,5 @@
 }
 
-static void main_change_netif_link(T_IFNET *ether)
+void main_change_netif_link(uint8_t link_up, uint8_t up)
 {
 	FLGPTN flgptn;
@@ -295,4 +453,56 @@
 	set_flg(FLG_SELECT_WAIT, flgptn);
 }
+
+void netif_link_callback(T_IFNET *ether)
+{
+	struct main_obj_t *obj = (struct main_obj_t *)&main_obj;
+	uint8_t link_up = (ether->flags & IF_FLAG_LINK_UP) != 0;
+	uint8_t up = (ether->flags & IF_FLAG_UP) != 0;
+	bool_t wake = false;
+
+	if (dhcp_enable) {
+		if (!link_up)
+			dhcp4c_rel_info();
+		else if (!up) {
+			wake = dhcp4c_renew_info() != E_OK;
+			if (wake) {
+				obj->dhcp = 1;
+			}
+		}
+	}
+	else {
+		up = link_up;
+	}
+
+	if ((obj->link_up != link_up) || (obj->up != up)) {
+		obj->link = 1;
+		wake = true;
+	}
+
+	obj->link_up = link_up;
+	obj->up = up;
+
+	if (wake && (obj->event_req == obj->event_res)) {
+		obj->event_req++;
+		rel_wai(MAIN_TASK);
+	}
+}
+
+void ntp_cli_state_changed(ntp_cli_state_t state)
+{
+	struct main_obj_t *obj = (struct main_obj_t *)&main_obj;
+	bool_t wake = obj->ntp_state != state;
+
+	if (wake) {
+		obj->ntp_state = state;
+		obj->ntp = 1;
+
+		if (obj->event_req == obj->event_res) {
+			obj->event_req++;
+			rel_wai(MAIN_TASK);
+		}
+	}
+}
+#endif
 
 /*
@@ -302,5 +512,12 @@
 {
 	shellcmd_state = 1;
-	shellcmd_exit_code = ntopt_parse(command, usrcmd_ntopt_callback, NULL);
+
+	if (setjmp(shellcmd_exit) == 0) {
+		shellcmd_exit_code = ntopt_parse(command, usrcmd_ntopt_callback, NULL);
+	}
+
+	//fflush(stdout);
+	clean_fd();
+
 	shellcmd_state = 2;
 }
@@ -315,4 +532,10 @@
 	{"hexdump", "Hex dump", usrcmd_hexdump},
 	{"date", "print date and time", usrcmd_date},
+#ifndef NTSHELL_NO_SOCKET
+	{"ping", "ping", usrcmd_ping},
+	{"dhcpc", "DHCP Client rel/renew/info", usrcmd_dhcp4c},
+	{"dnsc", "DNS client", usrcmd_dnsc },
+	{"ntpc", "NTP client", usrcmd_ntpc },
+#endif
 	{"info", "This is a description text string for info command.", usrcmd_info},
 	{"exit", "Exit Natural Tiny Shell", usrcmd_exit},
@@ -330,17 +553,25 @@
 
 	if (ntlibc_strcmp((const char *)args[1], "help") == 0) {
-		usrcmd_help(args[0], (char **)&args[1]);
+		found = 1;
+		result = usrcmd_help(args[0], (char **)&args[1]);
 	}
 	else for (int i = 0; i < cmd_table_info.count; i++) {
 		if (ntlibc_strcmp((const char *)args[1], p->cmd) == 0) {
-			return p->func(args[0], (char **)&args[1]);
+			found = 1;
+			result = p->func(args[0], (char **)&args[1]);
+			break;
 		}
 		p++;
 	}
-	if (setjmp(shellcmd_exit) == 0) {
-		(*((PowerOn_Reset_t *)0x18220000))(args);
-	}
-	clean_fd();
-	return 0;
+
+	if ((found == 0) && setjmp(shellcmd_exit) == 0) {
+		found = 1;
+		(*((PowerOn_Reset_t *)0x18200000))(args);
+	}
+
+	if ((found == 0) && (((const char *)args[1])[0] != '\0'))
+		ntstdio_printf(ntstdio, "Unknown command found. %s \n", (const char *)args[1]);
+
+	return result;
 }
 
@@ -349,8 +580,8 @@
 	const cmd_table_t *p = cmd_table_info.table;
 	for (int i = 0; i < cmd_table_info.count; i++) {
-		ntstdio_puts(&ntstdio, p->cmd);
-		ntstdio_puts(&ntstdio, "\t:");
-		ntstdio_puts(&ntstdio, p->desc);
-		ntstdio_puts(&ntstdio, "\n");
+		ntstdio_puts(ntstdio, p->cmd);
+		ntstdio_puts(ntstdio, "\t:");
+		ntstdio_puts(ntstdio, p->desc);
+		ntstdio_puts(ntstdio, "\n");
 		p++;
 	}
@@ -372,6 +603,4 @@
 void shell_abort()
 {
-	asm("bkpt #0");
-
 	shellcmd_exit_code = -1;
 	longjmp(shellcmd_exit, 1);
@@ -390,6 +619,7 @@
 }
 
-int execute_command(int wait)
-{
+int execute_command(struct main_obj_t *obj, int wait)
+{
+	T_RTSK rtsk;
 	ER ret;
 
@@ -399,5 +629,6 @@
 	}
 
-	tslp_tsk(100000);
+	if (ret == E_OK)
+		tslp_tsk(100000);
 
 	clean_fd();
@@ -413,7 +644,36 @@
 
 	do {
-		tslp_tsk(100000);
+		obj->state = main_state_servey_cmd;
+		obj->timer = 100000;
+
+		char c;
+		if (obj->ntshell.func_read(&c, sizeof(c), obj->ntshell.extobj) == 1) {
+			// Ctrl+Cが押された場合
+			if (c == 0x03) {
+				// コマンドタスクを終了
+				ret = ter_tsk(SHELLCMD_TASK);
+				if (ret != E_OK) {
+					syslog(LOG_ERROR, "ter_tsk => %d", ret);
+				}
+				shellcmd_exit_code = -1;
+				shellcmd_state = 4;
+				if (ret == E_OK)
+					tslp_tsk(100000);
+				break;
+			}
+
+			stdio_input(c);
+		}
+
+		ret = ref_tsk(SHELLCMD_TASK, &rtsk);
+		if ((ret != E_OK) || (rtsk.tskstat == TTS_DMT))
+			shellcmd_state = 3;
 	} while(shellcmd_state == 1);
 
+	obj->state = main_state_idle;
+	obj->timer = TMO_FEVR;
+
+	clean_fd();
+
 	return shellcmd_exit_code;
 }
@@ -421,5 +681,5 @@
 int shell_clock_getres(clockid_t clk_id, struct timespec *res)
 {
-	if (clk_id != CLOCK_REALTIME)
+	if ((clk_id != CLOCK_REALTIME) && (clk_id != CLOCK_MONOTONIC))
 		return -EINVAL;
 
@@ -434,5 +694,5 @@
 	SYSTIM now = 0;
 
-	if (clk_id != CLOCK_REALTIME)
+	if ((clk_id != CLOCK_REALTIME) && (clk_id != CLOCK_MONOTONIC))
 		return -EINVAL;
 
@@ -446,8 +706,16 @@
 int shell_clock_settime(clockid_t clk_id, const struct timespec *tp)
 {
-	if (clk_id != CLOCK_REALTIME)
+	if ((clk_id != CLOCK_REALTIME) && (clk_id != CLOCK_MONOTONIC))
 		return -EINVAL;
 
-	rtc_write(tp->tv_sec);
+	SYSTIM time;
+	ER ret;
+
+	time = (tp->tv_sec * 1000000ll) + (tp->tv_nsec / 1000ll);
+
+	ret = set_tim(time);
+	if (ret != E_OK) {
+		return -EPERM;
+	}
 
 	return 0;
@@ -482,9 +750,18 @@
 }
 
-struct sigaction sigtable[6];
-
-int shell_sigaction(int sig, const struct sigaction *restrict sa, struct sigaction *restrict old)
-{
-	struct sigaction *sat;
+// musl-1.1.18\src\internal\ksigaction.h
+struct k_sigaction {
+	void(*handler)(int);
+	unsigned long flags;
+	void(*restorer)(void);
+	unsigned mask[2];
+};
+
+struct k_sigaction sigtable[7];
+
+int shell_sigaction(int sig, const struct k_sigaction *restrict sa,
+	struct k_sigaction *restrict old, size_t size)
+{
+	struct k_sigaction *sat;
 
 	switch(sig){
@@ -507,4 +784,7 @@
 		sat = &sigtable[5];
 		break;
+	case SIGPIPE:
+		sat = &sigtable[6];
+		break;
 	default:
 		return -EINVAL;
@@ -512,7 +792,7 @@
 
 	if (old != NULL)
-		memcpy(old, sat, sizeof(struct sigaction));
-
-	memcpy(sat, sa, sizeof(struct sigaction));
+		memcpy(old, sat, offsetof(struct k_sigaction, mask) + size);
+
+	memcpy(sat, sa, offsetof(struct k_sigaction, mask) + size);
 
 	return 0;
@@ -524,81 +804,124 @@
 }
 
-int stdio_close(struct _IO_FILE *fp)
-{
-	return -EPERM;
-}
-
-size_t stdio_read(struct _IO_FILE *fp, unsigned char *data, size_t len)
-{
-	return -EPERM;
-}
-
-size_t stdio_write(struct _IO_FILE *fp, const unsigned char *data, size_t len)
-{
-	return -EPERM;
-}
-
-size_t stdin_read(struct _IO_FILE *fp, unsigned char *data, size_t len)
-{
-	int i = 0;
-	while (i < len) {
-		int c = ntstdio_getc(&ntstdio);
-		data[i++] = c;
-		if ((c == EOF) || (c == '\n'))
-			break;
-	}
-	return i;
-}
-
-size_t stdout_write(struct _IO_FILE *fp, const unsigned char *data, size_t len)
-{
-	for (int i = 0; i < len; i++) {
-		ntstdio_putc(&ntstdio, data[i]);
-	}
-	return len;
-}
-
-size_t stderr_write(struct _IO_FILE *fp, const unsigned char *data, size_t len)
-{
-	for (int i = 0; i < len; i++) {
-		ntstdio_putc(&ntstdio, data[i]);
-	}
-	return len;
-}
-
-int sio_close(struct _IO_FILE *fp)
-{
-	return -EPERM;
-}
-
-size_t sio_read(struct _IO_FILE *fp, unsigned char *data, size_t len)
-{
-	return -EPERM;
-}
-
-size_t sio_write(struct _IO_FILE *fp, const unsigned char *data, size_t len)
-{
-	return -EPERM;
-}
-
-off_t sio_seek(struct _IO_FILE *fp, off_t ofs, int org)
-{
-	return -EPERM;
-}
-
-int sio_ioctl(struct _IO_FILE *fp, int request, void *arg)
-{
-	switch (request) {
-	case TIOCGWINSZ:
+int shell_gettid()
+{
+	ID tskid;
+	ER ret;
+
+	ret = get_tid(&tskid);
+	if (ret != E_OK)
+		return -1;
+
+	return tskid;
+}
+
+int shell_tkill(int tid, int sig)
+{
+	if ((tid == SHELLCMD_TASK) && (sig == SIGABRT)) {
+		shell_abort();
+	}
+
+	no_implement("tkill");
+	return -1;
+}
+
+int shell_kill(int pid, int sig)
+{
+	DebugBreak();
+	return -1;
+}
+
+int shell_gettimeofday(struct timeval *tv, void *tzvp)
+{
+	SYSTIM time;
+	if (!tv) return 0;
+	get_tim(&time);
+	tv->tv_sec = time / 1000000;
+	tv->tv_usec = time - (tv->tv_sec * 1000000);
+	return 0;
+}
+
+int shell_nanosleep(const struct timespec *req, struct timespec *rem)
+{
+	ER ret;
+	TMO tmo;
+	SYSTIM prev, now, diff;
+
+	if ((req == NULL) || (req->tv_nsec < 0) || (req->tv_nsec >= 1000000000))
+		return -EINVAL;
+
+	get_tim(&prev);
+
+	tmo = req->tv_sec * 1000000 + req->tv_nsec / 1000;
+	ret = tslp_tsk(tmo);
+	if (ret == E_OK) {
+		if (rem != NULL) {
+			get_tim(&now);
+			diff = now - prev;
+			rem->tv_sec = diff / 1000000ll;
+			rem->tv_nsec = (diff - (rem->tv_sec * 1000000ll)) * 1000ll;
+		}
 		return 0;
-	case TCGETS:
-		return sio_tcgetattr(fp->fd, (struct termios *)arg);
-	case TCSETS + TCSANOW:
-	case TCSETS + TCSADRAIN:
-	case TCSETS + TCSAFLUSH:
-		return sio_tcsetattr(fp->fd, request - TCSETS, (const struct termios *)arg);
-	}
-
-	return -EINVAL;
-}
-
+	}
+	else if (ret == E_TMOUT) {
+		if (rem != NULL) {
+			rem->tv_sec = 0;
+			rem->tv_nsec = 0;
+		}
+		return 0;
+	}
+
+	return -EFAULT;
+}
+
+ssize_t shell_getrandom(void *buf, size_t buflen, unsigned int flags)
+{
+	SYSTIM now;
+	int32_t i;
+	int *output = (int *)buf;
+	size_t sz = buflen / 4;
+
+	get_tim(&now);
+	srand(now);
+
+	for (i = 0; i < sz; i++)
+		output[i] = rand();
+
+	for (i = 4 * sz; i < buflen; i++)
+		((char *)buf)[i] = rand();
+
+	return buflen;
+}
+
+extern uint32_t  __CmdBase;
+extern uint32_t  __CmdLimit;
+
+void *shell_brk(void *addr)
+{
+	if (addr == 0) {
+		return (void *)((intptr_t)&__CmdBase + 0x40000);
+	}
+	if ((addr >= (intptr_t)&__CmdBase + 0x40000) && (addr < &__CmdLimit)) {
+		return addr;
+	}
+	return (void *)-1;
+}
+
+void *shell_mmap2(void *start, size_t length, int prot, int flags, int fd, off_t pgoffset)
+{
+	if (fd != -1)
+		return -EINVAL;
+
+	if ((length >= 0) && (length <= (intptr_t)&__CmdLimit - ((intptr_t)&__CmdBase + 0x40000))) {
+		return &__CmdBase + 0x40000;
+	}
+	return (void *)-1;
+}
+
+int shell_mprotect(void *addr, size_t len, int prot)
+{
+	//if ((addr >= (intptr_t)&__CmdBase + 0x40000) && ((intptr_t)addr + len < &__CmdLimit)) {
+		return 0;
+	//}
+	//return -1;
+}
