/* TCP/IP routines stolen from the VMS GOPHERD */
#include stdio
#include socket
#include in
#include netdb
#if defined(UCX)
#include <errno.h>
#endif
#if defined(VMS) && (defined(WOLLONGONG) || defined(MULTINET) || defined(UCX))
/* Multinet and Wollongong (non UCX-emulation) use channel numbers */
/* for sockets, which are small multiples of 16. The first 5 */
/* channels can be assumed to be already used, so we assume that */
/* sockets start at 64, and that only 64 VAXC fds are simultaneously */
/* open in the program. Actually, the first socket is likely to be */
/* more like 176! */
#define IS_SOCKET(s) ((s)>=64)
/* Close a socket.
* Note that in old Wollongong and Multinet implementations close()
* works only on fds, not sockets.
* For UCX and Unix, closenet() is #defined to be close()
*/
int closenet(s)
int s;
{
if (IS_SOCKET(s)) {
#ifdef MULTINET
return (socket_close(s));
#endif
#ifdef WOLLONGONG
return (netclose(s));
#endif
#ifdef UCX
return (close(s));
#endif
}
else
close(s); /* non-channel UCX socket */
}
#endif /* WOLLONGONG or MULTINET or UCX */
/* Read "n" bytes from a descriptor.
* Use in place of read() when fd is a stream socket
*
* Returns the number of total bytes read.
*/
int readn(fd, ptr, nbytes)
int fd;
char *ptr;
int nbytes;
{
int nleft, nread;
nleft = nbytes;
while (nleft > 0) {
#if defined(VMS) && defined(WOLLONGONG)
nread = IS_SOCKET(fd) ? netread(fd, ptr, nleft) : read(fd, ptr, nleft);
#else
#if defined(VMS) && defined(MULTINET)
nread = IS_SOCKET(fd) ? socket_read(fd, ptr, nleft) : read(fd, ptr, nleft);
#else
nread = read(fd, ptr, nleft);
#endif
#endif
#if defined(VMS) && defined(UCX)
if (nread < 0 && errno == EPIPE)
break;
#endif
if (nread < 0)
return(nread); /* error, return <0 */
else if (nread == 0) /* EOF */
break;
nleft -= nread;
ptr += nread;
}
return(nbytes - nleft); /* return >= 0) */
}
/*
* Write "n" bytes to a descriptor.
* Use in place of write() when fd is a stream socket
*
* We return the number of bytes written
*/
int
writen(fd, ptr, nbytes)
int fd;
char *ptr;
int nbytes;
{
int nleft, nwritten;
nleft = nbytes;
while(nleft > 0) {
#if defined(VMS) && defined(WOLLONGONG)
nwritten = IS_SOCKET(fd) ? netwrite(fd, ptr, nleft) : write(fd, ptr, nleft);
#else
#if defined(VMS) && defined(MULTINET)
nwritten = IS_SOCKET(fd) ? socket_write(fd, ptr, nleft) : write(fd, ptr, nleft);
#else
nwritten = write(fd, ptr, nleft);
#endif
#endif
if (nwritten <= 0)
return(nwritten); /* error */
nleft -= nwritten;
ptr += nwritten;
}
return(nbytes - nleft);
}
/*
* Writestring uses the writen and strlen calls to write a
* string to the file descriptor fd. If the write fails
* a -1 is returned. Otherwise zero is returned.
*/
int writestring(fd, stringptr)
int fd;
char *stringptr;
{
int length;
if (stringptr == NULL)
return(0);
length = strlen(stringptr);
if (writen(fd, stringptr, length) != length) {
return(-1);
}
else
return(0);
}
/*
* Read from the socket into a buffer. Mucho more efficent in terms of
* system calls..
*
* returns bytes read, or <0 for an error
*/
#define RECVSIZE 4096
int readrecvbuf(sockfd, buf, len)
int sockfd;
char *buf;
int len;
{
static char recvbuf[RECVSIZE];
static int recvbufptr = 0;
static int recvbufsize = 0;
static int Oldsockfd = 0;
int bytesread = 0;
if (recvbufptr == 0 || Oldsockfd != sockfd) {
#if defined(VMS) && defined(WOLLONGONG)
recvbufsize = IS_SOCKET(sockfd) ?
netread(sockfd, recvbuf, RECVSIZE) : read(sockfd, recvbuf, RECVSIZE);
#else
#if defined(VMS) && defined(MULTINET)
recvbufsize = IS_SOCKET(sockfd) ?
socket_read(sockfd, recvbuf, RECVSIZE) : read(sockfd, recvbuf, RECVSIZE);
#else
recvbufsize = read(sockfd, recvbuf, RECVSIZE);
#endif
#endif
Oldsockfd = sockfd;
recvbufptr = 0;
if (recvbufsize == 0)
return(0);
#if defined(VMS) && defined(UCX)
if (recvbufsize < 0 && errno == EPIPE)
return(0);
#endif
}
while (len--) {
*buf++ = recvbuf[recvbufptr++];
bytesread++;
if (recvbufptr == recvbufsize && len != 0) {
recvbufsize = readn(sockfd, recvbuf, RECVSIZE);
recvbufptr = 0;
if (recvbufsize == 0)
return(bytesread);
if (recvbufsize < 0)
return(recvbufsize);
} else if (recvbufptr >= recvbufsize)
recvbufptr = 0;
}
return(bytesread);
}
/*
* Read a line from a descriptor. Read the line one byte at a time,
* looking for the newline. We store the newline in the buffer,
* then follow it with a null (the same as fgets(3)).
* We return the number of characters up to, but not including,
* the null (the same as strlen(3))
*/
int readline(fd, ptr, maxlen)
int fd;
char *ptr;
int maxlen;
{
int n;
int rc;
char c;
for (n=1; n < maxlen; n++) {
if ( (rc = readrecvbuf(fd, &c, 1)) == 1) {
*ptr++ = c;
if (c == '\n')
break;
}
else if (rc == 0) {
if (n == 1)
return(0); /* EOF, no data read */
else
break; /* EOF, some data was read */
}
else
return(-1); /* error */
}
*ptr = 0; /* Tack a NULL on the end */
return(n);
}
/*
* ZapCRLF removes all carriage returns and linefeeds from a C-string.
*/
void
ZapCRLF(inputline)
char *inputline;
{
char *cp;
cp = strchr(inputline, '\r'); /* Zap CR-LF */
if (cp != NULL)
*cp = '\0';
else {
cp = strchr(inputline, '\n');
if (cp != NULL)
*cp = '\0';
}
}
void inet_netnames(int sock, char *host_name)
{
struct sockaddr_in sa;
int length;
u_long net_addr;
struct hostent *hp;
length = sizeof(sa);
getpeername(sock, &sa, &length);
strcpy(host_name, inet_ntoa(sa.sin_addr));
hp = gethostbyaddr((char *) &sa.sin_addr,
sizeof (sa.sin_addr.s_addr), AF_INET);
if (hp != NULL)
strcpy(host_name, hp->h_name);
}
.
Response:
text/plain