xref: /openbsd-src/gnu/usr.bin/cvs/os2/porttcp.c (revision 13571821e83933f3c1d7fd1ab5ff9cd54f0eea7f)
1*13571821Stholo /****************************************************************
2*13571821Stholo **
3*13571821Stholo **	PORTTCP.C	- Support for portable TCP/IP
4*13571821Stholo **
5*13571821Stholo ****************************************************************/
6*13571821Stholo 
7*13571821Stholo #define TCPIP_IBM_NOHIDE
8*13571821Stholo #include	<stdio.h>
9*13571821Stholo #include	"tcpip.h"
10*13571821Stholo 
11*13571821Stholo /*
12*13571821Stholo  * Common unknown error buffer
13*13571821Stholo  */
14*13571821Stholo static char ErrUnknownBuf[36];
15*13571821Stholo 
16*13571821Stholo #ifndef SockStrError
17*13571821Stholo 
18*13571821Stholo /****************************************************************
19*13571821Stholo  *	Routine: SockStrError
20*13571821Stholo  *	Returns: Pointer to static buffer
21*13571821Stholo  *	Action : Convert SOCK_ERRNO into error text
22*13571821Stholo  ****************************************************************/
23*13571821Stholo 
24*13571821Stholo const char *
SockStrError(int SockErrno)25*13571821Stholo SockStrError(int SockErrno)
26*13571821Stholo {
27*13571821Stholo #if defined (TCPIP_IBM)  && defined (IBM_CPP)
28*13571821Stholo   switch (SockErrno)
29*13571821Stholo     {
30*13571821Stholo     case SOCEPERM:		return "Not owner";
31*13571821Stholo     case SOCESRCH:		return "No such process";
32*13571821Stholo     case SOCEINTR:		return "Interrupted system call";
33*13571821Stholo     case SOCENXIO:		return "No such device or address";
34*13571821Stholo     case SOCEBADF:		return "Bad file number";
35*13571821Stholo     case SOCEACCES:		return "Permission denied";
36*13571821Stholo     case SOCEFAULT:		return "Bad address";
37*13571821Stholo     case SOCEINVAL:		return "Invalid argument";
38*13571821Stholo     case SOCEMFILE:		return "Too many open files";
39*13571821Stholo     case SOCEPIPE:		return "Broken pipe";
40*13571821Stholo     case SOCEOS2ERR:		return "OS/2 Error";
41*13571821Stholo     case SOCEWOULDBLOCK:	return "Operation would block";
42*13571821Stholo     case SOCEINPROGRESS:	return "Operation now in progress";
43*13571821Stholo     case SOCEALREADY:		return "Operation already in progress";
44*13571821Stholo     case SOCENOTSOCK:		return "Socket operation on non-socket";
45*13571821Stholo     case SOCEDESTADDRREQ:	return "Destination address required";
46*13571821Stholo     case SOCEMSGSIZE:		return "Message too long";
47*13571821Stholo     case SOCEPROTOTYPE:		return "Protocol wrong type for socket";
48*13571821Stholo     case SOCENOPROTOOPT:	return "Protocol not available";
49*13571821Stholo     case SOCEPROTONOSUPPORT:    return "Protocol not supported";
50*13571821Stholo     case SOCESOCKTNOSUPPORT:    return "Socket type not supported";
51*13571821Stholo     case SOCEOPNOTSUPP:		return "Operation not supported on socket";
52*13571821Stholo     case SOCEPFNOSUPPORT:	return "Protocol family not supported";
53*13571821Stholo     case SOCEAFNOSUPPORT:
54*13571821Stholo       return "Address family not supported by protocol family";
55*13571821Stholo     case SOCEADDRINUSE:		return "Address already in use";
56*13571821Stholo     case SOCEADDRNOTAVAIL:	return "Can't assign requested address";
57*13571821Stholo     case SOCENETDOWN:		return "Network is down";
58*13571821Stholo     case SOCENETUNREACH:	return "Network is unreachable";
59*13571821Stholo     case SOCENETRESET:		return "Network dropped connection on reset";
60*13571821Stholo     case SOCECONNABORTED:	return "Software caused connection abort";
61*13571821Stholo     case SOCECONNRESET:		return "Connection reset by peer";
62*13571821Stholo     case SOCENOBUFS:		return "No buffer space available";
63*13571821Stholo     case SOCEISCONN:		return "Socket is already connected";
64*13571821Stholo     case SOCENOTCONN:		return "Socket is not connected";
65*13571821Stholo     case SOCESHUTDOWN:		return "Can't send after socket shutdown";
66*13571821Stholo     case SOCETOOMANYREFS:	return "Too many references: can't splice";
67*13571821Stholo     case SOCETIMEDOUT:		return "Connection timed out";
68*13571821Stholo     case SOCECONNREFUSED:	return "Connection refused";
69*13571821Stholo     case SOCELOOP:		return "Too many levels of symbolic links";
70*13571821Stholo     case SOCENAMETOOLONG:	return "File name too long";
71*13571821Stholo     case SOCEHOSTDOWN:		return "Host is down";
72*13571821Stholo     case SOCEHOSTUNREACH:	return "No route to host";
73*13571821Stholo     case SOCENOTEMPTY:		return "Directory not empty";
74*13571821Stholo 
75*13571821Stholo     default:
76*13571821Stholo       sprintf( ErrUnknownBuf, "SockStrErrno( %d ) unknown", SockErrno );
77*13571821Stholo       return ErrUnknownBuf;
78*13571821Stholo     }
79*13571821Stholo #else
80*13571821Stholo #error	SockStrError not supported for this OS
81*13571821Stholo #endif
82*13571821Stholo }
83*13571821Stholo 
84*13571821Stholo #endif /* SockStrError */
85*13571821Stholo 
86*13571821Stholo 
87*13571821Stholo /****************************************************************
88*13571821Stholo  *	Routine: HostStrError
89*13571821Stholo  *	Returns: Pointer to static buffer
90*13571821Stholo  *	Action : Convert HOST_ERRNO into error text
91*13571821Stholo  ****************************************************************/
92*13571821Stholo 
93*13571821Stholo const char *
HostStrError(int HostErrno)94*13571821Stholo HostStrError(int HostErrno)
95*13571821Stholo {
96*13571821Stholo   switch (HostErrno)
97*13571821Stholo     {
98*13571821Stholo     case HOST_NOT_FOUND:
99*13571821Stholo       return "Host not found";
100*13571821Stholo     case TRY_AGAIN:
101*13571821Stholo       return "Host not found (suggest try again)";
102*13571821Stholo     case NO_RECOVERY:
103*13571821Stholo       return "Non-recoverable error: FORMERR, REFUSED, NOTIMP";
104*13571821Stholo     case NO_DATA:
105*13571821Stholo       return "No Data (valid name, but no record of requested type)";
106*13571821Stholo 
107*13571821Stholo     default:
108*13571821Stholo       sprintf( ErrUnknownBuf, "HostStrErrno( %d ) unknown", HostErrno );
109*13571821Stholo       return ErrUnknownBuf;
110*13571821Stholo     }
111*13571821Stholo }
112*13571821Stholo 
113*13571821Stholo 
114*13571821Stholo #if defined( TCPIP_IBM )
115*13571821Stholo /****************************************************************
116*13571821Stholo  * Routine: IbmSockSend
117*13571821Stholo  * Returns: same as send
118*13571821Stholo  * Action : Do the right thing for IBM TCP/IP which includes
119*13571821Stholo  *	    the following two stupidities:
120*13571821Stholo  *		1) Never try to send more than 32K
121*13571821Stholo  *		2) Never pass a buffer that crosses a 64K boundary
122*13571821Stholo  *     	 If Flags is non-zero, this function only attempts
123*13571821Stholo  *	 to deal with condition (1) above.
124*13571821Stholo  ****************************************************************/
125*13571821Stholo 
126*13571821Stholo int
IbmSockSend(int Socket,const void * Buffer,int Len,int Flags)127*13571821Stholo IbmSockSend (int Socket, const void *Buffer, int Len, int Flags)
128*13571821Stholo {
129*13571821Stholo 	int Sent, ToSend, TotalSent = 0;
130*13571821Stholo 
131*13571821Stholo 	const char *Tmp = Buffer;
132*13571821Stholo 
133*13571821Stholo     /*
134*13571821Stholo      * If Flags have been passed in, the 64K boundary optimization
135*13571821Stholo      * can not be performed.  For example, MSG_PEEK would not work
136*13571821Stholo      * correctly.
137*13571821Stholo      */
138*13571821Stholo 	if (Flags)
139*13571821Stholo           return send (Socket, (char *) Buffer, min (0x7FFF, Len), Flags);
140*13571821Stholo 
141*13571821Stholo 	do
142*13571821Stholo         {
143*13571821Stholo           /* Never send across a 64K boundary */
144*13571821Stholo           ToSend = min (Len, (int) (0x10000 -  (0xFFFF & (long) Tmp)));
145*13571821Stholo 
146*13571821Stholo           /* Never send more than 32K */
147*13571821Stholo           if (ToSend > 0x7FFF)
148*13571821Stholo             ToSend = 0x7FFF;
149*13571821Stholo 
150*13571821Stholo           Sent = send (Socket, (char *) Tmp, ToSend, 0);
151*13571821Stholo           if (Sent < 0)
152*13571821Stholo             {
153*13571821Stholo               if ((TotalSent > 0) && (SOCK_ERRNO == EWOULDBLOCK))
154*13571821Stholo                 return TotalSent;
155*13571821Stholo               if (SOCK_ERRNO == EINTR)
156*13571821Stholo                 continue;
157*13571821Stholo               return Sent;
158*13571821Stholo             }
159*13571821Stholo           if (Sent < ToSend)
160*13571821Stholo             return TotalSent + Sent;
161*13571821Stholo 
162*13571821Stholo           Tmp += Sent;
163*13571821Stholo           TotalSent += Sent;
164*13571821Stholo           Len -= Sent;
165*13571821Stholo 	} while (Len > 0);
166*13571821Stholo 
167*13571821Stholo 	return TotalSent;
168*13571821Stholo }
169*13571821Stholo 
170*13571821Stholo 
171*13571821Stholo 
172*13571821Stholo /****************************************************************
173*13571821Stholo  * Routine: IbmSockRecv
174*13571821Stholo  * Returns: same as recv
175*13571821Stholo  * Action : Do the right thing for IBM TCP/IP which includes
176*13571821Stholo  *          the following two stupidities:
177*13571821Stholo  *			1) Never try to recv more than 32K
178*13571821Stholo  *			2) Never pass a buffer that crosses a 64K boundary
179*13571821Stholo  *		 If Flags is non-zero, this function only attempts
180*13571821Stholo  *		 to deal with condition (1) above.
181*13571821Stholo  ****************************************************************/
182*13571821Stholo 
183*13571821Stholo int
IbmSockRecv(int Socket,const void * Buffer,int Len,int Flags)184*13571821Stholo IbmSockRecv (int Socket, const void *Buffer, int Len, int Flags)
185*13571821Stholo {
186*13571821Stholo   int Recvd, ToRecv, TotalRecvd = 0;
187*13571821Stholo 
188*13571821Stholo   char *Tmp = Buffer;
189*13571821Stholo 
190*13571821Stholo   /* If Flags have been passed in, the 64K boundary optimization
191*13571821Stholo      probably can not be performed. */
192*13571821Stholo 
193*13571821Stholo 	if (Flags)
194*13571821Stholo           return recv (Socket, Buffer, min (0x7FFF, Len), Flags);
195*13571821Stholo 
196*13571821Stholo 	do
197*13571821Stholo 	{
198*13571821Stholo           /* Never send across a 64K boundary */
199*13571821Stholo           ToRecv = min( Len, (int)( 0x10000 - ( 0xFFFF & (long)Tmp )));
200*13571821Stholo 
201*13571821Stholo           /* Never send more than 32K */
202*13571821Stholo           if( ToRecv > 0x7FFF )
203*13571821Stholo             ToRecv = 0x7FFF;
204*13571821Stholo 
205*13571821Stholo           Recvd = recv (Socket, Tmp, ToRecv, 0);
206*13571821Stholo           if (Recvd <= 0)
207*13571821Stholo             {
208*13571821Stholo               if ((TotalRecvd > 0)
209*13571821Stholo                   && (Recvd == 0 || (SOCK_ERRNO == EWOULDBLOCK )))
210*13571821Stholo                 return TotalRecvd;
211*13571821Stholo               if (SOCK_ERRNO == EINTR)
212*13571821Stholo                 continue;
213*13571821Stholo 
214*13571821Stholo               return Recvd;
215*13571821Stholo             }
216*13571821Stholo           if (Recvd < ToRecv)
217*13571821Stholo             return TotalRecvd + Recvd;
218*13571821Stholo 
219*13571821Stholo           Tmp += Recvd;
220*13571821Stholo           TotalRecvd += Recvd;
221*13571821Stholo           Len -= Recvd;
222*13571821Stholo 	} while (Len > 0);
223*13571821Stholo 
224*13571821Stholo 	return TotalRecvd;
225*13571821Stholo }
226*13571821Stholo #endif /* defined( TCPIP_IBM ) */
227*13571821Stholo 
228