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 >
C/C++ Source or Header  |  1992-12-20  |  6KB  |  252 lines

  1. /*
  2.  * sockets - open a socket connection and read/write to nntp server
  3.  *
  4.  * Copyright (C) 1992 Stephen Hebditch. All rights reserved.
  5.  * TQM Communications, BCM Box 225, London, WC1N 3XX.
  6.  * steveh@orbital.demon.co.uk  +44 836 825962
  7.  *
  8.  * See README for more information and disclaimers
  9.  *
  10.  * Obtain the current time from the remote server in standard unix time
  11.  * format for use with the next NEWNEWS. If the client is unable to
  12.  * connect to the time server, then local time is used instead.
  13.  *
  14.  * 1.00   1 Oct 92  SH  Adapted from nntpxfer-e code.
  15.  * 1.00  29 Nov 92  SH  Incorporate code to set up a tcp connection
  16.  *                      and clean up the existing code.
  17.  * 1.01   4 Dec 92  SH  Print line before it is sent to server when
  18.  *                      debugging is on.
  19.  * 1.03  15 Dec 92  SH  Removed unnecessary close() in close_server.
  20.  *                      Syslog log level for connected message changed
  21.  *                      to LOG_INFO.
  22.  */
  23.  
  24. #include "slurp.h"
  25.  
  26. #include <signal.h>
  27. #include <setjmp.h>
  28. #include <errno.h>
  29. #include <unistd.h>
  30. #include <netdb.h>
  31. #include <sys/socket.h>
  32. #include <netinet/in.h>
  33. #include <arpa/inet.h>
  34.  
  35. #ifndef INADDR_NONE
  36.   #define INADDR_NONE 0xffffffff
  37. #endif
  38.  
  39. struct sockaddr_in serv_addr;
  40. struct servent serv_info;
  41. struct hostent host_info;
  42.  
  43. static int server;
  44. static FILE *server_rd_fp;
  45. static FILE *server_wr_fp;
  46.  
  47.  
  48. /*
  49.  * tcp_open - Open a tcp connection to 'host' for service 'service',
  50.  * returning a file descriptor for the socket.
  51.  */
  52.  
  53.     int
  54. tcp_open (char *host, char *service)
  55.     {
  56.     int sockfd, on;
  57.     unsigned long inaddr;
  58.     struct servent *sp;
  59.     struct hostent *hp;
  60.  
  61.     bzero ((char *) &serv_addr, sizeof (serv_addr));
  62.     serv_addr.sin_family = AF_INET;
  63.  
  64.     /* Get service information */
  65.     if ((sp = getservbyname (service, "tcp")) == NULL)
  66.         {
  67.         log_ret ("tcp_open: Unknown service %s/tcp", service);
  68.         return (-1);
  69.         }
  70.     serv_info = *sp;
  71.     serv_addr.sin_port = sp->s_port;
  72.  
  73.     /* Try to convert host name as dotted decimal */
  74.     if ((inaddr = inet_addr (host)) != INADDR_NONE)
  75.         {
  76.         bcopy ((char *) &inaddr, (char *) &serv_addr.sin_addr,
  77.                sizeof (inaddr));
  78.         host_info.h_name = NULL;
  79.         }
  80.     /* If that failed, then look up the host name */
  81.     else
  82.         {
  83.         if ((hp = gethostbyname (host)) == NULL)
  84.             {
  85.             log_ret ("tcp_open: Host name error: %s", host);
  86.             return (-1);
  87.             }
  88.         host_info = *hp;
  89.         bcopy (hp->h_addr, (char *) &serv_addr.sin_addr, hp->h_length);
  90.         }
  91.  
  92.     if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
  93.         {
  94.         log_ret ("tcp_open: Can't create TCP socket");
  95.         return (-1);
  96.         }
  97.  
  98.     if (connect (sockfd, (struct sockaddr *) &serv_addr,
  99.         sizeof (serv_addr)) < 0)
  100.         {
  101.         log_ret ("tcp_open: Can't connect to server %s", host);
  102.         (void) close (sockfd);
  103.         return (-1);
  104.         }
  105.  
  106.     on = 1;
  107.     if (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE, 
  108.                     (char *) &on, sizeof (on)) < 0)
  109.         log_ret ("tcp_open: Can't set KEEPALIVE on socket");
  110.  
  111.     return (sockfd);
  112.     }
  113.  
  114. /*
  115.  * server_init - Open a connection to the NNTP server. Returns -1 if an
  116.  * error occurs, otherwise the server's initial response code.
  117.  */
  118.  
  119.     int
  120. server_init (char *hostname)
  121.     {
  122.     char line [NNTP_STRLEN];
  123.  
  124.     /* First try and make the connection */
  125.     if ((server = tcp_open (hostname,"nntp")) < 0)
  126.         return (-1);
  127.  
  128.     /* Now fdopen to enable buffering of incoming data */
  129.     if ((server_rd_fp = fdopen (server, "r")) == NULL)
  130.         {
  131.         log_ret ("server_init: Can't fdopen socket for reading");
  132.         return (-1);
  133.         }
  134.     if ((server_wr_fp = fdopen (server, "w")) == NULL)
  135.         {
  136.         log_ret ("server_init: Can't fdopen socket for writing");
  137.         return (-1);
  138.         }
  139.  
  140.     /* Inform everyone that we're there */
  141. #ifdef SYSLOG
  142.     if (!debug_flag)
  143.         syslog(LOG_INFO, "Connected to nntp server at %s", hostname);
  144.     else
  145. #endif
  146.         (void) fprintf (stderr, "Connected to nntp server at %s\n", hostname);
  147.  
  148.     /* Get the greeting herald */
  149.     if (get_server (line, sizeof (line)))
  150.         return (-1);
  151.     if (debug_flag)
  152.         (void) fprintf (stderr, "-> %s\n", line);
  153.  
  154.     /* Return the banner code */
  155.     return (atoi (line));
  156.     }
  157.  
  158.  
  159. /*
  160.  * close_server - Close down the NNTP server connection
  161.  */
  162.  
  163.     void
  164. close_server ()
  165.     {
  166.     char line [NNTP_STRLEN];
  167.  
  168.     if (debug_flag)
  169.         (void) fprintf (stderr, "<- QUIT\n");
  170.     put_server ("QUIT");
  171.     (void) get_server (line, sizeof (line));
  172.     if (debug_flag)
  173.         (void) fprintf (stderr, "-> %s\n", line);
  174.  
  175.     (void) fclose (server_rd_fp);
  176.     (void) fclose (server_wr_fp);
  177.     }
  178.  
  179.  
  180. static jmp_buf env_alrm;
  181.  
  182.     static void
  183. sig_alrm (int signo)
  184.     {
  185.     longjmp (env_alrm, 1);
  186.     }
  187.  
  188. /*
  189.  * get_server - Read a line up to CRLF from the socket into a buffer.
  190.  */
  191.  
  192.     int
  193. get_server (char *line, int size)
  194.     {
  195.     int esave;
  196.     char *pos;
  197.     char *ret;
  198.  
  199.     /* Set up an alarm to handle socket timeout */
  200.     if (setjmp (env_alrm))
  201.         {
  202.         (void) alarm (0);                    /* Reset alarm clock */
  203.         (void) signal (SIGALRM, SIG_DFL);
  204.         server_wr_fp->_flag |= _IOERR;        /* Set error */
  205.         errno = EPIPE;
  206.         log_ret ("get_server: Read error on server socket");
  207.         return (-1);
  208.         }
  209.  
  210.     (void) signal (SIGALRM, sig_alrm);
  211.     (void) alarm (TIMEOUT);
  212.  
  213.     /* Read line */
  214.     ret = fgets (line, size, server_rd_fp);
  215.  
  216.     /* Reset the alarm */
  217.     esave = errno;
  218.     (void) alarm (0);
  219.     (void) signal (SIGALRM, SIG_DFL);
  220.     errno = esave;
  221.  
  222.     /* Report any error */
  223.     if (ret == NULL)
  224.         {
  225.         log_ret ("get_server: Read error on server socket");
  226.         return (-1);
  227.         }
  228.  
  229.     /* Kill the CRLF */
  230.     if (pos = strchr (line, '\r'))
  231.         *pos = '\0';
  232.     if (pos = strchr (line, '\n'))
  233.         *pos = '\0';
  234.  
  235.     return (0);
  236.     }
  237.  
  238. /*
  239.  * put_server - write a line from a linefer to a socket
  240.  */
  241.  
  242.     void
  243. put_server (char *line)
  244.     {
  245.  
  246.     if (fprintf (server_wr_fp, "%s\r\n", line) == EOF)
  247.         log_sys ("put_server: Write error on server socket");
  248.     (void) fflush (server_wr_fp);
  249.     }
  250.  
  251. /* END-OF-FILE */
  252.