Made to compile after hacking tftp driver into beginnings of a mini-filesystem.

This commit is contained in:
Joel Sherrill
1999-01-21 22:25:43 +00:00
parent 3048b8f3ac
commit 94b3ee1366
20 changed files with 1196 additions and 156 deletions

View File

@@ -13,6 +13,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
@@ -25,6 +26,12 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#ifndef set_errno_and_return_minus_one
#define set_errno_and_return_minus_one( _error ) \
do { errno = (_error); return -1; } while(0)
#endif
/* /*
* Range of UDP ports to try * Range of UDP ports to try
*/ */
@@ -136,6 +143,50 @@ static rtems_id tftp_mutex;
static int nStreams; static int nStreams;
static struct tftpStream ** volatile tftpStreams; static struct tftpStream ** volatile tftpStreams;
typedef struct {
rtems_id tftp_mutex;
int nStreams;
struct tftpStream ** volatile tftpStreams;
rtems_filesystem_mount_table_entry_t *mt_entry;
} tftp_fs_info;
int rtems_tftp_mount_me(
rtems_filesystem_mount_table_entry_t *temp_mt_entry
)
{
tftp_fs_info *fs_info;
rtems_status_code sc;
/*
* Allocate stuff for this file system.
*/
fs_info = calloc( 1, sizeof( tftp_fs_info ));
if ( !fs_info )
set_errno_and_return_minus_one( ENOMEM );
temp_mt_entry->fs_info = fs_info;
temp_mt_entry->mt_fs_root.node_access = fs_info;
sc = rtems_semaphore_create (
rtems_build_name('T', 'F', 'T', 'P'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&fs_info->tftp_mutex
);
if (sc != RTEMS_SUCCESSFUL)
set_errno_and_return_minus_one( ENOMEM ); /* ??? */
return 0;
}
/* /*
* Initialize the TFTP driver * Initialize the TFTP driver
*/ */
@@ -147,19 +198,7 @@ rtems_device_driver rtems_tftp_initialize(
void *pargp void *pargp
) )
{ {
rtems_status_code sc;
sc = rtems_semaphore_create (rtems_build_name('T', 'F', 'T', 'P'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&tftp_mutex);
if (sc != RTEMS_SUCCESSFUL)
return sc;
/* XXX change to a mount */ /* XXX change to a mount */
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor); rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
@@ -293,39 +332,44 @@ releaseStream (int s)
rtems_semaphore_release (tftp_mutex); rtems_semaphore_release (tftp_mutex);
} }
/* int rtems_tftp_evaluate_for_make(
* Open a TFTP stream const char *path, /* IN */
*/ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
rtems_device_driver rtems_tftp_open( const char **name /* OUT */
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
) )
{ {
rtems_libio_open_close_args_t *ap = pargp; set_errno_and_return_minus_one( EIO );
struct tftpStream *tp; }
int retryCount; /*
rtems_unsigned32 farAddress; * XXX - Fix return values.
int s;
int len;
char *cp1, *cp2;
char *remoteFilename;
rtems_interval now;
rtems_status_code sc;
/* XXX change to eval_path/open */
/*
* Read-only for now
*/ */
if (ap->flags & LIBIO_FLAGS_WRITE)
return RTEMS_NOT_IMPLEMENTED; int TFTP_eval_path(
const char *pathname, /* IN */
int flags, /* IN */
rtems_filesystem_location_info_t *pathloc /* IN/OUT */
)
{
rtems_unsigned32 farAddress;
int len;
const char *remoteFilename;
tftp_fs_info *fs_info;
const char *cp1, *cp2;
fs_info = pathloc->node_access;
/* /*
* Pick apart the name into a host:pathname pair * Pick apart the name into a host:pathname pair
*/ */
if (strlen (ap->iop->pathname) <= strlen (TFTP_PATHNAME_PREFIX)) /*
return RTEMS_INVALID_NAME; * XXX - I think this is handled by the caller of
cp2 = ap->iop->pathname + strlen (TFTP_PATHNAME_PREFIX); * the evaluate routine. ? Am I starting at the right
* place?
*/
cp2 = pathname+1;
if (*cp2 == '/') { if (*cp2 == '/') {
farAddress = rtems_bsdnet_bootp_server_address.s_addr; farAddress = rtems_bsdnet_bootp_server_address.s_addr;
} }
@@ -355,6 +399,37 @@ rtems_device_driver rtems_tftp_open(
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10)) if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
return RTEMS_INVALID_NAME; return RTEMS_INVALID_NAME;
return 0;
}
/*
* Open a TFTP stream
*/
rtems_device_driver rtems_tftp_open(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
)
{
rtems_libio_open_close_args_t *ap = pargp;
struct tftpStream *tp;
int retryCount;
rtems_unsigned32 farAddress = 0; /* XXX - node parameter */
int s;
int len;
char *cp1, *cp2;
char *remoteFilename = NULL; /* XXX - node parameter */
rtems_interval now;
rtems_status_code sc;
/*
* Read-only for now
*/
/* XXX - Move to the open routine */
if (ap->flags & LIBIO_FLAGS_WRITE)
return RTEMS_NOT_IMPLEMENTED;
/* /*
* Find a free stream * Find a free stream
*/ */

View File

@@ -14,7 +14,7 @@
#if defined(__rtems__) #if defined(__rtems__)
u_int16_t _getshort(const u_char *src); u_int16_t _getshort(const u_char *src);
u_int32_t _getlong(const u_char *src); u_int32_t _getlong(const u_char *src);
int gethostname (char *name, int namelen); int gethostname (char *name, size_t namelen);
int sethostname (char *name, int namelen); int sethostname (char *name, size_t namelen);
int issetugid (void); int issetugid (void);
#endif #endif

View File

@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
/* /*
* Some extra prototypes * Some extra prototypes
*/ */
int sethostname (char *name, int namelen); int sethostname (char *name, size_t namelen);
void domaininit (void *); void domaininit (void *);
void ifinit (void *); void ifinit (void *);
void ipintr (void); void ipintr (void);
@@ -174,5 +174,19 @@ void arpintr (void);
void bootpc_init(void); void bootpc_init(void);
int socket (int, int, int); int socket (int, int, int);
int ioctl (int, unsigned long, ...); int ioctl (int, unsigned long, ...);
struct socket *rtems_bsdnet_fdToSocket (int fd);
int rtems_bsdnet_makeFdForSocket (struct socket *);
/*
* Events used by networking routines.
* Everything will break if the application
* tries to use these events or if the `sleep'
* events are equal to any of the NETISR * events.
*/
#define SBWAIT_EVENT RTEMS_EVENT_24
#define SOSLEEP_EVENT RTEMS_EVENT_25
#define NETISR_IP_EVENT (1 << NETISR_IP)
#define NETISR_ARP_EVENT (1 << NETISR_ARP)
#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */ #endif /* _RTEMS_BSDNET_INTERNAL_H_ */

View File

@@ -0,0 +1,171 @@
/*
* $Id$
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/error.h>
#include <rtems/rtems_bsdnet.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/filio.h>
#include <net/if.h>
#include <net/route.h>
/*
*********************************************************************
* RTEMS implementation of select() system call *
*********************************************************************
*/
/*
* This implementation is quite restricted:
* Works on sockets only -- no support for other devices!
* A given socket can be in a read-select or a read/recv* by only
* one task at a time.
* A given socket can be in a write-select or a write/send* by only
* one task at a time.
*
* NOTE - select() is a very expensive system call. It should be avoided
* if at all possible. In many cases, rewriting the application
* to use multiple tasks (one per socket) is a better solution.
*/
static __inline int imin(int a, int b) { return (a < b ? a : b); }
static int
socket_select (struct socket *so, int which, rtems_id tid)
{
switch (which) {
case FREAD:
if (soreadable(so))
return (1);
so->so_rcv.sb_sel.si_pid = tid;
break;
case FWRITE:
if (sowriteable(so))
return (1);
so->so_snd.sb_sel.si_pid = tid;
break;
case 0:
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
return (1);
so->so_rcv.sb_sel.si_pid = tid;
break;
}
return (0);
}
static int
selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
{
struct socket *so;
int msk, i, fd;
fd_mask bits, bit;
int n = 0;
static int flag[3] = { FREAD, FWRITE, 0 };
for (msk = 0; msk < 3; msk++) {
if (ibits[msk] == NULL)
continue;
for (i = 0; i < nfd; i += NFDBITS) {
bits = ibits[msk][i/NFDBITS];
for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
if ((bits & bit) == 0)
continue;
bits &= ~bit;
so = rtems_bsdnet_fdToSocket (fd);
if (so == NULL)
return (EBADF);
if (socket_select (so, flag[msk], tid)) {
obits[msk][fd/NFDBITS] |=
(1 << (fd % NFDBITS));
n++;
}
}
}
}
*retval = n;
return (0);
}
int
select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
{
fd_mask *ibits[3], *obits[3];
fd_set ob[3];
int error, timo;
int retval;
rtems_id tid;
rtems_interval then, now;
rtems_event_set events;
if (nfds < 0)
return (EINVAL);
if (tv) {
timo = tv->tv_sec * hz + tv->tv_usec / tick;
if (timo == 0)
timo = 1;
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
}
else {
timo = 0;
}
#define getbits(name,i) if (name) { \
ibits[i] = &name->fds_bits[0]; \
obits[i] = &ob[i].fds_bits[0]; \
FD_ZERO(&ob[i]); \
} \
else ibits[i] = NULL
getbits (readfds, 0);
getbits (writefds, 1);
getbits (exceptfds, 2);
#undef getbits
rtems_task_ident (RTEMS_SELF, 0, &tid);
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
for (;;) {
rtems_bsdnet_semaphore_obtain ();
error = selscan(tid, ibits, obits, nfds, &retval);
rtems_bsdnet_semaphore_release ();
if (error || retval)
break;
if (timo) {
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
timo -= now - then;
if (timo <= 0)
break;
then = now;
}
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
}
#define putbits(name,i) if (name) *name = ob[i]
putbits (readfds, 0);
putbits (writefds, 1);
putbits (exceptfds, 2);
#undef putbits
if (error) {
errno = error;
retval = -1;
}
return (retval);
}

View File

@@ -15,7 +15,7 @@
static char *rtems_hostname; static char *rtems_hostname;
int int
gethostname (char *name, int namelen) gethostname (char *name, size_t namelen)
{ {
char *cp = rtems_hostname; char *cp = rtems_hostname;
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
} }
int int
sethostname (char *name, int namelen) sethostname (char *name, size_t namelen)
{ {
char *old, *new; char *old, *new;

View File

@@ -13,6 +13,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
@@ -25,6 +26,12 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#ifndef set_errno_and_return_minus_one
#define set_errno_and_return_minus_one( _error ) \
do { errno = (_error); return -1; } while(0)
#endif
/* /*
* Range of UDP ports to try * Range of UDP ports to try
*/ */
@@ -136,6 +143,50 @@ static rtems_id tftp_mutex;
static int nStreams; static int nStreams;
static struct tftpStream ** volatile tftpStreams; static struct tftpStream ** volatile tftpStreams;
typedef struct {
rtems_id tftp_mutex;
int nStreams;
struct tftpStream ** volatile tftpStreams;
rtems_filesystem_mount_table_entry_t *mt_entry;
} tftp_fs_info;
int rtems_tftp_mount_me(
rtems_filesystem_mount_table_entry_t *temp_mt_entry
)
{
tftp_fs_info *fs_info;
rtems_status_code sc;
/*
* Allocate stuff for this file system.
*/
fs_info = calloc( 1, sizeof( tftp_fs_info ));
if ( !fs_info )
set_errno_and_return_minus_one( ENOMEM );
temp_mt_entry->fs_info = fs_info;
temp_mt_entry->mt_fs_root.node_access = fs_info;
sc = rtems_semaphore_create (
rtems_build_name('T', 'F', 'T', 'P'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&fs_info->tftp_mutex
);
if (sc != RTEMS_SUCCESSFUL)
set_errno_and_return_minus_one( ENOMEM ); /* ??? */
return 0;
}
/* /*
* Initialize the TFTP driver * Initialize the TFTP driver
*/ */
@@ -147,19 +198,7 @@ rtems_device_driver rtems_tftp_initialize(
void *pargp void *pargp
) )
{ {
rtems_status_code sc;
sc = rtems_semaphore_create (rtems_build_name('T', 'F', 'T', 'P'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&tftp_mutex);
if (sc != RTEMS_SUCCESSFUL)
return sc;
/* XXX change to a mount */ /* XXX change to a mount */
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor); rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
@@ -293,39 +332,44 @@ releaseStream (int s)
rtems_semaphore_release (tftp_mutex); rtems_semaphore_release (tftp_mutex);
} }
/* int rtems_tftp_evaluate_for_make(
* Open a TFTP stream const char *path, /* IN */
*/ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
rtems_device_driver rtems_tftp_open( const char **name /* OUT */
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
) )
{ {
rtems_libio_open_close_args_t *ap = pargp; set_errno_and_return_minus_one( EIO );
struct tftpStream *tp; }
int retryCount; /*
rtems_unsigned32 farAddress; * XXX - Fix return values.
int s;
int len;
char *cp1, *cp2;
char *remoteFilename;
rtems_interval now;
rtems_status_code sc;
/* XXX change to eval_path/open */
/*
* Read-only for now
*/ */
if (ap->flags & LIBIO_FLAGS_WRITE)
return RTEMS_NOT_IMPLEMENTED; int TFTP_eval_path(
const char *pathname, /* IN */
int flags, /* IN */
rtems_filesystem_location_info_t *pathloc /* IN/OUT */
)
{
rtems_unsigned32 farAddress;
int len;
const char *remoteFilename;
tftp_fs_info *fs_info;
const char *cp1, *cp2;
fs_info = pathloc->node_access;
/* /*
* Pick apart the name into a host:pathname pair * Pick apart the name into a host:pathname pair
*/ */
if (strlen (ap->iop->pathname) <= strlen (TFTP_PATHNAME_PREFIX)) /*
return RTEMS_INVALID_NAME; * XXX - I think this is handled by the caller of
cp2 = ap->iop->pathname + strlen (TFTP_PATHNAME_PREFIX); * the evaluate routine. ? Am I starting at the right
* place?
*/
cp2 = pathname+1;
if (*cp2 == '/') { if (*cp2 == '/') {
farAddress = rtems_bsdnet_bootp_server_address.s_addr; farAddress = rtems_bsdnet_bootp_server_address.s_addr;
} }
@@ -355,6 +399,37 @@ rtems_device_driver rtems_tftp_open(
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10)) if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
return RTEMS_INVALID_NAME; return RTEMS_INVALID_NAME;
return 0;
}
/*
* Open a TFTP stream
*/
rtems_device_driver rtems_tftp_open(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
)
{
rtems_libio_open_close_args_t *ap = pargp;
struct tftpStream *tp;
int retryCount;
rtems_unsigned32 farAddress = 0; /* XXX - node parameter */
int s;
int len;
char *cp1, *cp2;
char *remoteFilename = NULL; /* XXX - node parameter */
rtems_interval now;
rtems_status_code sc;
/*
* Read-only for now
*/
/* XXX - Move to the open routine */
if (ap->flags & LIBIO_FLAGS_WRITE)
return RTEMS_NOT_IMPLEMENTED;
/* /*
* Find a free stream * Find a free stream
*/ */

View File

@@ -14,7 +14,7 @@
#if defined(__rtems__) #if defined(__rtems__)
u_int16_t _getshort(const u_char *src); u_int16_t _getshort(const u_char *src);
u_int32_t _getlong(const u_char *src); u_int32_t _getlong(const u_char *src);
int gethostname (char *name, int namelen); int gethostname (char *name, size_t namelen);
int sethostname (char *name, int namelen); int sethostname (char *name, size_t namelen);
int issetugid (void); int issetugid (void);
#endif #endif

View File

@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
/* /*
* Some extra prototypes * Some extra prototypes
*/ */
int sethostname (char *name, int namelen); int sethostname (char *name, size_t namelen);
void domaininit (void *); void domaininit (void *);
void ifinit (void *); void ifinit (void *);
void ipintr (void); void ipintr (void);
@@ -174,5 +174,19 @@ void arpintr (void);
void bootpc_init(void); void bootpc_init(void);
int socket (int, int, int); int socket (int, int, int);
int ioctl (int, unsigned long, ...); int ioctl (int, unsigned long, ...);
struct socket *rtems_bsdnet_fdToSocket (int fd);
int rtems_bsdnet_makeFdForSocket (struct socket *);
/*
* Events used by networking routines.
* Everything will break if the application
* tries to use these events or if the `sleep'
* events are equal to any of the NETISR * events.
*/
#define SBWAIT_EVENT RTEMS_EVENT_24
#define SOSLEEP_EVENT RTEMS_EVENT_25
#define NETISR_IP_EVENT (1 << NETISR_IP)
#define NETISR_ARP_EVENT (1 << NETISR_ARP)
#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */ #endif /* _RTEMS_BSDNET_INTERNAL_H_ */

View File

@@ -0,0 +1,171 @@
/*
* $Id$
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/error.h>
#include <rtems/rtems_bsdnet.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/filio.h>
#include <net/if.h>
#include <net/route.h>
/*
*********************************************************************
* RTEMS implementation of select() system call *
*********************************************************************
*/
/*
* This implementation is quite restricted:
* Works on sockets only -- no support for other devices!
* A given socket can be in a read-select or a read/recv* by only
* one task at a time.
* A given socket can be in a write-select or a write/send* by only
* one task at a time.
*
* NOTE - select() is a very expensive system call. It should be avoided
* if at all possible. In many cases, rewriting the application
* to use multiple tasks (one per socket) is a better solution.
*/
static __inline int imin(int a, int b) { return (a < b ? a : b); }
static int
socket_select (struct socket *so, int which, rtems_id tid)
{
switch (which) {
case FREAD:
if (soreadable(so))
return (1);
so->so_rcv.sb_sel.si_pid = tid;
break;
case FWRITE:
if (sowriteable(so))
return (1);
so->so_snd.sb_sel.si_pid = tid;
break;
case 0:
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
return (1);
so->so_rcv.sb_sel.si_pid = tid;
break;
}
return (0);
}
static int
selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
{
struct socket *so;
int msk, i, fd;
fd_mask bits, bit;
int n = 0;
static int flag[3] = { FREAD, FWRITE, 0 };
for (msk = 0; msk < 3; msk++) {
if (ibits[msk] == NULL)
continue;
for (i = 0; i < nfd; i += NFDBITS) {
bits = ibits[msk][i/NFDBITS];
for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
if ((bits & bit) == 0)
continue;
bits &= ~bit;
so = rtems_bsdnet_fdToSocket (fd);
if (so == NULL)
return (EBADF);
if (socket_select (so, flag[msk], tid)) {
obits[msk][fd/NFDBITS] |=
(1 << (fd % NFDBITS));
n++;
}
}
}
}
*retval = n;
return (0);
}
int
select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
{
fd_mask *ibits[3], *obits[3];
fd_set ob[3];
int error, timo;
int retval;
rtems_id tid;
rtems_interval then, now;
rtems_event_set events;
if (nfds < 0)
return (EINVAL);
if (tv) {
timo = tv->tv_sec * hz + tv->tv_usec / tick;
if (timo == 0)
timo = 1;
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
}
else {
timo = 0;
}
#define getbits(name,i) if (name) { \
ibits[i] = &name->fds_bits[0]; \
obits[i] = &ob[i].fds_bits[0]; \
FD_ZERO(&ob[i]); \
} \
else ibits[i] = NULL
getbits (readfds, 0);
getbits (writefds, 1);
getbits (exceptfds, 2);
#undef getbits
rtems_task_ident (RTEMS_SELF, 0, &tid);
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
for (;;) {
rtems_bsdnet_semaphore_obtain ();
error = selscan(tid, ibits, obits, nfds, &retval);
rtems_bsdnet_semaphore_release ();
if (error || retval)
break;
if (timo) {
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
timo -= now - then;
if (timo <= 0)
break;
then = now;
}
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
}
#define putbits(name,i) if (name) *name = ob[i]
putbits (readfds, 0);
putbits (writefds, 1);
putbits (exceptfds, 2);
#undef putbits
if (error) {
errno = error;
retval = -1;
}
return (retval);
}

View File

@@ -15,7 +15,7 @@
static char *rtems_hostname; static char *rtems_hostname;
int int
gethostname (char *name, int namelen) gethostname (char *name, size_t namelen)
{ {
char *cp = rtems_hostname; char *cp = rtems_hostname;
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
} }
int int
sethostname (char *name, int namelen) sethostname (char *name, size_t namelen)
{ {
char *old, *new; char *old, *new;

View File

@@ -13,6 +13,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
@@ -25,6 +26,12 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#ifndef set_errno_and_return_minus_one
#define set_errno_and_return_minus_one( _error ) \
do { errno = (_error); return -1; } while(0)
#endif
/* /*
* Range of UDP ports to try * Range of UDP ports to try
*/ */
@@ -136,6 +143,50 @@ static rtems_id tftp_mutex;
static int nStreams; static int nStreams;
static struct tftpStream ** volatile tftpStreams; static struct tftpStream ** volatile tftpStreams;
typedef struct {
rtems_id tftp_mutex;
int nStreams;
struct tftpStream ** volatile tftpStreams;
rtems_filesystem_mount_table_entry_t *mt_entry;
} tftp_fs_info;
int rtems_tftp_mount_me(
rtems_filesystem_mount_table_entry_t *temp_mt_entry
)
{
tftp_fs_info *fs_info;
rtems_status_code sc;
/*
* Allocate stuff for this file system.
*/
fs_info = calloc( 1, sizeof( tftp_fs_info ));
if ( !fs_info )
set_errno_and_return_minus_one( ENOMEM );
temp_mt_entry->fs_info = fs_info;
temp_mt_entry->mt_fs_root.node_access = fs_info;
sc = rtems_semaphore_create (
rtems_build_name('T', 'F', 'T', 'P'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&fs_info->tftp_mutex
);
if (sc != RTEMS_SUCCESSFUL)
set_errno_and_return_minus_one( ENOMEM ); /* ??? */
return 0;
}
/* /*
* Initialize the TFTP driver * Initialize the TFTP driver
*/ */
@@ -147,19 +198,7 @@ rtems_device_driver rtems_tftp_initialize(
void *pargp void *pargp
) )
{ {
rtems_status_code sc;
sc = rtems_semaphore_create (rtems_build_name('T', 'F', 'T', 'P'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&tftp_mutex);
if (sc != RTEMS_SUCCESSFUL)
return sc;
/* XXX change to a mount */ /* XXX change to a mount */
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor); rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
@@ -293,39 +332,44 @@ releaseStream (int s)
rtems_semaphore_release (tftp_mutex); rtems_semaphore_release (tftp_mutex);
} }
/* int rtems_tftp_evaluate_for_make(
* Open a TFTP stream const char *path, /* IN */
*/ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
rtems_device_driver rtems_tftp_open( const char **name /* OUT */
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
) )
{ {
rtems_libio_open_close_args_t *ap = pargp; set_errno_and_return_minus_one( EIO );
struct tftpStream *tp; }
int retryCount; /*
rtems_unsigned32 farAddress; * XXX - Fix return values.
int s;
int len;
char *cp1, *cp2;
char *remoteFilename;
rtems_interval now;
rtems_status_code sc;
/* XXX change to eval_path/open */
/*
* Read-only for now
*/ */
if (ap->flags & LIBIO_FLAGS_WRITE)
return RTEMS_NOT_IMPLEMENTED; int TFTP_eval_path(
const char *pathname, /* IN */
int flags, /* IN */
rtems_filesystem_location_info_t *pathloc /* IN/OUT */
)
{
rtems_unsigned32 farAddress;
int len;
const char *remoteFilename;
tftp_fs_info *fs_info;
const char *cp1, *cp2;
fs_info = pathloc->node_access;
/* /*
* Pick apart the name into a host:pathname pair * Pick apart the name into a host:pathname pair
*/ */
if (strlen (ap->iop->pathname) <= strlen (TFTP_PATHNAME_PREFIX)) /*
return RTEMS_INVALID_NAME; * XXX - I think this is handled by the caller of
cp2 = ap->iop->pathname + strlen (TFTP_PATHNAME_PREFIX); * the evaluate routine. ? Am I starting at the right
* place?
*/
cp2 = pathname+1;
if (*cp2 == '/') { if (*cp2 == '/') {
farAddress = rtems_bsdnet_bootp_server_address.s_addr; farAddress = rtems_bsdnet_bootp_server_address.s_addr;
} }
@@ -355,6 +399,37 @@ rtems_device_driver rtems_tftp_open(
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10)) if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
return RTEMS_INVALID_NAME; return RTEMS_INVALID_NAME;
return 0;
}
/*
* Open a TFTP stream
*/
rtems_device_driver rtems_tftp_open(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
)
{
rtems_libio_open_close_args_t *ap = pargp;
struct tftpStream *tp;
int retryCount;
rtems_unsigned32 farAddress = 0; /* XXX - node parameter */
int s;
int len;
char *cp1, *cp2;
char *remoteFilename = NULL; /* XXX - node parameter */
rtems_interval now;
rtems_status_code sc;
/*
* Read-only for now
*/
/* XXX - Move to the open routine */
if (ap->flags & LIBIO_FLAGS_WRITE)
return RTEMS_NOT_IMPLEMENTED;
/* /*
* Find a free stream * Find a free stream
*/ */

View File

@@ -14,7 +14,7 @@
#if defined(__rtems__) #if defined(__rtems__)
u_int16_t _getshort(const u_char *src); u_int16_t _getshort(const u_char *src);
u_int32_t _getlong(const u_char *src); u_int32_t _getlong(const u_char *src);
int gethostname (char *name, int namelen); int gethostname (char *name, size_t namelen);
int sethostname (char *name, int namelen); int sethostname (char *name, size_t namelen);
int issetugid (void); int issetugid (void);
#endif #endif

View File

@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
/* /*
* Some extra prototypes * Some extra prototypes
*/ */
int sethostname (char *name, int namelen); int sethostname (char *name, size_t namelen);
void domaininit (void *); void domaininit (void *);
void ifinit (void *); void ifinit (void *);
void ipintr (void); void ipintr (void);
@@ -174,5 +174,19 @@ void arpintr (void);
void bootpc_init(void); void bootpc_init(void);
int socket (int, int, int); int socket (int, int, int);
int ioctl (int, unsigned long, ...); int ioctl (int, unsigned long, ...);
struct socket *rtems_bsdnet_fdToSocket (int fd);
int rtems_bsdnet_makeFdForSocket (struct socket *);
/*
* Events used by networking routines.
* Everything will break if the application
* tries to use these events or if the `sleep'
* events are equal to any of the NETISR * events.
*/
#define SBWAIT_EVENT RTEMS_EVENT_24
#define SOSLEEP_EVENT RTEMS_EVENT_25
#define NETISR_IP_EVENT (1 << NETISR_IP)
#define NETISR_ARP_EVENT (1 << NETISR_ARP)
#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */ #endif /* _RTEMS_BSDNET_INTERNAL_H_ */

View File

@@ -0,0 +1,171 @@
/*
* $Id$
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/error.h>
#include <rtems/rtems_bsdnet.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/filio.h>
#include <net/if.h>
#include <net/route.h>
/*
*********************************************************************
* RTEMS implementation of select() system call *
*********************************************************************
*/
/*
* This implementation is quite restricted:
* Works on sockets only -- no support for other devices!
* A given socket can be in a read-select or a read/recv* by only
* one task at a time.
* A given socket can be in a write-select or a write/send* by only
* one task at a time.
*
* NOTE - select() is a very expensive system call. It should be avoided
* if at all possible. In many cases, rewriting the application
* to use multiple tasks (one per socket) is a better solution.
*/
static __inline int imin(int a, int b) { return (a < b ? a : b); }
static int
socket_select (struct socket *so, int which, rtems_id tid)
{
switch (which) {
case FREAD:
if (soreadable(so))
return (1);
so->so_rcv.sb_sel.si_pid = tid;
break;
case FWRITE:
if (sowriteable(so))
return (1);
so->so_snd.sb_sel.si_pid = tid;
break;
case 0:
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
return (1);
so->so_rcv.sb_sel.si_pid = tid;
break;
}
return (0);
}
static int
selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
{
struct socket *so;
int msk, i, fd;
fd_mask bits, bit;
int n = 0;
static int flag[3] = { FREAD, FWRITE, 0 };
for (msk = 0; msk < 3; msk++) {
if (ibits[msk] == NULL)
continue;
for (i = 0; i < nfd; i += NFDBITS) {
bits = ibits[msk][i/NFDBITS];
for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
if ((bits & bit) == 0)
continue;
bits &= ~bit;
so = rtems_bsdnet_fdToSocket (fd);
if (so == NULL)
return (EBADF);
if (socket_select (so, flag[msk], tid)) {
obits[msk][fd/NFDBITS] |=
(1 << (fd % NFDBITS));
n++;
}
}
}
}
*retval = n;
return (0);
}
int
select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
{
fd_mask *ibits[3], *obits[3];
fd_set ob[3];
int error, timo;
int retval;
rtems_id tid;
rtems_interval then, now;
rtems_event_set events;
if (nfds < 0)
return (EINVAL);
if (tv) {
timo = tv->tv_sec * hz + tv->tv_usec / tick;
if (timo == 0)
timo = 1;
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
}
else {
timo = 0;
}
#define getbits(name,i) if (name) { \
ibits[i] = &name->fds_bits[0]; \
obits[i] = &ob[i].fds_bits[0]; \
FD_ZERO(&ob[i]); \
} \
else ibits[i] = NULL
getbits (readfds, 0);
getbits (writefds, 1);
getbits (exceptfds, 2);
#undef getbits
rtems_task_ident (RTEMS_SELF, 0, &tid);
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
for (;;) {
rtems_bsdnet_semaphore_obtain ();
error = selscan(tid, ibits, obits, nfds, &retval);
rtems_bsdnet_semaphore_release ();
if (error || retval)
break;
if (timo) {
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
timo -= now - then;
if (timo <= 0)
break;
then = now;
}
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
}
#define putbits(name,i) if (name) *name = ob[i]
putbits (readfds, 0);
putbits (writefds, 1);
putbits (exceptfds, 2);
#undef putbits
if (error) {
errno = error;
retval = -1;
}
return (retval);
}

View File

@@ -15,7 +15,7 @@
static char *rtems_hostname; static char *rtems_hostname;
int int
gethostname (char *name, int namelen) gethostname (char *name, size_t namelen)
{ {
char *cp = rtems_hostname; char *cp = rtems_hostname;
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
} }
int int
sethostname (char *name, int namelen) sethostname (char *name, size_t namelen)
{ {
char *old, *new; char *old, *new;

View File

@@ -13,6 +13,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <string.h> #include <string.h>
@@ -25,6 +26,12 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#ifndef set_errno_and_return_minus_one
#define set_errno_and_return_minus_one( _error ) \
do { errno = (_error); return -1; } while(0)
#endif
/* /*
* Range of UDP ports to try * Range of UDP ports to try
*/ */
@@ -136,6 +143,50 @@ static rtems_id tftp_mutex;
static int nStreams; static int nStreams;
static struct tftpStream ** volatile tftpStreams; static struct tftpStream ** volatile tftpStreams;
typedef struct {
rtems_id tftp_mutex;
int nStreams;
struct tftpStream ** volatile tftpStreams;
rtems_filesystem_mount_table_entry_t *mt_entry;
} tftp_fs_info;
int rtems_tftp_mount_me(
rtems_filesystem_mount_table_entry_t *temp_mt_entry
)
{
tftp_fs_info *fs_info;
rtems_status_code sc;
/*
* Allocate stuff for this file system.
*/
fs_info = calloc( 1, sizeof( tftp_fs_info ));
if ( !fs_info )
set_errno_and_return_minus_one( ENOMEM );
temp_mt_entry->fs_info = fs_info;
temp_mt_entry->mt_fs_root.node_access = fs_info;
sc = rtems_semaphore_create (
rtems_build_name('T', 'F', 'T', 'P'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&fs_info->tftp_mutex
);
if (sc != RTEMS_SUCCESSFUL)
set_errno_and_return_minus_one( ENOMEM ); /* ??? */
return 0;
}
/* /*
* Initialize the TFTP driver * Initialize the TFTP driver
*/ */
@@ -147,19 +198,7 @@ rtems_device_driver rtems_tftp_initialize(
void *pargp void *pargp
) )
{ {
rtems_status_code sc;
sc = rtems_semaphore_create (rtems_build_name('T', 'F', 'T', 'P'),
1,
RTEMS_FIFO |
RTEMS_BINARY_SEMAPHORE |
RTEMS_NO_INHERIT_PRIORITY |
RTEMS_NO_PRIORITY_CEILING |
RTEMS_LOCAL,
0,
&tftp_mutex);
if (sc != RTEMS_SUCCESSFUL)
return sc;
/* XXX change to a mount */ /* XXX change to a mount */
rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor); rtems_io_register_name (TFTP_PATHNAME_PREFIX, major, minor);
return RTEMS_SUCCESSFUL; return RTEMS_SUCCESSFUL;
@@ -293,39 +332,44 @@ releaseStream (int s)
rtems_semaphore_release (tftp_mutex); rtems_semaphore_release (tftp_mutex);
} }
/* int rtems_tftp_evaluate_for_make(
* Open a TFTP stream const char *path, /* IN */
*/ rtems_filesystem_location_info_t *pathloc, /* IN/OUT */
rtems_device_driver rtems_tftp_open( const char **name /* OUT */
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
) )
{ {
rtems_libio_open_close_args_t *ap = pargp; set_errno_and_return_minus_one( EIO );
struct tftpStream *tp; }
int retryCount; /*
rtems_unsigned32 farAddress; * XXX - Fix return values.
int s;
int len;
char *cp1, *cp2;
char *remoteFilename;
rtems_interval now;
rtems_status_code sc;
/* XXX change to eval_path/open */
/*
* Read-only for now
*/ */
if (ap->flags & LIBIO_FLAGS_WRITE)
return RTEMS_NOT_IMPLEMENTED; int TFTP_eval_path(
const char *pathname, /* IN */
int flags, /* IN */
rtems_filesystem_location_info_t *pathloc /* IN/OUT */
)
{
rtems_unsigned32 farAddress;
int len;
const char *remoteFilename;
tftp_fs_info *fs_info;
const char *cp1, *cp2;
fs_info = pathloc->node_access;
/* /*
* Pick apart the name into a host:pathname pair * Pick apart the name into a host:pathname pair
*/ */
if (strlen (ap->iop->pathname) <= strlen (TFTP_PATHNAME_PREFIX)) /*
return RTEMS_INVALID_NAME; * XXX - I think this is handled by the caller of
cp2 = ap->iop->pathname + strlen (TFTP_PATHNAME_PREFIX); * the evaluate routine. ? Am I starting at the right
* place?
*/
cp2 = pathname+1;
if (*cp2 == '/') { if (*cp2 == '/') {
farAddress = rtems_bsdnet_bootp_server_address.s_addr; farAddress = rtems_bsdnet_bootp_server_address.s_addr;
} }
@@ -355,6 +399,37 @@ rtems_device_driver rtems_tftp_open(
if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10)) if (strlen (remoteFilename) > (TFTP_BUFSIZE - 10))
return RTEMS_INVALID_NAME; return RTEMS_INVALID_NAME;
return 0;
}
/*
* Open a TFTP stream
*/
rtems_device_driver rtems_tftp_open(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp
)
{
rtems_libio_open_close_args_t *ap = pargp;
struct tftpStream *tp;
int retryCount;
rtems_unsigned32 farAddress = 0; /* XXX - node parameter */
int s;
int len;
char *cp1, *cp2;
char *remoteFilename = NULL; /* XXX - node parameter */
rtems_interval now;
rtems_status_code sc;
/*
* Read-only for now
*/
/* XXX - Move to the open routine */
if (ap->flags & LIBIO_FLAGS_WRITE)
return RTEMS_NOT_IMPLEMENTED;
/* /*
* Find a free stream * Find a free stream
*/ */

View File

@@ -14,7 +14,7 @@
#if defined(__rtems__) #if defined(__rtems__)
u_int16_t _getshort(const u_char *src); u_int16_t _getshort(const u_char *src);
u_int32_t _getlong(const u_char *src); u_int32_t _getlong(const u_char *src);
int gethostname (char *name, int namelen); int gethostname (char *name, size_t namelen);
int sethostname (char *name, int namelen); int sethostname (char *name, size_t namelen);
int issetugid (void); int issetugid (void);
#endif #endif

View File

@@ -166,7 +166,7 @@ extern int rtems_bsdnet_nameserver_count;
/* /*
* Some extra prototypes * Some extra prototypes
*/ */
int sethostname (char *name, int namelen); int sethostname (char *name, size_t namelen);
void domaininit (void *); void domaininit (void *);
void ifinit (void *); void ifinit (void *);
void ipintr (void); void ipintr (void);
@@ -174,5 +174,19 @@ void arpintr (void);
void bootpc_init(void); void bootpc_init(void);
int socket (int, int, int); int socket (int, int, int);
int ioctl (int, unsigned long, ...); int ioctl (int, unsigned long, ...);
struct socket *rtems_bsdnet_fdToSocket (int fd);
int rtems_bsdnet_makeFdForSocket (struct socket *);
/*
* Events used by networking routines.
* Everything will break if the application
* tries to use these events or if the `sleep'
* events are equal to any of the NETISR * events.
*/
#define SBWAIT_EVENT RTEMS_EVENT_24
#define SOSLEEP_EVENT RTEMS_EVENT_25
#define NETISR_IP_EVENT (1 << NETISR_IP)
#define NETISR_ARP_EVENT (1 << NETISR_ARP)
#define NETISR_EVENTS (NETISR_IP_EVENT|NETISR_ARP_EVENT)
#endif /* _RTEMS_BSDNET_INTERNAL_H_ */ #endif /* _RTEMS_BSDNET_INTERNAL_H_ */

View File

@@ -0,0 +1,171 @@
/*
* $Id$
*/
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/error.h>
#include <rtems/rtems_bsdnet.h>
#include <sys/errno.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/filio.h>
#include <net/if.h>
#include <net/route.h>
/*
*********************************************************************
* RTEMS implementation of select() system call *
*********************************************************************
*/
/*
* This implementation is quite restricted:
* Works on sockets only -- no support for other devices!
* A given socket can be in a read-select or a read/recv* by only
* one task at a time.
* A given socket can be in a write-select or a write/send* by only
* one task at a time.
*
* NOTE - select() is a very expensive system call. It should be avoided
* if at all possible. In many cases, rewriting the application
* to use multiple tasks (one per socket) is a better solution.
*/
static __inline int imin(int a, int b) { return (a < b ? a : b); }
static int
socket_select (struct socket *so, int which, rtems_id tid)
{
switch (which) {
case FREAD:
if (soreadable(so))
return (1);
so->so_rcv.sb_sel.si_pid = tid;
break;
case FWRITE:
if (sowriteable(so))
return (1);
so->so_snd.sb_sel.si_pid = tid;
break;
case 0:
if (so->so_oobmark || (so->so_state & SS_RCVATMARK))
return (1);
so->so_rcv.sb_sel.si_pid = tid;
break;
}
return (0);
}
static int
selscan (rtems_id tid, fd_mask **ibits, fd_mask **obits, int nfd, int *retval)
{
struct socket *so;
int msk, i, fd;
fd_mask bits, bit;
int n = 0;
static int flag[3] = { FREAD, FWRITE, 0 };
for (msk = 0; msk < 3; msk++) {
if (ibits[msk] == NULL)
continue;
for (i = 0; i < nfd; i += NFDBITS) {
bits = ibits[msk][i/NFDBITS];
for (fd = i, bit = 1 ; bits && (fd < nfd) ; fd++, bit <<= 1) {
if ((bits & bit) == 0)
continue;
bits &= ~bit;
so = rtems_bsdnet_fdToSocket (fd);
if (so == NULL)
return (EBADF);
if (socket_select (so, flag[msk], tid)) {
obits[msk][fd/NFDBITS] |=
(1 << (fd % NFDBITS));
n++;
}
}
}
}
*retval = n;
return (0);
}
int
select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tv)
{
fd_mask *ibits[3], *obits[3];
fd_set ob[3];
int error, timo;
int retval;
rtems_id tid;
rtems_interval then, now;
rtems_event_set events;
if (nfds < 0)
return (EINVAL);
if (tv) {
timo = tv->tv_sec * hz + tv->tv_usec / tick;
if (timo == 0)
timo = 1;
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
}
else {
timo = 0;
}
#define getbits(name,i) if (name) { \
ibits[i] = &name->fds_bits[0]; \
obits[i] = &ob[i].fds_bits[0]; \
FD_ZERO(&ob[i]); \
} \
else ibits[i] = NULL
getbits (readfds, 0);
getbits (writefds, 1);
getbits (exceptfds, 2);
#undef getbits
rtems_task_ident (RTEMS_SELF, 0, &tid);
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT, &events);
for (;;) {
rtems_bsdnet_semaphore_obtain ();
error = selscan(tid, ibits, obits, nfds, &retval);
rtems_bsdnet_semaphore_release ();
if (error || retval)
break;
if (timo) {
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
timo -= now - then;
if (timo <= 0)
break;
then = now;
}
rtems_event_receive (SBWAIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, timo, &events);
}
#define putbits(name,i) if (name) *name = ob[i]
putbits (readfds, 0);
putbits (writefds, 1);
putbits (exceptfds, 2);
#undef putbits
if (error) {
errno = error;
retval = -1;
}
return (retval);
}

View File

@@ -15,7 +15,7 @@
static char *rtems_hostname; static char *rtems_hostname;
int int
gethostname (char *name, int namelen) gethostname (char *name, size_t namelen)
{ {
char *cp = rtems_hostname; char *cp = rtems_hostname;
@@ -26,7 +26,7 @@ gethostname (char *name, int namelen)
} }
int int
sethostname (char *name, int namelen) sethostname (char *name, size_t namelen)
{ {
char *old, *new; char *old, *new;