Initial commit, 3-52-19 alpha
[cls.git] / Extras / sockets / sock.c
blob8c6e9d6aa98691c16d4167728cd41c931ddd8fa2
1 /* Simple sockets interface derived from the sockets UICI
2 implementation in Appendix B of Practical UNIX Programming,
3 K. A. Robbins and S. Robbins, Prentice Hall, 1996. */
5 #if defined(__MWERKS__) && defined(macintosh)
6 # define MACINTOSH
7 # define EINTR 15
8 #endif
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <signal.h>
14 #include <errno.h>
15 #if defined(_Windows)
16 # include <winsock.h>
17 typedef long ssize_t;
18 #elif defined(MACINTOSH)
19 # include <GUSI.h>
20 #else
21 # include <unistd.h>
22 # include <netdb.h>
23 # include <sys/socket.h>
24 # include <netinet/in.h>
25 # include <netinet/tcp.h>
26 #endif
27 #include "sock.h"
29 #if defined(__hpux) || defined(MACINTOSH)
30 extern int h_errno; /* HP-UX 9.05 and GUSI forget to declare this in netdb.h */
31 #endif
33 #define MAXBACKLOG 5
35 static int Sock_error(Sock_error_t perr, int e, int he)
37 if (perr != NULL) {
38 perr->error = e;
39 perr->h_error = he;
41 return -1;
44 #ifdef MACINTOSH
45 extern void __sinit(void);
46 extern int __initialize (void *ignoredParameter);
47 int __initialize(void *ignoredParameter) {
48 __sinit();
49 return(0);
51 #endif
53 int Sock_init()
55 #if defined(_Windows)
56 WSADATA wsaData;
57 WORD wVers = MAKEWORD(1, 1);
58 if (WSAStartup(wVers, &wsaData) != 0)
59 return 1;
60 #elif defined(MACINTOSH)
61 GUSISetup(GUSIwithInternetSockets);
62 #elif defined(SIGPIPE)
63 struct sigaction act;
64 if (sigaction(SIGPIPE, (struct sigaction *)NULL, &act) < 0)
65 return 1;
66 if (act.sa_handler == SIG_DFL) {
67 act.sa_handler = SIG_IGN;
68 if (sigaction(SIGPIPE, &act, (struct sigaction *)NULL) < 0)
69 return 1;
71 #endif
72 return 0;
75 int Sock_open(Sock_port_t port, Sock_error_t perr)
77 int sock;
78 struct sockaddr_in server;
80 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
81 return Sock_error(perr, errno, 0);
83 server.sin_family = AF_INET;
84 server.sin_addr.s_addr = INADDR_ANY;
85 server.sin_port = htons((short)port);
87 if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) ||
88 (listen(sock, MAXBACKLOG) < 0))
89 return Sock_error(perr, errno, 0);
90 return sock;
93 int Sock_listen(int fd, char *cname, int buflen, Sock_error_t perr)
95 struct sockaddr_in net_client;
96 int len = sizeof(struct sockaddr);
97 int retval;
98 struct hostent *hostptr;
101 retval = accept(fd, (struct sockaddr *)(&net_client), &len);
102 while (retval == -1 && errno == EINTR);
103 if (retval == -1)
104 return Sock_error(perr, errno, 0);
106 if (cname != NULL && buflen > 0) {
107 size_t nlen;
108 char *name;
109 struct in_addr *iaddr = &(net_client.sin_addr);
110 hostptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
111 name = (hostptr == NULL) ? "unknown" : hostptr->h_name;
112 nlen = strlen(name);
113 if (buflen < nlen + 1)
114 nlen = buflen - 1;
115 strncpy(cname, name, nlen);
116 cname[nlen] = 0;
118 return retval;
121 int Sock_connect(Sock_port_t port, char *sname, Sock_error_t perr)
123 struct sockaddr_in server;
124 struct hostent *hp;
125 int sock;
126 int retval;
128 if (! (hp = gethostbyname(sname))
129 || (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
130 return Sock_error(perr, errno, h_errno);
132 memcpy((char *)&server.sin_addr, hp->h_addr_list[0], hp->h_length);
133 server.sin_port = htons((short)port);
134 server.sin_family = AF_INET;
137 retval = connect(sock, (struct sockaddr *) &server, sizeof(server));
138 while (retval == -1 && errno == EINTR);
139 if (retval == -1) {
140 Sock_error(perr, errno, 0);
141 #ifdef _Windows
142 closesocket(sock);
143 #else
144 close(sock);
145 #endif
146 return -1;
148 return sock;
151 int Sock_close(int fd, Sock_error_t perr)
153 #ifdef _Windows
154 if (closesocket(fd) != 0)
155 return Sock_error(perr, WSAENOTSOCK, 0);
156 #else
157 if (close(fd) < 0)
158 return Sock_error(perr, errno, 0);
159 #endif
160 else
161 return 0;
164 ssize_t Sock_read(int fd, void *buf, size_t size, Sock_error_t perr)
166 ssize_t retval;
168 retval = recv(fd, buf, size, 0);
169 while (retval == -1 && errno == EINTR);
170 if (retval == -1)
171 return Sock_error(perr, errno, 0);
172 else
173 return retval;
176 ssize_t Sock_write(int fd, void *buf, size_t size, Sock_error_t perr)
178 ssize_t retval;
180 retval = send(fd, buf, size, 0);
181 while (retval == -1 && errno == EINTR);
182 if (retval == -1)
183 return Sock_error(perr, errno, 0);
184 else
185 return retval;