1
/* ==== fd_sysv.c ============================================================
2
* Copyright (c) 1994 by Chris Provenzano, proven@mit.edu
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. All advertising materials mentioning features or use of this software
14
* must display the following acknowledgement:
15
* This product includes software developed by Chris Provenzano.
16
* 4. The name of Chris Provenzano may not be used to endorse or promote
17
* products derived from this software without specific prior written
20
* THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
21
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY
24
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
* Description : Transforms BSD socket calls to SYSV streams.
34
* 1.00 94/11/19 proven
35
* -Started coding this file.
39
static const char rcsid[] = "$Id$";
47
#if defined (HAVE_SYSCALL_PUTMSG) && defined (HAVE_SYSCALL_GETMSG) && !defined(HAVE_SYSCALL_SOCKETCALL) && !defined(HAVE_SYSCALL_SOCKET)
48
#define HAVE_STREAMS 1
50
#include <sys/types.h>
52
#include <sys/socket.h>
53
#include <sys/stream.h>
54
#include <sys/stropts.h>
56
#include <sys/tihdr.h>
57
#include <netinet/in.h>
58
#include <sys/timod.h>
60
#define STREAM_BUF_SIZE sizeof(union T_primitives) + sizeof(struct sockaddr)
62
extern struct pthread_queue fd_wait_read, fd_wait_write;
64
/* ==========================================================================
65
* putmsg_timedwait_basic()
67
static int putmsg_timedwait_basic(int fd, struct strbuf * ctlptr,
68
struct strbuf * dataptr, int flags, struct timespec * timeout)
73
pthread_run->sighandled=0; /* Added by monty */
74
while ((ret = machdep_sys_putmsg(fd_table[fd]->fd.i,
75
ctlptr, dataptr, flags)) < OK) {
76
if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
77
((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
78
pthread_sched_prevent();
80
/* queue pthread for a FDW_WAIT */
81
SET_PF_WAIT_EVENT(pthread_run);
82
pthread_run->data.fd.fd = fd_table[fd]->fd.i;
83
pthread_queue_enq(&fd_wait_write, pthread_run);
86
/* get current time */
87
struct timespec current_time;
88
machdep_gettimeofday(¤t_time);
89
sleep_schedule(& current_time, timeout);
91
pthread_resched_resume(PS_FDW_WAIT);
94
pthread_sched_prevent();
95
if (sleep_cancel(pthread_run) == NOTOK) {
96
CLEAR_PF_DONE_EVENT(pthread_run);
97
pthread_sched_resume();
102
pthread_sched_resume();
104
pthread_resched_resume(PS_FDW_WAIT);
106
CLEAR_PF_DONE_EVENT(pthread_run);
107
if (pthread_run->sighandled) /* Added by monty */
108
{ /* We where aborted */
121
/* ==========================================================================
124
int putmsg_timedwait(int fd, struct strbuf * ctlptr, struct strbuf * dataptr,
125
int flags, struct timespec * timeout)
129
if ((ret = fd_lock(fd, FD_WRITE, timeout)) == OK) {
130
ret = putmsg_timedwait_basic(fd, ctlptr, dataptr, flags, timeout);
131
fd_unlock(fd, FD_WRITE);
136
/* ==========================================================================
139
int putmsg(int fd, struct strbuf * ctlptr, struct strbuf * dataptr,
142
return(putmsg_timedwait(fd, ctlptr, dataptr, flags, NULL));
145
/* ==========================================================================
146
* getmsg_timedwait_basic()
148
int getmsg_timedwait_basic(int fd, struct strbuf * ctlptr,
149
struct strbuf * dataptr, int * flags, struct timespec * timeout)
153
pthread_run->sighandled=0; /* Added by monty */
154
while ((ret = machdep_sys_getmsg(fd_table[fd]->fd.i,
155
ctlptr, dataptr, flags)) < OK) {
156
if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
157
((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
158
pthread_sched_prevent();
160
/* queue pthread for a FDR_WAIT */
161
SET_PF_WAIT_EVENT(pthread_run);
162
pthread_run->data.fd.fd = fd_table[fd]->fd.i;
163
pthread_queue_enq(&fd_wait_read, pthread_run);
166
/* get current time */
167
struct timespec current_time;
168
machdep_gettimeofday(¤t_time);
169
sleep_schedule(& current_time, timeout);
171
pthread_resched_resume(PS_FDR_WAIT);
174
pthread_sched_prevent();
175
if (sleep_cancel(pthread_run) == NOTOK) {
176
CLEAR_PF_DONE_EVENT(pthread_run);
177
pthread_sched_resume();
178
SET_ERRNO(ETIMEDOUT);
182
pthread_sched_resume();
184
pthread_resched_resume(PS_FDR_WAIT);
186
CLEAR_PF_DONE_EVENT(pthread_run);
187
if (pthread_run->sighandled) /* Added by monty */
188
{ /* We where aborted */
202
/* ==========================================================================
205
int getmsg_timedwait(int fd, struct strbuf * ctlptr, struct strbuf * dataptr,
206
int * flags, struct timespec * timeout)
210
if ((ret = fd_lock(fd, FD_READ, timeout)) == OK) {
211
ret = getmsg_timedwait_basic(fd, ctlptr, dataptr, flags, timeout);
212
fd_unlock(fd, FD_READ);
217
/* ==========================================================================
220
int getmsg(int fd, struct strbuf * ctlptr, struct strbuf * dataptr,
223
return(getmsg_timedwait(fd, ctlptr, dataptr, flags, NULL));
228
/* ==========================================================================
229
* Here are the berkeley socket functions implemented with stream calls.
230
* These are not POSIX.
231
* ======================================================================= */
233
#if (!defined (HAVE_SYSCALL_BIND)) && defined(HAVE_STREAMS)
235
/* ==========================================================================
238
int bind(int fd, const struct sockaddr *name, int namelen)
240
char buf[STREAM_BUF_SIZE];
241
union T_primitives * res;
242
struct T_bind_req * req;
243
struct T_bind_ack * ack;
244
struct strbuf strbuf;
247
if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK)
249
req = (struct T_bind_req *)buf;
250
req->PRIM_type = T_BIND_REQ;
251
req->ADDR_length = namelen;
252
req->ADDR_offset = sizeof(struct T_bind_req);
253
req->CONIND_number = 4;
254
memcpy(buf + sizeof(struct T_bind_req), name, namelen);
256
strbuf.len = sizeof(struct T_bind_req) + namelen;
257
strbuf.maxlen = STREAM_BUF_SIZE;
260
if ((ret=putmsg_timedwait_basic(fd, &strbuf, NULL, 0, NULL)) == OK)
262
memset(buf, 0, STREAM_BUF_SIZE);
264
strbuf.len = sizeof(struct T_bind_ack) + namelen;
265
strbuf.maxlen = STREAM_BUF_SIZE;
269
if ((ret = getmsg_timedwait_basic(fd, &strbuf, NULL,
270
&flags, NULL)) >= OK)
272
res = (union T_primitives *)buf;
279
SET_ERRNO(EPROTO); /* What should this be? */
295
fd_unlock(fd, FD_RDWR);
302
#if (!defined (HAVE_SYSCALL_CONNECT)) && defined(HAVE_STREAMS)
304
/* ==========================================================================
307
int connect(int fd, const struct sockaddr *name, int namelen)
309
char buf[STREAM_BUF_SIZE];
310
union T_primitives * res;
311
struct T_conn_req * req;
312
struct T_conn_con * con;
313
struct T_ok_ack * ok;
314
struct strbuf strbuf;
317
if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK)
319
req = (struct T_conn_req *)buf;
320
req->PRIM_type = T_CONN_REQ;
321
req->DEST_length = namelen;
322
req->DEST_offset = sizeof(struct T_conn_req);
325
memcpy(buf + sizeof(struct T_conn_req), name, namelen);
327
strbuf.len = sizeof(struct T_conn_req) + namelen;
328
strbuf.maxlen = STREAM_BUF_SIZE;
331
if ((ret=putmsg_timedwait_basic(fd, &strbuf, NULL, 0, NULL)) != OK)
334
memset(buf, 0, STREAM_BUF_SIZE);
335
ok = (struct T_ok_ack *)buf;
337
strbuf.maxlen = STREAM_BUF_SIZE;
338
strbuf.len = STREAM_BUF_SIZE;
342
if ((ret=getmsg_timedwait_basic(fd, &strbuf, NULL, &flags, NULL)) < OK)
343
goto err; /* Fixed by monty */
344
if (ok->PRIM_type != T_OK_ACK)
346
ret= -EPROTO; /* What should this be? */
350
memset(buf, 0, STREAM_BUF_SIZE);
351
strbuf.maxlen = STREAM_BUF_SIZE;
352
strbuf.len = STREAM_BUF_SIZE;
356
if ((ret=getmsg_timedwait_basic(fd, &strbuf, NULL, &flags, NULL) < OK))
359
res = (union T_primitives *) buf;
368
ret= -EPROTO; /* What should this be? */
371
fd_unlock(fd, FD_RDWR);
376
fd_unlock(fd, FD_RDWR);
377
SET_ERRNO(-ret); /* Proably not needed... */
383
#if (!defined (HAVE_SYSCALL_LISTEN)) && defined(HAVE_STREAMS)
385
/* ==========================================================================
388
int listen(int fd, int backlog)
395
#if (!defined (HAVE_SYSCALL_SOCKET)) && defined(HAVE_STREAMS)
397
extern ssize_t __fd_kern_write();
398
static pthread_ssize_t __fd_sysv_read();
399
extern int __fd_kern_close();
400
extern int __fd_kern_fcntl();
401
extern int __fd_kern_writev();
402
extern int __fd_kern_readv();
403
extern off_t __fd_kern_lseek();
405
/* Normal file operations */
406
static struct fd_ops __fd_sysv_ops = {
407
__fd_kern_write, __fd_sysv_read, __fd_kern_close, __fd_kern_fcntl,
408
__fd_kern_writev, __fd_kern_readv, __fd_kern_lseek, 1
411
/* ==========================================================================
414
static pthread_ssize_t __fd_sysv_read(union fd_data fd_data, int flags,
415
void *buf, size_t nbytes, struct timespec * timeout)
417
struct strbuf dataptr;
425
dataptr.maxlen = nbytes;
427
pthread_run->sighandled=0; /* Added by monty */
428
while ((ret = machdep_sys_getmsg(fd, NULL, &dataptr, &getmsg_flags)) < OK) {
429
if (!(fd_table[fd]->flags & __FD_NONBLOCK) &&
430
((ret == -EWOULDBLOCK) || (ret == -EAGAIN))) {
431
pthread_sched_prevent();
433
/* queue pthread for a FDR_WAIT */
434
pthread_run->data.fd.fd = fd;
435
SET_PF_WAIT_EVENT(pthread_run);
436
pthread_queue_enq(&fd_wait_read, pthread_run);
439
/* get current time */
440
struct timespec current_time;
441
machdep_gettimeofday(¤t_time);
442
sleep_schedule(& current_time, timeout);
444
pthread_resched_resume(PS_FDR_WAIT);
447
pthread_sched_prevent();
448
if (sleep_cancel(pthread_run) == NOTOK) {
449
CLEAR_PF_DONE_EVENT(pthread_run);
450
pthread_sched_resume();
451
SET_ERRNO(ETIMEDOUT);
455
pthread_sched_resume();
457
pthread_resched_resume(PS_FDR_WAIT);
459
CLEAR_PF_DONE_EVENT(pthread_run);
460
if (pthread_run->sighandled) /* Added by monty */
461
{ /* We where aborted */
474
/* ==========================================================================
477
static int socket_tcp(int fd)
481
if ((ret = machdep_sys_open("/dev/tcp", O_RDWR | O_NONBLOCK, 0)) >= OK) {
482
/* Should fstat the file to determine what type it is */
483
fd_table[fd]->ops = & __fd_sysv_ops;
484
fd_table[fd]->type = FD_FULL_DUPLEX;
485
fd_table[fd]->fd.i = ret;
486
fd_table[fd]->flags = 0;
491
/* ==========================================================================
494
int socket(int af, int type, int protocol)
498
if ((fd = fd_allocate()) < OK)
505
if ((fd_kern = socket_tcp(fd)) >= OK)
510
if ((fd_kern = machdep_sys_open("/dev/udp",
511
O_RDWR | O_NONBLOCK, 0)) >= OK) {
512
/* Should fstat the file to determine what type it is */
513
fd_table[fd]->ops = & __fd_sysv_ops;
514
fd_table[fd]->type = FD_FULL_DUPLEX;
515
fd_table[fd]->fd.i = fd_kern;
516
fd_table[fd]->flags = 0;
522
SET_ERRNO(EPROTONOSUPPORT);
530
SET_ERRNO(EPROTONOSUPPORT);
533
fd_table[fd]->count = 0;
534
return(NOTOK); /* Fixed by monty */
539
#if (!defined (HAVE_SYSCALL_ACCEPT)) && defined(HAVE_STREAMS)
541
/* ==========================================================================
544
static int accept_fd(int fd, struct sockaddr *name, int *namelen, char * buf,
547
struct T_conn_res * res;
548
struct strbuf strbuf;
551
/* Get a new table entry */
552
if ((fd_new = fd_allocate()) < OK)
555
/* Get the new kernel entry */
556
if (!((fd_kern = socket_tcp(fd_new)) < OK)) {
557
res = (struct T_conn_res *)buf;
558
res->PRIM_type = T_CONN_RES;
559
/* res->QUEUE_ptr = (queue_t *)&fd_kern; */
562
res->SEQ_number = SEQ_number;
564
strbuf.maxlen = sizeof(union T_primitives) +sizeof(struct sockaddr);
565
strbuf.len = sizeof(struct T_conn_ind) + (*namelen);
569
struct strfdinsert insert;
571
insert.ctlbuf.maxlen = (sizeof(union T_primitives) +
572
sizeof(struct sockaddr));
573
insert.ctlbuf.len = sizeof(struct T_conn_ind);
574
insert.ctlbuf.buf = buf;
575
insert.databuf.maxlen = 0;
576
insert.databuf.len = 0;
577
insert.databuf.buf = NULL;
579
insert.fildes = fd_kern;
581
/* Should the following be checked ? */
582
machdep_sys_ioctl(fd_table[fd]->fd.i, I_FDINSERT, &insert);
585
/* if (putmsg_timedwait_basic(fd, &strbuf, NULL, 0, NULL) == OK) {
586
/* return(fd_new); */
591
/* Should the following be checked ? */
592
ret = getmsg_timedwait_basic(fd, &strbuf, NULL, &flags, NULL);
596
machdep_sys_close(fd_kern);
598
fd_table[fd_new]->count = 0;
603
/* ==========================================================================
606
int accept(int fd, struct sockaddr *name, int *namelen)
608
char buf[sizeof(union T_primitives) + sizeof(struct sockaddr)];
609
struct T_conn_ind * ind;
610
struct strbuf strbuf;
613
if ((ret = fd_lock(fd, FD_RDWR, NULL)) == OK)
615
ind = (struct T_conn_ind *)buf;
616
ind->PRIM_type = T_CONN_IND;
617
ind->SRC_length = (*namelen);
618
ind->SRC_offset = sizeof(struct T_conn_ind);
623
strbuf.maxlen = sizeof(union T_primitives) + sizeof(struct sockaddr);
624
strbuf.len = sizeof(struct T_conn_ind) + (*namelen);
628
if ((ret=getmsg_timedwait_basic(fd, &strbuf, NULL, &flags, NULL)) < OK)
634
ret = accept_fd(fd, name, namelen, buf, ind->SEQ_number);
635
fd_unlock(fd, FD_RDWR);
640
#endif /* HAVE_SYSCALL_ACCEPT */
642
#if (!defined (HAVE_SYSCALL_SENDTO)) && defined (HAVE_STREAMS)
644
/* ==========================================================================
647
ssize_t sendto_timedwait(int fd, const void * msg, size_t len, int flags,
648
const struct sockaddr *name, int namelen, struct timespec * timeout)
650
char buf[STREAM_BUF_SIZE];
651
struct T_unitdata_req * req;
652
struct strbuf dataptr;
653
struct strbuf ctlptr;
656
req = (struct T_unitdata_req *)buf;
657
req->PRIM_type = T_UNITDATA_REQ;
658
req->DEST_length = namelen;
659
req->DEST_offset = sizeof(struct T_unitdata_req);
662
memcpy(buf + sizeof(struct T_unitdata_req), name, namelen);
664
ctlptr.len = sizeof(struct T_unitdata_req) + namelen;
665
ctlptr.maxlen = STREAM_BUF_SIZE;
669
dataptr.maxlen = len;
670
dataptr.buf = (void *)msg;
672
if ((ret = putmsg_timedwait(fd, &ctlptr, &dataptr, 0, timeout)) == OK) {
678
/* ==========================================================================
681
ssize_t sendto(int fd, const void * msg, size_t len, int flags,
682
const struct sockaddr *to, int to_len)
684
return(sendto_timedwait(fd, msg, len, flags, to, to_len, NULL));
689
#if (!defined (HAVE_SYSCALL_SEND)) && defined (HAVE_STREAMS)
691
/* ==========================================================================
694
ssize_t send_timedwait(int fd, const void * msg, size_t len, int flags,
695
struct timespec * timeout)
697
char buf[STREAM_BUF_SIZE];
698
struct T_unitdata_req * req;
699
struct strbuf dataptr;
700
struct strbuf ctlptr;
703
req = (struct T_unitdata_req *)buf;
704
req->PRIM_type = T_UNITDATA_REQ;
705
req->DEST_length = 0;
706
req->DEST_offset = 0;
710
ctlptr.len = sizeof(struct T_unitdata_req);
711
ctlptr.maxlen = STREAM_BUF_SIZE;
715
dataptr.maxlen = len;
716
dataptr.buf = (void *)msg;
718
if ((ret = putmsg_timedwait(fd, &ctlptr, &dataptr, 0, timeout)) == OK) {
724
/* ==========================================================================
727
ssize_t send(int fd, const void * msg, size_t len, int flags)
729
return(send_timedwait(fd, msg, len, flags, NULL));
734
#if (!defined (HAVE_SYSCALL_RECVFROM)) && defined(HAVE_STREAMS)
736
/* ==========================================================================
737
* recvfrom_timedwait()
739
ssize_t recvfrom_timedwait(int fd, void * msg, size_t len, int flags,
740
struct sockaddr * name, int * namelen, struct timespec * timeout)
742
char buf[STREAM_BUF_SIZE];
743
struct T_unitdata_ind * ind;
744
struct strbuf dataptr;
745
struct strbuf ctlptr;
749
ctlptr.maxlen = STREAM_BUF_SIZE;
752
dataptr.maxlen = len;
758
ret = getmsg_timedwait(fd, &ctlptr, &dataptr, &prio, timeout);
761
ind = (struct T_unitdata_ind *)buf;
763
if (*namelen > ind->SRC_length)
764
*namelen = ind->SRC_length;
765
memcpy(name, buf + ind->SRC_offset, *namelen);
773
/* ==========================================================================
776
ssize_t recvfrom(int fd, void * buf, size_t len, int flags,
777
struct sockaddr * from, int * from_len)
779
return(recvfrom_timedwait(fd, buf, len, flags, from, from_len, NULL));
784
#if (!defined (HAVE_SYSCALL_RECV)) && defined(HAVE_STREAMS)
786
/* ==========================================================================
789
ssize_t recv_timedwait(int fd, void * msg, size_t len, int flags,
790
struct timespec * timeout)
792
char buf[STREAM_BUF_SIZE];
793
struct T_unitdata_ind * ind;
794
struct strbuf dataptr;
795
struct strbuf ctlptr;
799
ctlptr.maxlen = STREAM_BUF_SIZE;
802
dataptr.maxlen = len;
808
ret = getmsg_timedwait(fd, &ctlptr, &dataptr, &prio, timeout);
815
/* ==========================================================================
818
ssize_t recv(int fd, void * buf, size_t len, int flags,
819
struct sockaddr * from, int * from_len)
821
return(recv_timedwait(fd, buf, len, flags, NULL));
826
#if (!defined (HAVE_SYSCALL_SETSOCKOPT)) && defined(HAVE_STREAMS)
827
/* ==========================================================================
830
int setsockopt(int s, int level, int optname, const void *optval, int optlen)
836
struct foo { /* Used by getsockname and getpeername */
839
struct sockaddr *name;
842
#if (!defined (HAVE_SYSCALL_GETSOCKNAME)) && defined(HAVE_STREAMS)
843
/* ==========================================================================
848
int getsockname(int s, struct sockaddr *name, int *namelen)
852
if (*namelen < sizeof(struct sockaddr)) {
859
i = ioctl(s, TI_GETMYNAME, &foo);
865
#if (!defined (HAVE_SYSCALL_GETPEERNAME)) && defined(HAVE_STREAMS)
866
/* ==========================================================================
867
* getpeername() ; Added by Monty
870
int getpeername(int s, struct sockaddr *name, int *namelen)
874
if (*namelen < sizeof(struct sockaddr)) {
878
foo.a = 0x84; /* Max length ? */
879
foo.b = 0; /* Return length */
880
foo.name = name; /* Return buffer */
881
i = ioctl(s, TI_GETPEERNAME, &foo);
888
#if (!defined (HAVE_SYSCALL_SHUTDOWN)) && defined(HAVE_STREAMS)
889
/* ==========================================================================
893
int shutdown(int s, int how)