File: sock.c

package info (click to toggle)
xlispstat 3.52.14-1
  • links: PTS
  • area: main
  • in suites: potato
  • size: 7,560 kB
  • ctags: 12,676
  • sloc: ansic: 91,357; lisp: 21,759; sh: 1,525; makefile: 521; csh: 1
file content (186 lines) | stat: -rw-r--r-- 4,329 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/* Simple sockets interface derived from the sockets UICI
   implementation in Appendix B of Practical UNIX Programming,
   K. A. Robbins and S. Robbins, Prentice Hall, 1996. */

#if defined(__MWERKS__) && defined(macintosh)
#  define MACINTOSH
#  define EINTR 15
#endif

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>
#if defined(_Windows)
#  include <winsock.h>
   typedef long ssize_t;
#elif defined(MACINTOSH)
#  include <GUSI.h>
#else
#  include <unistd.h>
#  include <netdb.h>
#  include <sys/socket.h>
#  include <netinet/in.h>
#  include <netinet/tcp.h>
#endif
#include "sock.h"

#if defined(__hpux) || defined(MACINTOSH)
   extern int h_errno; /* HP-UX 9.05 and GUSI forget to declare this in netdb.h */
#endif

#define MAXBACKLOG 5

static int Sock_error(Sock_error_t perr, int e, int he)
{
  if (perr != NULL) {
    perr->error = e;
    perr->h_error = he;
  }
  return -1;
}

#ifdef MACINTOSH
extern void __sinit(void);
extern int __initialize (void *ignoredParameter);
int __initialize(void *ignoredParameter) {
  __sinit();
  return(0);
}
#endif

int Sock_init()
{
#if defined(_Windows)
  WSADATA wsaData;
  WORD wVers = MAKEWORD(1, 1);
  if (WSAStartup(wVers, &wsaData) != 0)
    return 1;
#elif defined(MACINTOSH)
  GUSISetup(GUSIwithInternetSockets);
#elif defined(SIGPIPE)
  struct sigaction act;
  if (sigaction(SIGPIPE, (struct sigaction *)NULL, &act) < 0)
    return 1;
  if (act.sa_handler == SIG_DFL) {
    act.sa_handler = SIG_IGN;
    if (sigaction(SIGPIPE, &act, (struct sigaction *)NULL) < 0)
      return 1;
  }
#endif
  return 0;
}

int Sock_open(Sock_port_t port, Sock_error_t perr)
{
  int sock;
  struct sockaddr_in server;
 
  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    return Sock_error(perr, errno, 0);
       
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = INADDR_ANY;
  server.sin_port = htons((short)port);
 
  if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) < 0) ||
      (listen(sock, MAXBACKLOG) < 0))
    return Sock_error(perr, errno, 0);
  return sock;
}

int Sock_listen(int fd, char *cname, int buflen, Sock_error_t perr)
{
  struct sockaddr_in net_client;
  int len = sizeof(struct sockaddr);
  int retval;
  struct hostent *hostptr;

  do
    retval = accept(fd, (struct sockaddr *)(&net_client), &len);
  while (retval == -1 && errno == EINTR);
  if (retval == -1)
    return Sock_error(perr, errno, 0);

  if (cname != NULL && buflen > 0) {
    size_t nlen;
    char *name;
    struct in_addr *iaddr = &(net_client.sin_addr);
    hostptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
    name = (hostptr == NULL) ? "unknown" :  hostptr->h_name;
    nlen = strlen(name);
    if (buflen < nlen + 1)
      nlen = buflen - 1;
    strncpy(cname, name, nlen);
    cname[nlen] = 0;
  }
  return retval;
}

int Sock_connect(Sock_port_t port, char *sname, Sock_error_t perr)
{
  struct sockaddr_in server;
  struct hostent *hp;
  int sock;
  int retval;
 
  if (! (hp = gethostbyname(sname))
      || (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    return Sock_error(perr, errno, h_errno);
       
  memcpy((char *)&server.sin_addr, hp->h_addr_list[0], hp->h_length);
  server.sin_port = htons((short)port);
  server.sin_family = AF_INET;

  do
    retval = connect(sock, (struct sockaddr *) &server, sizeof(server));
  while (retval == -1 && errno == EINTR);
  if (retval == -1) {
    Sock_error(perr, errno, 0);
#ifdef _Windows
    closesocket(sock);
#else
    close(sock);
#endif
    return -1;
  }
  return sock;
}

int Sock_close(int fd, Sock_error_t perr)
{
#ifdef _Windows
  if (closesocket(fd) != 0)
    return Sock_error(perr, WSAENOTSOCK, 0);
#else
  if (close(fd) < 0)
    return Sock_error(perr, errno, 0);
#endif
  else
    return 0;  
}

ssize_t Sock_read(int fd, void *buf, size_t size, Sock_error_t perr)
{
  ssize_t retval;
  do
    retval = recv(fd, buf, size, 0);
  while (retval == -1 && errno == EINTR);
  if (retval == -1)
    return Sock_error(perr, errno, 0);
  else
    return retval;
}    
 
ssize_t Sock_write(int fd, void *buf, size_t size, Sock_error_t perr)
{
  ssize_t retval;
  do
    retval = send(fd, buf, size, 0);
  while (retval == -1 && errno == EINTR);
  if (retval == -1)
    return Sock_error(perr, errno, 0);
  else
    return retval;
}