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