racket/examples/csocket.c
Jamie Taylor 7df230607b updated the sockets example to work with the current version of Chez.
Change the foreign procedure definitions to use the more portable int
  rather than integer-32.  Switch to a custom port
  [make-custom-binary-input/output-port] rather than a generic port
  [make-input/output-port], which resulted in deleting quite a bit of
  code.  Fix various compiler warnings in the C code, and along the way,
  fix a signedness bug in c_write that could have resulted in not writing
  the full buffer (but reporting that it did) in the case of errors from
  write.
    examples/csocket.c, examples/socket.ss

original commit: 9dfa900b251ba480ea13b1796a58d7398146d0b9
2016-09-12 14:29:02 -04:00

104 lines
2.3 KiB
C

/*/ csocket.c
R. Kent Dybvig May 1998
Updated by Jamie Taylor, Sept 2016
Public Domain
/*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
/* c_write attempts to write the entire buffer, pushing through
interrupts, socket delays, and partial-buffer writes */
int c_write(int fd, char *buf, ssize_t start, ssize_t n) {
ssize_t i, m;
buf += start;
m = n;
while (m > 0) {
if ((i = write(fd, buf, m)) < 0) {
if (errno != EAGAIN && errno != EINTR)
return i;
} else {
m -= i;
buf += i;
}
}
return n;
}
/* c_read pushes through interrupts and socket delays */
int c_read(int fd, char *buf, size_t start, size_t n) {
int i;
buf += start;
for (;;) {
i = read(fd, buf, n);
if (i >= 0) return i;
if (errno != EAGAIN && errno != EINTR) return -1;
}
}
/* bytes_ready(fd) returns true if there are bytes available
to be read from the socket identified by fd */
int bytes_ready(int fd) {
int n;
(void) ioctl(fd, FIONREAD, &n);
return n;
}
/* socket support */
/* do_socket() creates a new AF_UNIX socket */
int do_socket(void) {
return socket(AF_UNIX, SOCK_STREAM, 0);
}
/* do_bind(s, name) binds name to the socket s */
int do_bind(int s, char *name) {
struct sockaddr_un sun;
int length;
sun.sun_family = AF_UNIX;
(void) strcpy(sun.sun_path, name);
length = sizeof(sun.sun_family) + sizeof(sun.sun_path);
return bind(s, (struct sockaddr*)(&sun), length);
}
/* do_accept accepts a connection on socket s */
int do_accept(int s) {
struct sockaddr_un sun;
socklen_t length;
length = sizeof(sun.sun_family) + sizeof(sun.sun_path);
return accept(s, (struct sockaddr*)(&sun), &length);
}
/* do_connect initiates a socket connection */
int do_connect(int s, char *name) {
struct sockaddr_un sun;
int length;
sun.sun_family = AF_UNIX;
(void) strcpy(sun.sun_path, name);
length = sizeof(sun.sun_family) + sizeof(sun.sun_path);
return connect(s, (struct sockaddr*)(&sun), length);
}
/* get_error returns the operating system's error status */
char* get_error(void) {
extern int errno;
return strerror(errno);
}