diff options
Diffstat (limited to 'mit-pthreads/pthreads/fd_sysv.c')
-rw-r--r-- | mit-pthreads/pthreads/fd_sysv.c | 897 |
1 files changed, 897 insertions, 0 deletions
diff --git a/mit-pthreads/pthreads/fd_sysv.c b/mit-pthreads/pthreads/fd_sysv.c new file mode 100644 index 00000000000..6dc01a49aa4 --- /dev/null +++ b/mit-pthreads/pthreads/fd_sysv.c @@ -0,0 +1,897 @@ +/* ==== fd_sysv.c ============================================================ + * Copyright (c) 1994 by Chris Provenzano, proven@mit.edu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Chris Provenzano. + * 4. The name of Chris Provenzano may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Description : Transforms BSD socket calls to SYSV streams. + * + * 1.00 94/11/19 proven + * -Started coding this file. + */ + +#ifndef lint +static const char rcsid[] = "$Id$"; +#endif + +#include <config.h> +#include <pthread.h> +#include <fcntl.h> +#include <errno.h> + +#if defined (HAVE_SYSCALL_PUTMSG) && defined (HAVE_SYSCALL_GETMSG) && !defined(HAVE_SYSCALL_SOCKETCALL) && !defined(HAVE_SYSCALL_SOCKET) +#define HAVE_STREAMS 1 + +#include <sys/types.h> +#include <sys/uio.h> +#include <sys/socket.h> +#include <sys/stream.h> +#include <sys/stropts.h> +#include <tiuser.h> +#include <sys/tihdr.h> +#include <netinet/in.h> +#include <sys/timod.h> + +#define STREAM_BUF_SIZE sizeof(union T_primitives) + sizeof(struct sockaddr) + +extern struct pthread_queue fd_wait_read, fd_wait_write; + +/* ========================================================================== + * putmsg_timedwait_basic() + */ +static int putmsg_timedwait_basic(int fd, struct strbuf * ctlptr, + struct strbuf * dataptr, int flags, struct timespec * timeout) +{ + + int ret; + + pthread_run->sighandled=0; /* Added by monty */ + while ((ret = machdep_sys_putmsg(fd_table[fd]->fd.i, + ctlptr, dataptr, flags)) < OK) { + if (!(fd_table[fd]->flags & __FD_NONBLOCK) && + ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) { + pthread_sched_prevent(); + + /* queue pthread for a FDW_WAIT */ + SET_PF_WAIT_EVENT(pthread_run); + pthread_run->data.fd.fd = fd_table[fd]->fd.i; + pthread_queue_enq(&fd_wait_write, pthread_run); + + if (timeout) { + /* get current time */ + struct timespec current_time; + machdep_gettimeofday(¤t_time); + sleep_schedule(& current_time, timeout); + + pthread_resched_resume(PS_FDW_WAIT); + + /* We're awake */ + pthread_sched_prevent(); + if (sleep_cancel(pthread_run) == NOTOK) { + CLEAR_PF_DONE_EVENT(pthread_run); + pthread_sched_resume(); + SET_ERRNO(ETIMEDOUT); + ret = -ETIMEDOUT; + break; + } + pthread_sched_resume(); + } else { + pthread_resched_resume(PS_FDW_WAIT); + } + CLEAR_PF_DONE_EVENT(pthread_run); + if (pthread_run->sighandled) /* Added by monty */ + { /* We where aborted */ + SET_ERRNO(EINTR); + ret= -EINTR; + break; + } + } else { + SET_ERRNO(-ret); + break; + } + } + return(ret); +} + +/* ========================================================================== + * putmsg_timedwait() + */ +int putmsg_timedwait(int fd, struct strbuf * ctlptr, struct strbuf * dataptr, + int flags, struct timespec * timeout) +{ + int ret; + + if ((ret = fd_lock(fd, FD_WRITE, timeout)) == OK) { + ret = putmsg_timedwait_basic(fd, ctlptr, dataptr, flags, timeout); + fd_unlock(fd, FD_WRITE); + } + return(ret); +} + +/* ========================================================================== + * putmsg() + */ +int putmsg(int fd, struct strbuf * ctlptr, struct strbuf * dataptr, + int flags) +{ + return(putmsg_timedwait(fd, ctlptr, dataptr, flags, NULL)); +} + +/* ========================================================================== + * getmsg_timedwait_basic() + */ +int getmsg_timedwait_basic(int fd, struct strbuf * ctlptr, + struct strbuf * dataptr, int * flags, struct timespec * timeout) +{ + int ret; + + pthread_run->sighandled=0; /* Added by monty */ + while ((ret = machdep_sys_getmsg(fd_table[fd]->fd.i, + ctlptr, dataptr, flags)) < OK) { + if (!(fd_table[fd]->flags & __FD_NONBLOCK) && + ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) { + pthread_sched_prevent(); + + /* queue pthread for a FDR_WAIT */ + SET_PF_WAIT_EVENT(pthread_run); + pthread_run->data.fd.fd = fd_table[fd]->fd.i; + pthread_queue_enq(&fd_wait_read, pthread_run); + + if (timeout) { + /* get current time */ + struct timespec current_time; + machdep_gettimeofday(¤t_time); + sleep_schedule(& current_time, timeout); + + pthread_resched_resume(PS_FDR_WAIT); + + /* We're awake */ + pthread_sched_prevent(); + if (sleep_cancel(pthread_run) == NOTOK) { + CLEAR_PF_DONE_EVENT(pthread_run); + pthread_sched_resume(); + SET_ERRNO(ETIMEDOUT); + ret = -ETIMEDOUT; + break; + } + pthread_sched_resume(); + } else { + pthread_resched_resume(PS_FDR_WAIT); + } + CLEAR_PF_DONE_EVENT(pthread_run); + if (pthread_run->sighandled) /* Added by monty */ + { /* We where aborted */ + SET_ERRNO(EINTR); + ret= -EINTR; + break; + } + + } else { + SET_ERRNO(-ret); + break; + } + } + return(ret); +} + +/* ========================================================================== + * getmsg_timedwait() + */ +int getmsg_timedwait(int fd, struct strbuf * ctlptr, struct strbuf * dataptr, + int * flags, struct timespec * timeout) +{ + int ret; + + if ((ret = fd_lock(fd, FD_READ, timeout)) == OK) { + ret = getmsg_timedwait_basic(fd, ctlptr, dataptr, flags, timeout); + fd_unlock(fd, FD_READ); + } + return (ret); +} + +/* ========================================================================== + * getmsg() + */ +int getmsg(int fd, struct strbuf * ctlptr, struct strbuf * dataptr, + int * flags) +{ + return(getmsg_timedwait(fd, ctlptr, dataptr, flags, NULL)); +} + +#endif + +/* ========================================================================== + * Here are the berkeley socket functions implemented with stream calls. + * These are not POSIX. + * ======================================================================= */ + +#if (!defined (HAVE_SYSCALL_BIND)) && defined(HAVE_STREAMS) + +/* ========================================================================== + * bind() + */ +int bind(int fd, const struct sockaddr *name, int namelen) +{ + char buf[STREAM_BUF_SIZE]; + union T_primitives * res; + struct T_bind_req * req; + struct T_bind_ack * ack; + struct strbuf strbuf; + int flags, ret; + + if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) + { + req = (struct T_bind_req *)buf; + req->PRIM_type = T_BIND_REQ; + req->ADDR_length = namelen; + req->ADDR_offset = sizeof(struct T_bind_req); + req->CONIND_number = 4; + memcpy(buf + sizeof(struct T_bind_req), name, namelen); + + strbuf.len = sizeof(struct T_bind_req) + namelen; + strbuf.maxlen = STREAM_BUF_SIZE; + strbuf.buf = buf; + + if ((ret=putmsg_timedwait_basic(fd, &strbuf, NULL, 0, NULL)) == OK) + { + memset(buf, 0, STREAM_BUF_SIZE); + + strbuf.len = sizeof(struct T_bind_ack) + namelen; + strbuf.maxlen = STREAM_BUF_SIZE; + strbuf.buf = buf; + flags = 0; + + if ((ret = getmsg_timedwait_basic(fd, &strbuf, NULL, + &flags, NULL)) >= OK) + { + res = (union T_primitives *)buf; + + switch(res->type) { + case T_BIND_ACK: + ret = OK; + break; + default: + SET_ERRNO(EPROTO); /* What should this be? */ + ret = NOTOK; + break; + } + } + else + { + SET_ERRNO(-ret); + ret = NOTOK; + } + } + else + { + SET_ERRNO(-ret); + ret = NOTOK; + } + fd_unlock(fd, FD_RDWR); + } + return(ret); +} + +#endif + +#if (!defined (HAVE_SYSCALL_CONNECT)) && defined(HAVE_STREAMS) + +/* ========================================================================== + * connect() + */ +int connect(int fd, const struct sockaddr *name, int namelen) +{ + char buf[STREAM_BUF_SIZE]; + union T_primitives * res; + struct T_conn_req * req; + struct T_conn_con * con; + struct T_ok_ack * ok; + struct strbuf strbuf; + int flags, ret; + + if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) + { + req = (struct T_conn_req *)buf; + req->PRIM_type = T_CONN_REQ; + req->DEST_length = namelen; + req->DEST_offset = sizeof(struct T_conn_req); + req->OPT_length = 0; + req->OPT_offset = 0; + memcpy(buf + sizeof(struct T_conn_req), name, namelen); + + strbuf.len = sizeof(struct T_conn_req) + namelen; + strbuf.maxlen = STREAM_BUF_SIZE; + strbuf.buf = buf; + + if ((ret=putmsg_timedwait_basic(fd, &strbuf, NULL, 0, NULL)) != OK) + goto err; + + memset(buf, 0, STREAM_BUF_SIZE); + ok = (struct T_ok_ack *)buf; + + strbuf.maxlen = STREAM_BUF_SIZE; + strbuf.len = STREAM_BUF_SIZE; + strbuf.buf = buf; + flags = 0; + + if ((ret=getmsg_timedwait_basic(fd, &strbuf, NULL, &flags, NULL)) < OK) + goto err; /* Fixed by monty */ + if (ok->PRIM_type != T_OK_ACK) + { + ret= -EPROTO; /* What should this be? */ + goto err; + } + + memset(buf, 0, STREAM_BUF_SIZE); + strbuf.maxlen = STREAM_BUF_SIZE; + strbuf.len = STREAM_BUF_SIZE; + strbuf.buf = buf; + flags = 0; + + if ((ret=getmsg_timedwait_basic(fd, &strbuf, NULL, &flags, NULL) < OK)) + goto err; + + res = (union T_primitives *) buf; + switch(res->type) { + case T_CONN_CON: + ret = OK; + break; + case T_DISCON_IND: + ret= -ECONNREFUSED; + goto err; + default: + ret= -EPROTO; /* What should this be? */ + goto err; + } + fd_unlock(fd, FD_RDWR); + } + return(ret); + + err: + fd_unlock(fd, FD_RDWR); + SET_ERRNO(-ret); /* Proably not needed... */ + return NOTOK; +} + +#endif + +#if (!defined (HAVE_SYSCALL_LISTEN)) && defined(HAVE_STREAMS) + +/* ========================================================================== + * listen() + */ +int listen(int fd, int backlog) +{ + return(OK); +} + +#endif + +#if (!defined (HAVE_SYSCALL_SOCKET)) && defined(HAVE_STREAMS) + +extern ssize_t __fd_kern_write(); +static pthread_ssize_t __fd_sysv_read(); +extern int __fd_kern_close(); +extern int __fd_kern_fcntl(); +extern int __fd_kern_writev(); +extern int __fd_kern_readv(); +extern off_t __fd_kern_lseek(); + +/* Normal file operations */ +static struct fd_ops __fd_sysv_ops = { + __fd_kern_write, __fd_sysv_read, __fd_kern_close, __fd_kern_fcntl, + __fd_kern_writev, __fd_kern_readv, __fd_kern_lseek, 1 +}; + +/* ========================================================================== + * read() + */ +static pthread_ssize_t __fd_sysv_read(union fd_data fd_data, int flags, + void *buf, size_t nbytes, struct timespec * timeout) +{ + struct strbuf dataptr; + int fd = fd_data.i; + int getmsg_flags; + int ret; + + getmsg_flags = 0; + dataptr.len = 0; + dataptr.buf = buf; + dataptr.maxlen = nbytes; + + pthread_run->sighandled=0; /* Added by monty */ + while ((ret = machdep_sys_getmsg(fd, NULL, &dataptr, &getmsg_flags)) < OK) { + if (!(fd_table[fd]->flags & __FD_NONBLOCK) && + ((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) { + pthread_sched_prevent(); + + /* queue pthread for a FDR_WAIT */ + pthread_run->data.fd.fd = fd; + SET_PF_WAIT_EVENT(pthread_run); + pthread_queue_enq(&fd_wait_read, pthread_run); + + if (timeout) { + /* get current time */ + struct timespec current_time; + machdep_gettimeofday(¤t_time); + sleep_schedule(& current_time, timeout); + + pthread_resched_resume(PS_FDR_WAIT); + + /* We're awake */ + pthread_sched_prevent(); + if (sleep_cancel(pthread_run) == NOTOK) { + CLEAR_PF_DONE_EVENT(pthread_run); + pthread_sched_resume(); + SET_ERRNO(ETIMEDOUT); + ret = -ETIMEDOUT; + break; + } + pthread_sched_resume(); + } else { + pthread_resched_resume(PS_FDR_WAIT); + } + CLEAR_PF_DONE_EVENT(pthread_run); + if (pthread_run->sighandled) /* Added by monty */ + { /* We where aborted */ + SET_ERRNO(EINTR); + return(NOTOK); + } + } else { + SET_ERRNO(-ret); + return(NOTOK); + break; + } + } + return(dataptr.len); +} + +/* ========================================================================== + * socket_tcp() + */ +static int socket_tcp(int fd) +{ + int ret; + + if ((ret = machdep_sys_open("/dev/tcp", O_RDWR | O_NONBLOCK, 0)) >= OK) { + /* Should fstat the file to determine what type it is */ + fd_table[fd]->ops = & __fd_sysv_ops; + fd_table[fd]->type = FD_FULL_DUPLEX; + fd_table[fd]->fd.i = ret; + fd_table[fd]->flags = 0; + } + return(ret); +} + +/* ========================================================================== + * socket() + */ +int socket(int af, int type, int protocol) +{ + int fd, fd_kern; + + if ((fd = fd_allocate()) < OK) + return (fd); + + switch(af) { + case AF_INET: + switch(type) { + case SOCK_STREAM: + if ((fd_kern = socket_tcp(fd)) >= OK) + return(fd); + SET_ERRNO(-fd_kern); + break; + case SOCK_DGRAM: + if ((fd_kern = machdep_sys_open("/dev/udp", + O_RDWR | O_NONBLOCK, 0)) >= OK) { + /* Should fstat the file to determine what type it is */ + fd_table[fd]->ops = & __fd_sysv_ops; + fd_table[fd]->type = FD_FULL_DUPLEX; + fd_table[fd]->fd.i = fd_kern; + fd_table[fd]->flags = 0; + return(fd); + } + SET_ERRNO(-fd_kern); + break; + default: + SET_ERRNO(EPROTONOSUPPORT); + break; + } + break; + case AF_UNIX: + case AF_ISO: + case AF_NS: + default: + SET_ERRNO(EPROTONOSUPPORT); + break; + } + fd_table[fd]->count = 0; + return(NOTOK); /* Fixed by monty */ +} + +#endif + +#if (!defined (HAVE_SYSCALL_ACCEPT)) && defined(HAVE_STREAMS) + +/* ========================================================================== + * accept_fd() + */ +static int accept_fd(int fd, struct sockaddr *name, int *namelen, char * buf, + int SEQ_number) +{ + struct T_conn_res * res; + struct strbuf strbuf; + int fd_new, fd_kern; + + /* Get a new table entry */ + if ((fd_new = fd_allocate()) < OK) + return(NOTOK); + + /* Get the new kernel entry */ + if (!((fd_kern = socket_tcp(fd_new)) < OK)) { + res = (struct T_conn_res *)buf; + res->PRIM_type = T_CONN_RES; + /* res->QUEUE_ptr = (queue_t *)&fd_kern; */ + res->OPT_length = 0; + res->OPT_offset = 0; + res->SEQ_number = SEQ_number; + + strbuf.maxlen = sizeof(union T_primitives) +sizeof(struct sockaddr); + strbuf.len = sizeof(struct T_conn_ind) + (*namelen); + strbuf.buf = buf; + + { + struct strfdinsert insert; + + insert.ctlbuf.maxlen = (sizeof(union T_primitives) + + sizeof(struct sockaddr)); + insert.ctlbuf.len = sizeof(struct T_conn_ind); + insert.ctlbuf.buf = buf; + insert.databuf.maxlen = 0; + insert.databuf.len = 0; + insert.databuf.buf = NULL; + insert.flags = 0; + insert.fildes = fd_kern; + insert.offset = 4; + /* Should the following be checked ? */ + machdep_sys_ioctl(fd_table[fd]->fd.i, I_FDINSERT, &insert); + } + + /* if (putmsg_timedwait_basic(fd, &strbuf, NULL, 0, NULL) == OK) { + /* return(fd_new); */ + { + int flags = 0; + int ret; + + /* Should the following be checked ? */ + ret = getmsg_timedwait_basic(fd, &strbuf, NULL, &flags, NULL); + return(fd_new); + + } + machdep_sys_close(fd_kern); + } + fd_table[fd_new]->count = 0; + return(NOTOK); +} + + +/* ========================================================================== + * accept() + */ +int accept(int fd, struct sockaddr *name, int *namelen) +{ + char buf[sizeof(union T_primitives) + sizeof(struct sockaddr)]; + struct T_conn_ind * ind; + struct strbuf strbuf; + int flags, ret; + + if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK) + { + ind = (struct T_conn_ind *)buf; + ind->PRIM_type = T_CONN_IND; + ind->SRC_length = (*namelen); + ind->SRC_offset = sizeof(struct T_conn_ind); + ind->OPT_length = 0; + ind->OPT_offset = 0; + ind->SEQ_number = 0; + + strbuf.maxlen = sizeof(union T_primitives) + sizeof(struct sockaddr); + strbuf.len = sizeof(struct T_conn_ind) + (*namelen); + strbuf.buf = buf; + flags = 0; + + if ((ret=getmsg_timedwait_basic(fd, &strbuf, NULL, &flags, NULL)) < OK) + { + SET_ERRNO(-ret); + ret= NOTOK; + } + else + ret = accept_fd(fd, name, namelen, buf, ind->SEQ_number); + fd_unlock(fd, FD_RDWR); + } + return(ret); +} + +#endif /* HAVE_SYSCALL_ACCEPT */ + +#if (!defined (HAVE_SYSCALL_SENDTO)) && defined (HAVE_STREAMS) + +/* ========================================================================== + * sendto_timedwait() + */ +ssize_t sendto_timedwait(int fd, const void * msg, size_t len, int flags, + const struct sockaddr *name, int namelen, struct timespec * timeout) +{ + char buf[STREAM_BUF_SIZE]; + struct T_unitdata_req * req; + struct strbuf dataptr; + struct strbuf ctlptr; + ssize_t ret, prio; + + req = (struct T_unitdata_req *)buf; + req->PRIM_type = T_UNITDATA_REQ; + req->DEST_length = namelen; + req->DEST_offset = sizeof(struct T_unitdata_req); + req->OPT_length = 0; + req->OPT_offset = 0; + memcpy(buf + sizeof(struct T_unitdata_req), name, namelen); + + ctlptr.len = sizeof(struct T_unitdata_req) + namelen; + ctlptr.maxlen = STREAM_BUF_SIZE; + ctlptr.buf = buf; + + dataptr.len = len; + dataptr.maxlen = len; + dataptr.buf = (void *)msg; + + if ((ret = putmsg_timedwait(fd, &ctlptr, &dataptr, 0, timeout)) == OK) { + ret = len; + } + return(ret); +} + +/* ========================================================================== + * sendto() + */ +ssize_t sendto(int fd, const void * msg, size_t len, int flags, + const struct sockaddr *to, int to_len) +{ + return(sendto_timedwait(fd, msg, len, flags, to, to_len, NULL)); +} + +#endif + +#if (!defined (HAVE_SYSCALL_SEND)) && defined (HAVE_STREAMS) + +/* ========================================================================== + * send_timedwait() + */ +ssize_t send_timedwait(int fd, const void * msg, size_t len, int flags, + struct timespec * timeout) +{ + char buf[STREAM_BUF_SIZE]; + struct T_unitdata_req * req; + struct strbuf dataptr; + struct strbuf ctlptr; + ssize_t ret, prio; + + req = (struct T_unitdata_req *)buf; + req->PRIM_type = T_UNITDATA_REQ; + req->DEST_length = 0; + req->DEST_offset = 0; + req->OPT_length = 0; + req->OPT_offset = 0; + + ctlptr.len = sizeof(struct T_unitdata_req); + ctlptr.maxlen = STREAM_BUF_SIZE; + ctlptr.buf = buf; + + dataptr.len = len; + dataptr.maxlen = len; + dataptr.buf = (void *)msg; + + if ((ret = putmsg_timedwait(fd, &ctlptr, &dataptr, 0, timeout)) == OK) { + ret = len; + } + return(ret); +} + +/* ========================================================================== + * send() + */ +ssize_t send(int fd, const void * msg, size_t len, int flags) +{ + return(send_timedwait(fd, msg, len, flags, NULL)); +} + +#endif + +#if (!defined (HAVE_SYSCALL_RECVFROM)) && defined(HAVE_STREAMS) + +/* ========================================================================== + * recvfrom_timedwait() + */ +ssize_t recvfrom_timedwait(int fd, void * msg, size_t len, int flags, + struct sockaddr * name, int * namelen, struct timespec * timeout) +{ + char buf[STREAM_BUF_SIZE]; + struct T_unitdata_ind * ind; + struct strbuf dataptr; + struct strbuf ctlptr; + int ret, prio; + + ctlptr.len = 0; + ctlptr.maxlen = STREAM_BUF_SIZE; + ctlptr.buf = buf; + + dataptr.maxlen = len; + dataptr.len = 0; + dataptr.buf = msg; + + prio = 0; + + ret = getmsg_timedwait(fd, &ctlptr, &dataptr, &prio, timeout); + if (ret >= OK) { + if (name != NULL) { + ind = (struct T_unitdata_ind *)buf; + + if (*namelen > ind->SRC_length) + *namelen = ind->SRC_length; + memcpy(name, buf + ind->SRC_offset, *namelen); + } + ret = dataptr.len; + } + + return(ret); +} + +/* ========================================================================== + * recvfrom() + */ +ssize_t recvfrom(int fd, void * buf, size_t len, int flags, + struct sockaddr * from, int * from_len) +{ + return(recvfrom_timedwait(fd, buf, len, flags, from, from_len, NULL)); +} + +#endif + +#if (!defined (HAVE_SYSCALL_RECV)) && defined(HAVE_STREAMS) + +/* ========================================================================== + * recv_timedwait() + */ +ssize_t recv_timedwait(int fd, void * msg, size_t len, int flags, + struct timespec * timeout) +{ + char buf[STREAM_BUF_SIZE]; + struct T_unitdata_ind * ind; + struct strbuf dataptr; + struct strbuf ctlptr; + int ret, prio; + + ctlptr.len = 0; + ctlptr.maxlen = STREAM_BUF_SIZE; + ctlptr.buf = buf; + + dataptr.maxlen = len; + dataptr.len = 0; + dataptr.buf = msg; + + prio = 0; + + ret = getmsg_timedwait(fd, &ctlptr, &dataptr, &prio, timeout); + if (ret >= OK) + ret = dataptr.len; + + return(ret); +} + +/* ========================================================================== + * recv() + */ +ssize_t recv(int fd, void * buf, size_t len, int flags, + struct sockaddr * from, int * from_len) +{ + return(recv_timedwait(fd, buf, len, flags, NULL)); +} + +#endif + +#if (!defined (HAVE_SYSCALL_SETSOCKOPT)) && defined(HAVE_STREAMS) +/* ========================================================================== + * setsockopt() + */ +int setsockopt(int s, int level, int optname, const void *optval, int optlen) +{ + return(0); +} +#endif + +struct foo { /* Used by getsockname and getpeername */ + long a; + int b; + struct sockaddr *name; +}; + +#if (!defined (HAVE_SYSCALL_GETSOCKNAME)) && defined(HAVE_STREAMS) +/* ========================================================================== + * getsockname() + */ + + +int getsockname(int s, struct sockaddr *name, int *namelen) +{ + struct foo foo; + int i; + if (*namelen < sizeof(struct sockaddr)) { + SET_ERRNO(ENOMEM); + return(-1); + } + foo.a = 0x84; + foo.b = 0; + foo.name = name; + i = ioctl(s, TI_GETMYNAME, &foo); + *namelen = foo.b; + return(i); +} +#endif + +#if (!defined (HAVE_SYSCALL_GETPEERNAME)) && defined(HAVE_STREAMS) +/* ========================================================================== + * getpeername() ; Added by Monty + */ + +int getpeername(int s, struct sockaddr *name, int *namelen) +{ + struct foo foo; + int i; + if (*namelen < sizeof(struct sockaddr)) { + SET_ERRNO(ENOMEM); + return(-1); + } + foo.a = 0x84; /* Max length ? */ + foo.b = 0; /* Return length */ + foo.name = name; /* Return buffer */ + i = ioctl(s, TI_GETPEERNAME, &foo); + *namelen = foo.b; + return(i); +} +#endif + + +#if (!defined (HAVE_SYSCALL_SHUTDOWN)) && defined(HAVE_STREAMS) +/* ========================================================================== + * shutdown() + */ + +int shutdown(int s, int how) +{ + return(0); +} +#endif |