#include /* obligatory includes */ #include #include #include #include #include #include #include #include #include "sockets.h" /* as children die we should get catch their returns or else we get * zombies, A Bad Thing. fireman() catches falling children. */ void fireman(void) { while (waitpid(-1, NULL, WNOHANG) > 0) ; } /* code to establish a socket; originally from bzs@bu-cs.bu.edu */ /* not thread safe: server calls this once before creating threads */ int establish(unsigned short portnum) { char myname[MAXHOSTNAME+1]; int s; struct sockaddr_in sa; struct hostent *hp; memset(&sa, 0, sizeof(struct sockaddr_in)); /* clear our address */ gethostname(myname, MAXHOSTNAME); /* who are we? */ hp= gethostbyname(myname); /* get our address info */ if (hp == NULL) /* we don't exist !? */ return(-1); sa.sin_family= hp->h_addrtype; /* this is our host address */ sa.sin_port= htons(portnum); /* this is our port number */ if ((s= socket(AF_INET, SOCK_STREAM, 0)) < 0) /* create socket */ return(-1); if (bind(s,(struct sockaddr *)&sa,sizeof(struct sockaddr_in)) < 0) { close(s); return(-1); /* bind address to socket */ } listen(s, 3); /* max # of queued connects */ return(s); } /* wait for a connection to occur on a socket created with establish() */ int get_connection(int s) { int t; /* socket of connection */ if ((t = accept(s,NULL,NULL)) < 0) /* accept connection if there is one */ return(-1); return(t); } /* thread safe: gethostbyname -> gethostbyname_r (client threads call this) */ int call_socket(char *hostname, unsigned short portnum) { struct sockaddr_in sa; struct hostent *hp; int s; struct hostent ts_ret; char ts_buf[1000]; size_t ts_len = 1000; int ts_errnop; gethostbyname_r(hostname, &ts_ret, ts_buf, ts_len, &hp, &ts_errnop); if (hp == NULL) { /* do we know the host's */ errno= ECONNREFUSED; /* address? */ return(-1); /* no */ } memset(&sa,0,sizeof(sa)); memcpy((char *)&sa.sin_addr,hp->h_addr,hp->h_length); /* set address */ sa.sin_family= hp->h_addrtype; sa.sin_port= htons((u_short)portnum); if ((s= socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) /* get socket */ return(-1); if (connect(s,(struct sockaddr *)&sa,sizeof sa) < 0) { /* connect */ close(s); return(-1); } return(s); } int read_data(int s, /* connected socket */ char *buf, /* pointer to the buffer */ int n /* number of characters (bytes) we want */ ) { int bcount; /* counts bytes read */ int br; /* bytes read this pass */ bcount= 0; br= 0; while (bcount < n) { /* loop until full buffer */ if ((br= read(s,buf,n-bcount)) > 0) { bcount += br; /* increment byte counter */ buf += br; /* move buffer ptr for next read */ } else if (br < 0) /* signal an error to the caller */ return(-1); } return(bcount); } int write_data(int s, char *buf, int n) { int bcount; int br; bcount = 0; br = 0; while(bcount < n) { if ((br = write(s,buf,n-bcount)) > 0) { bcount += br; buf += br; } else if (br < 0) return (-1); } return (bcount); } int read_string(int s, char *buf) { int i = 0; i+=read_data(s, &buf[i], 1); if (i==0) return i; while(buf[i-1] != '\0') { i+=read_data(s, &buf[i], 1); } buf[i]='\0'; return i; }