Changes include:
-File descriptor management: all file descriptors now come from a common pool. Things like the internal sce descriptor, reference count, filename, flags and descriptor type are kept track of here. This allows for things like: pipe(), socket() and open() to return three consecutive descriptors if called in order. This behavior is required for some applications, furthemore select() is expected to poll file descriptors smaller than FD_SETSIZE which is 256, and this was impossible using the native descriptors.
It also allows some of the code to be simplified, like no more socket file desctiptor masking, or TTY's filename indicator.. etc. And also for adding pipe support, which was my main goal, as both this applications, and I'm sure more, use pipes for thread synchronization/communication.
One thing that needs to be done here is add a locking mechanism to the "get new desciptor" call, to make it thread safe. ATM, is as safe as malloc(), I guess.
-Pipe support: the pipe(..) function, and read/write.
-fcntl support: the function is now implemented, and allows to set and get file descriptor flags. Implementation is not 100% complete. But socket's can be set to non-blocking mode via a fcntl call now. Also, file descriptors can be duplicated (with ref-counting so the real close is only called on the last fd's close). -- Now dup
-socket code simplified a bit thanks to the descriptor management. select() implementation removed, as it only worked with sockets.
-new select() implementation: this implementation is far from perfect, as it manually polls file descriptors internally. Timeout setting is accurate to the millisecond. And it supports pipes and sockets. Support for files is yet to be completed (not sure how to implement it yet).
It works fine for me right now. Compiled against PSPRadio, retawq and links. But I kindly ask for your review before I commit to subversion.
svn diff patch follows for your review:
Code: Select all
Index: libc/sys/psp/pspcwd.c
===================================================================
--- libc/sys/psp/pspcwd.c	(revision 1866)
+++ libc/sys/psp/pspcwd.c	(working copy)
@@ -19,7 +19,6 @@
 #include <pspiofilemgr.h>
 
 char __psp_cwd[MAXPATHLEN + 1] = { 0 };
-char * __psp_filename_map[1024];
 
 /* Set the current working directory (CWD) to the path where the module was launched. */
 void __psp_init_cwd(char *argv_0)
Index: libc/sys/psp/Makefile.in
===================================================================
--- libc/sys/psp/Makefile.in	(revision 1866)
+++ libc/sys/psp/Makefile.in	(working copy)
@@ -92,19 +92,26 @@
 
 noinst_LIBRARIES = lib.a
 
-LIBCGLUE_MULT_OBJS = _close.o _exit.o _fork.o _fstat.o _getpid.o	                     _gettimeofday.o _kill.o _lseek.o _open.o _read.o	                     _sbrk.o _wait.o _write.o clock.o isatty.o time.o	                     _link.o _unlink.o sleep.o opendir.o readdir.o	                     closedir.o getcwd.o chdir.o mkdir.o rmdir.o	                     realpath.o _stat.o truncate.o access.o tzset.o	                     __psp_set_errno.o mlock.o
+LIBCGLUE_MULT_OBJS = _close.o _exit.o _fork.o _fstat.o _getpid.o	                     _gettimeofday.o _kill.o _lseek.o _open.o _read.o	                     _sbrk.o _wait.o _write.o clock.o isatty.o time.o	                     _link.o _unlink.o sleep.o opendir.o readdir.o	                     closedir.o getcwd.o chdir.o mkdir.o rmdir.o	                     realpath.o _stat.o truncate.o access.o tzset.o	                     __psp_set_errno.o mlock.o _fcntl.o
 
 
-SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o 				   listen.o recv.o recvfrom.o send.o sendto.o 				   setsockopt.o shutdown.o __psp_socket_map.o 				   getsockname.o getpeername.o select.o inet_ntoa.o
+SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o 				   listen.o recv.o recvfrom.o send.o sendto.o 				   setsockopt.o shutdown.o getsockname.o getpeername.o 				   inet_ntoa.o
 
 
+PIPE_OBJS = pipe.o 
+
+FDMAN_OBJS = fdman.o
+
+SELECT_OBJS = select.o
+
 XPRINTF_MULT_OBJS = vxprintf.o _xprintf.o __sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o _sprintf_r.o
 
 NETDB_MULT_OBJS = h_errno.o gethostbyaddr.o gethostbyname.o
 
-lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c
-lib_a_LIBADD = $(LIBCGLUE_MULT_OBJS) $(SOCKET_MULT_OBJS) $(XPRINTF_MULT_OBJS) $(NETDB_MULT_OBJS)
+lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c pipe.c fdman.c select.c
+lib_a_LIBADD = $(LIBCGLUE_MULT_OBJS) $(SOCKET_MULT_OBJS) $(XPRINTF_MULT_OBJS) 				$(NETDB_MULT_OBJS) $(PIPE_OBJS) $(FDMAN_OBJS) $(SELECT_OBJS)
 
+
 ACLOCAL_AMFLAGS = -I ../../..
 CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -120,15 +127,16 @@
 _gettimeofday.o _kill.o _lseek.o _open.o _read.o _sbrk.o _wait.o \
 _write.o clock.o isatty.o time.o _link.o _unlink.o sleep.o opendir.o \
 readdir.o closedir.o getcwd.o chdir.o mkdir.o rmdir.o realpath.o \
-_stat.o truncate.o access.o tzset.o __psp_set_errno.o mlock.o socket.o \
-accept.o bind.o connect.o getsockopt.o listen.o recv.o recvfrom.o \
-send.o sendto.o setsockopt.o shutdown.o __psp_socket_map.o \
-getsockname.o getpeername.o select.o inet_ntoa.o vxprintf.o _xprintf.o \
-__sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o \
-vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o \
-printf.o vprintf.o _sprintf_r.o h_errno.o gethostbyaddr.o \
-gethostbyname.o
-lib_a_OBJECTS =  libcglue.o socket.o pspcwd.o xprintf.o netdb.o
+_stat.o truncate.o access.o tzset.o __psp_set_errno.o mlock.o _fcntl.o \
+socket.o accept.o bind.o connect.o getsockopt.o listen.o recv.o \
+recvfrom.o send.o sendto.o setsockopt.o shutdown.o getsockname.o \
+getpeername.o inet_ntoa.o vxprintf.o _xprintf.o __sout.o vsnprintf.o \
+snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o \
+asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o \
+_sprintf_r.o h_errno.o gethostbyaddr.o gethostbyname.o pipe.o fdman.o \
+select.o
+lib_a_OBJECTS =  libcglue.o socket.o pspcwd.o xprintf.o netdb.o pipe.o \
+fdman.o select.o
 CFLAGS = @CFLAGS@
 COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 CCLD = $(CC)
@@ -215,7 +223,7 @@
 	  awk '    { files[$$0] = 1; } \
 	       END { for (i in files) print i; }'`; \
 	test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
-	  || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags  $$unique $(LISP))
+	  || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags  $$unique $(LISP) -o $$here/TAGS)
 
 mostlyclean-tags:
 
@@ -362,6 +370,15 @@
 $(NETDB_MULT_OBJS): netdb.c
 	$(COMPILE) -DF_$* $< -c -o $@
 
+$(PIPE_OBJS): pipe.c
+	$(COMPILE) -DF_$* $< -c -o $@
+
+$(FDMAN_OBJS): fdman.c
+	$(COMPILE) -DF_$* $< -c -o $@
+
+$(SELECT_OBJS): select.c
+	$(COMPILE) -DF_$* $< -c -o $@
+
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
 .NOEXPORT:
Index: libc/sys/psp/select.c
===================================================================
--- libc/sys/psp/select.c	(revision 0)
+++ libc/sys/psp/select.c	(revision 0)
@@ -0,0 +1,172 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * pipe.c - Socket wrappers to provide similar functions to normal unix
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ * 
+ */
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/select.h>
+#include <psptypes.h>
+#include <pspthreadman.h>
+
+#include "fdman.h"
+
+#define SELECT_POLLING_DELAY_IN_us	100
+
+static int __psp_poll_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds);
+
+int	select(int n, fd_set *readfds, fd_set *writefds,
+		   fd_set *exceptfds, struct timeval *timeout)
+{
+	int count;
+	clock_t start_time, time;
+	
+	start_time = clock();
+
+	count = 0;
+	
+	if (timeout) {
+		time = (timeout->tv_sec * CLOCKS_PER_SEC) + (timeout->tv_usec * (1*1000*1000/CLOCKS_PER_SEC));
+	} 
+	else {
+		time = 0; 
+	}
+	
+	for (;;) {
+		count = __psp_poll_select(n, readfds, writefds, exceptfds);
+		/* If timeout == NULL, then don't timeout! */
+		if ( (count > 0) || ((timeout != NULL) && ((clock() - start_time) >= time)) ) {
+			break;
+		}
+		else {
+			/* Nothing found, and not timed-out yet; let's yield for SELECT_POLLING_DELAY_IN_us, so we're not in a busy loop */
+			sceKernelDelayThread(SELECT_POLLING_DELAY_IN_us);
+		} 
+	}
+	
+	return count;
+}
+
+#define SCE_FD_SET(n, p) \
+	((p)->fds_bits[((n) & 0xFF) /__NFDBITS] |= (1 << ((n) % __NFDBITS)))
+
+static int __psp_poll_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds)
+{
+	int fd, count;
+	fd_set ready_readfds, ready_writefds, ready_exceptfds;
+	fd_set scereadfds, scewritefds, sceexceptfds;
+	SceKernelMppInfo info;
+	struct timeval scetv;
+
+	FD_ZERO(&ready_readfds);
+	FD_ZERO(&ready_writefds);
+	FD_ZERO(&ready_exceptfds);
+
+	info.size = sizeof(info);
+	scetv.tv_sec = 0;
+	scetv.tv_usec = 0;
+	count = 0;
+
+	for (fd = 0; fd < n; fd++)
+	{
+		if (__psp_descriptormap[fd] != NULL) {
+			switch(__psp_descriptormap[fd]->type)
+			{
+				case __PSP_DESCRIPTOR_TYPE_PIPE:
+					if (readfds && FD_ISSET(fd, readfds)) {
+						if (sceKernelReferMsgPipeStatus(__psp_descriptormap[fd]->sce_descriptor, &info) == 0) {
+							if (info.bufSize != info.freeSize) {
+								FD_SET(fd, &ready_readfds);
+								count++;
+							}
+						}
+						else {
+							FD_SET(fd, &ready_exceptfds);
+							count++;
+						}
+					}
+					if (writefds && FD_ISSET(fd, writefds)) {
+						if (sceKernelReferMsgPipeStatus(__psp_descriptormap[fd]->sce_descriptor, &info) == 0) {
+							if (info.freeSize > 0) {
+								FD_SET(fd, &ready_writefds);
+								count++;
+							}
+						}
+						else {
+							FD_SET(fd, &ready_exceptfds);
+							count++;
+						}
+					}
+					break;
+				case __PSP_DESCRIPTOR_TYPE_FILE:
+					if (readfds && FD_ISSET(fd, readfds)) {
+						if (readfds && FD_ISSET(fd, readfds)) {
+							/** Just set it for now */
+							FD_SET(fd, &ready_readfds);
+							count++;
+						}
+					} 
+					break;
+				case __PSP_DESCRIPTOR_TYPE_SOCKET:
+					if (readfds && FD_ISSET(fd, readfds)) {
+						int sce_ret, sce_fd;
+						sce_fd = __psp_descriptormap[fd]->sce_descriptor;
+						FD_ZERO(&scereadfds);
+						SCE_FD_SET(sce_fd, &scereadfds);
+						errno = 0;
+						sce_ret = sceNetInetSelect (sce_fd+1, &scereadfds, NULL, NULL, &scetv);
+						if (sce_ret>0) {
+							FD_SET(fd, &ready_readfds);
+							count++;
+						}
+						else if (sce_ret == -1) {
+							errno = sceNetInetGetErrno();
+							if (exceptfds && FD_ISSET(fd, exceptfds)) {
+								FD_SET(fd, &ready_exceptfds);
+								count++;
+							} else {
+								count = -1;
+							}
+						}
+					}
+					if (writefds && FD_ISSET(fd, writefds)) {
+						int sce_ret;
+						FD_ZERO(&scewritefds);
+						SCE_FD_SET(__psp_descriptormap[fd]->sce_descriptor, &scewritefds);
+						sce_ret = sceNetInetSelect (__psp_descriptormap[fd]->sce_descriptor+1, NULL, &scewritefds, NULL, &scetv);
+						if (sce_ret>0) {
+							FD_SET(fd, &ready_writefds);
+							count++;
+						}
+						else if (sce_ret == -1) {
+							if (exceptfds && FD_ISSET(fd, exceptfds)) {
+								FD_SET(fd, &ready_exceptfds);
+								count++;
+							} 
+							else {
+								count = -1;
+							}
+						}
+					}
+					break;
+			}
+		}
+	}
+
+	if (count > 0) {
+		if (readfds)
+			*readfds   = ready_readfds;
+		if (writefds)
+			*writefds  = ready_writefds;
+		if (exceptfds)
+			*exceptfds = ready_exceptfds;
+	}
+
+	return count;
+}
+
Property changes on: libc/sys/psp/select.c
___________________________________________________________________
Name: svn:eol-style
   + native
Index: libc/sys/psp/fdman.c
===================================================================
--- libc/sys/psp/fdman.c	(revision 0)
+++ libc/sys/psp/fdman.c	(revision 0)
@@ -0,0 +1,103 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * fdman.c - File descriptor management.
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ */
+ 
+#include <psptypes.h>
+#include <errno.h>
+#include "fdman.h"
+
+static __psp_descriptormap_type  __psp_descriptor_data_pool[__PSP_FILENO_MAX];
+__psp_descriptormap_type        *__psp_descriptormap       [__PSP_FILENO_MAX];
+
+void __psp_fdman_init()
+{
+	int scefd;
+
+	/* Initialize descriptor data*/
+	memset(__psp_descriptor_data_pool, 0, sizeof(__psp_descriptormap_type) *__PSP_FILENO_MAX);
+	/* Initialize descriptor map*/
+	memset(__psp_descriptormap,        0, sizeof(__psp_descriptormap_type*)*__PSP_FILENO_MAX);
+
+	scefd = sceKernelStdin();
+	if ((scefd >= 0) && (scefd < __PSP_FILENO_MAX)) {
+		__psp_descriptormap[0] = &__psp_descriptor_data_pool[0];
+		__psp_descriptormap[0]->sce_descriptor = scefd;
+		__psp_descriptormap[0]->type = __PSP_DESCRIPTOR_TYPE_TTY;
+	}
+	scefd = sceKernelStdout();
+	if ((scefd >= 0) && (scefd < __PSP_FILENO_MAX)) {
+		__psp_descriptormap[1] = &__psp_descriptor_data_pool[1];
+		__psp_descriptormap[1]->sce_descriptor = scefd;
+		__psp_descriptormap[1]->type = __PSP_DESCRIPTOR_TYPE_TTY;
+	}
+	scefd = sceKernelStderr();
+	if ((scefd >= 0) && (scefd < __PSP_FILENO_MAX)) {
+		__psp_descriptormap[2] = &__psp_descriptor_data_pool[2];
+		__psp_descriptormap[2]->sce_descriptor = scefd;
+		__psp_descriptormap[2]->type = __PSP_DESCRIPTOR_TYPE_TTY;
+	}
+}
+
+int __psp_fdman_get_new_descriptor()
+{
+	int i = 0;
+//lock here
+	for (i = 0; i < __PSP_FILENO_MAX; i++) {
+		if (__psp_descriptormap[i] == NULL) {
+			__psp_descriptormap[i] = &__psp_descriptor_data_pool[i];
+			__psp_descriptormap[i]->ref_count++;
+			return i;
+		}
+	}
+//unlock here
+	
+	errno = ENOMEM;
+	return -1;
+}
+
+int __psp_fdman_get_dup_descriptor(int fd)
+{
+	int i = 0;
+	
+	if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
+		errno = EBADF;
+		return -1;
+	}
+
+	//lock here
+	for (i = 0; i < __PSP_FILENO_MAX; i++) {
+		if (__psp_descriptormap[i] == NULL) {
+			__psp_descriptormap[i] = &__psp_descriptor_data_pool[fd];
+			__psp_descriptormap[i]->ref_count++;
+			return i;
+		}
+	}
+	//unlock here
+	
+	errno = ENOMEM;
+	return -1;
+}
+
+void __psp_fdman_release_descriptor(int fd)
+{
+	__psp_descriptormap[fd]->ref_count--;
+	
+	if (__psp_descriptormap[fd]->ref_count == 0) {
+		
+		if (__psp_descriptormap[fd]->filename != NULL) {
+			free(__psp_descriptormap[fd]->filename);
+		}
+		__psp_descriptormap[fd]->filename       = NULL;
+		__psp_descriptormap[fd]->sce_descriptor = 0;
+		__psp_descriptormap[fd]->type           = 0;//__PSP_DESCRIPTOR_TYPE_NA;
+		__psp_descriptormap[fd]->flags          = 0;
+		
+	}
+	__psp_descriptormap[fd] = NULL;
+}
Property changes on: libc/sys/psp/fdman.c
___________________________________________________________________
Name: svn:eol-style
   + native
Index: libc/sys/psp/libcglue.c
===================================================================
--- libc/sys/psp/libcglue.c	(revision 1866)
+++ libc/sys/psp/libcglue.c	(working copy)
@@ -35,6 +35,7 @@
 #include <psputility.h>
 #include <pspstdio.h>
 #include <pspintrman.h>
+#include "fdman.h"
 
 extern char __psp_cwd[MAXPATHLEN + 1];
 extern void __psp_init_cwd(char *argv_0);
@@ -47,8 +48,12 @@
 extern ssize_t __psp_socket_recv(int s, void *buf, size_t len, int flags) __attribute__((weak));
 extern ssize_t __psp_socket_send(int s, const void *buf, size_t len, int flags) __attribute__((weak));
 
-#define __PSP_FILENO_MAX 1024
-extern char * __psp_filename_map[__PSP_FILENO_MAX];
+extern int pipe(int fildes[2]);
+extern int __psp_pipe_close(int filedes);
+extern int __psp_pipe_nonblocking_read(int fd, void *buf, size_t len);
+extern int __psp_pipe_read(int fd, void *buf, size_t len);
+extern int __psp_pipe_write(int fd, const void *buf, size_t size);
+extern int __psp_pipe_nonblocking_write(int fd, const void *buf, size_t len);
 
 int __psp_set_errno(int code);
 
@@ -158,7 +163,7 @@
 #ifdef F__open
 int _open(const char *name, int flags, int mode)
 {
-	int fd;
+	int scefd, fd;
 	int sce_flags;
 	char dest[MAXPATHLEN + 1];
 
@@ -188,79 +193,166 @@
 		sce_flags |= PSP_O_NBLOCK;
 	}
 	
-	fd = sceIoOpen(dest, sce_flags, mode);
-	if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
-		__psp_filename_map[fd] = strdup(dest);
+	scefd = sceIoOpen(dest, sce_flags, mode);
+	if (scefd >= 0) {
+		fd = __psp_fdman_get_new_descriptor();
+		if (fd != -1) {
+			__psp_descriptormap[fd]->sce_descriptor = scefd;
+			__psp_descriptormap[fd]->type     		= __PSP_DESCRIPTOR_TYPE_FILE;
+			__psp_descriptormap[fd]->flags    		= flags;
+			__psp_descriptormap[fd]->filename 		= strdup(dest);
+			return fd;
+		}
+		else {
+			sceIoClose(scefd);
+			errno = ENOMEM;
+			return -1;
+		}
+	} 
+	else {
+		return __psp_set_errno(scefd);
 	}
-	return __psp_set_errno(fd);
+	
 }
 #endif
 
 #ifdef F__close
 int _close(int fd)
 {
-	if (fd < 0) {
+	int ret = 0;
+
+	if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
 		errno = EBADF;
 		return -1;
 	}
 
-	if (SOCKET_IS_VALID(fd) && __psp_socket_close != NULL) {
-		return __psp_socket_close(fd);
+	switch(__psp_descriptormap[fd]->type)
+	{
+		case __PSP_DESCRIPTOR_TYPE_FILE:
+		case __PSP_DESCRIPTOR_TYPE_TTY:
+			if (__psp_descriptormap[fd]->ref_count == 1) {
+				ret = __psp_set_errno(sceIoClose(__psp_descriptormap[fd]->sce_descriptor));
+			}
+			__psp_fdman_release_descriptor(fd);
+			return ret;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE:
+			return __psp_pipe_close(fd);
+			break;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET:
+			if (__psp_socket_close != NULL) {
+				ret = __psp_socket_close(fd);
+				return ret;
+			}
+			break;
+		default:
+			break;
 	}
 
-	if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
-		if (__psp_filename_map[fd] != NULL) {
-			free(__psp_filename_map[fd]);
-			__psp_filename_map[fd] = NULL;
-		}
-	}
-
-	return __psp_set_errno(sceIoClose(fd));
+	errno = EBADF;
+	return -1;
 }
 #endif
 
 #ifdef F__read
 int _read(int fd, void *buf, size_t size)
 {
-	if (fd < 0) {
+	if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
 		errno = EBADF;
 		return -1;
 	}
 
-	if (SOCKET_IS_VALID(fd) && __psp_socket_recv != NULL) {
-		return __psp_socket_recv(fd, buf, size, 0);
+	switch(__psp_descriptormap[fd]->type)
+	{
+		case __PSP_DESCRIPTOR_TYPE_FILE:
+		case __PSP_DESCRIPTOR_TYPE_TTY:
+			return __psp_set_errno(sceIoRead(__psp_descriptormap[fd]->sce_descriptor, buf, size));
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE:
+			if (__psp_descriptormap[fd]->flags & O_NONBLOCK) {
+				return __psp_pipe_nonblocking_read(fd, buf, size);
+			}
+			else {
+				return __psp_pipe_read(fd, buf, size);
+			}
+			break;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET:
+			if (__psp_socket_recv != NULL) {
+				return __psp_socket_recv(fd, buf, size, 0);
+			}
+			break;
+		default:
+			break;
 	}
 
-	return __psp_set_errno(sceIoRead(fd, buf, size));
+	errno = EBADF;
+	return -1;
+
 }
 #endif
 
 #ifdef F__write
 int _write(int fd, const void *buf, size_t size)
 {
-	if (fd < 0) {
+	if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
 		errno = EBADF;
 		return -1;
 	}
 
-	if (SOCKET_IS_VALID(fd) && __psp_socket_send != NULL) {
-		return __psp_socket_send(fd, buf, size, 0);
+	switch(__psp_descriptormap[fd]->type)
+	{
+		case __PSP_DESCRIPTOR_TYPE_FILE:
+		case __PSP_DESCRIPTOR_TYPE_TTY:
+			return __psp_set_errno(sceIoWrite(__psp_descriptormap[fd]->sce_descriptor, buf, size));
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE:
+			if (__psp_descriptormap[fd]->flags & O_NONBLOCK) {
+				return __psp_pipe_nonblocking_write(fd, buf, size);
+			}
+			else {
+				return __psp_pipe_write(fd, buf, size);
+			}
+			break;
+			break;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET:
+			if (__psp_socket_send != NULL) {
+				return __psp_socket_send(fd, buf, size, 0);
+			}
+			break;
+		default:
+			break;
 	}
 
-	return __psp_set_errno(sceIoWrite(fd, buf, size));
+	errno = EBADF;
+	return -1;
 }
 #endif
 
 #ifdef F__lseek
 off_t _lseek(int fd, off_t offset, int whence)
 {
-	if (fd < 0) {
+	if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
 		errno = EBADF;
 		return -1;
 	}
 
-	/* We don't have to do anything with the whence argument because SEEK_* == PSP_SEEK_*. */
-	return (off_t) __psp_set_errno(sceIoLseek(fd, offset, whence));
+	switch(__psp_descriptormap[fd]->type)
+	{
+		case __PSP_DESCRIPTOR_TYPE_FILE:
+			/* We don't have to do anything with the whence argument because SEEK_* == PSP_SEEK_*. */
+			return (off_t) __psp_set_errno(sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, offset, whence));
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE:
+			break;
+		case __PSP_DESCRIPTOR_TYPE_SOCKET:
+			break;
+		default:
+			break;
+	}
+
+	errno = EBADF;
+	return -1;
+
 }
 #endif
 
@@ -466,26 +558,37 @@
 {
 	int ret;
 	SceOff oldpos;
-	if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
-		if (__psp_filename_map[fd] != NULL) {
-			if (strcmp(__psp_filename_map[fd], "  __PSP_STDIO") == 0) {
-				memset(sbuf, '\0', sizeof(struct stat));
-				sbuf->st_mode = S_IFCHR;
-				return 0;
-			} else {
-				ret = stat(__psp_filename_map[fd], sbuf);
+	if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
+		errno = EBADF;
+		return -1;
+	}
+
+	switch(__psp_descriptormap[fd]->type)
+	{
+		case __PSP_DESCRIPTOR_TYPE_TTY:
+			memset(sbuf, '\0', sizeof(struct stat));
+			sbuf->st_mode = S_IFCHR;
+			return 0;
+			break;		
+		case __PSP_DESCRIPTOR_TYPE_FILE:
+			if (__psp_descriptormap[fd]->filename != NULL) {
+				ret = stat(__psp_descriptormap[fd]->filename, sbuf);
 				
 				/* Find true size of the open file */
-				oldpos = sceIoLseek(fd, 0, SEEK_CUR);
+				oldpos = sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, 0, SEEK_CUR);
 				if (oldpos != (off_t) -1) {
-					sbuf->st_size = (off_t) sceIoLseek(fd, 0, SEEK_END);
-					sceIoLseek(fd, oldpos, SEEK_SET);
+					sbuf->st_size = (off_t) sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, 0, SEEK_END);
+					sceIoLseek(__psp_descriptormap[fd]->sce_descriptor, oldpos, SEEK_SET);
 				}
-
 				return ret;
 			}
-		}
+			break;
+		case __PSP_DESCRIPTOR_TYPE_PIPE:
+		case __PSP_DESCRIPTOR_TYPE_SOCKET:
+		default:
+			break;
 	}
+
 	errno = EBADF;
 	return -1;
 }
@@ -494,16 +597,17 @@
 #ifdef F_isatty
 int isatty(int fd)
 {
-	if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
-		if (__psp_filename_map[fd] != NULL) {
-			if (strcmp(__psp_filename_map[fd], "  __PSP_STDIO") == 0) {
-				return 1;
-			} else {
-				return 0;
-			}
-		}
+	if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
+		errno = EBADF;
+		return 0;
 	}
-	return 0;
+
+	if (__psp_descriptormap[fd]->type == __PSP_DESCRIPTOR_TYPE_TTY) {
+		return 1;
+	}
+	else {
+		return 0;
+	}
 }
 #endif
 
@@ -627,6 +731,68 @@
 }
 #endif
 
+#ifdef F__fcntl
+int _fcntl(int fd, int cmd, ...)
+{
+	if (fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd] == NULL) {
+		errno = EBADF;
+		return -1;
+	}
+
+	switch (cmd)
+	{
+		case F_DUPFD:
+		{
+			return __psp_fdman_get_dup_descriptor(fd);
+			break;
+		}
+		case F_GETFL:
+		{
+			return __psp_descriptormap[fd]->flags;
+			break;
+		}
+		case F_SETFL:
+		{
+			int newfl;
+			va_list args;
+	
+			va_start (args, cmd);         /* Initialize the argument list. */
+			newfl =  va_arg(args, int);
+			va_end (args);                /* Clean up. */
+
+			__psp_descriptormap[fd]->flags = newfl;
+
+			switch(__psp_descriptormap[fd]->type)
+			{
+				case __PSP_DESCRIPTOR_TYPE_FILE:
+					break;
+				case __PSP_DESCRIPTOR_TYPE_PIPE:
+					break;
+				case __PSP_DESCRIPTOR_TYPE_SOCKET:
+					if (newfl & O_NONBLOCK)
+					{
+						int one = 1;
+						return setsockopt(fd, SOL_SOCKET, SO_NONBLOCK, (char *)&one, sizeof(one));
+					}
+					else
+					{
+						int zero = 0;
+						return setsockopt(fd, SOL_SOCKET, SO_NONBLOCK, (char *)&zero, sizeof(zero));
+					}
+					break;
+				default:
+					break;
+			}
+			return 0;
+			break;
+		}
+	}
+
+	errno = EBADF;
+	return -1;
+}
+#endif /* F__fcntl */
+
 #ifdef F_tzset
 void tzset(void)
 {
@@ -717,27 +883,13 @@
 */
 void __psp_libc_init(int argc, char *argv[])
 {
-	int fd;
 	(void) argc;
 
 	/* Initialize cwd from this program's path */
 	__psp_init_cwd(argv[0]);
 
-	/* Initialize filenamap */
-	memset(__psp_filename_map, '\0', sizeof(char *) * __PSP_FILENO_MAX);
-
-	fd = sceKernelStdin();
-	if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
-		 __psp_filename_map[fd] = strdup("  __PSP_STDIO");
-	}
-	fd = sceKernelStdout();
-	if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
-		 __psp_filename_map[fd] = strdup("  __PSP_STDIO");
-	}
-	fd = sceKernelStderr();
-	if ((fd >= 0) && (fd < __PSP_FILENO_MAX)) {
-		 __psp_filename_map[fd] = strdup("  __PSP_STDIO");
-	}
+	/* Initialize filedescriptor management */
+	__psp_fdman_init();
 }
 
 #endif /* F__exit */
Index: libc/sys/psp/socket.c
===================================================================
--- libc/sys/psp/socket.c	(revision 1866)
+++ libc/sys/psp/socket.c	(working copy)
@@ -9,6 +9,7 @@
  * Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
  * 
  */
+#include <fcntl.h>
 #include <errno.h>
 #include <sys/socket.h>
 #include <sys/select.h>
@@ -16,57 +17,48 @@
 #include <arpa/inet.h>
 
 #include <psptypes.h>
+#include "fdman.h"
 
-#define __PSP_SOCKET_MAX 1024
-extern char __psp_socket_map[__PSP_SOCKET_MAX];
-
-#ifdef F___psp_socket_map
-char __psp_socket_map[__PSP_SOCKET_MAX];
-#endif
-
 #ifdef F_socket
 int	socket(int domain, int type, int protocol)
 {
-	int sock;
+	int sock, scesock;
 	int i;
 
-	sock = sceNetInetSocket(domain, type, protocol);
-	if(sock < 0)
-	{
+	scesock = sceNetInetSocket(domain, type, protocol);
+	if(scesock < 0)	{
 		errno = sceNetInetGetErrno();
 		return -1;
 	}
 
-	if((sock >= 0) && (sock < __PSP_SOCKET_MAX))
-	{
-		__psp_socket_map[sock] = 1;
+	sock = __psp_fdman_get_new_descriptor();
+	if( sock != -1 )	{
+		__psp_descriptormap[sock]->sce_descriptor = scesock;
+		__psp_descriptormap[sock]->type = __PSP_DESCRIPTOR_TYPE_SOCKET;
 	}
-	else
-	{
-		sceNetInetClose(sock);
+	else {
+		sceNetInetClose(scesock);
 		errno = ENOENT;
 		return -1;
 	}
 
-	return sock | SOCKET_FD_PAT;
+	return sock;
 }
 
 /* These are glue routines that are called from _close(), _read(), and
    _write().  They are here so that any program that uses socket() will pull
    them in and have expanded socket capability. */
 
-int __psp_socket_close(int s)
+int __psp_socket_close(int sock)
 {
-	int ret;
-	int sock;
+	int ret = 0;
 
-	sock = SOCKET_GET_SOCK(s);
-	if((sock > 0) && (sock < __PSP_SOCKET_MAX))
-	{
-		__psp_socket_map[sock] = 0;
+	if (__psp_descriptormap[sock]->ref_count == 1) {
+		ret = sceNetInetClose(__psp_descriptormap[sock]->sce_descriptor);
 	}
 
-	ret = sceNetInetClose(sock);
+	__psp_fdman_release_descriptor(sock);
+
 	if(ret < 0)
 	{
 		/* If close is defined likely errno is */
@@ -91,36 +83,32 @@
 #ifdef F_accept
 int	accept(int s, struct sockaddr *addr, socklen_t *addrlen)
 {
-	int sock;
-	int new;
+	int newscesock, newsock;
 
-	if(!(SOCKET_IS_VALID(s)))
-	{
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET) {
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
+	newscesock = sceNetInetAccept(__psp_descriptormap[s]->sce_descriptor, addr, addrlen);
+	if( (newscesock >= 0) ) {
+		newsock = __psp_fdman_get_new_descriptor();
+		if ( newsock != -1 ) {
+			__psp_descriptormap[newsock]->sce_descriptor = newscesock;
+			__psp_descriptormap[newsock]->type = __PSP_DESCRIPTOR_TYPE_SOCKET;
+		}
+		else {
+			sceNetInetClose(newscesock);
+			errno = ENOENT;
+			return -1;
+		}
 	}
-
-	new = sceNetInetAccept(sock, addr, addrlen);
-	if((new >= 0) && (new < __PSP_SOCKET_MAX))
-	{
-		__psp_socket_map[new] = 1;
-	}
-	else
-	{
-		sceNetInetClose(new);
+	else {
 		errno = ENOENT;
 		return -1;
 	}
 
-	return new | SOCKET_FD_PAT;
+	return newsock;
 }
 #endif
 
@@ -128,23 +116,14 @@
 int	bind(int s, const struct sockaddr *my_addr, socklen_t addrlen)
 {
 	int ret;
-	int sock;
 	
-	if(!(SOCKET_IS_VALID(s)))
+	if( __psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET )
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetBind(sock, my_addr, addrlen);
+	ret = sceNetInetBind(__psp_descriptormap[s]->sce_descriptor, my_addr, addrlen);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -158,30 +137,21 @@
 #ifdef F_connect
 int	connect(int s, const struct sockaddr *serv_addr, socklen_t addrlen)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetConnect(sock, serv_addr, addrlen);
+	ret = sceNetInetConnect(__psp_descriptormap[s]->sce_descriptor, serv_addr, addrlen);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
 		return -1;
 	}
-
+	
 	return 0;
 }
 #endif
@@ -189,30 +159,21 @@
 #ifdef F_setsockopt
 int	getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetGetsockopt(sock, level, optname, optval, optlen);
+	ret = sceNetInetGetsockopt(__psp_descriptormap[s]->sce_descriptor, level, optname, optval, optlen);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
 		return -1;
 	}
-
+	
 	return 0;
 }
 #endif
@@ -220,24 +181,15 @@
 #ifdef F_listen
 int	listen(int s, int backlog)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetListen(sock, backlog);
+	ret = sceNetInetListen(__psp_descriptormap[s]->sce_descriptor, backlog);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -251,24 +203,15 @@
 #ifdef F_recv
 ssize_t	recv(int s, void *buf, size_t len, int flags)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetRecv(sock, buf, len, flags);
+	ret = sceNetInetRecv(__psp_descriptormap[s]->sce_descriptor, buf, len, flags);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -282,24 +225,15 @@
 #ifdef F_recvfrom
 ssize_t	recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetRecvfrom(sock, buf, len, flags, from, fromlen);
+	ret = sceNetInetRecvfrom(__psp_descriptormap[s]->sce_descriptor, buf, len, flags, from, fromlen);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -313,24 +247,15 @@
 #ifdef F_send
 ssize_t	send(int s, const void *buf, size_t len, int flags)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetSend(sock, buf, len, flags);
+	ret = sceNetInetSend(__psp_descriptormap[s]->sce_descriptor, buf, len, flags);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -344,24 +269,15 @@
 #ifdef F_sendto
 ssize_t	sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetSendto(sock, buf, len, flags, to, tolen);
+	ret = sceNetInetSendto(__psp_descriptormap[s]->sce_descriptor, buf, len, flags, to, tolen);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -375,29 +291,31 @@
 #ifdef F_setsockopt
 int	setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetSetsockopt(sock, level, optname, optval, optlen);
+	ret = sceNetInetSetsockopt(__psp_descriptormap[s]->sce_descriptor, level, optname, optval, optlen);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
 		return -1;
 	}
+	else
+	{
+		if ( (level == SOL_SOCKET) && (optname == SO_NONBLOCK) ) {
+			if (*((int*)optval) == 1) {
+				__psp_descriptormap[s]->flags |= O_NONBLOCK;
+			}
+			else {
+				__psp_descriptormap[s]->flags &= ~O_NONBLOCK;
+			}	
+		}
+	}
 
 	return 0;
 }
@@ -406,24 +324,15 @@
 #ifdef F_shutdown
 int	shutdown(int s, int how)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetShutdown(sock, how);
+	ret = sceNetInetShutdown(__psp_descriptormap[s]->sce_descriptor, how);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -437,24 +346,15 @@
 #ifdef F_getpeername
 int	getpeername(int s, struct sockaddr *name, socklen_t *namelen)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetGetpeername(sock, name, namelen);
+	ret = sceNetInetGetpeername(__psp_descriptormap[s]->sce_descriptor, name, namelen);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -468,24 +368,15 @@
 #ifdef F_getsockname
 int	getsockname(int s, struct sockaddr *name, socklen_t *namelen)
 {
-	int sock;
 	int ret;
 
-	if(!(SOCKET_IS_VALID(s)))
+	if(__psp_descriptormap[s] == NULL || __psp_descriptormap[s]->type != __PSP_DESCRIPTOR_TYPE_SOCKET)
 	{
 		errno = EBADF;
 		return -1;
 	}
 
-	sock = SOCKET_GET_SOCK(s);
-
-	if(__psp_socket_map[sock] == 0)
-	{
-		errno = EBADF;
-		return -1;
-	}
-
-	ret = sceNetInetGetsockname(sock, name, namelen);
+	ret = sceNetInetGetsockname(__psp_descriptormap[s]->sce_descriptor, name, namelen);
 	if(ret < 0)
 	{
 		errno = sceNetInetGetErrno();
@@ -496,23 +387,6 @@
 }
 #endif
 
-#ifdef F_select
-int	select(int n, fd_set *readfds, fd_set *writefds,
-	    fd_set *exceptfds, struct timeval *timeout)
-{
-	int ret;
-
-	ret = sceNetInetSelect(n, readfds, writefds, exceptfds, timeout);
-	if(ret < 0)
-	{
-		errno = sceNetInetGetErrno();
-		return -1;
-	}
-
-	return ret;
-}
-#endif
-
 #ifdef F_inet_ntoa
 char *inet_ntoa(struct in_addr in)
 {
Index: libc/sys/psp/Makefile.am
===================================================================
--- libc/sys/psp/Makefile.am	(revision 1866)
+++ libc/sys/psp/Makefile.am	(working copy)
@@ -12,19 +12,26 @@
                      _link.o _unlink.o sleep.o opendir.o readdir.o	\
                      closedir.o getcwd.o chdir.o mkdir.o rmdir.o	\
                      realpath.o _stat.o truncate.o access.o tzset.o	\
-                     __psp_set_errno.o mlock.o
+                     __psp_set_errno.o mlock.o _fcntl.o
 
 SOCKET_MULT_OBJS = socket.o accept.o bind.o connect.o getsockopt.o \
 				   listen.o recv.o recvfrom.o send.o sendto.o \
-				   setsockopt.o shutdown.o __psp_socket_map.o \
-				   getsockname.o getpeername.o select.o inet_ntoa.o
+				   setsockopt.o shutdown.o getsockname.o getpeername.o \
+				   inet_ntoa.o
+				   
+PIPE_OBJS = pipe.o 
 
+FDMAN_OBJS = fdman.o
+
+SELECT_OBJS = select.o
+
 XPRINTF_MULT_OBJS = vxprintf.o _xprintf.o __sout.o vsnprintf.o snprintf.o vsprintf.o sprintf.o __mout.o mprintf.o vmprintf.o asprintf.o vasprintf.o __fout.o fprintf.o vfprintf.o printf.o vprintf.o _sprintf_r.o
 
 NETDB_MULT_OBJS = h_errno.o gethostbyaddr.o gethostbyname.o
 
-lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c
-lib_a_LIBADD  = $(LIBCGLUE_MULT_OBJS) $(SOCKET_MULT_OBJS) $(XPRINTF_MULT_OBJS) $(NETDB_MULT_OBJS)
+lib_a_SOURCES = libcglue.c socket.c pspcwd.c xprintf.c netdb.c pipe.c fdman.c select.c
+lib_a_LIBADD  = $(LIBCGLUE_MULT_OBJS) $(SOCKET_MULT_OBJS) $(XPRINTF_MULT_OBJS) \
+				$(NETDB_MULT_OBJS) $(PIPE_OBJS) $(FDMAN_OBJS) $(SELECT_OBJS)
 
 all: crt0.o
 
@@ -40,5 +47,14 @@
 $(NETDB_MULT_OBJS): netdb.c
 	$(COMPILE) -DF_$* $< -c -o $@
 
+$(PIPE_OBJS): pipe.c
+	$(COMPILE) -DF_$* $< -c -o $@
+
+$(FDMAN_OBJS): fdman.c
+	$(COMPILE) -DF_$* $< -c -o $@
+
+$(SELECT_OBJS): select.c
+	$(COMPILE) -DF_$* $< -c -o $@
+
 ACLOCAL_AMFLAGS = -I ../../..
 CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host
Index: libc/sys/psp/fdman.h
===================================================================
--- libc/sys/psp/fdman.h	(revision 0)
+++ libc/sys/psp/fdman.h	(revision 0)
@@ -0,0 +1,38 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * fdman.h - File descriptor management.
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ */
+
+#ifndef _FDMAN_H_
+	#define _FDMAN_H_
+	
+	#define __PSP_FILENO_MAX 1024
+
+	typedef enum {
+		__PSP_DESCRIPTOR_TYPE_FILE  ,
+		__PSP_DESCRIPTOR_TYPE_PIPE ,
+		__PSP_DESCRIPTOR_TYPE_SOCKET,
+		__PSP_DESCRIPTOR_TYPE_TTY
+	} __psp_fdman_fd_types;
+	
+	typedef struct {
+		char * filename;
+		u8     type;
+		u32    sce_descriptor;
+		u32    flags;
+		u32    ref_count;
+	} __psp_descriptormap_type;
+	 
+	extern __psp_descriptormap_type *__psp_descriptormap[__PSP_FILENO_MAX];
+	
+	void __psp_fdman_init();
+	int  __psp_fdman_get_new_descriptor();
+	int  __psp_fdman_get_dup_descriptor(int fd);
+	void __psp_fdman_release_descriptor(int fd);
+
+#endif
Property changes on: libc/sys/psp/fdman.h
___________________________________________________________________
Name: svn:eol-style
   + native
Index: libc/sys/psp/sys/fd_set.h
===================================================================
--- libc/sys/psp/sys/fd_set.h	(revision 1866)
+++ libc/sys/psp/sys/fd_set.h	(working copy)
@@ -56,11 +56,14 @@
 } fd_set;
 
 #define	FD_SET(n, p)	\
-    ((p)->fds_bits[((n) & 0xFF) /__NFDBITS] |= (1 << ((n) % __NFDBITS)))
+	((p)->fds_bits[(n) /__NFDBITS] |= (1 << ((n) % __NFDBITS)))
+
 #define	FD_CLR(n, p)	\
-    ((p)->fds_bits[((n) & 0xFF) /__NFDBITS] &= ~(1 << ((n) % __NFDBITS)))
+	((p)->fds_bits[(n) /__NFDBITS] &= ~(1 << ((n) % __NFDBITS)))
+
 #define	FD_ISSET(n, p)	\
-    ((p)->fds_bits[((n) & 0xFF) /__NFDBITS] & (1 << ((n) % __NFDBITS)))
+	((p)->fds_bits[(n) /__NFDBITS] & (1 << ((n) % __NFDBITS)))
+
 #define	FD_ZERO(p)	(void)__builtin_memset((p), 0, sizeof(*(p)))
 
 #endif /* _SYS_FD_SET_H_ */
Index: libc/sys/psp/sys/socket.h
===================================================================
--- libc/sys/psp/sys/socket.h	(revision 1866)
+++ libc/sys/psp/sys/socket.h	(working copy)
@@ -110,6 +110,7 @@
 #define	SO_ERROR	0x1007		/* get error status and clear */
 #define	SO_TYPE		0x1008		/* get socket type */
 #define	SO_OVERFLOWED	0x1009		/* datagrams: return packets dropped */
+#define	SO_NONBLOCK     0x1009		/* non-blocking I/O */
 
 /*
  * Structure used for manipulating linger option.
@@ -266,10 +267,6 @@
 int	shutdown(int, int);
 int	socket(int, int, int);
 
-#define SOCKET_FD_PAT      0x7F000000
-#define SOCKET_IS_VALID(x) (((x) & SOCKET_FD_PAT) == SOCKET_FD_PAT)
-#define SOCKET_GET_SOCK(x) ((x) & ~SOCKET_FD_PAT)
-
 /* sceNetInet socket API. */
 int	sceNetInetAccept(int s, struct sockaddr *addr, socklen_t *addrlen);
 int	sceNetInetBind(int s, const struct sockaddr *my_addr, socklen_t addrlen);
Index: libc/sys/psp/pipe.c
===================================================================
--- libc/sys/psp/pipe.c	(revision 0)
+++ libc/sys/psp/pipe.c	(revision 0)
@@ -0,0 +1,265 @@
+/*
+ * PSP Software Development Kit - http://www.pspdev.org
+ * -----------------------------------------------------------------------
+ * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
+ *
+ * pipe.c - Socket wrappers to provide similar functions to normal unix
+ *
+ * Copyright (c) 2006 Rafael Cabezas <rafpsp@gmail.com>
+ * 
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <sys/syslimits.h>
+#include <sys/fd_set.h>
+
+#include <psptypes.h>
+#include <pspthreadman.h>
+#include <pspmodulemgr.h>
+#include <pspkerror.h>
+#include "fdman.h"
+
+/* Pipe functions */
+/* Returns how many bytes are in the pipe -- waiting to be read */
+size_t __psp_pipe_peekmsgsize(int fd)
+{
+	SceKernelMppInfo info;
+	info.size = sizeof(info);
+	if (sceKernelReferMsgPipeStatus(__psp_descriptormap[fd]->sce_descriptor, &info) == 0) {
+		return (info.bufSize - info.freeSize);
+	}
+	else {
+		return -1;
+	}
+}
+
+int pipe(int fildes[2])
+{
+	static int iIndex = 0;
+	char name[32];
+	iIndex++;
+
+	sprintf(name, "__psp_pipe_%02d", iIndex);
+
+	SceUID uid = sceKernelCreateMsgPipe(name, PSP_MEMORY_PARTITION_USER, 0, (void *)PIPE_BUF, NULL);
+
+	if (uid >= 0) {
+		fildes[0] = __psp_fdman_get_new_descriptor();
+		if (fildes[0] != -1) {
+			__psp_descriptormap[fildes[0]]->sce_descriptor = uid;
+			__psp_descriptormap[fildes[0]]->type = __PSP_DESCRIPTOR_TYPE_PIPE;
+		} 
+		else {
+			sceKernelDeleteMsgPipe(uid);
+			errno = EFAULT;
+			return -1;
+		}
+		
+		fildes[1] = __psp_fdman_get_dup_descriptor(fildes[0]);
+		if (fildes[1] != -1) {
+			__psp_descriptormap[fildes[1]]->sce_descriptor = uid;
+			return 0;
+		} 
+		else {
+			sceKernelDeleteMsgPipe(uid);
+			errno = EFAULT;
+			return -1;
+		}
+		
+	}
+	else {
+		errno = EFAULT;
+		return -1;
+	}
+}
+
+int __psp_pipe_close(int fd)
+{
+	int ret = 0;
+
+	if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || (__psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE) ) {
+		errno = EBADF;
+		return -1;
+	}
+	
+		
+	if ( __psp_descriptormap[fd]->ref_count == 1 ) {
+			/**
+			* Delete a message pipe
+			*
+			* @param uid - The UID of the pipe
+			*
+			* @return 0 on success, < 0 on error
+			*/
+			ret = sceKernelDeleteMsgPipe(__psp_descriptormap[fd]->sce_descriptor);
+	}
+	
+	__psp_fdman_release_descriptor(fd);
+			
+	if(ret < 0) {
+		return __psp_set_errno(ret);
+	}
+	
+	return 0;
+}
+
+int __psp_pipe_nonblocking_read(int fd, void *buf, size_t len)
+{
+	int ret;
+	int sceuid;
+	int size;
+	
+	if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE ) {
+		errno = EBADF;
+		return -1;
+	}
+	
+	sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+	size = __psp_pipe_peekmsgsize(fd);
+	if (size > 0) {
+		if (size < len) {
+			len = size;
+		}
+	}
+	else {
+		errno = EBADF;
+		return -1;
+	}
+ 
+	/**
+	* Receive a message from a pipe
+	*
+	* @param uid - The UID of the pipe
+	* @param message - Pointer to the message
+	* @param size - Size of the message
+	* @param unk1 - Unknown
+	* @param unk2 - Unknown
+	* @param timeout - Timeout for receive
+	*
+	* @return 0 on success, < 0 on error
+	*/
+    ret = sceKernelTryReceiveMsgPipe(sceuid, buf, len, 0, 0);
+	
+	if (ret == 0) {/* Success - Data */
+		return len;
+	}
+	else if (ret == SCE_KERNEL_ERROR_MPP_EMPTY) {/* No data */
+		errno = EAGAIN;
+		return -1;
+	}
+	else {/* Error */
+		return __psp_set_errno(ret);
+	}
+}
+
+int __psp_pipe_read(int fd, void *buf, size_t len)
+{
+	int ret;
+	int sceuid;
+	int size;
+	
+	if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE ) {
+		errno = EBADF;
+		return -1;
+	}
+	
+	sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+	size = __psp_pipe_peekmsgsize(fd);
+	if (size > 0) {
+		if (size < len) {
+			len = size;
+		}
+	}
+	else {
+		errno = EBADF;
+		return -1;
+	}
+
+	/**
+	* Receive a message from a pipe
+	*
+	* @param uid - The UID of the pipe
+	* @param message - Pointer to the message
+	* @param size - Size of the message
+	* @param unk1 - Unknown
+	* @param unk2 - Unknown
+	* @param timeout - Timeout for receive
+	*
+	* @return 0 on success, < 0 on error
+	*/
+	ret = sceKernelReceiveMsgPipe(sceuid, buf, len, 0, NULL, NULL);
+	
+	if (ret == 0) {/* Success - Data */
+		return len;
+	}
+	else {/* Error */
+		return __psp_set_errno(ret);
+	}
+}
+
+int __psp_pipe_write(int fd, const void *buf, size_t len)
+{
+	int ret;
+	int sceuid;
+	char *cbuf;
+	
+	if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE ) {
+		errno = EBADF;
+		return -1;
+	}
+	
+	sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+	/**
+	* Send a message to a pipe
+	*
+	* @param uid - The UID of the pipe
+	* @param message - Pointer to the message
+	* @param size - Size of the message
+	* @param unk1 - Unknown
+	* @param unk2 - Unknown
+	* @param timeout - Timeout for send
+	*
+	* @return 0 on success, < 0 on error
+	*/
+	cbuf = (char *)buf;
+	ret = sceKernelSendMsgPipe(sceuid, cbuf, len, 0, NULL, NULL);
+	
+	if (ret == 0) {/* Success - Data */
+		return len;
+	}
+	else {/* Error */
+		return __psp_set_errno(ret);
+	}
+}
+
+int __psp_pipe_nonblocking_write(int fd, const void *buf, size_t len)
+{
+	int ret;
+	int sceuid;
+	char *cbuf;
+	
+	if( fd < 0 || fd > (__PSP_FILENO_MAX - 1) || __psp_descriptormap[fd]->type != __PSP_DESCRIPTOR_TYPE_PIPE ) {
+		errno = EBADF;
+		return -1;
+	}
+	
+	sceuid = __psp_descriptormap[fd]->sce_descriptor;
+
+	cbuf = (char *)buf;
+	ret = sceKernelTrySendMsgPipe(sceuid, cbuf, len, 0, 0);
+	
+	if (ret == 0) {/* Success - Data */
+		return len;
+	}
+	else if (ret == SCE_KERNEL_ERROR_MPP_FULL) {
+		errno = EAGAIN;
+		return -1;
+	}
+	else {/* Error */
+		return __psp_set_errno(ret);
+	}
+}
+
Property changes on: libc/sys/psp/pipe.c
___________________________________________________________________
Name: svn:eol-style
   + native
Index: configure.host
===================================================================
--- configure.host	(revision 1866)
+++ configure.host	(working copy)
@@ -574,7 +574,7 @@
 	  mipsallegrex*-psp-*)
 		sys_dir=psp
 		syscall_dir=syscalls
-		newlib_cflags="${newlib_cflags} -G0 -DCOMPACT_CTYPE -DCLOCK_PROVIDED -DMALLOC_ALIGNMENT=16 -I${prefix}/psp/sdk/include" ;;
+		newlib_cflags="${newlib_cflags} -G0 -mno-explicit-relocs -DCOMPACT_CTYPE -DCLOCK_PROVIDED -DHAVE_FCNTL -DMALLOC_ALIGNMENT=16 -I${prefix}/psp/sdk/include" ;;
 	  *)
 		newlib_cflags="${newlib_cflags} -DMISSING_SYSCALL_NAMES" ;;
 	esac
Raf.
PS: Edit: a bit of cleanup