/*
INet Socket Code
by Johnson Earls
version 1.0
created 9-Dec-90
changed by cknight
version 1.1
[changed it to fit in with SpiderBot,
also made it a linked-list implementation]
2-Mar-91
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <ctype.h>
#include <sys/time.h>
#include "stringops.h"
#include "socket.h"
sockrec *socket_allocate(sockrec *s, long data)
{
sockrec *new;
#ifdef FUNCTIONS
puts ("**socket_allocate");
#endif
new = allocate (sockrec);
new->data = data;
new->next = s;
return new;
}
sockrec *socket_deallocate(sockrec *s, sockrec *d)
{
sockrec *list;
#ifdef FUNCTIONS
puts ("**socket_deallocate");
#endif
if (s == d)
{
list = s->next;
free (s);
return list;
}
else
{
sockrec *temp;
for (list = s; (list->next != s) && (list->next != NULL);
list = list->next);
if (list->next != NULL)
{
temp = list->next;
list->next = temp->next;
free (temp);
}
return s;
}
}
int socket_connect(sockrec *s, char *name, int port)
{
struct hostent *host;
struct sockaddr_in sin;
unsigned char IPadr[4], lp, flag;
char *p;
#ifdef FUNCTIONS
puts ("**socket_connect");
#endif
if (isdigit(*(name)))
{
lp = flag = IPadr[0] = IPadr[1] = IPadr[2] = IPadr[3] = 0;
p = name;
while (*p)
{
if (*p == '.')
if ((!flag) || (lp == 3))
return(ERR_SOCKBADADDR);
else
lp++;
else
if (isdigit(*p))
{
IPadr[lp] = IPadr[lp] * 10 + (*p) - '0';
flag = 1;
}
else
return(ERR_SOCKBADADDR);
p++;
}
if (lp < 3)
return(ERR_SOCKBADADDR);
}
else
{
host = gethostbyname(name);
if (host == (struct hostent *)0)
return(ERR_SOCKBADADDR);
(void)bcopy(host->h_addr, IPadr, 4);
}
if ((s->sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return(ERR_SOCKCANTCREATE);
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
(void)bcopy(IPadr, (char *)&sin.sin_addr, 4);
if (connect(s->sd, &sin, sizeof(struct sockaddr_in)) < 0)
return(ERR_SOCKCANTCONNECT);
return(0);
}
void socket_disconnect(sockrec *s)
{
#ifdef FUNCTIONS
puts ("**socket_disconnect");
#endif
close(*s);
}
int socket_read(sockrec *s, char **str)
{
char buf[65536]; /* longer than will be needed [hopefully] */
char *p, ch;
int ret;
#ifdef FUNCTIONS
puts ("**socket_read");
#endif
p = buf;
while(1) {
if ((ret=recv(s->sd, &ch, 1, 0)) < 0)
return(ERR_SOCKERRREAD);
else if (!ret)
return(ERR_SOCKCLOSED);
if (ch == '\n') break;
if (ch != '\r')
*(p++) = ch;
}
*p = '\0';
copystring (*str, buf);
return(0);
}
int socket_write(sockrec *s, char *str)
{
char nl = '\n';
#ifdef FUNCTIONS
puts ("**socket_write");
#endif
if ((write(s->sd, str, strlen(str)) < 0) || (write(s->sd, &nl, 1)))
return(ERR_SOCKERRWRITE);
return(0);
}
int socket_write_noret(sockrec *s, char *str)
{
#ifdef FUNCTIONS
puts ("**socket_write_noret");
#endif
if ((write(s->sd, str, strlen(str)) < 0))
return(ERR_SOCKERRWRITE);
return(0);
}
int socket_ready(sockrec *s)
{
#ifdef FUNCTIONS
puts ("**socket_ready");
#endif
return(socket_wait(s, 0L, 50L));
}
int socket_wait(sockrec *s, long timeout, long utimeout)
{
struct timeval wait;
fd_set readfds;
#ifdef FUNCTIONS
puts ("**socket_wait");
#endif
wait.tv_sec = timeout;
wait.tv_usec = utimeout;
FD_ZERO(&readfds);
FD_SET(s->sd, &readfds);
if (timeout < 0) {
if (select(FD_SETSIZE, &readfds, (fd_set *)0, (fd_set *)0,
(struct timeval *)0) < 0)
return(ERR_SOCKSELECT);
} else
if (select(FD_SETSIZE, &readfds, (fd_set *)0, (fd_set *)0, &wait) < 0)
return(ERR_SOCKSELECT);
if (FD_ISSET(s->sd, &readfds)) return(1);
return(0);
}
int socket_wait_kbd(sockrec *s, long timeout, long utimeout)
{
struct timeval wait;
fd_set readfds;
#ifdef FUNCTIONS
puts ("**socket_wait_kbd");
#endif
wait.tv_sec = timeout;
wait.tv_usec = utimeout;
FD_ZERO(&readfds);
FD_SET(s->sd, &readfds);
FD_SET(0, &readfds);
if (timeout < 0) {
if (select(FD_SETSIZE, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0)
return(ERR_SOCKSELECT);
} else
if (select(FD_SETSIZE, &readfds, (fd_set *)0, (fd_set *)0, &wait) < 0)
return(ERR_SOCKSELECT);
if (FD_ISSET(s->sd, &readfds)) return(1);
if (FD_ISSET(0, &readfds)) return(2);
return(0);
}