home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / mthreads / part01 / nntpinit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-20  |  9.5 KB  |  393 lines

  1. /* $Id: nntpinit.c,v 3.0 1991/11/22 04:12:21 davison Trn $
  2. */
  3. /* This software is Copyright 1992 by Stan Barber. 
  4.  *
  5.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  6.  * use this software as long as: there is no monetary profit gained
  7.  * specifically from the use or reproduction or this software, it is not
  8.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  9.  * included prominently in any copy made. 
  10.  *
  11.  * The authors make no claims as to the fitness or correctness of this software
  12.  * for any use whatsoever, and it is provided as is. Any use of this software
  13.  * is at the user's own risk. 
  14.  */
  15.  
  16. #undef    DECNET    /* If you want decnet support */
  17. #undef    EXCELAN   /* Excelan EXOS 205 support */
  18. #undef    NONETDB      /* Define if you're missing netdb.h */
  19.  
  20. #include "EXTERN.h"
  21. #include "common.h"
  22. #include "nntpclient.h"
  23.  
  24. #ifdef USE_NNTP
  25.  
  26. #include <sys/socket.h>
  27. #include <netinet/in.h>
  28. #ifdef NONETDB
  29. # define IPPORT_NNTP    ((unsigned short) 119)
  30. #else
  31. # include <netdb.h>
  32. #endif /* !EXCELAN */
  33.  
  34. #ifdef EXCELAN
  35. int connect _((int, struct sockaddr *));
  36. unsigned short htons _((unsigned short));
  37. unsigned long rhost _((char **));
  38. int rresvport p((int));
  39. int socket _((int, struct sockproto *, struct sockaddr_in *, int));
  40. #endif /* EXCELAN */
  41.  
  42. #ifdef DECNET
  43. #include <netdnet/dn.h>
  44. #include <netdnet/dnetdb.h>
  45. #endif /* DECNET */
  46.  
  47. unsigned long inet_addr _((char *x));
  48. int get_tcp_socket _((char *machine));
  49.  
  50. int
  51. server_init(server)
  52. char *server;
  53. {
  54.     char line2[NNTP_STRLEN];
  55.     int sockt_rd, sockt_wr;
  56. #ifdef DECNET
  57.     char *cp;
  58.  
  59.     cp = index(server, ':');
  60.  
  61.     if (cp && cp[1] == ':') {
  62.     *cp = '\0';
  63.     sockt_rd = get_dnet_socket(server);
  64.     } else
  65.     sockt_rd = get_tcp_socket(server);
  66. #else /* !DECNET */
  67.     sockt_rd = get_tcp_socket(server);
  68. #endif
  69.  
  70.     if (sockt_rd < 0)
  71.     return -1;
  72.     sockt_wr = dup(sockt_rd);
  73.  
  74.     /* Now we'll make file pointers (i.e., buffered I/O) out of
  75.     ** the socket file descriptor.  Note that we can't just
  76.     ** open a fp for reading and writing -- we have to open
  77.     ** up two separate fp's, one for reading, one for writing. */
  78.     if ((ser_rd_fp = fdopen(sockt_rd, "r")) == NULL) {
  79.     perror("server_init: fdopen #1");
  80.     return -1;
  81.     }
  82.     if ((ser_wr_fp = fdopen(sockt_wr, "w")) == NULL) {
  83.     perror("server_init: fdopen #2");
  84.     ser_rd_fp = NULL;
  85.     return -1;
  86.     }
  87.  
  88.     /* Now get the server's signon message */
  89.     nntp_check(FALSE);
  90.  
  91.     if (*ser_line == NNTP_CLASS_OK) {
  92.     /* Send a MODE READER command in case we're talking to innd.
  93.     ** If understood, use that reply. */
  94.     nntp_command("MODE READER");
  95.     nntp_gets(line2, sizeof line2);
  96.     if (atoi(line2) != NNTP_BAD_COMMAND_VAL)
  97.         strcpy(ser_line, line2);
  98.     }
  99.     return atoi(ser_line);
  100. }
  101.  
  102. int
  103. get_tcp_socket(server)
  104. char *server;
  105. {
  106.     int portno;    
  107.     int s;
  108.     struct sockaddr_in sin;
  109. #ifdef __hpux
  110.     int socksize = 0;
  111.     int socksizelen = sizeof socksize;
  112. #endif
  113. #ifdef NONETDB
  114.     bzero((char *) &sin, sizeof(sin));
  115.     sin.sin_family = AF_INET;
  116. #else
  117.     struct servent *getservbyname(), *sp;
  118.     struct hostent *gethostbyname(), *hp;
  119. #ifdef h_addr
  120.     int x = 0;
  121.     register char **cp;
  122.     static char *alist[1];
  123. #endif /* h_addr */
  124.     static struct hostent def;
  125.     static struct in_addr defaddr;
  126.     static char namebuf[ 256 ];
  127.  
  128.     if ((sp = getservbyname("nntp", "tcp")) ==  NULL) {
  129.     fprintf(stderr, "nntp/tcp: Unknown service.\n");
  130.     return -1;
  131.     }
  132.     portno = sp->s_port;
  133.     /* If not a raw ip address, try nameserver */
  134.     if (!isdigit(*server)
  135.      || (long)(defaddr.s_addr = inet_addr(server)) == -1)
  136.     hp = gethostbyname(server);
  137.     else {
  138.     /* Raw ip address, fake  */
  139.     (void) strcpy(namebuf, server);
  140.     def.h_name = namebuf;
  141. #ifdef h_addr
  142.     def.h_addr_list = alist;
  143. #endif
  144.     def.h_addr = (char *)&defaddr;
  145.     def.h_length = sizeof(struct in_addr);
  146.     def.h_addrtype = AF_INET;
  147.     def.h_aliases = 0;
  148.     hp = &def;
  149.     }
  150.     if (hp == NULL) {
  151.     fprintf(stderr, "%s: Unknown host.\n", server);
  152.     return -1;
  153.     }
  154.  
  155.     bzero((char *) &sin, sizeof(sin));
  156.     sin.sin_family = hp->h_addrtype;
  157.     sin.sin_port = portno;
  158. #endif /* !NONETDB */
  159.  
  160.     /* The following is kinda gross.  The name server under 4.3
  161.     ** returns a list of addresses, each of which should be tried
  162.     ** in turn if the previous one fails.  However, 4.2 hostent
  163.     ** structure doesn't have this list of addresses.
  164.     ** Under 4.3, h_addr is a #define to h_addr_list[0].
  165.     ** We use this to figure out whether to include the NS specific
  166.     ** code... */
  167. #ifdef h_addr
  168.     /* get a socket and initiate connection -- use multiple addresses */
  169.     for (cp = hp->h_addr_list; cp && *cp; cp++) {
  170.     s = socket(hp->h_addrtype, SOCK_STREAM, 0);
  171.     if (s < 0) {
  172.         perror("socket");
  173.         return -1;
  174.     }
  175.         bcopy(*cp, (char *)&sin.sin_addr, hp->h_length);
  176.         
  177.     if (x < 0)
  178.         fprintf(stderr, "trying %s\n", inet_ntoa(sin.sin_addr));
  179.     x = connect(s, (struct sockaddr *)&sin, sizeof (sin));
  180.     if (x == 0)
  181.         break;
  182.         fprintf(stderr, "connection to %s: ", inet_ntoa(sin.sin_addr));
  183.     perror("");
  184.     (void) close(s);
  185.     }
  186.     if (x < 0) {
  187.     fprintf(stderr, "giving up...\n");
  188.     return -1;
  189.     }
  190. #else /* no name server */
  191. #ifdef EXCELAN
  192.     s = socket(SOCK_STREAM, (struct sockproto *)NULL, &sin, SO_KEEPALIVE);
  193.     if (s < 0) {
  194.     /* Get the socket */
  195.     perror("socket");
  196.     return -1;
  197.     }
  198.     bzero((char *) &sin, sizeof(sin));
  199.     sin.sin_family = AF_INET;
  200.     sin.sin_port = htons(IPPORT_NNTP);
  201.  
  202.     /* set up addr for the connect */
  203.     if ((sin.sin_addr.s_addr = rhost(&server)) == -1) {
  204.     fprintf(stderr, "%s: Unknown host.\n", server);
  205.     return -1;
  206.     }
  207.  
  208.     /* And then connect */
  209.     if (connect(s, (struct sockaddr *)&sin) < 0) {
  210.     perror("connect");
  211.     (void) close(s);
  212.     return -1;
  213.     }
  214. #else /* not EXCELAN */
  215.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  216.     perror("socket");
  217.     return -1;
  218.     }
  219.  
  220.     /* And then connect */
  221.  
  222.     bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
  223.     if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
  224.     perror("connect");
  225.     (void) close(s);
  226.     return -1;
  227.     }
  228.  
  229. #endif /* !EXCELAN */
  230. #endif /* !h_addr */
  231. #ifdef __hpux    /* recommended by raj@cup.hp.com */
  232. #define    HPSOCKSIZE 0x8000
  233.     getsockopt(s, SOL_SOCKET, SO_SNDBUF, (caddr_t)&socksize, (caddr_t)&socksizelen);
  234.     if (socksize < HPSOCKSIZE) {
  235.     socksize = HPSOCKSIZE;
  236.     setsockopt(s, SOL_SOCKET, SO_SNDBUF, (caddr_t)&socksize, sizeof(socksize));
  237.     }
  238.     socksize = 0;
  239.     socksizelen = sizeof(socksize);
  240.     getsockopt(s, SOL_SOCKET, SO_RCVBUF, (caddr_t)&socksize, (caddr_t)&socksizelen);
  241.     if (socksize < HPSOCKSIZE) {
  242.     socksize = HPSOCKSIZE;
  243.     setsockopt(s, SOL_SOCKET, SO_RCVBUF, (caddr_t)&socksize, sizeof(socksize));
  244.     }
  245. #endif
  246.     return s;
  247. }
  248.  
  249. #ifdef DECNET
  250. int
  251. get_dnet_socket(server)
  252. char *server;
  253. {
  254.     int s, area, node;
  255.     struct sockaddr_dn sdn;
  256.     struct nodeent *getnodebyname(), *np;
  257.  
  258.     bzero((char *) &sdn, sizeof(sdn));
  259.  
  260.     switch (s = sscanf(server, "%d%*[.]%d", &area, &node)) {
  261.     case 1: 
  262.     node = area;
  263.     area = 0;
  264.     case 2: 
  265.     node += area*1024;
  266.     sdn.sdn_add.a_len = 2;
  267.     sdn.sdn_family = AF_DECnet;
  268.     sdn.sdn_add.a_addr[0] = node % 256;
  269.     sdn.sdn_add.a_addr[1] = node / 256;
  270.     break;
  271.     default:
  272.     if ((np = getnodebyname(server)) == NULL) {
  273.         fprintf(stderr, "%s: Unknown host.\n", server);
  274.         return -1;
  275.     } else {
  276.         bcopy(np->n_addr, (char *) sdn.sdn_add.a_addr, np->n_length);
  277.         sdn.sdn_add.a_len = np->n_length;
  278.         sdn.sdn_family = np->n_addrtype;
  279.     }
  280.     break;
  281.     }
  282.     sdn.sdn_objnum = 0;
  283.     sdn.sdn_flags = 0;
  284.     sdn.sdn_objnamel = strlen("NNTP");
  285.     bcopy("NNTP", &sdn.sdn_objname[0], sdn.sdn_objnamel);
  286.  
  287.     if ((s = socket(AF_DECnet, SOCK_STREAM, 0)) < 0) {
  288.     nerror("socket");
  289.     return -1;
  290.     }
  291.  
  292.     /* And then connect */
  293.     if (connect(s, (struct sockaddr *) &sdn, sizeof(sdn)) < 0) {
  294.     nerror("connect");
  295.     close(s);
  296.     return -1;
  297.     }
  298.     return s;
  299. }
  300. #endif /* DECNET */
  301.  
  302. #ifdef EXCELAN
  303. /*
  304.  * inet_addr for EXCELAN (which does not have it!)
  305.  *
  306.  */
  307. unsigned long
  308. inet_addr(cp)
  309. register char   *cp;
  310. {
  311.     unsigned long val, base, n;
  312.     register char c;
  313.     unsigned long octet[4], *octetptr = octet;
  314. #ifndef htonl
  315.     extern  unsigned long   htonl();
  316. #endif  /* htonl */
  317. again:
  318.     /*
  319.      * Collect number up to ``.''.
  320.      * Values are specified as for C:
  321.      * 0x=hex, 0=octal, other=decimal.
  322.      */
  323.     val = 0; base = 10;
  324.     if (*cp == '0')
  325.         base = 8, cp++;
  326.     if (*cp == 'x' || *cp == 'X')
  327.         base = 16, cp++;
  328.     while (c = *cp) {
  329.         if (isdigit(c)) {
  330.             val = (val * base) + (c - '0');
  331.             cp++;
  332.             continue;
  333.         }
  334.         if (base == 16 && isxdigit(c)) {
  335.             val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
  336.             cp++;
  337.             continue;
  338.         }
  339.         break;
  340.     }
  341.     if (*cp == '.') {
  342.         /*
  343.          * Internet format:
  344.          *      a.b.c.d
  345.          *      a.b.c   (with c treated as 16-bits)
  346.          *      a.b     (with b treated as 24 bits)
  347.          */
  348.         if (octetptr >= octet + 4)
  349.             return (-1);
  350.         *octetptr++ = val, cp++;
  351.         goto again;
  352.     }
  353.     /*
  354.      * Check for trailing characters.
  355.      */
  356.     if (*cp && !isspace(*cp))
  357.         return (-1);
  358.     *octetptr++ = val;
  359.     /*
  360.      * Concoct the address according to
  361.      * the number of octet specified.
  362.      */
  363.     n = octetptr - octet;
  364.     switch (n) {
  365.  
  366.     case 1:                         /* a -- 32 bits */
  367.         val = octet[0];
  368.         break;
  369.  
  370.     case 2:                         /* a.b -- 8.24 bits */
  371.         val = (octet[0] << 24) | (octet[1] & 0xffffff);
  372.         break;
  373.  
  374.     case 3:                         /* a.b.c -- 8.8.16 bits */
  375.         val = (octet[0] << 24) | ((octet[1] & 0xff) << 16) |
  376.             (octet[2] & 0xffff);
  377.         break;
  378.  
  379.     case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
  380.         val = (octet[0] << 24) | ((octet[1] & 0xff) << 16) |
  381.               ((octet[2] & 0xff) << 8) | (octet[3] & 0xff);
  382.         break;
  383.  
  384.     default:
  385.         return (-1);
  386.     }
  387.     val = htonl(val);
  388.     return (val);
  389. }
  390. #endif /* EXCELAN */
  391.  
  392. #endif /* USE_NNTP */
  393.