home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
s
/
slurp103.zip
/
SOCKETS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-20
|
6KB
|
252 lines
/*
* sockets - open a socket connection and read/write to nntp server
*
* Copyright (C) 1992 Stephen Hebditch. All rights reserved.
* TQM Communications, BCM Box 225, London, WC1N 3XX.
* steveh@orbital.demon.co.uk +44 836 825962
*
* See README for more information and disclaimers
*
* Obtain the current time from the remote server in standard unix time
* format for use with the next NEWNEWS. If the client is unable to
* connect to the time server, then local time is used instead.
*
* 1.00 1 Oct 92 SH Adapted from nntpxfer-e code.
* 1.00 29 Nov 92 SH Incorporate code to set up a tcp connection
* and clean up the existing code.
* 1.01 4 Dec 92 SH Print line before it is sent to server when
* debugging is on.
* 1.03 15 Dec 92 SH Removed unnecessary close() in close_server.
* Syslog log level for connected message changed
* to LOG_INFO.
*/
#include "slurp.h"
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
struct sockaddr_in serv_addr;
struct servent serv_info;
struct hostent host_info;
static int server;
static FILE *server_rd_fp;
static FILE *server_wr_fp;
/*
* tcp_open - Open a tcp connection to 'host' for service 'service',
* returning a file descriptor for the socket.
*/
int
tcp_open (char *host, char *service)
{
int sockfd, on;
unsigned long inaddr;
struct servent *sp;
struct hostent *hp;
bzero ((char *) &serv_addr, sizeof (serv_addr));
serv_addr.sin_family = AF_INET;
/* Get service information */
if ((sp = getservbyname (service, "tcp")) == NULL)
{
log_ret ("tcp_open: Unknown service %s/tcp", service);
return (-1);
}
serv_info = *sp;
serv_addr.sin_port = sp->s_port;
/* Try to convert host name as dotted decimal */
if ((inaddr = inet_addr (host)) != INADDR_NONE)
{
bcopy ((char *) &inaddr, (char *) &serv_addr.sin_addr,
sizeof (inaddr));
host_info.h_name = NULL;
}
/* If that failed, then look up the host name */
else
{
if ((hp = gethostbyname (host)) == NULL)
{
log_ret ("tcp_open: Host name error: %s", host);
return (-1);
}
host_info = *hp;
bcopy (hp->h_addr, (char *) &serv_addr.sin_addr, hp->h_length);
}
if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
{
log_ret ("tcp_open: Can't create TCP socket");
return (-1);
}
if (connect (sockfd, (struct sockaddr *) &serv_addr,
sizeof (serv_addr)) < 0)
{
log_ret ("tcp_open: Can't connect to server %s", host);
(void) close (sockfd);
return (-1);
}
on = 1;
if (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE,
(char *) &on, sizeof (on)) < 0)
log_ret ("tcp_open: Can't set KEEPALIVE on socket");
return (sockfd);
}
/*
* server_init - Open a connection to the NNTP server. Returns -1 if an
* error occurs, otherwise the server's initial response code.
*/
int
server_init (char *hostname)
{
char line [NNTP_STRLEN];
/* First try and make the connection */
if ((server = tcp_open (hostname,"nntp")) < 0)
return (-1);
/* Now fdopen to enable buffering of incoming data */
if ((server_rd_fp = fdopen (server, "r")) == NULL)
{
log_ret ("server_init: Can't fdopen socket for reading");
return (-1);
}
if ((server_wr_fp = fdopen (server, "w")) == NULL)
{
log_ret ("server_init: Can't fdopen socket for writing");
return (-1);
}
/* Inform everyone that we're there */
#ifdef SYSLOG
if (!debug_flag)
syslog(LOG_INFO, "Connected to nntp server at %s", hostname);
else
#endif
(void) fprintf (stderr, "Connected to nntp server at %s\n", hostname);
/* Get the greeting herald */
if (get_server (line, sizeof (line)))
return (-1);
if (debug_flag)
(void) fprintf (stderr, "-> %s\n", line);
/* Return the banner code */
return (atoi (line));
}
/*
* close_server - Close down the NNTP server connection
*/
void
close_server ()
{
char line [NNTP_STRLEN];
if (debug_flag)
(void) fprintf (stderr, "<- QUIT\n");
put_server ("QUIT");
(void) get_server (line, sizeof (line));
if (debug_flag)
(void) fprintf (stderr, "-> %s\n", line);
(void) fclose (server_rd_fp);
(void) fclose (server_wr_fp);
}
static jmp_buf env_alrm;
static void
sig_alrm (int signo)
{
longjmp (env_alrm, 1);
}
/*
* get_server - Read a line up to CRLF from the socket into a buffer.
*/
int
get_server (char *line, int size)
{
int esave;
char *pos;
char *ret;
/* Set up an alarm to handle socket timeout */
if (setjmp (env_alrm))
{
(void) alarm (0); /* Reset alarm clock */
(void) signal (SIGALRM, SIG_DFL);
server_wr_fp->_flag |= _IOERR; /* Set error */
errno = EPIPE;
log_ret ("get_server: Read error on server socket");
return (-1);
}
(void) signal (SIGALRM, sig_alrm);
(void) alarm (TIMEOUT);
/* Read line */
ret = fgets (line, size, server_rd_fp);
/* Reset the alarm */
esave = errno;
(void) alarm (0);
(void) signal (SIGALRM, SIG_DFL);
errno = esave;
/* Report any error */
if (ret == NULL)
{
log_ret ("get_server: Read error on server socket");
return (-1);
}
/* Kill the CRLF */
if (pos = strchr (line, '\r'))
*pos = '\0';
if (pos = strchr (line, '\n'))
*pos = '\0';
return (0);
}
/*
* put_server - write a line from a linefer to a socket
*/
void
put_server (char *line)
{
if (fprintf (server_wr_fp, "%s\r\n", line) == EOF)
log_sys ("put_server: Write error on server socket");
(void) fflush (server_wr_fp);
}
/* END-OF-FILE */