Index: EcnlProtoTool/trunk/ntshell/src/fdtable.c
===================================================================
--- EcnlProtoTool/trunk/ntshell/src/fdtable.c	(revision 434)
+++ EcnlProtoTool/trunk/ntshell/src/fdtable.c	(revision 441)
@@ -43,76 +43,126 @@
 #include "syssvc/serial.h"
 #include "syssvc/syslog.h"
-#include <tinet_config.h>
-#include <netinet/in.h>
-#include <netinet/in_itron.h>
-#include <tinet_nic_defs.h>
-#include <tinet_cfg.h>
-#include <netinet/in_var.h>
-#include <net/ethernet.h>
-#include <net/if6_var.h>
-#include <net/net.h>
-#include <net/if_var.h>
-#include <netinet/udp_var.h>
-//#include <ethernet_api.h>
-#include "ff.h"
+#include "target_syssvc.h"
 #include "fdtable.h"
 #include "kernel_cfg.h"
-//#include <string.h>
-
-#define SIO_PORTID 1
-
-#define IO_TYPE_FREE	0
-#define IO_TYPE_SIO		1
-#define IO_TYPE_FILE	2
-#define IO_TYPE_DIR		3
-#define IO_TYPE_TCP		4
-#define IO_TYPE_UDP		5
-
-static struct _IO_FILE fd_table[8 * sizeof(FLGPTN)] = {
-	{ 0, IO_TYPE_SIO, 0, stdio_close, stdin_read, stdio_write, sio_seek, sio_ioctl },
-	{ 1, IO_TYPE_SIO, 0, stdio_close, stdio_read, stdout_write, sio_seek, sio_ioctl },
-	{ 2, IO_TYPE_SIO, 0, stdio_close, stdio_read, stderr_write, sio_seek, sio_ioctl },
+#include <string.h>
+#include "util/ntstdio.h"
+#include "hal/serial_api.h"
+
+#ifdef _DEBUG
+static const char THIS_FILE[] = __FILE__;
+#endif
+
+extern IO_TYPE IO_TYPE_STDIN;
+extern IO_TYPE IO_TYPE_STDOUT;
+extern IO_TYPE IO_TYPE_STDERR;
+
+static struct SHELL_FILE fd_table[8 * sizeof(FLGPTN)] = {
+	{ STDIN_FILENO, &IO_TYPE_STDIN, 0 },
+	{ STDOUT_FILENO, &IO_TYPE_STDOUT, 0 },
+	{ STDERR_FILENO, &IO_TYPE_STDERR, 0 },
 };
 #define fd_table_count (sizeof(fd_table) / sizeof(fd_table[0]))
 
-static int new_fd(int type, int id)
-{
+struct SHELL_FILE *new_fp(IO_TYPE *type, int id, int writable)
+{
+	struct SHELL_FILE *fp = NULL;
+	ER ret;
+
+	ret = wai_sem(SEM_FILEDESC);
+	if (ret < 0) {
+		syslog(LOG_ERROR, "wai_sem => %d", ret);
+	}
+
 	for (int fd = 3; fd < fd_table_count; fd++) {
-		struct _IO_FILE *fp = &fd_table[fd];
-		if (fp->type != IO_TYPE_FREE)
+		fp = &fd_table[fd];
+		if (fp->type != NULL)
 			continue;
 
+		memset(fp, 0, sizeof(struct SHELL_FILE));
 		fp->fd = fd;
 		fp->type = type;
 		fp->handle = id;
-		return fd;
-	}
-
-	return -ENOMEM;
-}
-
-static struct _IO_FILE *id_to_fd(int type, int id)
-{
+		fp->writable = writable;
+		break;
+	}
+
+	ret = sig_sem(SEM_FILEDESC);
+	if (ret < 0) {
+		syslog(LOG_ERROR, "sig_sem => %d", ret);
+	}
+
+	if (fp != NULL) {
+		FLGPTN flgptn = 0;
+
+		FD_SET(fp->fd, (fd_set *)&flgptn);
+
+		ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
+		if (ret != E_OK) {
+			syslog(LOG_ERROR, "clr_flg => %d", ret);
+		}
+	}
+
+	return fp;
+}
+
+struct SHELL_FILE *id_to_fd(IO_TYPE *type, int id)
+{
+	struct SHELL_FILE *fp = NULL;
+	ER ret;
+
+	ret = wai_sem(SEM_FILEDESC);
+	if (ret < 0) {
+		syslog(LOG_ERROR, "wai_sem => %d", ret);
+	}
+
 	for (int fd = 3; fd < fd_table_count; fd++) {
-		struct _IO_FILE *fp = &fd_table[fd];
+		fp = &fd_table[fd];
 		if ((fp->type == type) && (fp->handle == id))
-			return fp;
-	}
-
-	return NULL;
-}
-
-static int delete_fd(int type, int id)
-{
-	struct _IO_FILE *fp = id_to_fd(type, id);
+			break;
+	}
+
+	ret = sig_sem(SEM_FILEDESC);
+	if (ret < 0) {
+		syslog(LOG_ERROR, "sig_sem => %d", ret);
+	}
+
+	return fp;
+}
+
+int delete_fd_by_id(IO_TYPE *type, int id)
+{
+	struct SHELL_FILE *fp = id_to_fd(type, id);
 	if (fp == NULL)
 		return -EBADF;
 
-	memset(fp, 0, sizeof(struct _IO_FILE));
+	return delete_fp(fp);
+}
+
+int delete_fp(struct SHELL_FILE *fp)
+{
+	ER ret;
+
+	if (fp->type == NULL)
+		return 0;
+
+	fp->type->delete(fp);
+
+	ret = wai_sem(SEM_FILEDESC);
+	if (ret < 0) {
+		syslog(LOG_ERROR, "wai_sem => %d", ret);
+	}
+
+	memset(fp, 0, sizeof(struct SHELL_FILE));
+
+	ret = sig_sem(SEM_FILEDESC);
+	if (ret < 0) {
+		syslog(LOG_ERROR, "sig_sem => %d", ret);
+	}
 
 	return 0;
 }
 
-struct _IO_FILE *fd_to_fp(int fd)
+struct SHELL_FILE *fd_to_fp(int fd)
 {
 	if ((fd < 0) || (fd >= fd_table_count))
@@ -121,132 +171,13 @@
 }
 
-struct _IO_FILE *new_sio_fd(int sioid)
-{
-	int fd = new_fd(IO_TYPE_SIO, sioid);
-	if ((fd < 0) || (fd >= fd_table_count))
-		return NULL;
-
-	struct _IO_FILE *fp = &fd_table[fd];
-	fp->close = sio_close;
-	fp->read = sio_read;
-	fp->write = sio_write;
-	fp->seek = sio_seek;
-	fp->ioctl = sio_ioctl;
-
-	return fp;
-}
-
-int delete_sio_fd(int sioid)
-{
-	return delete_fd(IO_TYPE_SIO, sioid);
-}
-
-struct _IO_FILE *sioid_to_fd(int sioid)
-{
-	return id_to_fd(IO_TYPE_SIO, sioid);
-}
-
-struct _IO_FILE *new_file_fd(int fileid)
-{
-	int fd = new_fd(IO_TYPE_FILE, fileid);
-	if ((fd < 0) || (fd >= fd_table_count))
-		return NULL;
-
-	struct _IO_FILE *fp = &fd_table[fd];
-	fp->close = file_close;
-	fp->read = file_read;
-	fp->write = file_write;
-	fp->seek = file_seek;
-	fp->ioctl = file_ioctl;
-
-	return fp;
-}
-
-int delete_file_fd(int fileid)
-{
-	return delete_fd(IO_TYPE_FILE, fileid);
-}
-
-struct _IO_FILE *fileid_to_fd(int fileid)
-{
-	return id_to_fd(IO_TYPE_FILE, fileid);
-}
-
-struct _IO_FILE *new_dir_fd(int fileid)
-{
-	int fd = new_fd(IO_TYPE_DIR, fileid);
-	if ((fd < 0) || (fd >= fd_table_count))
-		return NULL;
-
-	struct _IO_FILE *fp = &fd_table[fd];
-	fp->close = dir_close;
-	fp->read = dir_read;
-	fp->write = dir_write;
-	fp->seek = dir_seek;
-	fp->ioctl = dir_ioctl;
-
-	return fp;
-}
-
-int delete_dir_fd(int dirid)
-{
-	return delete_fd(IO_TYPE_DIR, dirid);
-}
-
-struct _IO_FILE *dirid_to_fd(int dirid)
-{
-	return id_to_fd(IO_TYPE_DIR, dirid);
-}
-
-struct _IO_FILE *new_tcp_fd(int tcpid)
-{
-	int fd = new_fd(IO_TYPE_TCP, tcpid);
-	if ((fd < 0) || (fd >= fd_table_count))
-		return NULL;
-
-	struct _IO_FILE *fp = &fd_table[fd];
-	fp->close = tcp_fd_close;
-	fp->read = tcp_fd_read;
-	fp->write = tcp_fd_write;
-	fp->seek = tcp_fd_seek;
-	fp->ioctl = tcp_fd_ioctl;
-
-	return fp;
-}
-
-int delete_tcp_fd(int tcpid)
-{
-	return delete_fd(IO_TYPE_TCP, tcpid);
-}
-
-struct _IO_FILE *tcpid_to_fd(int tcpid)
-{
-	return id_to_fd(IO_TYPE_TCP, tcpid);
-}
-
-struct _IO_FILE *new_udp_fd(int udpid)
-{
-	int fd = new_fd(IO_TYPE_UDP, udpid);
-	if ((fd < 0) || (fd >= fd_table_count))
-		return NULL;
-
-	struct _IO_FILE *fp = &fd_table[fd];
-	fp->close = udp_fd_close;
-	fp->read = udp_fd_read;
-	fp->write = udp_fd_write;
-	fp->seek = udp_fd_seek;
-	fp->ioctl = udp_fd_ioctl;
-
-	return fp;
-}
-
-int delete_udp_fd(int udpid)
-{
-	return delete_fd(IO_TYPE_UDP, udpid);
-}
-
-struct _IO_FILE *udpid_to_fd(int udpid)
-{
-	return id_to_fd(IO_TYPE_UDP, udpid);
+void memand(void *dst, void *src, size_t len)
+{
+	uint8_t *d = (uint8_t *)dst;
+	uint8_t *s = (uint8_t *)src;
+	uint8_t *e = &s[len];
+
+	while (s < e) {
+		*d++ &= *s++;
+	}
 }
 
@@ -258,9 +189,9 @@
 };
 
-ER shell_get_evts(struct fd_events *evts, TMO tmout);
+ER shell_get_evts(struct fd_events *evts, TMO *tmout);
 
 #define TMO_MAX INT_MAX
 
-int shell_select(int n, fd_set *__restrict rfds, fd_set *__restrict wfds, fd_set *__restrict efds, struct timeval *__restrict tv)
+int shell_select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict efds, struct timeval *restrict tv)
 {
 	ER ret;
@@ -275,20 +206,35 @@
 	}
 
-	memcpy(&evts.readfds, rfds, sizeof(fd_set));
-	memcpy(&evts.writefds, wfds, sizeof(fd_set));
-	memcpy(&evts.errorfds, efds, sizeof(fd_set));
+	if (rfds != NULL)
+		memcpy(&evts.readfds, rfds, sizeof(fd_set));
+	else
+		memset(&evts.readfds, 0, sizeof(fd_set));
+	if (wfds != NULL)
+		memcpy(&evts.writefds, wfds, sizeof(fd_set));
+	else
+		memset(&evts.writefds, 0, sizeof(fd_set));
+	if (efds != NULL)
+		memcpy(&evts.errorfds, efds, sizeof(fd_set));
+	else
+		memset(&evts.errorfds, 0, sizeof(fd_set));
 	evts.count = 0;
 
-	ret = shell_get_evts(&evts, tmout);
+	ret = shell_get_evts(&evts, &tmout);
 	if (ret == E_OK) {
-		memcpy(rfds, &evts.readfds, sizeof(fd_set));
-		memcpy(wfds, &evts.writefds, sizeof(fd_set));
-		memcpy(efds, &evts.errorfds, sizeof(fd_set));
+		if (rfds != NULL)
+			memand(rfds, &evts.readfds, sizeof(fd_set));
+		if (wfds != NULL)
+			memand(wfds, &evts.writefds, sizeof(fd_set));
+		if (efds != NULL)
+			memand(efds, &evts.errorfds, sizeof(fd_set));
 		return evts.count;
 	}
 	if (ret == E_TMOUT) {
-		memset(rfds, 0, sizeof(fd_set));
-		memset(wfds, 0, sizeof(fd_set));
-		memset(efds, 0, sizeof(fd_set));
+		if (rfds != NULL)
+			memset(rfds, 0, sizeof(fd_set));
+		if (wfds != NULL)
+			memset(wfds, 0, sizeof(fd_set));
+		if (efds != NULL)
+			memset(efds, 0, sizeof(fd_set));
 		return 0;
 	}
@@ -310,4 +256,5 @@
 		tmout = TMO_MAX;
 
+retry:
 	memset(&evts, 0, sizeof(evts));
 
@@ -327,5 +274,5 @@
 	}
 
-	ret = shell_get_evts(&evts, tmout);
+	ret = shell_get_evts(&evts, &tmout);
 	if (ret == E_OK) {
 		int result = 0;
@@ -345,4 +292,6 @@
 				result++;
 		}
+		if (result == 0)
+			goto retry;
 		return result;
 	}
@@ -354,191 +303,121 @@
 }
 
-void stdio_update_evts()
-{
-	int fd = STDIN_FILENO;
-	struct _IO_FILE *fp = &fd_table[fd];
-	T_SERIAL_RPOR rpor;
-	FLGPTN flgptn = 0;
-
-	ER ret = serial_ref_por(SIO_PORTID, &rpor);
-	if (ret != E_OK)
-		return;
-
-	if (rpor.reacnt != 0) {
-		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
-
-		FD_SET(fd, (fd_set *)&flgptn);
-	}
-	if (rpor.wricnt != 0) {
-		if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
-
-		FD_SET(fd, (fd_set *)&flgptn);
-	}
-
-	if (flgptn != 0) {
-		set_flg(FLG_SELECT_WAIT, flgptn);
-	}
-}
-
-void stdio_flgptn(FLGPTN *flgptn)
-{
-	int fd = STDIN_FILENO;
-	struct _IO_FILE *fp = &fd_table[fd];
-	T_SERIAL_RPOR rpor;
-	*flgptn = 0;
-
-	ER ret = serial_ref_por(SIO_PORTID, &rpor);
-	if (ret != E_OK)
-		return;
-
-	if (rpor.reacnt != 0) {
-		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
-
-		FD_SET(fd, (fd_set *)flgptn);
-	}
-	if (rpor.wricnt != 0) {
-		if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
-
-		FD_SET(fd, (fd_set *)flgptn);
-	}
-}
-
-ER socket_tcp_callback(ID cepid, FN fncd, void *p_parblk)
-{
-	struct _IO_FILE *fp = tcpid_to_fd(cepid);
-	FLGPTN flgptn = 0;
-
-	if (fp == NULL)
-		return E_PAR;
-
-	int fd = fp->fd;
-	FD_SET(fd, (fd_set *)&flgptn);
-
-	switch (fncd) {
-	case TFN_TCP_RCV_DAT:
-		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
-
-		set_flg(FLG_SELECT_WAIT, flgptn);
-		return E_OK;
-
-	case TFN_TCP_SND_DAT:
-		if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
-
-		set_flg(FLG_SELECT_WAIT, flgptn);
-		return E_OK;
-
-	case TFN_TCP_CAN_CEP:
-		if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
-
-		set_flg(FLG_SELECT_WAIT, flgptn);
-		return E_OK;
-
-	case TFN_TCP_DEL_REP:
-		delete_tcp_rep(cepid);
-		return E_OK;
-
-	case TFN_TCP_DEL_CEP:
-		delete_tcp_fd(cepid);
-		return E_OK;
-
-	default:
-		return E_OK;
-	}
-}
-
-ER socket_udp_callback(ID cepid, FN fncd, void *p_parblk)
-{
-	struct _IO_FILE *fp = udpid_to_fd(cepid);
-	FLGPTN flgptn = 0;
-
-	if (fp == NULL)
-		return E_PAR;
-
-	int fd = fp->fd;
-	FD_SET(fd, (fd_set *)&flgptn);
-
-	switch (fncd) {
-	case TFN_UDP_CRE_CEP:
-	case TFN_UDP_RCV_DAT:
-		if (fp->readevt_w == fp->readevt_r) fp->readevt_w++;
-
-		set_flg(FLG_SELECT_WAIT, flgptn);
-		return E_OK;
-
-	case TFN_UDP_SND_DAT:
-		if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_w++;
-
-		set_flg(FLG_SELECT_WAIT, flgptn);
-		return E_OK;
-
-	case TFN_UDP_CAN_CEP:
-		if (fp->errorevt_w == fp->errorevt_r) fp->errorevt_w++;
-
-		set_flg(FLG_SELECT_WAIT, flgptn);
-		return E_OK;
-
-	case TFN_UDP_DEL_CEP:
-		delete_udp_fd(cepid);
-		return E_OK;
-
-	default:
-		return E_OK;
-	}
-}
-
-ER shell_get_evts(struct fd_events *evts, TMO tmout)
-{
-	ER ret;
-	FLGPTN waitptn, flgptn = 0;
-
-	stdio_update_evts();
-
-	waitptn = *((FLGPTN *)&evts->readfds) | *((FLGPTN *)&evts->writefds) | *((FLGPTN *)&evts->errorfds);
-	memset(evts, 0, sizeof(*evts));
-
-	/* イベント待ち */
-	ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, tmout);
-	if (ret != E_OK) {
-		if (ret != E_TMOUT) {
-			syslog(LOG_ERROR, "twai_flg => %d", ret);
-			return ret;
-		}
-
-		stdio_flgptn(&flgptn);
-
-		if (flgptn == 0)
+ER shell_get_evts(struct fd_events *evts, TMO *tmout)
+{
+	int count;
+	SYSTIM prev, now;
+	FLGPTN flgptn;
+
+	get_tim(&prev);
+
+	for (;;) {
+		ER ret;
+		FLGPTN waitptn, readfds = 0, writefds = 0;
+		struct SHELL_FILE *fp = NULL;
+
+#ifndef NTSHELL_NO_SOCKET
+		waitptn = *((FLGPTN *)&evts->errorfds);
+#else
+		waitptn = *((FLGPTN *)&evts->readfds) | *((FLGPTN *)&evts->errorfds);
+#endif
+		count = 0;
+		for (int fd = 0; fd < fd_table_count; fd++) {
+			fp = &fd_table[fd];
+
+			if (FD_ISSET(fd, &evts->readfds)) {
+				if (fp->type->readable(fp)) {
+					FD_SET(fd, (fd_set *)&readfds);
+					count++;
+					if (fp->readevt_w == fp->readevt_r) fp->readevt_r--;
+				}
+				else {
+					FD_SET(fd, (fd_set *)&waitptn);
+				}
+			}
+
+			if (FD_ISSET(fd, &evts->writefds)) {
+				if (fp->type->writable(fp)) {
+					FD_SET(fd, (fd_set *)&writefds);
+					count++;
+					if (fp->writeevt_w == fp->writeevt_r) fp->writeevt_r--;
+				}
+				else {
+					FD_SET(fd, (fd_set *)&waitptn);
+				}
+			}
+		}
+		memset(evts, 0, sizeof(*evts));
+
+		if (waitptn == 0) {
+			memcpy(&evts->readfds, &readfds, sizeof(evts->readfds));
+			memcpy(&evts->writefds, &writefds, sizeof(evts->writefds));
+			evts->count = count;
+			return E_OK;
+		}
+		else if ((readfds | writefds) != 0) {
+			set_flg(FLG_SELECT_WAIT, (readfds | writefds));
+		}
+
+		/* イベント待ち */
+		flgptn = 0;
+		ret = twai_flg(FLG_SELECT_WAIT, waitptn, TWF_ORW, &flgptn, *tmout);
+		if (ret != E_OK) {
+			if (ret != E_TMOUT) {
+				syslog(LOG_ERROR, "twai_flg => %d", ret);
+				return ret;
+			}
+		}
+
+		if (flgptn != 0) {
+			flgptn &= waitptn;
+
+			/* 受け取ったフラグのみクリア */
+			ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
+			if (ret != E_OK) {
+				syslog(LOG_ERROR, "clr_flg => %d", ret);
+			}
+		}
+
+		count = 0;
+		for (int fd = 0; fd < fd_table_count; fd++) {
+			fp = &fd_table[fd];
+
+			if (FD_ISSET(fd, (fd_set *)&waitptn)
+				&& (fp->readevt_w != fp->readevt_r)) {
+				fp->readevt_r++;
+				FD_SET(fd, &evts->readfds);
+				count++;
+			}
+			if (FD_ISSET(fd, (fd_set *)&waitptn)
+				&& (fp->writeevt_w != fp->writeevt_r)) {
+				fp->writeevt_r++;
+				FD_SET(fd, &evts->writefds);
+				count++;
+			}
+			if (FD_ISSET(fd, (fd_set *)&waitptn)
+				&& (fp->errorevt_w != fp->errorevt_r)) {
+				fp->errorevt_r++;
+				FD_SET(fd, &evts->errorfds);
+				count++;
+			}
+		}
+
+		if (count > 0)
+			break;
+
+		get_tim(&now);
+
+		SYSTIM elapse = now - prev;
+		if (elapse > *tmout) {
+			*tmout = 0;
+			evts->count = 0;
 			return E_TMOUT;
-	}
-	flgptn &= waitptn;
-
-	/* 受け取ったフラグのみクリア */
-	ret = clr_flg(FLG_SELECT_WAIT, ~flgptn);
-	if (ret != E_OK) {
-		syslog(LOG_ERROR, "clr_flg => %d", ret);
-	}
-
-	struct _IO_FILE *fp = NULL;
-	for (int fd = 0; fd < fd_table_count; fd++) {
-		if (!FD_ISSET(fd, (fd_set *)&flgptn))
-			continue;
-
-		fp = &fd_table[fd];
-
-		if (fp->readevt_w != fp->readevt_r) {
-			fp->readevt_r++;
-			FD_SET(fd, &evts->readfds);
-			evts->count++;
-		}
-		if (fp->writeevt_w != fp->writeevt_r) {
-			fp->writeevt_r++;
-			FD_SET(fd, &evts->writefds);
-			evts->count++;
-		}
-		if (fp->errorevt_w != fp->errorevt_r) {
-			fp->errorevt_r++;
-			FD_SET(fd, &evts->errorfds);
-			evts->count++;
-		}
-	}
+		}
+
+		prev = now;
+		*tmout -= elapse;
+	}
+
+	evts->count = count;
 
 	return E_OK;
@@ -547,5 +426,5 @@
 void clean_fd()
 {
-	struct _IO_FILE *fp = NULL;
+	struct SHELL_FILE *fp = NULL;
 	for (int fd = 3; fd < fd_table_count; fd++) {
 		fp = &fd_table[fd];
@@ -553,16 +432,164 @@
 			continue;
 
-		fp->close(fp);
-
-		memset(fp, 0, sizeof(*fp));
-	}
+		fp->type->close(fp);
+
+		delete_fp(fp);
+	}
+}
+
+int shell_close(int fd)
+{
+	struct SHELL_FILE *fp = fd_to_fp(fd);
+	if ((fp == NULL) || (fp->type == NULL))
+		return -EBADF;
+
+	int ret = fp->type->close(fp);
+
+	delete_fp(fp);
+
+	return ret;
+}
+
+ssize_t shell_read(int fd, void *data, size_t len)
+{
+	struct SHELL_FILE *fp = fd_to_fp(fd);
+	if ((fp == NULL) || (fp->type == NULL))
+		return -EBADF;
+
+	return fp->type->read(fp, (unsigned char *)data, len);
+}
+
+int shell_readv(int fd, const struct iovec *iov, int iovcnt)
+{
+	int result = 0;
+	struct SHELL_FILE *fp = fd_to_fp(fd);
+	if ((fp == NULL) || (fp->type == NULL))
+		return -EBADF;
+
+	const struct iovec *end = &iov[iovcnt];
+	for (; iov < end; iov++) {
+		result += fp->type->read(fp, (unsigned char *)iov->iov_base, iov->iov_len);
+	}
+
+	return result;
+}
+
+ssize_t shell_write(int fd, const void *data, size_t len)
+{
+	struct SHELL_FILE *fp = fd_to_fp(fd);
+	if ((fp == NULL) || (fp->type == NULL))
+		return -EBADF;
+
+	return fp->type->write(fp, (unsigned char *)data, len);
+}
+
+int shell_writev(int fd, const struct iovec *iov, int iovcnt)
+{
+	int result = 0;
+	struct SHELL_FILE *fp = fd_to_fp(fd);
+	if ((fp == NULL) || (fp->type == NULL))
+		return -EBADF;
+
+	const struct iovec *end = &iov[iovcnt];
+	for (; iov < end; iov++) {
+		result += fp->type->write(fp, (unsigned char *)iov->iov_base, iov->iov_len);
+	}
+
+	return result;
+}
+
+int shell_llseek(int fd, off_t ptr, off_t *result, int dir)
+{
+	struct SHELL_FILE *fp = fd_to_fp(fd);
+	if ((fp == NULL) || (fp->type == NULL))
+		return -EBADF;
+
+	off_t ret = fp->type->seek(fp, ptr, dir);
+	if (ret < 0)
+		return ret;
+
+	*result = ret;
+	return 0;
 }
 
 int shell_ioctl(int fd, int request, void *arg)
 {
-	struct _IO_FILE *fp = fd_to_fp(fd);
+	struct SHELL_FILE *fp = fd_to_fp(fd);
 	if (fp == NULL)
 		return -EBADF;
 
-	return fp->ioctl(fp, request, arg);
-}
+	return fp->type->ioctl(fp, request, arg);
+}
+
+#ifdef NTSHELL_NO_SOCKET
+
+int shell_socket(int family, int type, int protocol)
+{
+	return -ENOMEM;
+}
+
+int shell_bind(int fd, const struct sockaddr *addr, socklen_t len)
+{
+	return -ENOMEM;
+}
+
+int shell_listen(int fd, int backlog)
+{
+	return -ENOMEM;
+}
+
+int shell_connect(int fd, const struct sockaddr *addr, socklen_t len)
+{
+	return -ENOMEM;
+}
+
+int shell_accept(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
+{
+	return -ENOMEM;
+}
+
+ssize_t shell_sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t alen)
+{
+	return -ENOMEM;
+}
+
+ssize_t shell_sendmsg(int fd, const struct msghdr *msg, int flags)
+{
+	return -ENOMEM;
+}
+
+ssize_t shell_recvfrom(int fd, void *restrict buf, size_t len, int flags, struct sockaddr *restrict addr, socklen_t *restrict alen)
+{
+	return -ENOMEM;
+}
+
+ssize_t shell_recvmsg(int fd, struct msghdr *msg, int flags)
+{
+	return -ENOMEM;
+}
+
+int shell_shutdown(int fd, int how)
+{
+	return -ENOMEM;
+}
+
+int shell_getsockopt(int fd, int level, int optname, void *optval, socklen_t *restrict optlen)
+{
+	return -ENOMEM;
+}
+
+int shell_setsockopt(int fd, int level, int optname, const void *optval, socklen_t optlen)
+{
+	return -ENOMEM;
+}
+
+int shell_getpeername(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
+{
+	return -ENOMEM;
+}
+
+int shell_getsockname(int fd, struct sockaddr *restrict addr, socklen_t *restrict len)
+{
+	return -ENOMEM;
+}
+#endif
