endif
CPPFLAGS += -I$(ACESSDIR)/Usermode/include/ -DARCHDIR=$(ARCHDIR) -DARCHDIR_is_$(ARCHDIR)=1
CPPFLAGS += $(addprefix -I,$(wildcard $(ACESSUSERDIR)Libraries/*/include_exp/))
-CFLAGS += -Wall -g
+CFLAGS += -Wall -g -std=gnu99
LDFLAGS += -g -nostdlib -shared -eSoMain -x --no-undefined -L$(OUTPUTDIR)Libs/
# vim: ft=make
\r
OBJ = stub.o heap.o stdlib.o env.o stdio.o string.o rand.o\r
OBJ += perror.o scanf.o signals.o strtoi.o strtof.o\r
-OBJ += printf.o time.o\r
+OBJ += printf.o time.o errno.o\r
OBJ += arch/$(ARCHDIR).ao\r
# signals.o\r
DEPFILES := $(OBJ:%.o=%.d)\r
--- /dev/null
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * errno.c
+ * - errno and strerror
+ */
+#include "lib.h"
+#include <errno.h>
+#include <acess/sys.h>
+
+EXPORT int *libc_geterrno()
+{
+ return &_errno;
+}
+
+EXPORT const char *strerror(int errnum)
+{
+ switch(errnum)
+ {
+ case ENOSYS: return "Invalid instruction/syscall";
+ case ENOENT: return "No such file or directory";
+ case EINVAL: return "Bad arguments";
+ case EPERM: return "Permissions error";
+ default:
+ _SysDebug("strerror: errnum=%i unk", errnum);
+ return "unknown error";
+ }
+}
+
EBUSY, // Resource is busy
ERANGE, // Value out of range
ENOTFOUND, // Item not found
- EREADONLY, // Read only
+ EREADONLY, // Read only (duplicate with EROFS?)
ENOTIMPL, // Not implemented
ENOENT, // No entry?
EEXIST, // Already exists
ENOTDIR, // Not a directory
EIO, // IO Error
EINTR, // Operation interrupted (signal)
+ EWOULDBLOCK, // Operation would have blocked
ENODEV, // ???
EADDRNOTAVAIL, // ?
EINPROGRESS, // ?
EROFS,
+ EPERM, // Permissions error
EAGAIN, // Try again
+/**
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * errno.h
+ * - Error values and related functions
+ */
#ifndef _ERRNO_H_
#define _ERRNO_H_
extern int *libc_geterrno();
#define errno (*libc_geterrno())
-#define strerror(_x) "Unimplemented"
+extern const char *strerr(int errnum);
#include "errno.enum.h"
return tmp;
}
-long atoll(const char *str)
+long long atoll(const char *str)
{
long long tmp = strtoll(str, NULL, 0);
return tmp;
return -1;\r
}\r
\r
-EXPORT int *libc_geterrno()\r
-{\r
- return &_errno;\r
-}\r
-\r
#if USE_CPUID\r
/**\r
* \brief Call the CPUID opcode\r
if( openmode & O_NONBLOCK )
openflags |= OPENFLAG_NONBLOCK;
- return _SysOpen(path, openflags, create_mode);
+ int ret = _SysOpen(path, openflags, create_mode);
+ _SysDebug("open('%s', 0%o, 0%o) = %i", path, openmode, create_mode, ret);
+ return ret;
}
int creat(const char *path, mode_t mode)
{
_SysDebug("libposix: dup() does not share offsets/flags");
// NOTE: Acess's CopyFD doesn't cause offset sharing
- // TODO: Check that -1 does cause a new allocation
- return _SysCopyFD(oldfd, -1);
+ int ret = _SysCopyFD(oldfd, -1);
+ _SysDebug("dup(%i) = %i", oldfd, ret);
+ return ret;
}
int dup2(int oldfd, int newfd)
{
_SysDebug("libposix: dup2() does not share offsets/flags");
// NOTE: Acess's CopyFD doesn't cause offset sharing
+ _SysDebug("dup2(%i,%i)", oldfd, newfd);
return _SysCopyFD(oldfd, newfd);
}
int select(int nfd, fd_set *rfd, fd_set *wfd, fd_set *efd, struct timeval *timeout)
{
-
+ long long int ltimeout = 0, *ltimeoutp = NULL;
if( timeout )
{
- long long int ltimeout = 0;
ltimeout = timeout->tv_sec*1000 + timeout->tv_usec / 1000;
- int ret = _SysSelect(nfd, rfd, wfd, efd, <imeout, 0);
- return ret;
- }
- else
- {
- return _SysSelect(nfd, rfd, wfd, efd, NULL, 0);
+ ltimeoutp = <imeout;
}
+ _SysDebug("select(%i,{0x%x},{0x%x},{0x%x},%lli)",
+ nfd, (rfd?rfd->flags[0]:0), (wfd?wfd->flags[0]:0), (efd?efd->flags[0]:0),
+ (ltimeoutp ? *ltimeoutp : -1)
+ );
+ return _SysSelect(nfd, rfd, wfd, efd, ltimeoutp, 0);
}
int pipe(int pipefd[2])
pipefd[0] = _SysOpen("/Devices/fifo/anon", OPENFLAG_READ|OPENFLAG_WRITE);
pipefd[1] = _SysCopyFD(pipefd[0], -1);
_SysFDFlags(pipefd[1], OPENFLAG_READ|OPENFLAG_WRITE, OPENFLAG_WRITE);
+ _SysDebug("pipe({%i,%i})", pipefd[0], pipefd[1]);
return 0;
}
#include <net.h> // Net_ParseAddress
#include <stdlib.h> // malloc
#include <string.h> // memcpy
+#include <stdlib.h> // strtol
#include <acess/sys.h>
// === CODE ===
int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
{
- static const struct addrinfo defhints = {.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG};
+ static const struct addrinfo defhints = {
+ .ai_family = AF_UNSPEC,
+ .ai_flags = AI_V4MAPPED | AI_ADDRCONFIG
+ };
struct addrinfo *ret = NULL;
+ _SysDebug("getaddrinfo('%s','%s',%p,%p)", node, service, hints, res);
+
// Error checks
if( !node && !service ) return EAI_NONAME;
// - No luck with above, and hints->ai_flags doesn't have AI_NUMERICHOST set
if( !ret && !(hints->ai_flags & AI_NUMERICHOST) )
{
+ _SysDebug("getaddrinfo: TODO DNS Lookups");
// TODO: DNS Lookups
// ? /Acess/Conf/Nameservers
// ? /Acess/Conf/Hosts
}
}
- int default_socktype = 0;
- int default_protocol = 0;
+ int default_socktype = hints->ai_socktype;
+ int default_protocol = hints->ai_protocol;
int default_port = 0;
+ #if 0
+ if( default_protocol == 0 )
+ {
+ switch(default_socktype)
+ {
+ case SOCK_DGRAM:
+ default_protocol =
+ }
+ }
+ #endif
+
// Convert `node` into types
if( service )
{
- // TODO: Read something like /Acess/Conf/services
+ char *end;
+
+ default_port = strtol(service, &end, 0);
+ if( *end != '\0' && !(hints->ai_flags & AI_NUMERICSERV) )
+ {
+ // TODO: Read something like /Acess/Conf/services
+ _SysDebug("getaddrinfo: TODO Service translation");
+ }
+
+ if( *end != '\0' )
+ {
+ return EAI_NONAME;
+ }
}
struct addrinfo *ai;
case AF_INET:
if( in->sin_port == 0 )
in->sin_port = default_port;
+ _SysDebug("%p: IPv4 [%s]:%i %i,%i",
+ ai, Net_PrintAddress(4, &in->sin_addr),
+ in->sin_port, ai->ai_socktype, ai->ai_protocol);
break;
case AF_INET6:
if( in6->sin6_port == 0 )
in6->sin6_port = default_port;
+ _SysDebug("%p: IPv6 [%s]:%i %i,%i",
+ ai, Net_PrintAddress(6, &in6->sin6_addr),
+ in6->sin6_port, ai->ai_socktype, ai->ai_protocol);
break;
default:
_SysDebug("getaddrinfo: Unknown address family %i (setting port)", ai->ai_family);
#define AI_V4MAPPED 0x002
#define AI_ADDRCONFIG 0x004
#define AI_NUMERICHOST 0x008
+#define AI_NUMERICSERV 0x010
#define NI_NAMEREQD (1<<0)
#define NI_DGRAM (1<<1)
#ifndef _LIBPSOCKET__NETINET__IN_H_
#define _LIBPSOCKET__NETINET__IN_H_
+#include <sys/socket.h> // sa_family_t
#include <stdint.h>
typedef uint32_t in_addr_t;
struct sockaddr_in
{
- uint16_t sin_family;
+ sa_family_t sin_family;
uint16_t sin_port;
struct in_addr sin_addr;
};
struct sockaddr_in6
{
- uint16_t sin6_family;
+ sa_family_t sin6_family;
uint16_t sin6_port;
uint32_t sin6_flowinfo;
struct in6_addr sin6_addr;
#include <stdlib.h> // malloc/free
#include <string.h>
#include <netinet/in.h>
+#include <errno.h>
#include "common.h"
#define MAXFD 32
+#define IOCTL_TCPC_PORT 5
+#define IOCTL_TCPC_HOST 6
+#define IOCTL_TCPC_CONNECT 7
+#define IOCTL_TCPS_PORT 5
+
typedef struct s_sockinfo
{
int fd;
struct sockaddr *remote;
} t_sockinfo;
+// === PROTOTYPES ===
+void _CommitClient(int sockfd);
+
struct s_sockinfo gSockInfo[MAXFD];
static int giNumPreinit = 0;
{
t_sockinfo *si = NULL;
- if( domain < 0 || domain > AF_INET6 ) return -1;
- if( type < 0 || type > SOCK_RDM ) return -1;
+ if( domain < 0 || domain > AF_INET6 ) {
+ _SysDebug("socket: Domain %i invalid", domain);
+ errno = EINVAL;
+ return -1;
+ }
+ if( type < 0 || type > SOCK_RDM ) {
+ _SysDebug("socket: Type %i invalid", type);
+ errno = EINVAL;
+ return -1;
+ }
// Allocate an info struct
si = _GetInfo(0);
- if( !si ) return -1;
+ if( !si ) {
+ errno = ENOMEM;
+ return -1;
+ }
int fd = _SysOpen("/Devices/null", OPENFLAG_RDWR);
if( fd == -1 ) return -1;
si->protocol = protocol;
si->local = NULL;
si->remote = NULL;
-
+
+ _SysDebug("socket(%i,%i,%i) = %i", domain, type, protocol, fd);
return fd;
}
return 0;
}
-int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+size_t _getAddrData(const struct sockaddr *addr, const void **dataptr, int *port)
{
- t_sockinfo *si = _GetInfo(sockfd);;
- if( !si ) return -1;
+ size_t addrLen = 0;
+ const struct sockaddr_in *in4 = (void*)addr;
+ const struct sockaddr_in6 *in6 = (void*)addr;
+ switch( addr->sa_family )
+ {
+ case AF_INET:
+ *dataptr = &in4->sin_addr;
+ addrLen = 4;
+ *port = in4->sin_port;
+ break;
+ case AF_INET6:
+ *dataptr = &in6->sin6_addr;
+ addrLen = 16;
+ *port = in6->sin6_port;
+ break;
+ default:
+ _SysDebug("libpsocket _getAddrData: Unkown sa_family %i", addr->sa_family);
+ return 0;
+ }
+ return addrLen;
+}
- if( si->remote ) {
- // Oops?
+int _OpenIf(int DestFD, const struct sockaddr *addr, const char *file, int *port)
+{
+ const uint8_t *addrBuffer = NULL;
+ size_t addrLen = 0;
+
+ addrLen = _getAddrData(addr, (const void **)&addrBuffer, port);
+ if( addrLen == 0 ) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ char hexAddr[addrLen*2+1];
+ int bNonZero = 0;
+ for( int i = 0; i < addrLen; i ++ ) {
+ hexAddr[i*2+0] = "0123456789ABCDEF"[addrBuffer[i] >> 4];
+ hexAddr[i*2+1] = "0123456789ABCDEF"[addrBuffer[i] & 15];
+ if(addrBuffer[i]) bNonZero = 1;
+ }
+ hexAddr[addrLen*2] = 0;
+
+ char *path;
+ if( bNonZero )
+ path = mkstr("/Devices/ip/routes/@%i:%s/%s", addr->sa_family, hexAddr, file);
+ else
+ path = mkstr("/Devices/ip/*%i/%s", addr->sa_family, file);
+
+ int ret = _SysReopen(DestFD, path, OPENFLAG_RDWR);
+ _SysDebug("libpsocket: _SysReopen(%i, '%s') = %i", DestFD, path, ret);
+ free(path);
+ // TODO: Error-check?
+ return ret;
+}
+
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+ t_sockinfo *si = _GetInfo(sockfd);
+ if( !si || si->remote ) {
+ _SysDebug("connect: FD %i already connected", sockfd);
+ errno = EALREADY;
return -1;
}
si->remote = malloc( addrlen );
memcpy(si->remote, addr, addrlen);
- return 0;
+ int ret = 0;
+ if( si->type == SOCK_STREAM )
+ {
+ int lport = 0;
+ const struct sockaddr *bindaddr = (si->local ? si->local : addr);
+ ret = _OpenIf(sockfd, bindaddr, "tcpc", &lport);
+ if(ret == -1)
+ return ret;
+
+ if( si->local ) {
+ //_SysIOCtl(sockfd, IOCTL_TCPC_LPORT, &lport);
+ _SysDebug("connect: TODO - Bind to local port");
+ }
+
+ int port;
+ const void *addrdata;
+ _getAddrData(addr, &addrdata, &port);
+
+ _SysIOCtl(sockfd, IOCTL_TCPC_PORT, &port);
+ _SysIOCtl(sockfd, IOCTL_TCPC_HOST, (void*)addrdata);
+ ret = _SysIOCtl(sockfd, IOCTL_TCPC_CONNECT, NULL);
+ _SysDebug("connect: :%i = %i", port, ret);
+ }
+ else
+ {
+ _SysDebug("connect: TODO - non-TCP clients (%i)", si->type);
+ }
+
+ _CommitClient(sockfd);
+
+ return ret;
}
int listen(int sockfd, int backlog)
t_sockinfo *si = _GetInfo(sockfd);
if( !si ) return ;
- const char *file;
-
- file = "tcps";
-
if( !si->local ) {
// Um... oops?
return ;
}
- uint8_t *addrBuffer = NULL;
- size_t addrLen = 0;
- switch( si->local->sa_family )
- {
- case AF_INET:
- addrBuffer = (void*)&((struct sockaddr_in*)si->local)->sin_addr;
- addrLen = 4;
- break;
- case AF_INET6:
- addrBuffer = (void*)&((struct sockaddr_in6*)si->local)->sin6_addr;
- addrLen = 16;
- break;
- default:
+ if( si->type != SOCK_STREAM ) {
+ _SysDebug("TODO: Non-tcp servers");
return ;
}
-
- char hexAddr[addrLen*2+1];
- int bNonZero = 0, i;
- for( i = 0; i < addrLen; i ++ ) {
- hexAddr[i*2+0] = "0123456789ABCDEF"[addrBuffer[i] >> 4];
- hexAddr[i*2+1] = "0123456789ABCDEF"[addrBuffer[i] & 15];
- if(addrBuffer[i]) bNonZero = 1;
- }
-
- char *path;
- if( bNonZero )
- path = mkstr("/Devices/ip/routes/@%i:%s/%s", si->local->sa_family, file);
- else
- path = mkstr("/Devices/ip/*%i/%s", si->local->sa_family, file);
- _SysReopen(si->fd, path, OPENFLAG_RDWR);
- // TODO: Error-check
+ // Bind to the local address
+ int port;
+ int ret = _OpenIf(sockfd, si->local, "tcps", &port);
+ if( ret == -1 ) {
+ return ;
+ }
- free(path);
-
+ // Bind to port
// TODO: Set up socket
+ _SysIOCtl(sockfd, IOCTL_TCPS_PORT, &port);
_ClearInfo(si);
}